mirror of https://github.com/OpenVidu/openvidu.git
8662 lines
1.2 MiB
8662 lines
1.2 MiB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var objectCreate = Object.create || objectCreatePolyfill
|
|
var objectKeys = Object.keys || objectKeysPolyfill
|
|
var bind = Function.prototype.bind || functionBindPolyfill
|
|
|
|
function EventEmitter() {
|
|
if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) {
|
|
this._events = objectCreate(null);
|
|
this._eventsCount = 0;
|
|
}
|
|
|
|
this._maxListeners = this._maxListeners || undefined;
|
|
}
|
|
module.exports = EventEmitter;
|
|
|
|
// Backwards-compat with node 0.10.x
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
EventEmitter.prototype._events = undefined;
|
|
EventEmitter.prototype._maxListeners = undefined;
|
|
|
|
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
// added to it. This is a useful default which helps finding memory leaks.
|
|
var defaultMaxListeners = 10;
|
|
|
|
var hasDefineProperty;
|
|
try {
|
|
var o = {};
|
|
if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 });
|
|
hasDefineProperty = o.x === 0;
|
|
} catch (err) { hasDefineProperty = false }
|
|
if (hasDefineProperty) {
|
|
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
enumerable: true,
|
|
get: function() {
|
|
return defaultMaxListeners;
|
|
},
|
|
set: function(arg) {
|
|
// check whether the input is a positive number (whose value is zero or
|
|
// greater and not a NaN).
|
|
if (typeof arg !== 'number' || arg < 0 || arg !== arg)
|
|
throw new TypeError('"defaultMaxListeners" must be a positive number');
|
|
defaultMaxListeners = arg;
|
|
}
|
|
});
|
|
} else {
|
|
EventEmitter.defaultMaxListeners = defaultMaxListeners;
|
|
}
|
|
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
|
if (typeof n !== 'number' || n < 0 || isNaN(n))
|
|
throw new TypeError('"n" argument must be a positive number');
|
|
this._maxListeners = n;
|
|
return this;
|
|
};
|
|
|
|
function $getMaxListeners(that) {
|
|
if (that._maxListeners === undefined)
|
|
return EventEmitter.defaultMaxListeners;
|
|
return that._maxListeners;
|
|
}
|
|
|
|
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
|
return $getMaxListeners(this);
|
|
};
|
|
|
|
// These standalone emit* functions are used to optimize calling of event
|
|
// handlers for fast cases because emit() itself often has a variable number of
|
|
// arguments and can be deoptimized because of that. These functions always have
|
|
// the same number of arguments and thus do not get deoptimized, so the code
|
|
// inside them can execute faster.
|
|
function emitNone(handler, isFn, self) {
|
|
if (isFn)
|
|
handler.call(self);
|
|
else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
listeners[i].call(self);
|
|
}
|
|
}
|
|
function emitOne(handler, isFn, self, arg1) {
|
|
if (isFn)
|
|
handler.call(self, arg1);
|
|
else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
listeners[i].call(self, arg1);
|
|
}
|
|
}
|
|
function emitTwo(handler, isFn, self, arg1, arg2) {
|
|
if (isFn)
|
|
handler.call(self, arg1, arg2);
|
|
else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
listeners[i].call(self, arg1, arg2);
|
|
}
|
|
}
|
|
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
|
|
if (isFn)
|
|
handler.call(self, arg1, arg2, arg3);
|
|
else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
listeners[i].call(self, arg1, arg2, arg3);
|
|
}
|
|
}
|
|
|
|
function emitMany(handler, isFn, self, args) {
|
|
if (isFn)
|
|
handler.apply(self, args);
|
|
else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
listeners[i].apply(self, args);
|
|
}
|
|
}
|
|
|
|
EventEmitter.prototype.emit = function emit(type) {
|
|
var er, handler, len, args, i, events;
|
|
var doError = (type === 'error');
|
|
|
|
events = this._events;
|
|
if (events)
|
|
doError = (doError && events.error == null);
|
|
else if (!doError)
|
|
return false;
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (doError) {
|
|
if (arguments.length > 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 = 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;
|
|
};
|
|
|
|
module.exports = freeice;
|
|
},{"./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"
|
|
]
|
|
|
|
},{}],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;
|
|
|
|
// Ensure that just a single AudioContext is internally created
|
|
audioContext = options.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() {
|
|
return audioContext.suspend();
|
|
}
|
|
harker.resume = function() {
|
|
return 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) {
|
|
if (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) {
|
|
if (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 <https://mths.be/platform>
|
|
* Copyright 2014-2018 Benjamin Tan <https://bnjmnt4n.now.sh/>
|
|
* Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
|
|
* Available under MIT license <https://mths.be/mit>
|
|
*/
|
|
;(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);
|
|
if (i !== -1) {
|
|
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.6 - git.io/ee
|
|
* Unlicense - http://unlicense.org/
|
|
* Oliver Caldwell - https://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){
|
|
module.exports={
|
|
"author": "OpenVidu",
|
|
"dependencies": {
|
|
"@types/node": "12.6.8",
|
|
"@types/platform": "1.3.2",
|
|
"freeice": "2.2.2",
|
|
"hark": "1.2.3",
|
|
"platform": "1.3.5",
|
|
"uuid": "3.3.2",
|
|
"wolfy87-eventemitter": "5.2.6"
|
|
},
|
|
"description": "OpenVidu Browser",
|
|
"devDependencies": {
|
|
"browserify": "16.3.0",
|
|
"grunt": "1.0.4",
|
|
"grunt-autoprefixer": "3.0.4",
|
|
"grunt-cli": "1.3.2",
|
|
"grunt-contrib-copy": "1.0.0",
|
|
"grunt-contrib-sass": "1.0.0",
|
|
"grunt-contrib-uglify": "4.0.1",
|
|
"grunt-contrib-watch": "1.1.0",
|
|
"grunt-string-replace": "1.3.1",
|
|
"grunt-ts": "6.0.0-beta.22",
|
|
"tsify": "4.0.1",
|
|
"tslint": "5.18.0",
|
|
"typedoc": "0.15.0",
|
|
"typescript": "3.5.3",
|
|
"uglify-js": "3.6.0"
|
|
},
|
|
"license": "Apache-2.0",
|
|
"main": "lib/index.js",
|
|
"name": "openvidu-browser",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git://github.com/OpenVidu/openvidu"
|
|
},
|
|
"scripts": {
|
|
"browserify": "VERSION=${VERSION:-}; cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v",
|
|
"browserify-prod": "VERSION=${VERSION:-}; cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/uglify-js/bin/uglifyjs --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js",
|
|
"build": "cd src/OpenVidu && ./../../node_modules/typescript/bin/tsc && cd ../.. && ./node_modules/typescript/bin/tsc --declaration src/index.ts --outDir ./lib --sourceMap --lib dom,es5,es2015.promise,scripthost",
|
|
"docs": "./node_modules/typedoc/bin/typedoc --options ./config/typedoc.js --out ./docs ./src && rm -rf ../../openvidu.io/api/openvidu-browser/* && cp -R ./docs/. ../../openvidu.io/api/openvidu-browser",
|
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
},
|
|
"types": "lib/index.d.ts",
|
|
"version": "2.11.0"
|
|
}
|
|
|
|
},{}],17:[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":21}],18:[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 + ']';
|
|
this.options = opts;
|
|
this.connectionId = opts.id;
|
|
this.creationTime = opts.createdAt;
|
|
if (opts.metadata) {
|
|
this.data = opts.metadata;
|
|
}
|
|
if (opts.streams) {
|
|
this.initRemoteStreams(opts.streams);
|
|
}
|
|
}
|
|
else {
|
|
msg += '(local)';
|
|
}
|
|
console.info(msg);
|
|
}
|
|
Connection.prototype.sendIceCandidate = function (candidate) {
|
|
console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' +
|
|
this.connectionId, 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,
|
|
createdAt: opts.createdAt,
|
|
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,
|
|
filter: !!opts.filter ? opts.filter : 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":24}],19:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
|
|
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
|
|
var Filter = (function () {
|
|
function Filter(type, options) {
|
|
this.handlers = {};
|
|
this.type = type;
|
|
this.options = options;
|
|
}
|
|
Filter.prototype.execMethod = function (method, params) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
console.info('Executing filter method to stream ' + _this.stream.streamId);
|
|
var stringParams;
|
|
if (typeof params !== 'string') {
|
|
try {
|
|
stringParams = JSON.stringify(params);
|
|
}
|
|
catch (error) {
|
|
var errorMsg = "'params' property must be a JSON formatted object";
|
|
console.error(errorMsg);
|
|
reject(errorMsg);
|
|
}
|
|
}
|
|
else {
|
|
stringParams = params;
|
|
}
|
|
_this.stream.session.openvidu.sendRequest('execFilterMethod', { streamId: _this.stream.streamId, method: method, params: stringParams }, function (error, response) {
|
|
if (error) {
|
|
console.error('Error executing filter method for Stream ' + _this.stream.streamId, error);
|
|
if (error.code === 401) {
|
|
reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to execute a filter method"));
|
|
}
|
|
else {
|
|
reject(error);
|
|
}
|
|
}
|
|
else {
|
|
console.info('Filter method successfully executed on Stream ' + _this.stream.streamId);
|
|
var oldValue = Object.assign({}, _this.stream.filter);
|
|
_this.stream.filter.lastExecMethod = { method: method, params: JSON.parse(stringParams) };
|
|
_this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.stream.session, _this.stream, 'filter', _this.stream.filter, oldValue, 'execFilterMethod')]);
|
|
_this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.stream.streamManager, _this.stream, 'filter', _this.stream.filter, oldValue, 'execFilterMethod')]);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Filter.prototype.addEventListener = function (eventType, handler) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
console.info('Adding filter event listener to event ' + eventType + ' to stream ' + _this.stream.streamId);
|
|
_this.stream.session.openvidu.sendRequest('addFilterEventListener', { streamId: _this.stream.streamId, eventType: eventType }, function (error, response) {
|
|
if (error) {
|
|
console.error('Error adding filter event listener to event ' + eventType + 'for Stream ' + _this.stream.streamId, error);
|
|
if (error.code === 401) {
|
|
reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener"));
|
|
}
|
|
else {
|
|
reject(error);
|
|
}
|
|
}
|
|
else {
|
|
_this.handlers[eventType] = handler;
|
|
console.info('Filter event listener to event ' + eventType + ' successfully applied on Stream ' + _this.stream.streamId);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Filter.prototype.removeEventListener = function (eventType) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
console.info('Removing filter event listener to event ' + eventType + ' to stream ' + _this.stream.streamId);
|
|
_this.stream.session.openvidu.sendRequest('removeFilterEventListener', { streamId: _this.stream.streamId, eventType: eventType }, function (error, response) {
|
|
if (error) {
|
|
console.error('Error removing filter event listener to event ' + eventType + 'for Stream ' + _this.stream.streamId, error);
|
|
if (error.code === 401) {
|
|
reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener"));
|
|
}
|
|
else {
|
|
reject(error);
|
|
}
|
|
}
|
|
else {
|
|
delete _this.handlers[eventType];
|
|
console.info('Filter event listener to event ' + eventType + ' successfully removed on Stream ' + _this.stream.streamId);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
return Filter;
|
|
}());
|
|
exports.Filter = Filter;
|
|
|
|
},{"../OpenViduInternal/Enums/OpenViduError":28,"../OpenViduInternal/Events/StreamPropertyChangedEvent":39}],20:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
|
|
var platform = require("platform");
|
|
var LocalRecorder = (function () {
|
|
function LocalRecorder(stream) {
|
|
this.stream = stream;
|
|
this.chunks = [];
|
|
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 (platform.name === 'Safari') {
|
|
this.videoPreview.setAttribute('playsinline', 'true');
|
|
}
|
|
if (typeof parentElement === 'string') {
|
|
var parentElementDom = document.getElementById(parentElement);
|
|
if (parentElementDom) {
|
|
this.videoPreview = parentElementDom.appendChild(this.videoPreview);
|
|
}
|
|
}
|
|
else {
|
|
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 = [];
|
|
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":27,"platform":8}],21:[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 EventEmitter = require("wolfy87-eventemitter");
|
|
var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
|
|
var platform = require("platform");
|
|
platform['isIonicIos'] = (platform.product === 'iPhone' || platform.product === 'iPad') && platform.ua.indexOf('Safari') === -1;
|
|
platform['isIonicAndroid'] = platform.os.family === 'Android' && platform.name == "Android Browser";
|
|
var packageJson = require('../../package.json');
|
|
var OpenVidu = (function () {
|
|
function OpenVidu() {
|
|
var _this = this;
|
|
this.publishers = [];
|
|
this.secret = '';
|
|
this.recorder = false;
|
|
this.advancedConfiguration = {};
|
|
this.webrtcStatsInterval = 0;
|
|
this.ee = new EventEmitter();
|
|
this.libraryVersion = packageJson.version;
|
|
console.info("'OpenVidu' initialized");
|
|
console.info("openvidu-browser version: " + this.libraryVersion);
|
|
if (platform.os.family === 'iOS' || platform.os.family === 'Android') {
|
|
window.addEventListener('orientationchange', function () {
|
|
_this.publishers.forEach(function (publisher) {
|
|
if (publisher.stream.isLocalStreamPublished && !!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 getNewVideoDimensions_1 = function () {
|
|
return new Promise(function (resolve, reject) {
|
|
if (platform['isIonicIos']) {
|
|
resolve({
|
|
newWidth: publisher.stream.streamManager.videos[0].video.videoWidth,
|
|
newHeight: publisher.stream.streamManager.videos[0].video.videoHeight
|
|
});
|
|
}
|
|
else {
|
|
var firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
|
var newWidth = ((platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth);
|
|
var newHeight = ((platform.name.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight);
|
|
resolve({ newWidth: newWidth, newHeight: newHeight });
|
|
}
|
|
});
|
|
};
|
|
var repeatUntilChange_1 = setInterval(function () {
|
|
getNewVideoDimensions_1().then(function (newDimensions) {
|
|
sendStreamPropertyChangedEvent_1(oldWidth_1, oldHeight_1, newDimensions.newWidth, newDimensions.newHeight);
|
|
});
|
|
}, 75);
|
|
var sendStreamPropertyChangedEvent_1 = function (oldWidth, oldHeight, newWidth, newHeight) {
|
|
attempts_1++;
|
|
if (attempts_1 > 10) {
|
|
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: (typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack) ? 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: (typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'),
|
|
videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined,
|
|
filter: properties.filter
|
|
};
|
|
}
|
|
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', [error]);
|
|
});
|
|
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 family = platform.os.family;
|
|
var userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
|
if (family === 'iOS' && (browser !== 'Safari' || userAgent.indexOf('CriOS') !== -1 || userAgent.indexOf('FxiOS') !== -1)) {
|
|
return 0;
|
|
}
|
|
if ((browser !== 'Safari') &&
|
|
(browser !== 'Chrome') && (browser !== 'Chrome Mobile') &&
|
|
(browser !== 'Firefox') && (browser !== 'Firefox Mobile') &&
|
|
(browser !== 'Opera') && (browser !== 'Opera Mobile') &&
|
|
(browser !== 'Android Browser') && (browser !== 'Electron')) {
|
|
return 0;
|
|
}
|
|
else {
|
|
return 1;
|
|
}
|
|
};
|
|
OpenVidu.prototype.checkScreenSharingCapabilities = function () {
|
|
var browser = platform.name;
|
|
var family = platform.os.family;
|
|
if (family === 'iOS' || family === 'Android') {
|
|
return 0;
|
|
}
|
|
if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Electron')) {
|
|
return 0;
|
|
}
|
|
else {
|
|
return 1;
|
|
}
|
|
};
|
|
OpenVidu.prototype.getDevices = function () {
|
|
return new Promise(function (resolve, reject) {
|
|
navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
|
|
var devices = [];
|
|
if (platform['isIonicAndroid'] && cordova.plugins && cordova.plugins.EnumerateDevicesPlugin) {
|
|
cordova.plugins.EnumerateDevicesPlugin.getEnumerateDevices().then(function (pluginDevices) {
|
|
var pluginAudioDevices = [];
|
|
var videoDevices = [];
|
|
var audioDevices = [];
|
|
pluginAudioDevices = pluginDevices.filter(function (device) { return device.kind === 'audioinput'; });
|
|
videoDevices = deviceInfos.filter(function (device) { return device.kind === 'videoinput'; });
|
|
audioDevices = deviceInfos.filter(function (device) { return device.kind === 'audioinput'; });
|
|
videoDevices.forEach(function (deviceInfo, index) {
|
|
if (!deviceInfo.label) {
|
|
var label = "";
|
|
if (index === 0) {
|
|
label = "Front Camera";
|
|
}
|
|
else if (index === 1) {
|
|
label = "Back Camera";
|
|
}
|
|
else {
|
|
label = "Unknown Camera";
|
|
}
|
|
devices.push({
|
|
kind: deviceInfo.kind,
|
|
deviceId: deviceInfo.deviceId,
|
|
label: label
|
|
});
|
|
}
|
|
else {
|
|
devices.push({
|
|
kind: deviceInfo.kind,
|
|
deviceId: deviceInfo.deviceId,
|
|
label: deviceInfo.label
|
|
});
|
|
}
|
|
});
|
|
audioDevices.forEach(function (deviceInfo, index) {
|
|
if (!deviceInfo.label) {
|
|
var label = "";
|
|
switch (index) {
|
|
case 0:
|
|
label = 'Default';
|
|
break;
|
|
case 1:
|
|
var defaultMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Built'); })[0];
|
|
label = defaultMatch ? defaultMatch.label : 'Built-in Microphone';
|
|
break;
|
|
case 2:
|
|
var wiredMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Wired'); })[0];
|
|
if (wiredMatch) {
|
|
label = wiredMatch.label;
|
|
}
|
|
else {
|
|
label = 'Headset earpiece';
|
|
}
|
|
break;
|
|
case 3:
|
|
var wirelessMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Bluetooth'); })[0];
|
|
label = wirelessMatch ? wirelessMatch.label : 'Wireless';
|
|
break;
|
|
default:
|
|
label = "Unknown Microphone";
|
|
break;
|
|
}
|
|
devices.push({
|
|
kind: deviceInfo.kind,
|
|
deviceId: deviceInfo.deviceId,
|
|
label: label
|
|
});
|
|
}
|
|
else {
|
|
devices.push({
|
|
kind: deviceInfo.kind,
|
|
deviceId: deviceInfo.deviceId,
|
|
label: deviceInfo.label
|
|
});
|
|
}
|
|
});
|
|
resolve(devices);
|
|
});
|
|
}
|
|
else {
|
|
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' ||
|
|
(platform.name.indexOf('Firefox') !== -1 && publisherProperties.videoSource === 'window') ||
|
|
(platform.name === 'Electron' && publisherProperties.videoSource.startsWith('screen:'))) {
|
|
if (!_this.checkScreenSharingCapabilities()) {
|
|
var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera or Electron. Detected client: ' + platform.name);
|
|
console.error(error);
|
|
reject(error);
|
|
}
|
|
else {
|
|
if (platform.name === 'Electron') {
|
|
var prefix = "screen:";
|
|
var videoSourceString = publisherProperties.videoSource;
|
|
var electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length);
|
|
mediaConstraints['video'] = {
|
|
mandatory: {
|
|
chromeMediaSource: 'desktop',
|
|
chromeMediaSourceId: electronScreenId
|
|
}
|
|
};
|
|
resolve(mediaConstraints);
|
|
}
|
|
else {
|
|
if (!!_this.advancedConfiguration.screenShareChromeExtension && !(platform.name.indexOf('Firefox') !== -1) && !navigator.mediaDevices['getDisplayMedia']) {
|
|
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 {
|
|
if (navigator.mediaDevices['getDisplayMedia']) {
|
|
resolve(mediaConstraints);
|
|
}
|
|
else {
|
|
var firefoxString = platform.name.indexOf('Firefox') !== -1 ? publisherProperties.videoSource : undefined;
|
|
screenSharingAuto.getScreenId(firefoxString, 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),
|
|
filterEventDispatched: this.session.onFilterEventDispatched.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(4102, "Connection closed by client");
|
|
};
|
|
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.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('networkDisconnect');
|
|
}
|
|
else {
|
|
alert('Connection error. Please reload page.');
|
|
}
|
|
};
|
|
OpenVidu.prototype.reconnectingCallback = function () {
|
|
console.warn('Websocket connection lost (reconnecting)');
|
|
if (!this.isRoomAvailable()) {
|
|
alert('Connection error. Please reload page.');
|
|
}
|
|
};
|
|
OpenVidu.prototype.reconnectedCallback = function () {
|
|
var _this = this;
|
|
console.warn('Websocket reconnected');
|
|
if (this.isRoomAvailable()) {
|
|
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, function (error, response) {
|
|
if (!!error) {
|
|
console.error(error);
|
|
_this.session.onLostConnection("networkDisconnect");
|
|
_this.jsonRpcClient.close(4101, "Reconnection fault");
|
|
}
|
|
else {
|
|
_this.jsonRpcClient.resetPing();
|
|
_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;
|
|
|
|
},{"../../package.json":16,"../OpenViduInternal/Enums/OpenViduError":28,"../OpenViduInternal/Enums/VideoInsertMode":29,"../OpenViduInternal/Events/StreamPropertyChangedEvent":39,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":46,"../OpenViduInternal/ScreenSharing/Screen-Capturing":51,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":50,"./LocalRecorder":20,"./Publisher":22,"./Session":23,"platform":8,"wolfy87-eventemitter":15}],22:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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;
|
|
});
|
|
if (!!this.session && !!this.stream.streamId) {
|
|
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;
|
|
});
|
|
if (!!this.session && !!this.stream.streamId) {
|
|
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 constraints = {};
|
|
var constraintsAux = {};
|
|
var timeForDialogEvent = 1250;
|
|
var startTime;
|
|
var errorCallback = function (openViduError) {
|
|
_this.accessDenied = true;
|
|
_this.accessAllowed = false;
|
|
reject(openViduError);
|
|
};
|
|
var successCallback = function (mediaStream) {
|
|
_this.accessAllowed = true;
|
|
_this.accessDenied = false;
|
|
if (typeof MediaStreamTrack !== 'undefined' && _this.properties.audioSource instanceof MediaStreamTrack) {
|
|
mediaStream.removeTrack(mediaStream.getAudioTracks()[0]);
|
|
mediaStream.addTrack(_this.properties.audioSource);
|
|
}
|
|
if (typeof MediaStreamTrack !== 'undefined' && _this.properties.videoSource instanceof MediaStreamTrack) {
|
|
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');
|
|
if (platform.name === 'Safari') {
|
|
_this.videoReference.setAttribute('playsinline', 'true');
|
|
}
|
|
_this.stream.setMediaStream(mediaStream);
|
|
if (!!_this.firstVideoElement) {
|
|
_this.createVideoElement(_this.firstVideoElement.targetElement, _this.properties.insertMode);
|
|
}
|
|
_this.videoReference.srcObject = mediaStream;
|
|
if (!_this.stream.displayMyRemote()) {
|
|
_this.stream.updateMediaStreamInVideos();
|
|
}
|
|
delete _this.firstVideoElement;
|
|
if (_this.stream.isSendVideo()) {
|
|
if (!_this.stream.isSendScreen()) {
|
|
if (platform['isIonicIos'] || platform.name === 'Safari') {
|
|
_this.videoReference.style.display = 'none';
|
|
document.body.appendChild(_this.videoReference);
|
|
var videoDimensionsSet_1 = function () {
|
|
_this.stream.videoDimensions = {
|
|
width: _this.videoReference.videoWidth,
|
|
height: _this.videoReference.videoHeight
|
|
};
|
|
_this.stream.isLocalStreamReadyToPublish = true;
|
|
_this.stream.ee.emitEvent('stream-ready-to-publish', []);
|
|
document.body.removeChild(_this.videoReference);
|
|
};
|
|
var interval_1;
|
|
_this.videoReference.addEventListener('loadedmetadata', function () {
|
|
if (_this.videoReference.videoWidth === 0) {
|
|
interval_1 = setInterval(function () {
|
|
if (_this.videoReference.videoWidth !== 0) {
|
|
clearInterval(interval_1);
|
|
videoDimensionsSet_1();
|
|
}
|
|
}, 40);
|
|
}
|
|
else {
|
|
videoDimensionsSet_1();
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
var _a = mediaStream.getVideoTracks()[0].getSettings(), width = _a.width, height = _a.height;
|
|
if ((platform.os.family === 'iOS' || platform.os.family === 'Android') && (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.addEventListener('loadedmetadata', 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' || platform.name === 'Opera') ? _this.videoReference.videoWidth : firefoxSettings.width;
|
|
var newHeight = (platform.name === 'Chrome' || platform.name === 'Opera') ? _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();
|
|
};
|
|
var getMediaSuccess = function (mediaStream, definedAudioConstraint) {
|
|
_this.clearPermissionDialogTimer(startTime, timeForDialogEvent);
|
|
if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) {
|
|
constraintsAux.audio = definedAudioConstraint;
|
|
constraintsAux.video = false;
|
|
startTime = Date.now();
|
|
_this.setPermissionDialogTimer(timeForDialogEvent);
|
|
navigator.mediaDevices.getUserMedia(constraintsAux)
|
|
.then(function (audioOnlyStream) {
|
|
_this.clearPermissionDialogTimer(startTime, timeForDialogEvent);
|
|
mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
|
|
successCallback(mediaStream);
|
|
})
|
|
.catch(function (error) {
|
|
_this.clearPermissionDialogTimer(startTime, timeForDialogEvent);
|
|
if (error.name === 'Error') {
|
|
error.name = error.constructor.name;
|
|
}
|
|
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);
|
|
}
|
|
};
|
|
var getMediaError = function (error) {
|
|
console.error(error);
|
|
_this.clearPermissionDialogTimer(startTime, timeForDialogEvent);
|
|
if (error.name === 'Error') {
|
|
error.name = error.constructor.name;
|
|
}
|
|
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;
|
|
case 'aborterror':
|
|
case 'notreadableerror':
|
|
errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ALREADY_IN_USE;
|
|
errorMessage = error.toString();
|
|
errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
|
|
break;
|
|
default:
|
|
errorName = OpenViduError_1.OpenViduErrorName.GENERIC_ERROR;
|
|
errorMessage = error.toString();
|
|
errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
|
|
break;
|
|
}
|
|
};
|
|
if ((typeof MediaStreamTrack !== 'undefined' && _this.properties.videoSource instanceof MediaStreamTrack && !_this.properties.audioSource)
|
|
|| (typeof MediaStreamTrack !== 'undefined' && _this.properties.audioSource instanceof MediaStreamTrack && !_this.properties.videoSource)
|
|
|| (typeof MediaStreamTrack !== 'undefined' && _this.properties.videoSource instanceof MediaStreamTrack && _this.properties.audioSource instanceof MediaStreamTrack)) {
|
|
var mediaStream = new MediaStream();
|
|
if (typeof MediaStreamTrack !== 'undefined' && _this.properties.videoSource instanceof MediaStreamTrack) {
|
|
mediaStream.addTrack(_this.properties.videoSource);
|
|
}
|
|
if (typeof MediaStreamTrack !== 'undefined' && _this.properties.audioSource instanceof MediaStreamTrack) {
|
|
mediaStream.addTrack(_this.properties.audioSource);
|
|
}
|
|
successCallback(mediaStream);
|
|
return;
|
|
}
|
|
_this.openvidu.generateMediaConstraints(_this.properties)
|
|
.then(function (myConstraints) {
|
|
constraints = myConstraints;
|
|
var outboundStreamOptions = {
|
|
mediaConstraints: constraints,
|
|
publisherProperties: _this.properties
|
|
};
|
|
_this.stream.setOutboundStreamOptions(outboundStreamOptions);
|
|
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;
|
|
startTime = Date.now();
|
|
_this.setPermissionDialogTimer(timeForDialogEvent);
|
|
if (_this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') {
|
|
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
|
.then(function (mediaStream) {
|
|
getMediaSuccess(mediaStream, definedAudioConstraint_1);
|
|
})
|
|
.catch(function (error) {
|
|
getMediaError(error);
|
|
});
|
|
}
|
|
else {
|
|
navigator.mediaDevices.getUserMedia(constraintsAux)
|
|
.then(function (mediaStream) {
|
|
getMediaSuccess(mediaStream, definedAudioConstraint_1);
|
|
})
|
|
.catch(function (error) {
|
|
getMediaError(error);
|
|
});
|
|
}
|
|
}
|
|
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":28,"../OpenViduInternal/Events/StreamEvent":37,"../OpenViduInternal/Events/StreamPropertyChangedEvent":39,"../OpenViduInternal/Events/VideoElementEvent":40,"./Session":23,"./Stream":24,"./StreamManager":25,"platform":8}],23:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var Connection_1 = require("./Connection");
|
|
var Filter_1 = require("./Filter");
|
|
var Subscriber_1 = require("./Subscriber");
|
|
var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent");
|
|
var FilterEvent_1 = require("../OpenViduInternal/Events/FilterEvent");
|
|
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 EventEmitter = require("wolfy87-eventemitter");
|
|
var platform = require("platform");
|
|
var Session = (function () {
|
|
function Session(openvidu) {
|
|
this.streamManagers = [];
|
|
this.remoteStreamsCreated = {};
|
|
this.isFirstIonicIosSubscriber = true;
|
|
this.countDownForIonicIosSubscribersActive = true;
|
|
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 + ' (version ' + platform.version + ') for ' + platform.os.family + ' 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 : '';
|
|
var typeAux = signal.type ? signal.type : 'signal';
|
|
if (!!typeAux) {
|
|
if (typeAux.substring(0, 7) !== 'signal:') {
|
|
typeAux = 'signal:' + typeAux;
|
|
}
|
|
}
|
|
signalMessage['type'] = typeAux;
|
|
_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.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.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.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];
|
|
if (Object.keys(_this.remoteStreamsCreated).length === 0) {
|
|
_this.isFirstIonicIosSubscriber = true;
|
|
_this.countDownForIonicIosSubscribersActive = true;
|
|
}
|
|
}
|
|
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];
|
|
if (Object.keys(_this.remoteStreamsCreated).length === 0) {
|
|
_this.isFirstIonicIosSubscriber = true;
|
|
_this.countDownForIonicIosSubscribersActive = true;
|
|
}
|
|
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)]);
|
|
if (msg.type !== 'signal') {
|
|
_this.ee.emitEvent(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;
|
|
var callback = 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;
|
|
case 'filter':
|
|
oldValue = stream.filter;
|
|
msg.newValue = (Object.keys(msg.newValue).length > 0) ? msg.newValue : undefined;
|
|
if (msg.newValue !== undefined) {
|
|
stream.filter = new Filter_1.Filter(msg.newValue.type, msg.newValue.options);
|
|
stream.filter.stream = stream;
|
|
if (msg.newValue.lastExecMethod) {
|
|
stream.filter.lastExecMethod = msg.newValue.lastExecMethod;
|
|
}
|
|
}
|
|
else {
|
|
delete stream.filter;
|
|
}
|
|
msg.newValue = stream.filter;
|
|
break;
|
|
}
|
|
_this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, msg.property, msg.newValue, oldValue, msg.reason)]);
|
|
if (!!stream.streamManager) {
|
|
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");
|
|
}
|
|
};
|
|
if (msg.connectionId === this.connection.connectionId) {
|
|
callback(this.connection);
|
|
}
|
|
else {
|
|
this.getRemoteConnection(msg.connectionId, 'Remote connection ' + msg.connectionId + " unknown when 'onStreamPropertyChanged'. " +
|
|
'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections)))
|
|
.then(function (connection) {
|
|
callback(connection);
|
|
})
|
|
.catch(function (openViduError) {
|
|
console.error(openViduError);
|
|
});
|
|
}
|
|
};
|
|
Session.prototype.recvIceCandidate = function (msg) {
|
|
var candidate = {
|
|
candidate: msg.candidate,
|
|
component: msg.component,
|
|
foundation: msg.foundation,
|
|
ip: msg.ip,
|
|
port: msg.port,
|
|
priority: msg.priority,
|
|
protocol: msg.protocol,
|
|
relatedAddress: msg.relatedAddress,
|
|
relatedPort: msg.relatedPort,
|
|
sdpMid: msg.sdpMid,
|
|
sdpMLineIndex: msg.sdpMLineIndex,
|
|
tcpType: msg.tcpType,
|
|
usernameFragment: msg.usernameFragment,
|
|
type: msg.type,
|
|
toJSON: function () {
|
|
return { candidate: msg.candidate };
|
|
}
|
|
};
|
|
this.getConnection(msg.senderConnectionId, 'Connection not found for connectionId ' + msg.senderConnectionId + ' owning 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 (reason) {
|
|
console.warn('Lost connection in session ' + this.sessionId + ' waiting for reconnect');
|
|
if (!!this.sessionId && !this.connection.disposed) {
|
|
this.leave(true, reason);
|
|
}
|
|
};
|
|
Session.prototype.onRecoveredConnection = function () {
|
|
console.warn('Recovered connection in Session ' + this.sessionId);
|
|
};
|
|
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, response.reason)]);
|
|
};
|
|
Session.prototype.onFilterEventDispatched = function (response) {
|
|
var connectionId = response.connectionId;
|
|
var streamId = response.streamId;
|
|
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
|
|
.then(function (connection) {
|
|
console.info('Filter event dispatched');
|
|
var stream = connection.stream;
|
|
stream.filter.handlers[response.eventType](new FilterEvent_1.FilterEvent(stream.filter, response.eventType, response.data));
|
|
});
|
|
};
|
|
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,
|
|
platform: !!platform.description ? platform.description : 'unknown',
|
|
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.creationTime = response.createdAt;
|
|
_this.connection.data = response.metadata;
|
|
_this.connection.rpcSessionId = response.sessionId;
|
|
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 match = token.match(/^(wss?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
|
|
if (!!match) {
|
|
var url = {
|
|
protocol: match[1],
|
|
host: match[2],
|
|
hostname: match[3],
|
|
port: match[4],
|
|
pathname: match[5],
|
|
search: match[6],
|
|
hash: match[7]
|
|
};
|
|
var params = token.split('?');
|
|
var queryParams = decodeURI(params[1])
|
|
.split('&')
|
|
.map(function (param) { return param.split('='); })
|
|
.reduce(function (values, _a) {
|
|
var key = _a[0], value = _a[1];
|
|
values[key] = value;
|
|
return values;
|
|
}, {});
|
|
this.sessionId = queryParams['sessionId'];
|
|
var secret = queryParams['secret'];
|
|
var recorder = queryParams['recorder'];
|
|
var turnUsername = queryParams['turnUsername'];
|
|
var turnCredential = queryParams['turnCredential'];
|
|
var role = queryParams['role'];
|
|
var webrtcStatsInterval = queryParams['webrtcStatsInterval'];
|
|
var openviduServerVersion = queryParams['version'];
|
|
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;
|
|
}
|
|
if (!!webrtcStatsInterval) {
|
|
this.openvidu.webrtcStatsInterval = +webrtcStatsInterval;
|
|
}
|
|
if (!!openviduServerVersion) {
|
|
console.info("openvidu-server version: " + openviduServerVersion);
|
|
if (openviduServerVersion !== this.openvidu.libraryVersion) {
|
|
console.error('OpenVidu Server (' + openviduServerVersion +
|
|
') and OpenVidu Browser (' + this.openvidu.libraryVersion +
|
|
') versions do NOT match. There may be incompatibilities');
|
|
}
|
|
}
|
|
this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
|
|
this.openvidu.httpUri = 'https://' + url.host;
|
|
}
|
|
else {
|
|
console.error('Token "' + token + '" is not valid');
|
|
}
|
|
};
|
|
return Session;
|
|
}());
|
|
exports.Session = Session;
|
|
|
|
},{"../OpenViduInternal/Enums/OpenViduError":28,"../OpenViduInternal/Enums/VideoInsertMode":29,"../OpenViduInternal/Events/ConnectionEvent":30,"../OpenViduInternal/Events/FilterEvent":32,"../OpenViduInternal/Events/RecordingEvent":34,"../OpenViduInternal/Events/SessionDisconnectedEvent":35,"../OpenViduInternal/Events/SignalEvent":36,"../OpenViduInternal/Events/StreamEvent":37,"../OpenViduInternal/Events/StreamPropertyChangedEvent":39,"./Connection":18,"./Filter":19,"./Subscriber":26,"platform":8,"wolfy87-eventemitter":15}],24:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var Filter_1 = require("./Filter");
|
|
var Subscriber_1 = require("./Subscriber");
|
|
var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer");
|
|
var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats");
|
|
var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent");
|
|
var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
|
|
var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
|
|
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
|
|
var EventEmitter = require("wolfy87-eventemitter");
|
|
var hark = require("hark");
|
|
var platform = require("platform");
|
|
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.publisherStartSpeakingEventEnabled = false;
|
|
this.publisherStopSpeakingEventEnabled = false;
|
|
this.volumeChangeEventEnabled = false;
|
|
this.session = session;
|
|
if (options.hasOwnProperty('id')) {
|
|
this.inboundStreamOpts = options;
|
|
this.streamId = this.inboundStreamOpts.id;
|
|
this.creationTime = this.inboundStreamOpts.createdAt;
|
|
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;
|
|
}
|
|
if (!!this.inboundStreamOpts.filter && (Object.keys(this.inboundStreamOpts.filter).length > 0)) {
|
|
if (!!this.inboundStreamOpts.filter.lastExecMethod && Object.keys(this.inboundStreamOpts.filter.lastExecMethod).length === 0) {
|
|
delete this.inboundStreamOpts.filter.lastExecMethod;
|
|
}
|
|
this.filter = this.inboundStreamOpts.filter;
|
|
}
|
|
}
|
|
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 (typeof MediaStreamTrack !== 'undefined' && this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) {
|
|
this.typeOfVideo = 'CUSTOM';
|
|
}
|
|
else {
|
|
this.typeOfVideo = this.isSendScreen() ? 'SCREEN' : 'CAMERA';
|
|
}
|
|
}
|
|
if (!!this.outboundStreamOpts.publisherProperties.filter) {
|
|
this.filter = this.outboundStreamOpts.publisherProperties.filter;
|
|
}
|
|
}
|
|
this.ee.on('mediastream-updated', function () {
|
|
_this.streamManager.updateMediaStream(_this.mediaStream);
|
|
console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
|
|
});
|
|
}
|
|
Stream.prototype.on = function (type, handler) {
|
|
var _this = this;
|
|
this.ee.on(type, function (event) {
|
|
if (event) {
|
|
console.info("Event '" + type + "' triggered by stream '" + _this.streamId + "'", event);
|
|
}
|
|
else {
|
|
console.info("Event '" + type + "' triggered by stream '" + _this.streamId + "'");
|
|
}
|
|
handler(event);
|
|
});
|
|
return this;
|
|
};
|
|
Stream.prototype.once = function (type, handler) {
|
|
var _this = this;
|
|
this.ee.once(type, function (event) {
|
|
if (event) {
|
|
console.info("Event '" + type + "' triggered once by stream '" + _this.streamId + "'", event);
|
|
}
|
|
else {
|
|
console.info("Event '" + type + "' triggered once by stream '" + _this.streamId + "'");
|
|
}
|
|
handler(event);
|
|
});
|
|
return this;
|
|
};
|
|
Stream.prototype.off = function (type, handler) {
|
|
if (!handler) {
|
|
this.ee.removeAllListeners(type);
|
|
}
|
|
else {
|
|
this.ee.off(type, handler);
|
|
}
|
|
return this;
|
|
};
|
|
Stream.prototype.applyFilter = function (type, options) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
console.info('Applying filter to stream ' + _this.streamId);
|
|
options = !!options ? options : {};
|
|
if (typeof options !== 'string') {
|
|
options = JSON.stringify(options);
|
|
}
|
|
_this.session.openvidu.sendRequest('applyFilter', { streamId: _this.streamId, type: type, options: options }, function (error, response) {
|
|
if (error) {
|
|
console.error('Error applying filter for Stream ' + _this.streamId, error);
|
|
if (error.code === 401) {
|
|
reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to apply a filter"));
|
|
}
|
|
else {
|
|
reject(error);
|
|
}
|
|
}
|
|
else {
|
|
console.info('Filter successfully applied on Stream ' + _this.streamId);
|
|
var oldValue = _this.filter;
|
|
_this.filter = new Filter_1.Filter(type, options);
|
|
_this.filter.stream = _this;
|
|
_this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this, 'filter', _this.filter, oldValue, 'applyFilter')]);
|
|
_this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.streamManager, _this, 'filter', _this.filter, oldValue, 'applyFilter')]);
|
|
resolve(_this.filter);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.removeFilter = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
console.info('Removing filter of stream ' + _this.streamId);
|
|
_this.session.openvidu.sendRequest('removeFilter', { streamId: _this.streamId }, function (error, response) {
|
|
if (error) {
|
|
console.error('Error removing filter for Stream ' + _this.streamId, error);
|
|
if (error.code === 401) {
|
|
reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to remove a filter"));
|
|
}
|
|
else {
|
|
reject(error);
|
|
}
|
|
}
|
|
else {
|
|
console.info('Filter successfully removed from Stream ' + _this.streamId);
|
|
var oldValue = _this.filter;
|
|
delete _this.filter;
|
|
_this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this, 'filter', _this.filter, oldValue, 'applyFilter')]);
|
|
_this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.streamManager, _this, 'filter', _this.filter, oldValue, 'applyFilter')]);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
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) {
|
|
var isSenderAndCustomTrack = !!this.outboundStreamOpts &&
|
|
typeof MediaStreamTrack !== 'undefined' && this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack;
|
|
this.webRtcPeer.dispose(isSenderAndCustomTrack);
|
|
}
|
|
if (!!this.speechEvent) {
|
|
if (!!this.speechEvent.stop) {
|
|
this.speechEvent.stop();
|
|
}
|
|
delete this.speechEvent;
|
|
}
|
|
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 () {
|
|
var screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen';
|
|
if (platform.name === 'Electron') {
|
|
screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' &&
|
|
this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:');
|
|
}
|
|
return !!this.outboundStreamOpts && 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();
|
|
if (!this.publisherStartSpeakingEventEnabled) {
|
|
this.publisherStartSpeakingEventEnabled = true;
|
|
this.speechEvent.on('speaking', function () {
|
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
});
|
|
}
|
|
if (!this.publisherStopSpeakingEventEnabled) {
|
|
this.publisherStopSpeakingEventEnabled = true;
|
|
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();
|
|
if (!this.publisherStartSpeakingEventEnabled) {
|
|
this.publisherStartSpeakingEventEnabled = true;
|
|
this.speechEvent.once('speaking', function () {
|
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
_this.disableSpeakingEvents();
|
|
});
|
|
}
|
|
if (!this.publisherStopSpeakingEventEnabled) {
|
|
this.publisherStopSpeakingEventEnabled = true;
|
|
this.speechEvent.once('stopped_speaking', function () {
|
|
_this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
|
_this.disableSpeakingEvents();
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.disableSpeakingEvents = function () {
|
|
if (!!this.speechEvent) {
|
|
if (this.volumeChangeEventEnabled) {
|
|
this.speechEvent.off('speaking');
|
|
this.speechEvent.off('stopped_speaking');
|
|
}
|
|
else {
|
|
this.speechEvent.stop();
|
|
delete this.speechEvent;
|
|
}
|
|
}
|
|
this.publisherStartSpeakingEventEnabled = false;
|
|
this.publisherStopSpeakingEventEnabled = false;
|
|
};
|
|
Stream.prototype.enableVolumeChangeEvent = function () {
|
|
var _this = this;
|
|
this.setSpeechEventIfNotExists();
|
|
if (!this.volumeChangeEventEnabled) {
|
|
this.volumeChangeEventEnabled = true;
|
|
this.speechEvent.on('volume_change', function (harkEvent) {
|
|
var oldValue = _this.speechEvent.oldVolumeValue;
|
|
var value = { newValue: harkEvent, oldValue: oldValue };
|
|
_this.speechEvent.oldVolumeValue = harkEvent;
|
|
_this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent_1.StreamManagerEvent(_this.streamManager, 'streamAudioVolumeChange', value)]);
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.enableOnceVolumeChangeEvent = function () {
|
|
var _this = this;
|
|
this.setSpeechEventIfNotExists();
|
|
if (!this.volumeChangeEventEnabled) {
|
|
this.volumeChangeEventEnabled = true;
|
|
this.speechEvent.once('volume_change', function (harkEvent) {
|
|
var oldValue = _this.speechEvent.oldVolumeValue;
|
|
var value = { newValue: harkEvent, oldValue: oldValue };
|
|
_this.speechEvent.oldVolumeValue = harkEvent;
|
|
_this.disableVolumeChangeEvent();
|
|
_this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent_1.StreamManagerEvent(_this.streamManager, 'streamAudioVolumeChange', value)]);
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.disableVolumeChangeEvent = function () {
|
|
if (!!this.speechEvent) {
|
|
if (this.session.speakingEventsEnabled) {
|
|
this.speechEvent.off('volume_change');
|
|
}
|
|
else {
|
|
this.speechEvent.stop();
|
|
delete this.speechEvent;
|
|
}
|
|
}
|
|
this.volumeChangeEventEnabled = false;
|
|
};
|
|
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 = (typeof MediaStreamTrack !== 'undefined' && _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),
|
|
filter: _this.outboundStreamOpts.publisherProperties.filter
|
|
}, 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, false)
|
|
.then(function () {
|
|
_this.streamId = response.id;
|
|
_this.creationTime = response.createdAt;
|
|
_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 {
|
|
if (_this.session.isFirstIonicIosSubscriber) {
|
|
_this.session.isFirstIonicIosSubscriber = false;
|
|
setTimeout(function () {
|
|
_this.session.countDownForIonicIosSubscribersActive = false;
|
|
}, 400);
|
|
}
|
|
var needsTimeoutOnProcessAnswer = _this.session.countDownForIonicIosSubscribersActive;
|
|
_this.webRtcPeer.processAnswer(response.sdpAnswer, needsTimeoutOnProcessAnswer).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 () {
|
|
if (platform['isIonicIos']) {
|
|
var pc1 = this.webRtcPeer.pc;
|
|
this.mediaStream = pc1.getRemoteStreams()[0];
|
|
}
|
|
else {
|
|
this.mediaStream = new MediaStream();
|
|
var receiver = void 0;
|
|
for (var _i = 0, _a = this.webRtcPeer.pc.getReceivers(); _i < _a.length; _i++) {
|
|
receiver = _a[_i];
|
|
if (!!receiver.track) {
|
|
this.mediaStream.addTrack(receiver.track);
|
|
}
|
|
}
|
|
}
|
|
console.debug('Peer remote stream', this.mediaStream);
|
|
if (!!this.mediaStream) {
|
|
if (this.streamManager instanceof Subscriber_1.Subscriber) {
|
|
if (!!this.mediaStream.getAudioTracks()[0]) {
|
|
var enabled = !!(this.streamManager.properties.subscribeToAudio);
|
|
this.mediaStream.getAudioTracks()[0].enabled = enabled;
|
|
}
|
|
if (!!this.mediaStream.getVideoTracks()[0]) {
|
|
var enabled = !!(this.streamManager.properties.subscribeToVideo);
|
|
this.mediaStream.getVideoTracks()[0].enabled = enabled;
|
|
}
|
|
}
|
|
this.updateMediaStreamInVideos();
|
|
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;
|
|
};
|
|
Stream.prototype.gatherStatsForPeer = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (_this.isLocal()) {
|
|
_this.getRTCPeerConnection().getSenders().forEach(function (sender) { return sender.getStats()
|
|
.then(function (response) {
|
|
response.forEach(function (report) {
|
|
if (_this.isReportWanted(report)) {
|
|
var finalReport = {};
|
|
finalReport['type'] = report.type;
|
|
finalReport['timestamp'] = report.timestamp;
|
|
finalReport['id'] = report.id;
|
|
if (report.type === 'outbound-rtp') {
|
|
finalReport['ssrc'] = report.ssrc;
|
|
finalReport['firCount'] = report.firCount;
|
|
finalReport['pliCount'] = report.pliCount;
|
|
finalReport['nackCount'] = report.nackCount;
|
|
finalReport['qpSum'] = report.qpSum;
|
|
if (!!report.kind) {
|
|
finalReport['mediaType'] = report.kind;
|
|
}
|
|
else if (!!report.mediaType) {
|
|
finalReport['mediaType'] = report.mediaType;
|
|
}
|
|
else {
|
|
finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio';
|
|
}
|
|
if (finalReport['mediaType'] === 'video') {
|
|
finalReport['framesEncoded'] = report.framesEncoded;
|
|
}
|
|
finalReport['packetsSent'] = report.packetsSent;
|
|
finalReport['bytesSent'] = report.bytesSent;
|
|
}
|
|
if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) {
|
|
finalReport['availableOutgoingBitrate'] = report.availableOutgoingBitrate;
|
|
finalReport['rtt'] = report.currentRoundTripTime;
|
|
finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived;
|
|
}
|
|
if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') {
|
|
}
|
|
console.log(finalReport);
|
|
}
|
|
});
|
|
}); });
|
|
}
|
|
else {
|
|
_this.getRTCPeerConnection().getReceivers().forEach(function (receiver) { return receiver.getStats()
|
|
.then(function (response) {
|
|
response.forEach(function (report) {
|
|
if (_this.isReportWanted(report)) {
|
|
var finalReport = {};
|
|
finalReport['type'] = report.type;
|
|
finalReport['timestamp'] = report.timestamp;
|
|
finalReport['id'] = report.id;
|
|
if (report.type === 'inbound-rtp') {
|
|
finalReport['ssrc'] = report.ssrc;
|
|
finalReport['firCount'] = report.firCount;
|
|
finalReport['pliCount'] = report.pliCount;
|
|
finalReport['nackCount'] = report.nackCount;
|
|
finalReport['qpSum'] = report.qpSum;
|
|
if (!!report.kind) {
|
|
finalReport['mediaType'] = report.kind;
|
|
}
|
|
else if (!!report.mediaType) {
|
|
finalReport['mediaType'] = report.mediaType;
|
|
}
|
|
else {
|
|
finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio';
|
|
}
|
|
if (finalReport['mediaType'] === 'video') {
|
|
finalReport['framesDecoded'] = report.framesDecoded;
|
|
}
|
|
finalReport['packetsReceived'] = report.packetsReceived;
|
|
finalReport['packetsLost'] = report.packetsLost;
|
|
finalReport['jitter'] = report.jitter;
|
|
finalReport['bytesReceived'] = report.bytesReceived;
|
|
}
|
|
if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) {
|
|
finalReport['availableIncomingBitrate'] = report.availableIncomingBitrate;
|
|
finalReport['rtt'] = report.currentRoundTripTime;
|
|
finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived;
|
|
}
|
|
if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') {
|
|
}
|
|
console.log(finalReport);
|
|
}
|
|
});
|
|
}); });
|
|
}
|
|
});
|
|
};
|
|
Stream.prototype.isReportWanted = function (report) {
|
|
return report.type === 'inbound-rtp' && !this.isLocal() ||
|
|
report.type === 'outbound-rtp' && this.isLocal() ||
|
|
(report.type === 'candidate-pair' && report.nominated && report.bytesSent > 0);
|
|
};
|
|
return Stream;
|
|
}());
|
|
exports.Stream = Stream;
|
|
|
|
},{"../OpenViduInternal/Enums/OpenViduError":28,"../OpenViduInternal/Events/PublisherSpeakingEvent":33,"../OpenViduInternal/Events/StreamManagerEvent":38,"../OpenViduInternal/Events/StreamPropertyChangedEvent":39,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":52,"../OpenViduInternal/WebRtcStats/WebRtcStats":53,"./Filter":19,"./Subscriber":26,"hark":5,"platform":8,"wolfy87-eventemitter":15}],25:[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 platform = require("platform");
|
|
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: '',
|
|
canplayListenerAdded: false
|
|
};
|
|
if (platform.name === 'Safari') {
|
|
this.firstVideoElement.video.setAttribute('playsinline', 'true');
|
|
}
|
|
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, 'streamPlaying', undefined)]);
|
|
};
|
|
}
|
|
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, 'streamPlaying', undefined)]);
|
|
this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
|
|
}
|
|
}
|
|
if (type === 'streamAudioVolumeChange' && this.stream.hasAudio) {
|
|
this.stream.enableVolumeChangeEvent();
|
|
}
|
|
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, 'streamPlaying', undefined)]);
|
|
this.ee.emitEvent('videoPlaying', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
|
|
}
|
|
}
|
|
if (type === 'streamAudioVolumeChange' && this.stream.hasAudio) {
|
|
this.stream.enableOnceVolumeChangeEvent();
|
|
}
|
|
return this;
|
|
};
|
|
StreamManager.prototype.off = function (type, handler) {
|
|
if (!handler) {
|
|
this.ee.removeAllListeners(type);
|
|
}
|
|
else {
|
|
this.ee.off(type, handler);
|
|
}
|
|
if (type === 'streamAudioVolumeChange') {
|
|
this.stream.disableVolumeChangeEvent();
|
|
}
|
|
return this;
|
|
};
|
|
StreamManager.prototype.addVideoElement = function (video) {
|
|
this.initializeVideoProperties(video);
|
|
if (this.stream.isLocal() && this.stream.displayMyRemote()) {
|
|
if (video.srcObject !== this.stream.getMediaStream()) {
|
|
video.srcObject = this.stream.getMediaStream();
|
|
}
|
|
}
|
|
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,
|
|
canplayListenerAdded: false
|
|
});
|
|
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(targetElement);
|
|
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,
|
|
canplayListenerAdded: false
|
|
};
|
|
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())) {
|
|
if (video.srcObject !== this.stream.getMediaStream()) {
|
|
video.srcObject = this.stream.getMediaStream();
|
|
}
|
|
}
|
|
video.autoplay = true;
|
|
video.controls = false;
|
|
if (platform.name === 'Safari') {
|
|
video.setAttribute('playsinline', 'true');
|
|
}
|
|
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 (video.style.transform === 'rotateY(180deg)' && !this.stream.outboundStreamOpts.publisherProperties.mirror) {
|
|
this.removeMirrorVideo(video);
|
|
}
|
|
else if (this.stream.outboundStreamOpts.publisherProperties.mirror && !this.stream.isSendScreen()) {
|
|
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);
|
|
streamManagerVideo.canplayListenerAdded = false;
|
|
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[i].video.removeEventListener('canplay', this.canPlayListener);
|
|
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].canplayListenerAdded)) {
|
|
this.videos[0].video.addEventListener('canplay', this.canPlayListener);
|
|
this.videos[0].canplayListenerAdded = true;
|
|
}
|
|
};
|
|
StreamManager.prototype.updateMediaStream = function (mediaStream) {
|
|
this.videos.forEach(function (streamManagerVideo) {
|
|
streamManagerVideo.video.srcObject = mediaStream;
|
|
if (platform['isIonicIos']) {
|
|
var vParent = streamManagerVideo.video.parentElement;
|
|
var newVideo = streamManagerVideo.video;
|
|
vParent.replaceChild(newVideo, streamManagerVideo.video);
|
|
streamManagerVideo.video = newVideo;
|
|
}
|
|
});
|
|
};
|
|
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) {
|
|
if (!platform['isIonicIos']) {
|
|
video.style.transform = 'rotateY(180deg)';
|
|
video.style.webkitTransform = 'rotateY(180deg)';
|
|
}
|
|
};
|
|
StreamManager.prototype.removeMirrorVideo = function (video) {
|
|
video.style.transform = 'unset';
|
|
video.style.webkitTransform = 'unset';
|
|
};
|
|
return StreamManager;
|
|
}());
|
|
exports.StreamManager = StreamManager;
|
|
|
|
},{"../OpenViduInternal/Enums/VideoInsertMode":29,"../OpenViduInternal/Events/StreamManagerEvent":38,"../OpenViduInternal/Events/VideoElementEvent":40,"platform":8,"wolfy87-eventemitter":15}],26:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":25}],27:[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 = {}));
|
|
|
|
},{}],28:[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["DEVICE_ALREADY_IN_USE"] = "DEVICE_ALREADY_IN_USE";
|
|
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;
|
|
|
|
},{}],29:[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 = {}));
|
|
|
|
},{}],30:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],31:[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;
|
|
|
|
},{}],32:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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 FilterEvent = (function (_super) {
|
|
__extends(FilterEvent, _super);
|
|
function FilterEvent(target, eventType, data) {
|
|
var _this = _super.call(this, false, target, eventType) || this;
|
|
_this.data = data;
|
|
return _this;
|
|
}
|
|
FilterEvent.prototype.callDefaultBehavior = function () { };
|
|
return FilterEvent;
|
|
}(Event_1.Event));
|
|
exports.FilterEvent = FilterEvent;
|
|
|
|
},{"./Event":31}],33:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],34:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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, reason) {
|
|
var _this = _super.call(this, false, target, type) || this;
|
|
_this.id = id;
|
|
if (name !== id) {
|
|
_this.name = name;
|
|
}
|
|
_this.reason = reason;
|
|
return _this;
|
|
}
|
|
RecordingEvent.prototype.callDefaultBehavior = function () { };
|
|
return RecordingEvent;
|
|
}(Event_1.Event));
|
|
exports.RecordingEvent = RecordingEvent;
|
|
|
|
},{"./Event":31}],35:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],36:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],37:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":22,"../../OpenVidu/Session":23,"./Event":31}],38:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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, type, value) {
|
|
var _this = _super.call(this, false, target, type) || this;
|
|
_this.value = value;
|
|
return _this;
|
|
}
|
|
StreamManagerEvent.prototype.callDefaultBehavior = function () { };
|
|
return StreamManagerEvent;
|
|
}(Event_1.Event));
|
|
exports.StreamManagerEvent = StreamManagerEvent;
|
|
|
|
},{"./Event":31}],39:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],40:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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":31}],41:[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;
|
|
|
|
},{}],42:[function(require,module,exports){
|
|
var JsonRpcClient = require('./jsonrpcclient');
|
|
exports.JsonRpcClient = JsonRpcClient;
|
|
|
|
},{"./jsonrpcclient":43}],43:[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;
|
|
}
|
|
stopPing();
|
|
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;
|
|
updateNotReconnectIfLessThan();
|
|
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;
|
|
stopPing();
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
function stopPing() {
|
|
clearInterval(pingInterval);
|
|
pingPongStarted = false;
|
|
enabledPings = false;
|
|
pingNextNum = -1;
|
|
rpc.cancel();
|
|
}
|
|
this.close = function (code, reason) {
|
|
Logger.debug("Closing with code: " + code + " because: " + reason);
|
|
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(code, reason);
|
|
});
|
|
}
|
|
else {
|
|
ws.close(code, reason);
|
|
}
|
|
};
|
|
this.forceClose = function (millis) {
|
|
ws.forceClose(millis);
|
|
};
|
|
this.reconnect = function () {
|
|
ws.reconnectWs();
|
|
};
|
|
this.resetPing = function () {
|
|
enabledPings = true;
|
|
pingNextNum = 0;
|
|
usePing();
|
|
};
|
|
}
|
|
module.exports = JsonRpcClient;
|
|
|
|
},{"../":46,"./transports/webSocketWithReconnection":45}],44:[function(require,module,exports){
|
|
var WebSocketWithReconnection = require('./webSocketWithReconnection');
|
|
exports.WebSocketWithReconnection = WebSocketWithReconnection;
|
|
|
|
},{"./webSocketWithReconnection":45}],45:[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 : {})
|
|
|
|
},{}],46:[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(4003, "Cancel request");
|
|
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":41,"./clients":42,"./clients/transports":44,"./packers":49,"events":1,"inherits":6}],47:[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;
|
|
|
|
},{}],48:[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;
|
|
|
|
},{}],49:[function(require,module,exports){
|
|
var JsonRPC = require('./JsonRPC');
|
|
var XmlRPC = require('./XmlRPC');
|
|
exports.JsonRPC = JsonRPC;
|
|
exports.XmlRPC = XmlRPC;
|
|
|
|
},{"./JsonRPC":47,"./XmlRPC":48}],50:[function(require,module,exports){
|
|
window.getScreenId = function (firefoxString, 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: firefoxString,
|
|
mediaSource: firefoxString
|
|
}
|
|
});
|
|
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;
|
|
|
|
},{}],51:[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;
|
|
|
|
},{}],52:[function(require,module,exports){
|
|
"use strict";
|
|
var __extends = (this && this.__extends) || (function () {
|
|
var extendStatics = function (d, b) {
|
|
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 extendStatics(d, b);
|
|
};
|
|
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) {
|
|
if (!!event.candidate) {
|
|
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) {
|
|
if (platform['isIonicIos']) {
|
|
var pc2 = _this.pc;
|
|
pc2.addStream(_this.configuration.mediaStream);
|
|
}
|
|
else {
|
|
for (var _i = 0, _a = _this.configuration.mediaStream.getTracks(); _i < _a.length; _i++) {
|
|
var track = _a[_i];
|
|
_this.pc.addTrack(track, _this.configuration.mediaStream);
|
|
}
|
|
}
|
|
resolve();
|
|
}
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.dispose = function (videoSourceIsMediaStreamTrack) {
|
|
console.debug('Disposing WebRtcPeer');
|
|
try {
|
|
if (this.pc) {
|
|
if (this.pc.signalingState === 'closed') {
|
|
return;
|
|
}
|
|
this.remoteCandidatesQueue = [];
|
|
this.localCandidatesQueue = [];
|
|
if (platform['isIonicIos']) {
|
|
var pc1 = this.pc;
|
|
for (var _i = 0, _a = pc1.getLocalStreams(); _i < _a.length; _i++) {
|
|
var sender = _a[_i];
|
|
if (!videoSourceIsMediaStreamTrack) {
|
|
sender.stop();
|
|
}
|
|
pc1.removeStream(sender);
|
|
}
|
|
for (var _b = 0, _c = pc1.getRemoteStreams(); _b < _c.length; _b++) {
|
|
var receiver = _c[_b];
|
|
if (!!receiver.track) {
|
|
receiver.stop();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (var _d = 0, _e = this.pc.getSenders(); _d < _e.length; _d++) {
|
|
var sender = _e[_d];
|
|
if (!videoSourceIsMediaStreamTrack) {
|
|
if (!!sender.track) {
|
|
sender.track.stop();
|
|
}
|
|
}
|
|
this.pc.removeTrack(sender);
|
|
}
|
|
for (var _f = 0, _g = this.pc.getReceivers(); _f < _g.length; _f++) {
|
|
var receiver = _g[_f];
|
|
if (!!receiver.track) {
|
|
receiver.track.stop();
|
|
}
|
|
}
|
|
}
|
|
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));
|
|
if (platform.name === 'Safari' && platform.ua.indexOf('Safari') !== -1) {
|
|
if (offerAudio) {
|
|
_this.pc.addTransceiver('audio', {
|
|
direction: _this.configuration.mode,
|
|
});
|
|
}
|
|
if (offerVideo) {
|
|
_this.pc.addTransceiver('video', {
|
|
direction: _this.configuration.mode,
|
|
});
|
|
}
|
|
_this.pc
|
|
.createOffer()
|
|
.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); });
|
|
}
|
|
else {
|
|
_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.processAnswer = function (sdpAnswer, needsTimeoutOnProcessAnswer) {
|
|
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');
|
|
}
|
|
if (platform['isIonicIos']) {
|
|
if (needsTimeoutOnProcessAnswer) {
|
|
setTimeout(function () {
|
|
console.info('setRemoteDescription run after timeout for Ionic iOS device');
|
|
_this.pc.setRemoteDescription(new RTCSessionDescription(answer)).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
|
|
}, 250);
|
|
}
|
|
else {
|
|
_this.pc.setRemoteDescription(new RTCSessionDescription(answer)).then(function () { return resolve(); }).catch(function (error) { return reject(error); });
|
|
}
|
|
}
|
|
else {
|
|
_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); });
|
|
}
|
|
else {
|
|
_this.iceCandidateList.push(iceCandidate);
|
|
resolve();
|
|
}
|
|
break;
|
|
default:
|
|
_this.iceCandidateList.push(iceCandidate);
|
|
resolve();
|
|
}
|
|
});
|
|
};
|
|
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}],53:[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',
|
|
'et_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',
|
|
'et_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',
|
|
'et_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',
|
|
'et_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}]},{},[17])
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL2J5dGVzVG9VdWlkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvbGliL3JuZy1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvdjEuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy93aWxkZW1pdHRlci93aWxkZW1pdHRlci5qcyIsIi4uL25vZGVfbW9kdWxlcy93b2xmeTg3LWV2ZW50ZW1pdHRlci9FdmVudEVtaXR0ZXIuanMiLCIuLi9wYWNrYWdlLmpzb24iLCJNYWluLnRzIiwiT3BlblZpZHUvQ29ubmVjdGlvbi50cyIsIk9wZW5WaWR1L0ZpbHRlci50cyIsIk9wZW5WaWR1L0xvY2FsUmVjb3JkZXIudHMiLCJPcGVuVmlkdS9PcGVuVmlkdS50cyIsIk9wZW5WaWR1L1B1Ymxpc2hlci50cyIsIk9wZW5WaWR1L1Nlc3Npb24udHMiLCJPcGVuVmlkdS9TdHJlYW0udHMiLCJPcGVuVmlkdS9TdHJlYW1NYW5hZ2VyLnRzIiwiT3BlblZpZHUvU3Vic2NyaWJlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0ZpbHRlckV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvTWFwcGVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9qc29ucnBjY2xpZW50LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbi5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL0pzb25SUEMuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9YbWxSUEMuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM2dCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDanNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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RyxhQUFhLENBQUM7UUFDckQsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLGNBQWMsQ0FBQztJQUMxQixDQUFDO0lBRU8sc0NBQWdCLEdBQXhCLFVBQXlCLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUztRQUFqRCxpQkFjQztRQWJHLElBQUksUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFFMUMsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFBLFFBQVE7Z0JBQ2xDLElBQU0sTUFBTSxHQUFHLEtBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RCLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUN2QjthQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUU5RixPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBQyxRQUFRO2dCQUN4QixJQUFNLE1BQU0sR0FBRyxLQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2hELFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN0QixDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQ3ZCO0lBQ0wsQ0FBQztJQUVMLGtCQUFDO0FBQUQsQ0FyWUEsQUFxWUMsSUFBQTtBQXJZWSxrQ0FBVyIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgb2JqZWN0Q3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCBvYmplY3RDcmVhdGVQb2x5ZmlsbFxudmFyIG9iamVjdEtleXMgPSBPYmplY3Qua2V5cyB8fCBvYmplY3RLZXlzUG9seWZpbGxcbnZhciBiaW5kID0gRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgfHwgZnVuY3Rpb25CaW5kUG9seWZpbGxcblxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMsICdfZXZlbnRzJykpIHtcbiAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICB9XG5cbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxudmFyIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxudmFyIGhhc0RlZmluZVByb3BlcnR5O1xudHJ5IHtcbiAgdmFyIG8gPSB7fTtcbiAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sICd4JywgeyB2YWx1ZTogMCB9KTtcbiAgaGFzRGVmaW5lUHJvcGVydHkgPSBvLnggPT09IDA7XG59IGNhdGNoIChlcnIpIHsgaGFzRGVmaW5lUHJvcGVydHkgPSBmYWxzZSB9XG5pZiAoaGFzRGVmaW5lUHJvcGVydHkpIHtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50RW1pdHRlciwgJ2RlZmF1bHRNYXhMaXN0ZW5lcnMnLCB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKGFyZykge1xuICAgICAgLy8gY2hlY2sgd2hldGhlciB0aGUgaW5wdXQgaXMgYSBwb3NpdGl2ZSBudW1iZXIgKHdob3NlIHZhbHVlIGlzIHplcm8gb3JcbiAgICAgIC8vIGdyZWF0ZXIgYW5kIG5vdCBhIE5hTikuXG4gICAgICBpZiAodHlwZW9mIGFyZyAhPT0gJ251bWJlcicgfHwgYXJnIDwgMCB8fCBhcmcgIT09IGFyZylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJkZWZhdWx0TWF4TGlzdGVuZXJzXCIgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICAgICAgZGVmYXVsdE1heExpc3RlbmVycyA9IGFyZztcbiAgICB9XG4gIH0pO1xufSBlbHNlIHtcbiAgRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBkZWZhdWx0TWF4TGlzdGVuZXJzO1xufVxuXG4vLyBPYnZpb3VzbHkgbm90IGFsbCBFbWl0dGVycyBzaG91bGQgYmUgbGltaXRlZCB0byAxMC4gVGhpcyBmdW5jdGlvbiBhbGxvd3Ncbi8vIHRoYXQgdG8gYmUgaW5jcmVhc2VkLiBTZXQgdG8gemVybyBmb3IgdW5saW1pdGVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBzZXRNYXhMaXN0ZW5lcnMobikge1xuICBpZiAodHlwZW9mIG4gIT09ICdudW1iZXInIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiblwiIGFyZ3VtZW50IG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiAkZ2V0TWF4TGlzdGVuZXJzKHRoYXQpIHtcbiAgaWYgKHRoYXQuX21heExpc3RlbmVycyA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgcmV0dXJuIHRoYXQuX21heExpc3RlbmVycztcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5nZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRNYXhMaXN0ZW5lcnMoKSB7XG4gIHJldHVybiAkZ2V0TWF4TGlzdGVuZXJzKHRoaXMpO1xufTtcblxuLy8gVGhlc2Ugc3RhbmRhbG9uZSBlbWl0KiBmdW5jdGlvbnMgYXJlIHVzZWQgdG8gb3B0aW1pemUgY2FsbGluZyBvZiBldmVudFxuLy8gaGFuZGxlcnMgZm9yIGZhc3QgY2FzZXMgYmVjYXVzZSBlbWl0KCkgaXRzZWxmIG9mdGVuIGhhcyBhIHZhcmlhYmxlIG51bWJlciBvZlxuLy8gYXJndW1lbnRzIGFuZCBjYW4gYmUgZGVvcHRpbWl6ZWQgYmVjYXVzZSBvZiB0aGF0LiBUaGVzZSBmdW5jdGlvbnMgYWx3YXlzIGhhdmVcbi8vIHRoZSBzYW1lIG51bWJlciBvZiBhcmd1bWVudHMgYW5kIHRodXMgZG8gbm90IGdldCBkZW9wdGltaXplZCwgc28gdGhlIGNvZGVcbi8vIGluc2lkZSB0aGVtIGNhbiBleGVjdXRlIGZhc3Rlci5cbmZ1bmN0aW9uIGVtaXROb25lKGhhbmRsZXIsIGlzRm4sIHNlbGYpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZik7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRPbmUoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSkge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSk7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFR3byhoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmcxLCBhcmcyKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYsIGFyZzEsIGFyZzIpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0VGhyZWUoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMiwgYXJnMykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBlbWl0TWFueShoYW5kbGVyLCBpc0ZuLCBzZWxmLCBhcmdzKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuYXBwbHkoc2VsZiwgYXJncyk7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkoc2VsZiwgYXJncyk7XG4gIH1cbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gZW1pdCh0eXBlKSB7XG4gIHZhciBlciwgaGFuZGxlciwgbGVuLCBhcmdzLCBpLCBldmVudHM7XG4gIHZhciBkb0Vycm9yID0gKHR5cGUgPT09ICdlcnJvcicpO1xuXG4gIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgaWYgKGV2ZW50cylcbiAgICBkb0Vycm9yID0gKGRvRXJyb3IgJiYgZXZlbnRzLmVycm9yID09IG51bGwpO1xuICBlbHNlIGlmICghZG9FcnJvcilcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgLy8gSWYgdGhlcmUgaXMgbm8gJ2Vycm9yJyBldmVudCBsaXN0ZW5lciB0aGVuIHRocm93LlxuICBpZiAoZG9FcnJvcikge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSlcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgIGlmIChlciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICB0aHJvdyBlcjsgLy8gVW5oYW5kbGVkICdlcnJvcicgZXZlbnRcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQXQgbGVhc3QgZ2l2ZSBzb21lIGtpbmQgb2YgY29udGV4dCB0byB0aGUgdXNlclxuICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcignVW5oYW5kbGVkIFwiZXJyb3JcIiBldmVudC4gKCcgKyBlciArICcpJyk7XG4gICAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBoYW5kbGVyID0gZXZlbnRzW3R5cGVdO1xuXG4gIGlmICghaGFuZGxlcilcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIGlzRm4gPSB0eXBlb2YgaGFuZGxlciA9PT0gJ2Z1bmN0aW9uJztcbiAgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgc3dpdGNoIChsZW4pIHtcbiAgICAgIC8vIGZhc3QgY2FzZXNcbiAgICBjYXNlIDE6XG4gICAgICBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCB0aGlzKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMjpcbiAgICAgIGVtaXRPbmUoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMzpcbiAgICAgIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgdGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0pO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA0OlxuICAgICAgZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdLCBhcmd1bWVudHNbM10pO1xuICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICBkZWZhdWx0OlxuICAgICAgYXJncyA9IG5ldyBBcnJheShsZW4gLSAxKTtcbiAgICAgIGZvciAoaSA9IDE7IGkgPCBsZW47IGkrKylcbiAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICBlbWl0TWFueShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuZnVuY3Rpb24gX2FkZExpc3RlbmVyKHRhcmdldCwgdHlwZSwgbGlzdGVuZXIsIHByZXBlbmQpIHtcbiAgdmFyIG07XG4gIHZhciBldmVudHM7XG4gIHZhciBleGlzdGluZztcblxuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgaWYgKCFldmVudHMpIHtcbiAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICB0YXJnZXQuX2V2ZW50c0NvdW50ID0gMDtcbiAgfSBlbHNlIHtcbiAgICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAgIC8vIGFkZGluZyBpdCB0byB0aGUgbGlzdGVuZXJzLCBmaXJzdCBlbWl0IFwibmV3TGlzdGVuZXJcIi5cbiAgICBpZiAoZXZlbnRzLm5ld0xpc3RlbmVyKSB7XG4gICAgICB0YXJnZXQuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgIGxpc3RlbmVyLmxpc3RlbmVyID8gbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgICAgIC8vIFJlLWFzc2lnbiBgZXZlbnRzYCBiZWNhdXNlIGEgbmV3TGlzdGVuZXIgaGFuZGxlciBjb3VsZCBoYXZlIGNhdXNlZCB0aGVcbiAgICAgIC8vIHRoaXMuX2V2ZW50cyB0byBiZSBhc3NpZ25lZCB0byBhIG5ldyBvYmplY3RcbiAgICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICAgIH1cbiAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXTtcbiAgfVxuXG4gIGlmICghZXhpc3RpbmcpIHtcbiAgICAvLyBPcHRpbWl6ZSB0aGUgY2FzZSBvZiBvbmUgbGlzdGVuZXIuIERvbid0IG5lZWQgdGhlIGV4dHJhIGFycmF5IG9iamVjdC5cbiAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICAgICsrdGFyZ2V0Ll9ldmVudHNDb3VudDtcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIGV4aXN0aW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID1cbiAgICAgICAgICBwcmVwZW5kID8gW2xpc3RlbmVyLCBleGlzdGluZ10gOiBbZXhpc3RpbmcsIGxpc3RlbmVyXTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgICAgaWYgKHByZXBlbmQpIHtcbiAgICAgICAgZXhpc3RpbmcudW5zaGlmdChsaXN0ZW5lcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleGlzdGluZy5wdXNoKGxpc3RlbmVyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICAgIGlmICghZXhpc3Rpbmcud2FybmVkKSB7XG4gICAgICBtID0gJGdldE1heExpc3RlbmVycyh0YXJnZXQpO1xuICAgICAgaWYgKG0gJiYgbSA+IDAgJiYgZXhpc3RpbmcubGVuZ3RoID4gbSkge1xuICAgICAgICBleGlzdGluZy53YXJuZWQgPSB0cnVlO1xuICAgICAgICB2YXIgdyA9IG5ldyBFcnJvcignUG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSBsZWFrIGRldGVjdGVkLiAnICtcbiAgICAgICAgICAgIGV4aXN0aW5nLmxlbmd0aCArICcgXCInICsgU3RyaW5nKHR5cGUpICsgJ1wiIGxpc3RlbmVycyAnICtcbiAgICAgICAgICAgICdhZGRlZC4gVXNlIGVtaXR0ZXIuc2V0TWF4TGlzdGVuZXJzKCkgdG8gJyArXG4gICAgICAgICAgICAnaW5jcmVhc2UgbGltaXQuJyk7XG4gICAgICAgIHcubmFtZSA9ICdNYXhMaXN0ZW5lcnNFeGNlZWRlZFdhcm5pbmcnO1xuICAgICAgICB3LmVtaXR0ZXIgPSB0YXJnZXQ7XG4gICAgICAgIHcudHlwZSA9IHR5cGU7XG4gICAgICAgIHcuY291bnQgPSBleGlzdGluZy5sZW5ndGg7XG4gICAgICAgIGlmICh0eXBlb2YgY29uc29sZSA9PT0gJ29iamVjdCcgJiYgY29uc29sZS53YXJuKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCclczogJXMnLCB3Lm5hbWUsIHcubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZExpc3RlbmVyID1cbiAgICBmdW5jdGlvbiBwcmVwZW5kTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIHRydWUpO1xuICAgIH07XG5cbmZ1bmN0aW9uIG9uY2VXcmFwcGVyKCkge1xuICBpZiAoIXRoaXMuZmlyZWQpIHtcbiAgICB0aGlzLnRhcmdldC5yZW1vdmVMaXN0ZW5lcih0aGlzLnR5cGUsIHRoaXMud3JhcEZuKTtcbiAgICB0aGlzLmZpcmVkID0gdHJ1ZTtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCk7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSk7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdKTtcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCwgYXJndW1lbnRzWzBdLCBhcmd1bWVudHNbMV0sXG4gICAgICAgICAgICBhcmd1bWVudHNbMl0pO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7ICsraSlcbiAgICAgICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB0aGlzLmxpc3RlbmVyLmFwcGx5KHRoaXMudGFyZ2V0LCBhcmdzKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gX29uY2VXcmFwKHRhcmdldCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIHN0YXRlID0geyBmaXJlZDogZmFsc2UsIHdyYXBGbjogdW5kZWZpbmVkLCB0YXJnZXQ6IHRhcmdldCwgdHlwZTogdHlwZSwgbGlzdGVuZXI6IGxpc3RlbmVyIH07XG4gIHZhciB3cmFwcGVkID0gYmluZC5jYWxsKG9uY2VXcmFwcGVyLCBzdGF0ZSk7XG4gIHdyYXBwZWQubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgc3RhdGUud3JhcEZuID0gd3JhcHBlZDtcbiAgcmV0dXJuIHdyYXBwZWQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIG9uY2UodHlwZSwgbGlzdGVuZXIpIHtcbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gIHRoaXMub24odHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kT25jZUxpc3RlbmVyID1cbiAgICBmdW5jdGlvbiBwcmVwZW5kT25jZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICB0aGlzLnByZXBlbmRMaXN0ZW5lcih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbi8vIEVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZiBhbmQgb25seSBpZiB0aGUgbGlzdGVuZXIgd2FzIHJlbW92ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID1cbiAgICBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGxpc3QsIGV2ZW50cywgcG9zaXRpb24sIGksIG9yaWdpbmFsTGlzdGVuZXI7XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICAgICAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICAgICAgaWYgKCFldmVudHMpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBsaXN0ID0gZXZlbnRzW3R5cGVdO1xuICAgICAgaWYgKCFsaXN0KVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8IGxpc3QubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgZGVsZXRlIGV2ZW50c1t0eXBlXTtcbiAgICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3QubGlzdGVuZXIgfHwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBsaXN0ICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHBvc2l0aW9uID0gLTE7XG5cbiAgICAgICAgZm9yIChpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIGlmIChsaXN0W2ldID09PSBsaXN0ZW5lciB8fCBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgb3JpZ2luYWxMaXN0ZW5lciA9IGxpc3RbaV0ubGlzdGVuZXI7XG4gICAgICAgICAgICBwb3NpdGlvbiA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gMClcbiAgICAgICAgICBsaXN0LnNoaWZ0KCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBzcGxpY2VPbmUobGlzdCwgcG9zaXRpb24pO1xuXG4gICAgICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMSlcbiAgICAgICAgICBldmVudHNbdHlwZV0gPSBsaXN0WzBdO1xuXG4gICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIG9yaWdpbmFsTGlzdGVuZXIgfHwgbGlzdGVuZXIpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUFsbExpc3RlbmVycyA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpIHtcbiAgICAgIHZhciBsaXN0ZW5lcnMsIGV2ZW50cywgaTtcblxuICAgICAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICAgICAgaWYgKCFldmVudHMpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gICAgICBpZiAoIWV2ZW50cy5yZW1vdmVMaXN0ZW5lcikge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnRzW3R5cGVdKSB7XG4gICAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1t0eXBlXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB2YXIga2V5cyA9IG9iamVjdEtleXMoZXZlbnRzKTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICBrZXkgPSBrZXlzW2ldO1xuICAgICAgICAgIGlmIChrZXkgPT09ICdyZW1vdmVMaXN0ZW5lcicpIGNvbnRpbnVlO1xuICAgICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoJ3JlbW92ZUxpc3RlbmVyJyk7XG4gICAgICAgIHRoaXMuX2V2ZW50cyA9IG9iamVjdENyZWF0ZShudWxsKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgbGlzdGVuZXJzID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gICAgICB9IGVsc2UgaWYgKGxpc3RlbmVycykge1xuICAgICAgICAvLyBMSUZPIG9yZGVyXG4gICAgICAgIGZvciAoaSA9IGxpc3RlbmVycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG5mdW5jdGlvbiBfbGlzdGVuZXJzKHRhcmdldCwgdHlwZSwgdW53cmFwKSB7XG4gIHZhciBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcblxuICBpZiAoIWV2ZW50cylcbiAgICByZXR1cm4gW107XG5cbiAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG4gIGlmICghZXZsaXN0ZW5lcilcbiAgICByZXR1cm4gW107XG5cbiAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKVxuICAgIHJldHVybiB1bndyYXAgPyBbZXZsaXN0ZW5lci5saXN0ZW5lciB8fCBldmxpc3RlbmVyXSA6IFtldmxpc3RlbmVyXTtcblxuICByZXR1cm4gdW53cmFwID8gdW53cmFwTGlzdGVuZXJzKGV2bGlzdGVuZXIpIDogYXJyYXlDbG9uZShldmxpc3RlbmVyLCBldmxpc3RlbmVyLmxlbmd0aCk7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24gbGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgdHJ1ZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJhd0xpc3RlbmVycyA9IGZ1bmN0aW9uIHJhd0xpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSkge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIubGlzdGVuZXJDb3VudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGxpc3RlbmVyQ291bnQuY2FsbChlbWl0dGVyLCB0eXBlKTtcbiAgfVxufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gbGlzdGVuZXJDb3VudDtcbmZ1bmN0aW9uIGxpc3RlbmVyQ291bnQodHlwZSkge1xuICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuXG4gIGlmIChldmVudHMpIHtcbiAgICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcblxuICAgIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIGlmIChldmxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDA7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZXZlbnROYW1lcyA9IGZ1bmN0aW9uIGV2ZW50TmFtZXMoKSB7XG4gIHJldHVybiB0aGlzLl9ldmVudHNDb3VudCA+IDAgPyBSZWZsZWN0Lm93bktleXModGhpcy5fZXZlbnRzKSA6IFtdO1xufTtcblxuLy8gQWJvdXQgMS41eCBmYXN0ZXIgdGhhbiB0aGUgdHdvLWFyZyB2ZXJzaW9uIG9mIEFycmF5I3NwbGljZSgpLlxuZnVuY3Rpb24gc3BsaWNlT25lKGxpc3QsIGluZGV4KSB7XG4gIGZvciAodmFyIGkgPSBpbmRleCwgayA9IGkgKyAxLCBuID0gbGlzdC5sZW5ndGg7IGsgPCBuOyBpICs9IDEsIGsgKz0gMSlcbiAgICBsaXN0W2ldID0gbGlzdFtrXTtcbiAgbGlzdC5wb3AoKTtcbn1cblxuZnVuY3Rpb24gYXJyYXlDbG9uZShhcnIsIG4pIHtcbiAgdmFyIGNvcHkgPSBuZXcgQXJyYXkobik7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKVxuICAgIGNvcHlbaV0gPSBhcnJbaV07XG4gIHJldHVybiBjb3B5O1xufVxuXG5mdW5jdGlvbiB1bndyYXBMaXN0ZW5lcnMoYXJyKSB7XG4gIHZhciByZXQgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmV0Lmxlbmd0aDsgKytpKSB7XG4gICAgcmV0W2ldID0gYXJyW2ldLmxpc3RlbmVyIHx8IGFycltpXTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBvYmplY3RDcmVhdGVQb2x5ZmlsbChwcm90bykge1xuICB2YXIgRiA9IGZ1bmN0aW9uKCkge307XG4gIEYucHJvdG90eXBlID0gcHJvdG87XG4gIHJldHVybiBuZXcgRjtcbn1cbmZ1bmN0aW9uIG9iamVjdEtleXNQb2x5ZmlsbChvYmopIHtcbiAgdmFyIGtleXMgPSBbXTtcbiAgZm9yICh2YXIgayBpbiBvYmopIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrKSkge1xuICAgIGtleXMucHVzaChrKTtcbiAgfVxuICByZXR1cm4gaztcbn1cbmZ1bmN0aW9uIGZ1bmN0aW9uQmluZFBvbHlmaWxsKGNvbnRleHQpIHtcbiAgdmFyIGZuID0gdGhpcztcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcbiAgfTtcbn1cbiIsIi8qIGpzaGludCBub2RlOiB0cnVlICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBub3JtYWxpY2UgPSByZXF1aXJlKCdub3JtYWxpY2UnKTtcblxuLyoqXG4gICMgZnJlZWljZVxuXG4gIFRoZSBgZnJlZWljZWAgbW9kdWxlIGlzIGEgc2ltcGxlIHdheSBvZiBnZXR0aW5nIHJhbmRvbSBTVFVOIG9yIFRVUk4gc2VydmVyXG4gIGZvciB5b3VyIFdlYlJUQyBhcHBsaWNhdGlvbi4gIFRoZSBsaXN0IG9mIHNlcnZlcnMgKGp1c3QgU1RVTiBhdCB0aGlzIHN0YWdlKVxuICB3ZXJlIHNvdXJjZWQgZnJvbSB0aGlzIFtnaXN0XShodHRwczovL2dpc3QuZ2l0aHViLmNvbS96eml1bmkvMzc0MTkzMykuXG5cbiAgIyMgRXhhbXBsZSBVc2VcblxuICBUaGUgZm9sbG93aW5nIGRlbW9uc3RyYXRlcyBob3cgeW91IGNhbiB1c2UgYGZyZWVpY2VgIHdpdGhcbiAgW3J0Yy1xdWlja2Nvbm5lY3RdKGh0dHBzOi8vZ2l0aHViLmNvbS9ydGMtaW8vcnRjLXF1aWNrY29ubmVjdCk6XG5cbiAgPDw8IGV4YW1wbGVzL3F1aWNrY29ubmVjdC5qc1xuXG4gIEFzIHRoZSBgZnJlZWljZWAgbW9kdWxlIGdlbmVyYXRlcyBpY2Ugc2VydmVycyBpbiBhIGxpc3QgY29tcGxpYW50IHdpdGggdGhlXG4gIFdlYlJUQyBzcGVjIHlvdSB3aWxsIGJlIGFibGUgdG8gdXNlIGl0IHdpdGggcmF3IGBSVENQZWVyQ29ubmVjdGlvbmBcbiAgY29uc3RydWN0b3JzIGFuZCBvdGhlciBXZWJSVEMgbGlicmFyaWVzLlxuXG4gICMjIEhleSwgZG9uJ3QgdXNlIG15IFNUVU4vVFVSTiBzZXJ2ZXIhXG5cbiAgSWYgZm9yIHNvbWUgcmVhc29uIHlvdXIgZnJlZSBTVFVOIG9yIFRVUk4gc2VydmVyIGVuZHMgdXAgaW4gdGhlXG4gIGxpc3Qgb2Ygc2VydmVycyAoW3N0dW5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci9zdHVuLmpzb24pIG9yXG4gIFt0dXJuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvdHVybi5qc29uKSlcbiAgdGhhdCBpcyB1c2VkIGluIHRoaXMgbW9kdWxlLCB5b3UgY2FuIGZlZWxcbiAgZnJlZSB0byBvcGVuIGFuIGlzc3VlIG9uIHRoaXMgcmVwb3NpdG9yeSBhbmQgdGhvc2Ugc2VydmVycyB3aWxsIGJlIHJlbW92ZWRcbiAgd2l0aGluIDI0IGhvdXJzIChvciBzb29uZXIpLiAgVGhpcyBpcyB0aGUgcXVpY2tlc3QgYW5kIHByb2JhYmx5IHRoZSBtb3N0XG4gIHBvbGl0ZSB3YXkgdG8gaGF2ZSBzb21ldGhpbmcgcmVtb3ZlZCAoYW5kIHByb3ZpZGVzIHVzIHNvbWUgdmlzaWJpbGl0eVxuICBpZiBzb21lb25lIG9wZW5zIGEgcHVsbCByZXF1ZXN0IHJlcXVlc3RpbmcgdGhhdCBhIHNlcnZlciBpcyBhZGRlZCkuXG5cbiAgIyMgUGxlYXNlIGFkZCBteSBzZXJ2ZXIhXG5cbiAgSWYgeW91IGhhdmUgYSBzZXJ2ZXIgdGhhdCB5b3Ugd2lzaCB0byBhZGQgdG8gdGhlIGxpc3QsIHRoYXQncyBhd2Vzb21lISBJJ21cbiAgc3VyZSBJIHNwZWFrIG9uIGJlaGFsZiBvZiBhIHdob2xlIHBpbGUgb2YgV2ViUlRDIGRldmVsb3BlcnMgd2hvIHNheSB0aGFua3MuXG4gIFRvIGdldCBpdCBpbnRvIHRoZSBsaXN0LCBmZWVsIGZyZWUgdG8gZWl0aGVyIG9wZW4gYSBwdWxsIHJlcXVlc3Qgb3IgaWYgeW91XG4gIGZpbmQgdGhhdCBwcm9jZXNzIGEgYml0IGRhdW50aW5nIHRoZW4ganVzdCBjcmVhdGUgYW4gaXNzdWUgcmVxdWVzdGluZ1xuICB0aGUgYWRkaXRpb24gb2YgdGhlIHNlcnZlciAobWFrZSBzdXJlIHlvdSBwcm92aWRlIGFsbCB0aGUgZGV0YWlscywgYW5kIGlmXG4gIHlvdSBoYXZlIGEgVGVybXMgb2YgU2VydmljZSB0aGVuIGluY2x1ZGluZyB0aGF0IGluIHRoZSBQUi9pc3N1ZSB3b3VsZCBiZVxuICBhd2Vzb21lKS5cblxuICAjIyBJIGtub3cgb2YgYSBmcmVlIHNlcnZlciwgY2FuIEkgYWRkIGl0P1xuXG4gIFN1cmUsIGlmIHlvdSBkbyB5b3VyIGhvbWV3b3JrIGFuZCBtYWtlIHN1cmUgaXQgaXMgb2sgdG8gdXNlIChJJ20gY3VycmVudGx5XG4gIGluIHRoZSBwcm9jZXNzIG9mIHJldmlld2luZyB0aGUgdGVybXMgb2YgdGhvc2UgU1RVTiBzZXJ2ZXJzIGluY2x1ZGVkIGZyb21cbiAgdGhlIG9yaWdpbmFsIGxpc3QpLiAgSWYgaXQncyBvayB0byBnbywgdGhlbiBwbGVhc2Ugc2VlIHRoZSBwcmV2aW91cyBlbnRyeVxuICBmb3IgaG93IHRvIGFkZCBpdC5cblxuICAjIyBDdXJyZW50IExpc3Qgb2YgU2VydmVyc1xuXG4gICogY3VycmVudCBhcyBhdCB0aGUgdGltZSBvZiBsYXN0IGBSRUFETUUubWRgIGZpbGUgZ2VuZXJhdGlvblxuXG4gICMjIyBTVFVOXG5cbiAgPDw8IHN0dW4uanNvblxuXG4gICMjIyBUVVJOXG5cbiAgPDw8IHR1cm4uanNvblxuXG4qKi9cblxudmFyIGZyZWVpY2UgPSBmdW5jdGlvbihvcHRzKSB7XG4gIC8vIGlmIGEgbGlzdCBvZiBzZXJ2ZXJzIGhhcyBiZWVuIHByb3ZpZGVkLCB0aGVuIHVzZSBpdCBpbnN0ZWFkIG9mIGRlZmF1bHRzXG4gIHZhciBzZXJ2ZXJzID0ge1xuICAgIHN0dW46IChvcHRzIHx8IHt9KS5zdHVuIHx8IHJlcXVpcmUoJy4vc3R1bi5qc29uJyksXG4gICAgdHVybjogKG9wdHMgfHwge30pLnR1cm4gfHwgcmVxdWlyZSgnLi90dXJuLmpzb24nKVxuICB9O1xuXG4gIHZhciBzdHVuQ291bnQgPSAob3B0cyB8fCB7fSkuc3R1bkNvdW50IHx8IDI7XG4gIHZhciB0dXJuQ291bnQgPSAob3B0cyB8fCB7fSkudHVybkNvdW50IHx8IDA7XG4gIHZhciBzZWxlY3RlZDtcblxuICBmdW5jdGlvbiBnZXRTZXJ2ZXJzKHR5cGUsIGNvdW50KSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpbnB1dCA9IFtdLmNvbmNhdChzZXJ2ZXJzW3R5cGVdKTtcbiAgICB2YXIgaWR4O1xuXG4gICAgd2hpbGUgKGlucHV0Lmxlbmd0aCAmJiBvdXQubGVuZ3RoIDwgY291bnQpIHtcbiAgICAgIGlkeCA9IChNYXRoLnJhbmRvbSgpICogaW5wdXQubGVuZ3RoKSB8IDA7XG4gICAgICBvdXQgPSBvdXQuY29uY2F0KGlucHV0LnNwbGljZShpZHgsIDEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0Lm1hcChmdW5jdGlvbih1cmwpIHtcbiAgICAgICAgLy9JZiBpdCdzIGEgbm90IGEgc3RyaW5nLCBkb24ndCB0cnkgdG8gXCJub3JtYWxpY2VcIiBpdCBvdGhlcndpc2UgdXNpbmcgdHlwZTp1cmwgd2lsbCBzY3JldyBpdCB1cFxuICAgICAgICBpZiAoKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9ybWFsaWNlKHR5cGUgKyAnOicgKyB1cmwpO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBhZGQgc3R1biBzZXJ2ZXJzXG4gIHNlbGVjdGVkID0gW10uY29uY2F0KGdldFNlcnZlcnMoJ3N0dW4nLCBzdHVuQ291bnQpKTtcblxuICBpZiAodHVybkNvdW50KSB7XG4gICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5jb25jYXQoZ2V0U2VydmVycygndHVybicsIHR1cm5Db3VudCkpO1xuICB9XG5cbiAgcmV0dXJuIHNlbGVjdGVkO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmcmVlaWNlOyIsIm1vZHVsZS5leHBvcnRzPVtcbiAgXCJzdHVuLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4xLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4yLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4zLmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW40LmwuZ29vZ2xlLmNvbToxOTMwMlwiLFxuICBcInN0dW4uZWtpZ2EubmV0XCIsXG4gIFwic3R1bi5pZGVhc2lwLmNvbVwiLFxuICBcInN0dW4uc2NobHVuZC5kZVwiLFxuICBcInN0dW4uc3R1bnByb3RvY29sLm9yZzozNDc4XCIsXG4gIFwic3R1bi52b2lwYXJvdW5kLmNvbVwiLFxuICBcInN0dW4udm9pcGJ1c3Rlci5jb21cIixcbiAgXCJzdHVuLnZvaXBzdHVudC5jb21cIixcbiAgXCJzdHVuLnZveGdyYXRpYS5vcmdcIlxuXVxuIiwibW9kdWxlLmV4cG9ydHM9W11cbiIsInZhciBXaWxkRW1pdHRlciA9IHJlcXVpcmUoJ3dpbGRlbWl0dGVyJyk7XG5cbmZ1bmN0aW9uIGdldE1heFZvbHVtZSAoYW5hbHlzZXIsIGZmdEJpbnMpIHtcbiAgdmFyIG1heFZvbHVtZSA9IC1JbmZpbml0eTtcbiAgYW5hbHlzZXIuZ2V0RmxvYXRGcmVxdWVuY3lEYXRhKGZmdEJpbnMpO1xuXG4gIGZvcih2YXIgaT00LCBpaT1mZnRCaW5zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICBpZiAoZmZ0Qmluc1tpXSA+IG1heFZvbHVtZSAmJiBmZnRCaW5zW2ldIDwgMCkge1xuICAgICAgbWF4Vm9sdW1lID0gZmZ0Qmluc1tpXTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIG1heFZvbHVtZTtcbn1cblxuXG52YXIgYXVkaW9Db250ZXh0VHlwZTtcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICBhdWRpb0NvbnRleHRUeXBlID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fCB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0O1xufVxuLy8gdXNlIGEgc2luZ2xlIGF1ZGlvIGNvbnRleHQgZHVlIHRvIGhhcmR3YXJlIGxpbWl0c1xudmFyIGF1ZGlvQ29udGV4dCA9IG51bGw7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cmVhbSwgb3B0aW9ucykge1xuICB2YXIgaGFya2VyID0gbmV3IFdpbGRFbWl0dGVyKCk7XG5cbiAgLy8gbWFrZSBpdCBub3QgYnJlYWsgaW4gbm9uLXN1cHBvcnRlZCBicm93c2Vyc1xuICBpZiAoIWF1ZGlvQ29udGV4dFR5cGUpIHJldHVybiBoYXJrZXI7XG5cbiAgLy9Db25maWdcbiAgdmFyIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9LFxuICAgICAgc21vb3RoaW5nID0gKG9wdGlvbnMuc21vb3RoaW5nIHx8IDAuMSksXG4gICAgICBpbnRlcnZhbCA9IChvcHRpb25zLmludGVydmFsIHx8IDUwKSxcbiAgICAgIHRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkLFxuICAgICAgcGxheSA9IG9wdGlvbnMucGxheSxcbiAgICAgIGhpc3RvcnkgPSBvcHRpb25zLmhpc3RvcnkgfHwgMTAsXG4gICAgICBydW5uaW5nID0gdHJ1ZTtcblxuICAvLyBFbnN1cmUgdGhhdCBqdXN0IGEgc2luZ2xlIEF1ZGlvQ29udGV4dCBpcyBpbnRlcm5hbGx5IGNyZWF0ZWRcbiAgYXVkaW9Db250ZXh0ID0gb3B0aW9ucy5hdWRpb0NvbnRleHQgfHwgYXVkaW9Db250ZXh0IHx8IG5ldyBhdWRpb0NvbnRleHRUeXBlKCk7XG5cbiAgdmFyIHNvdXJjZU5vZGUsIGZmdEJpbnMsIGFuYWx5c2VyO1xuXG4gIGFuYWx5c2VyID0gYXVkaW9Db250ZXh0LmNyZWF0ZUFuYWx5c2VyKCk7XG4gIGFuYWx5c2VyLmZmdFNpemUgPSA1MTI7XG4gIGFuYWx5c2VyLnNtb290aGluZ1RpbWVDb25zdGFudCA9IHNtb290aGluZztcbiAgZmZ0QmlucyA9IG5ldyBGbG9hdDMyQXJyYXkoYW5hbHlzZXIuZnJlcXVlbmN5QmluQ291bnQpO1xuXG4gIGlmIChzdHJlYW0uanF1ZXJ5KSBzdHJlYW0gPSBzdHJlYW1bMF07XG4gIGlmIChzdHJlYW0gaW5zdGFuY2VvZiBIVE1MQXVkaW9FbGVtZW50IHx8IHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxWaWRlb0VsZW1lbnQpIHtcbiAgICAvL0F1ZGlvIFRhZ1xuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFFbGVtZW50U291cmNlKHN0cmVhbSk7XG4gICAgaWYgKHR5cGVvZiBwbGF5ID09PSAndW5kZWZpbmVkJykgcGxheSA9IHRydWU7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfSBlbHNlIHtcbiAgICAvL1dlYlJUQyBTdHJlYW1cbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhU3RyZWFtU291cmNlKHN0cmVhbSk7XG4gICAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IC01MDtcbiAgfVxuXG4gIHNvdXJjZU5vZGUuY29ubmVjdChhbmFseXNlcik7XG4gIGlmIChwbGF5KSBhbmFseXNlci5jb25uZWN0KGF1ZGlvQ29udGV4dC5kZXN0aW5hdGlvbik7XG5cbiAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG5cbiAgaGFya2VyLnN1c3BlbmQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN1c3BlbmQoKTtcbiAgfVxuICBoYXJrZXIucmVzdW1lID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5yZXN1bWUoKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaGFya2VyLCAnc3RhdGUnLCB7IGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdGF0ZTtcbiAgfX0pO1xuICBhdWRpb0NvbnRleHQub25zdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgIGhhcmtlci5lbWl0KCdzdGF0ZV9jaGFuZ2UnLCBhdWRpb0NvbnRleHQuc3RhdGUpO1xuICB9XG5cbiAgaGFya2VyLnNldFRocmVzaG9sZCA9IGZ1bmN0aW9uKHQpIHtcbiAgICB0aHJlc2hvbGQgPSB0O1xuICB9O1xuXG4gIGhhcmtlci5zZXRJbnRlcnZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICBpbnRlcnZhbCA9IGk7XG4gIH07XG5cbiAgaGFya2VyLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCAtMTAwLCB0aHJlc2hvbGQpO1xuICAgIGlmIChoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICB9XG4gICAgYW5hbHlzZXIuZGlzY29ubmVjdCgpO1xuICAgIHNvdXJjZU5vZGUuZGlzY29ubmVjdCgpO1xuICB9O1xuICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5ID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgaGlzdG9yeTsgaSsrKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCk7XG4gIH1cblxuICAvLyBQb2xsIHRoZSBhbmFseXNlciBub2RlIHRvIGRldGVybWluZSBpZiBzcGVha2luZ1xuICAvLyBhbmQgZW1pdCBldmVudHMgaWYgY2hhbmdlZFxuICB2YXIgbG9vcGVyID0gZnVuY3Rpb24oKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcblxuICAgICAgLy9jaGVjayBpZiBzdG9wIGhhcyBiZWVuIGNhbGxlZFxuICAgICAgaWYoIXJ1bm5pbmcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudFZvbHVtZSA9IGdldE1heFZvbHVtZShhbmFseXNlciwgZmZ0Qmlucyk7XG5cbiAgICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgY3VycmVudFZvbHVtZSwgdGhyZXNob2xkKTtcblxuICAgICAgdmFyIGhpc3RvcnkgPSAwO1xuICAgICAgaWYgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQgJiYgIWhhcmtlci5zcGVha2luZykge1xuICAgICAgICAvLyB0cmlnZ2VyIHF1aWNrbHksIHNob3J0IGhpc3RvcnlcbiAgICAgICAgZm9yICh2YXIgaSA9IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoIC0gMzsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPj0gMikge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IHRydWU7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZvbHVtZSA8IHRocmVzaG9sZCAmJiBoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID09IDApIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnNoaWZ0KCk7XG4gICAgICBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5LnB1c2goMCArIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkKSk7XG5cbiAgICAgIGxvb3BlcigpO1xuICAgIH0sIGludGVydmFsKTtcbiAgfTtcbiAgbG9vcGVyKCk7XG5cbiAgcmV0dXJuIGhhcmtlcjtcbn1cbiIsImlmICh0eXBlb2YgT2JqZWN0LmNyZWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAvLyBpbXBsZW1lbnRhdGlvbiBmcm9tIHN0YW5kYXJkIG5vZGUuanMgJ3V0aWwnIG1vZHVsZVxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGlmIChzdXBlckN0b3IpIHtcbiAgICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICAgIHZhbHVlOiBjdG9yLFxuICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgaWYgKHN1cGVyQ3Rvcikge1xuICAgICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICAgIHZhciBUZW1wQ3RvciA9IGZ1bmN0aW9uICgpIHt9XG4gICAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgICBjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IGN0b3JcbiAgICB9XG4gIH1cbn1cbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+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+Pj4gOCB8IDB4ODA7XG5cbiAgLy8gYGNsb2NrX3NlcV9sb3dgXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjtcblxuICAvLyBgbm9kZWBcbiAgZm9yICh2YXIgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmID8gYnVmIDogYnl0ZXNUb1V1aWQoYik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdjE7XG4iLCJ2YXIgcm5nID0gcmVxdWlyZSgnLi9saWIvcm5nJyk7XG52YXIgYnl0ZXNUb1V1aWQgPSByZXF1aXJlKCcuL2xpYi9ieXRlc1RvVXVpZCcpO1xuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICB2YXIgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcblxuICBpZiAodHlwZW9mKG9wdGlvbnMpID09ICdzdHJpbmcnKSB7XG4gICAgYnVmID0gb3B0aW9ucyA9PT0gJ2JpbmFyeScgPyBuZXcgQXJyYXkoMTYpIDogbnVsbDtcbiAgICBvcHRpb25zID0gbnVsbDtcbiAgfVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBybmcpKCk7XG5cbiAgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuICBybmRzWzZdID0gKHJuZHNbNl0gJiAweDBmKSB8IDB4NDA7XG4gIHJuZHNbOF0gPSAocm5kc1s4XSAmIDB4M2YpIHwgMHg4MDtcblxuICAvLyBDb3B5IGJ5dGVzIHRvIGJ1ZmZlciwgaWYgcHJvdmlkZWRcbiAgaWYgKGJ1Zikge1xuICAgIGZvciAodmFyIGlpID0gMDsgaWkgPCAxNjsgKytpaSkge1xuICAgICAgYnVmW2kgKyBpaV0gPSBybmRzW2lpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmIHx8IGJ5dGVzVG9VdWlkKHJuZHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHY0O1xuIiwiLypcbldpbGRFbWl0dGVyLmpzIGlzIGEgc2xpbSBsaXR0bGUgZXZlbnQgZW1pdHRlciBieSBAaGVucmlram9yZXRlZyBsYXJnZWx5IGJhc2VkXG5vbiBAdmlzaW9ubWVkaWEncyBFbWl0dGVyIGZyb20gVUkgS2l0LlxuXG5XaHk/IEkgd2FudGVkIGl0IHN0YW5kYWxvbmUuXG5cbkkgYWxzbyB3YW50ZWQgc3VwcG9ydCBmb3Igd2lsZGNhcmQgZW1pdHRlcnMgbGlrZSB0aGlzOlxuXG5lbWl0dGVyLm9uKCcqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgb3RoZXIsIGV2ZW50LCBwYXlsb2Fkcykge1xuXG59KTtcblxuZW1pdHRlci5vbignc29tZW5hbWVzcGFjZSonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBwYXlsb2Fkcykge1xuXG59KTtcblxuUGxlYXNlIG5vdGUgdGhhdCBjYWxsYmFja3MgdHJpZ2dlcmVkIGJ5IHdpbGRjYXJkIHJlZ2lzdGVyZWQgZXZlbnRzIGFsc28gZ2V0XG50aGUgZXZlbnQgbmFtZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQuXG4qL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdpbGRFbWl0dGVyO1xuXG5mdW5jdGlvbiBXaWxkRW1pdHRlcigpIHsgfVxuXG5XaWxkRW1pdHRlci5taXhpbiA9IGZ1bmN0aW9uIChjb25zdHJ1Y3Rvcikge1xuICAgIHZhciBwcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgfHwgY29uc3RydWN0b3I7XG5cbiAgICBwcm90b3R5cGUuaXNXaWxkRW1pdHRlcj0gdHJ1ZTtcblxuICAgIC8vIExpc3RlbiBvbiB0aGUgZ2l2ZW4gYGV2ZW50YCB3aXRoIGBmbmAuIFN0b3JlIGEgZ3JvdXAgbmFtZSBpZiBwcmVzZW50LlxuICAgIHByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xuICAgICAgICB2YXIgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xuICAgICAgICBmdW5jLl9ncm91cE5hbWUgPSBncm91cDtcbiAgICAgICAgKHRoaXMuY2FsbGJhY2tzW2V2ZW50XSA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSB8fCBbXSkucHVzaChmdW5jKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8vIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxuICAgIC8vIHRpbWUgdGhlbiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQuXG4gICAgcHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICAgICAgaGFzR3JvdXAgPSAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMyksXG4gICAgICAgICAgICBncm91cCA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZnVuYyA9IGhhc0dyb3VwID8gYXJndW1lbnRzWzJdIDogYXJndW1lbnRzWzFdO1xuICAgICAgICBmdW5jdGlvbiBvbigpIHtcbiAgICAgICAgICAgIHNlbGYub2ZmKGV2ZW50LCBvbik7XG4gICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbihldmVudCwgZ3JvdXAsIG9uKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8vIFVuYmluZHMgYW4gZW50aXJlIGdyb3VwXG4gICAgcHJvdG90eXBlLnJlbGVhc2VHcm91cCA9IGZ1bmN0aW9uIChncm91cE5hbWUpIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcbiAgICAgICAgdmFyIGl0ZW0sIGksIGxlbiwgaGFuZGxlcnM7XG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xuICAgICAgICAgICAgaGFuZGxlcnMgPSB0aGlzLmNhbGxiYWNrc1tpdGVtXTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGhhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2ldLl9ncm91cE5hbWUgPT09IGdyb3VwTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKCdyZW1vdmluZycpO1xuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXQgYW5kIHNob3J0ZW4gdGhlIGFycmF5IHdlJ3JlIGxvb3BpbmcgdGhyb3VnaFxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgICAgICAgICAgbGVuLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvLyBSZW1vdmUgdGhlIGdpdmVuIGNhbGxiYWNrIGZvciBgZXZlbnRgIG9yIGFsbFxuICAgIC8vIHJlZ2lzdGVyZWQgY2FsbGJhY2tzLlxuICAgIHByb3RvdHlwZS5vZmYgPSBmdW5jdGlvbiAoZXZlbnQsIGZuKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XG4gICAgICAgIHZhciBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm4gdGhpcztcblxuICAgICAgICAvLyByZW1vdmUgYWxsIGhhbmRsZXJzXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZW1vdmUgc3BlY2lmaWMgaGFuZGxlclxuICAgICAgICBpID0gY2FsbGJhY2tzLmluZGV4T2YoZm4pO1xuICAgICAgICBpZiAoaSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2tzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8vLyBFbWl0IGBldmVudGAgd2l0aCB0aGUgZ2l2ZW4gYXJncy5cbiAgICAvLyBhbHNvIGNhbGxzIGFueSBgKmAgaGFuZGxlcnNcbiAgICBwcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgICAgIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcbiAgICAgICAgICAgIHNwZWNpYWxDYWxsYmFja3MgPSB0aGlzLmdldFdpbGRjYXJkQ2FsbGJhY2tzKGV2ZW50KSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBsZW4sXG4gICAgICAgICAgICBpdGVtLFxuICAgICAgICAgICAgbGlzdGVuZXJzO1xuXG4gICAgICAgIGlmIChjYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGNhbGxiYWNrcy5zbGljZSgpO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzcGVjaWFsQ2FsbGJhY2tzKSB7XG4gICAgICAgICAgICBsZW4gPSBzcGVjaWFsQ2FsbGJhY2tzLmxlbmd0aDtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IHNwZWNpYWxDYWxsYmFja3Muc2xpY2UoKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgW2V2ZW50XS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8vIEhlbHBlciBmb3IgZm9yIGZpbmRpbmcgc3BlY2lhbCB3aWxkY2FyZCBldmVudCBoYW5kbGVycyB0aGF0IG1hdGNoIHRoZSBldmVudFxuICAgIHByb3RvdHlwZS5nZXRXaWxkY2FyZENhbGxiYWNrcyA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcbiAgICAgICAgdmFyIGl0ZW0sXG4gICAgICAgICAgICBzcGxpdCxcbiAgICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICAgIGZvciAoaXRlbSBpbiB0aGlzLmNhbGxiYWNrcykge1xuICAgICAgICAgICAgc3BsaXQgPSBpdGVtLnNwbGl0KCcqJyk7XG4gICAgICAgICAgICBpZiAoaXRlbSA9PT0gJyonIHx8IChzcGxpdC5sZW5ndGggPT09IDIgJiYgZXZlbnROYW1lLnNsaWNlKDAsIHNwbGl0WzBdLmxlbmd0aCkgPT09IHNwbGl0WzBdKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5jb25jYXQodGhpcy5jYWxsYmFja3NbaXRlbV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxufTtcblxuV2lsZEVtaXR0ZXIubWl4aW4oV2lsZEVtaXR0ZXIpO1xuIiwiLyohXG4gKiBFdmVudEVtaXR0ZXIgdjUuMi42IC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHBzOi8vb2xpLm1lLnVrL1xuICogQHByZXNlcnZlXG4gKi9cblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qKlxuICAgICAqIENsYXNzIGZvciBtYW5hZ2luZyBldmVudHMuXG4gICAgICogQ2FuIGJlIGV4dGVuZGVkIHRvIHByb3ZpZGUgZXZlbnQgZnVuY3Rpb25hbGl0eSBpbiBvdGhlciBjbGFzc2VzLlxuICAgICAqXG4gICAgICogQGNsYXNzIEV2ZW50RW1pdHRlciBNYW5hZ2VzIGV2ZW50IHJlZ2lzdGVyaW5nIGFuZCBlbWl0dGluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7fVxuXG4gICAgLy8gU2hvcnRjdXRzIHRvIGltcHJvdmUgc3BlZWQgYW5kIHNpemVcbiAgICB2YXIgcHJvdG8gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlO1xuICAgIHZhciBvcmlnaW5hbEdsb2JhbFZhbHVlID0gZXhwb3J0cy5FdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQgaW4gaXRzIHN0b3JhZ2UgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IGxpc3RlbmVycyBBcnJheSBvZiBsaXN0ZW5lcnMgdG8gc2VhcmNoIHRocm91Z2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGxvb2sgZm9yLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gSW5kZXggb2YgdGhlIHNwZWNpZmllZCBsaXN0ZW5lciwgLTEgaWYgbm90IGZvdW5kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVycywgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIGEgbWV0aG9kIHdoaWxlIGtlZXBpbmcgdGhlIGNvbnRleHQgY29ycmVjdCwgdG8gYWxsb3cgZm9yIG92ZXJ3cml0aW5nIG9mIHRhcmdldCBtZXRob2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGFsaWFzZWQgbWV0aG9kXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxpYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gYWxpYXNDbG9zdXJlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbbmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaWxsIGluaXRpYWxpc2UgdGhlIGV2ZW50IG9iamVjdCBhbmQgbGlzdGVuZXIgYXJyYXlzIGlmIHJlcXVpcmVkLlxuICAgICAqIFdpbGwgcmV0dXJuIGFuIG9iamVjdCBpZiB5b3UgdXNlIGEgcmVnZXggc2VhcmNoLiBUaGUgb2JqZWN0IGNvbnRhaW5zIGtleXMgZm9yIGVhY2ggbWF0Y2hlZCBldmVudC4gU28gL2JhW3J6XS8gbWlnaHQgcmV0dXJuIGFuIG9iamVjdCBjb250YWluaW5nIGJhciBhbmQgYmF6LiBCdXQgb25seSBpZiB5b3UgaGF2ZSBlaXRoZXIgZGVmaW5lZCB0aGVtIHdpdGggZGVmaW5lRXZlbnQgb3IgYWRkZWQgc29tZSBsaXN0ZW5lcnMgdG8gdGhlbS5cbiAgICAgKiBFYWNoIHByb3BlcnR5IGluIHRoZSBvYmplY3QgcmVzcG9uc2UgaXMgYW4gYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfE9iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgdGhlIGV2ZW50LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldExpc3RlbmVycyhldnQpIHtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmV0dXJuIGEgY29uY2F0ZW5hdGVkIGFycmF5IG9mIGFsbCBtYXRjaGluZyBldmVudHMgaWZcbiAgICAgICAgLy8gdGhlIHNlbGVjdG9yIGlzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAgICBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2Vba2V5XSA9IGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0gZXZlbnRzW2V2dF0gfHwgKGV2ZW50c1tldnRdID0gW10pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgbGlzdGVuZXIgb2JqZWN0cyBhbmQgZmxhdHRlbnMgaXQgaW50byBhIGxpc3Qgb2YgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3RbXX0gbGlzdGVuZXJzIFJhdyBsaXN0ZW5lciBvYmplY3RzLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW119IEp1c3QgdGhlIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90by5mbGF0dGVuTGlzdGVuZXJzID0gZnVuY3Rpb24gZmxhdHRlbkxpc3RlbmVycyhsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGZsYXRMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgZmxhdExpc3RlbmVycy5wdXNoKGxpc3RlbmVyc1tpXS5saXN0ZW5lcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmxhdExpc3RlbmVycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgcmVxdWVzdGVkIGxpc3RlbmVycyB2aWEgZ2V0TGlzdGVuZXJzIGJ1dCB3aWxsIGFsd2F5cyByZXR1cm4gdGhlIHJlc3VsdHMgaW5zaWRlIGFuIG9iamVjdC4gVGhpcyBpcyBtYWlubHkgZm9yIGludGVybmFsIHVzZSBidXQgb3RoZXJzIG1heSBmaW5kIGl0IHVzZWZ1bC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciBhbiBldmVudCBpbiBhbiBvYmplY3QuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzQXNPYmplY3QgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnNBc09iamVjdChldnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBpZiAobGlzdGVuZXJzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICByZXNwb25zZVtldnRdID0gbGlzdGVuZXJzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlIHx8IGxpc3RlbmVycztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaXNWYWxpZExpc3RlbmVyIChsaXN0ZW5lcikge1xuICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyID09PSAnZnVuY3Rpb24nIHx8IGxpc3RlbmVyIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIubGlzdGVuZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiB0byB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBhZGRlZCBpZiBpdCBpcyBhIGR1cGxpY2F0ZS5cbiAgICAgKiBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGl0IGlzIGNhbGxlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSB0aGVuIHRoZSBsaXN0ZW5lciB3aWxsIGJlIGFkZGVkIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBhZGQgdGhlIGFycmF5IG9mIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICogWWVhaCwgdGhpcyBmdW5jdGlvbiBkb2VzIHF1aXRlIGEgYml0LiBUaGF0J3MgcHJvYmFibHkgYSBiYWQgdGhpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyhmYWxzZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBjYW4gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byByZW1vdmUgdGhlIGxpc3RlbmVycyBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byByZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnModHJ1ZSwgZXZ0LCBsaXN0ZW5lcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBFZGl0cyBsaXN0ZW5lcnMgaW4gYnVsay4gVGhlIGFkZExpc3RlbmVycyBhbmQgcmVtb3ZlTGlzdGVuZXJzIG1ldGhvZHMgYm90aCB1c2UgdGhpcyB0byBkbyB0aGVpciBqb2IuIFlvdSBzaG91bGQgcmVhbGx5IHVzZSB0aG9zZSBpbnN0ZWFkLCB0aGlzIGlzIGEgbGl0dGxlIGxvd2VyIGxldmVsLlxuICAgICAqIFRoZSBmaXJzdCBhcmd1bWVudCB3aWxsIGRldGVybWluZSBpZiB0aGUgbGlzdGVuZXJzIGFyZSByZW1vdmVkICh0cnVlKSBvciBhZGRlZCAoZmFsc2UpLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50IHlvdSBjYW4gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkL3JlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gbWFuaXB1bGF0ZSB0aGUgbGlzdGVuZXJzIG9mIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVtb3ZlIFRydWUgaWYgeW91IHdhbnQgdG8gcmVtb3ZlIGxpc3RlbmVycywgZmFsc2UgaWYgeW91IHdhbnQgdG8gYWRkLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkL3JlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5tYW5pcHVsYXRlTGlzdGVuZXJzID0gZnVuY3Rpb24gbWFuaXB1bGF0ZUxpc3RlbmVycyhyZW1vdmUsIGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIHZhciBzaW5nbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVyIDogdGhpcy5hZGRMaXN0ZW5lcjtcbiAgICAgICAgdmFyIG11bHRpcGxlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lcnMgOiB0aGlzLmFkZExpc3RlbmVycztcblxuICAgICAgICAvLyBJZiBldnQgaXMgYW4gb2JqZWN0IHRoZW4gcGFzcyBlYWNoIG9mIGl0cyBwcm9wZXJ0aWVzIHRvIHRoaXMgbWV0aG9kXG4gICAgICAgIGlmICh0eXBlb2YgZXZ0ID09PSAnb2JqZWN0JyAmJiAhKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIGZvciAoaSBpbiBldnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZ0Lmhhc093blByb3BlcnR5KGkpICYmICh2YWx1ZSA9IGV2dFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGFzcyB0aGUgc2luZ2xlIGxpc3RlbmVyIHN0cmFpZ2h0IHRocm91Z2ggdG8gdGhlIHNpbmd1bGFyIG1ldGhvZFxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgcGFzcyBiYWNrIHRvIHRoZSBtdWx0aXBsZSBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGUuY2FsbCh0aGlzLCBpLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTbyBldnQgbXVzdCBiZSBhIHN0cmluZ1xuICAgICAgICAgICAgLy8gQW5kIGxpc3RlbmVycyBtdXN0IGJlIGFuIGFycmF5IG9mIGxpc3RlbmVyc1xuICAgICAgICAgICAgLy8gTG9vcCBvdmVyIGl0IGFuZCBwYXNzIGVhY2ggb25lIHRvIHRoZSBtdWx0aXBsZSBtZXRob2RcbiAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGV2dCwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgZnJvbSBhIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYW4gZXZlbnQgdGhlbiBhbGwgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAgICAgKiBUaGF0IG1lYW5zIGV2ZXJ5IGV2ZW50IHdpbGwgYmUgZW1wdGllZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ2V4IHRvIHJlbW92ZSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IFtldnRdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvci4gV2lsbCByZW1vdmUgZnJvbSBldmVyeSBldmVudCBpZiBub3QgcGFzc2VkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gcmVtb3ZlRXZlbnQoZXZ0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGV2dDtcbiAgICAgICAgdmFyIGV2ZW50cyA9IHRoaXMuX2dldEV2ZW50cygpO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJlbW92ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiB0aGUgc3RhdGUgb2YgZXZ0XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnRcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbZXZ0XTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgZXZlbnRzIG1hdGNoaW5nIHRoZSByZWdleC5cbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBpbiBhbGwgZXZlbnRzXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUV2ZW50LlxuICAgICAqXG4gICAgICogQWRkZWQgdG8gbWlycm9yIHRoZSBub2RlIEFQSS5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBhbGlhcygncmVtb3ZlRXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGFuIGV2ZW50IG9mIHlvdXIgY2hvaWNlLlxuICAgICAqIFdoZW4gZW1pdHRlZCwgZXZlcnkgbGlzdGVuZXIgYXR0YWNoZWQgdG8gdGhhdCBldmVudCB3aWxsIGJlIGV4ZWN1dGVkLlxuICAgICAqIElmIHlvdSBwYXNzIHRoZSBvcHRpb25hbCBhcmd1bWVudCBhcnJheSB0aGVuIHRob3NlIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBldmVyeSBsaXN0ZW5lciB1cG9uIGV4ZWN1dGlvbi5cbiAgICAgKiBCZWNhdXNlIGl0IHVzZXMgYGFwcGx5YCwgeW91ciBhcnJheSBvZiBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgYXMgaWYgeW91IHdyb3RlIHRoZW0gb3V0IHNlcGFyYXRlbHkuXG4gICAgICogU28gdGhleSB3aWxsIG5vdCBhcnJpdmUgd2l0aGluIHRoZSBhcnJheSBvbiB0aGUgb3RoZXIgc2lkZSwgdGhleSB3aWxsIGJlIHNlcGFyYXRlLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFthcmdzXSBPcHRpb25hbCBhcnJheSBvZiBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24gZW1pdEV2ZW50KGV2dCwgYXJncykge1xuICAgICAgICB2YXIgbGlzdGVuZXJzTWFwID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXI7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzTWFwKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzTWFwLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnNNYXBba2V5XS5zbGljZSgwKTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHNoYWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGlzIGV4ZWN1dGVkIGVpdGhlciB3aXRoIGEgYmFzaWMgY2FsbCBvciBhbiBhcHBseSBpZiB0aGVyZSBpcyBhbiBhcmdzIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lci5vbmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBsaXN0ZW5lci5saXN0ZW5lci5hcHBseSh0aGlzLCBhcmdzIHx8IFtdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IHRoaXMuX2dldE9uY2VSZXR1cm5WYWx1ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIubGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGVtaXRFdmVudFxuICAgICAqL1xuICAgIHByb3RvLnRyaWdnZXIgPSBhbGlhcygnZW1pdEV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0bHkgZGlmZmVyZW50IGZyb20gZW1pdEV2ZW50IGluIHRoYXQgaXQgd2lsbCBwYXNzIGl0cyBhcmd1bWVudHMgb24gdG8gdGhlIGxpc3RlbmVycywgYXMgb3Bwb3NlZCB0byB0YWtpbmcgYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3Mgb24uXG4gICAgICogQXMgd2l0aCBlbWl0RXZlbnQsIHlvdSBjYW4gcGFzcyBhIHJlZ2V4IGluIHBsYWNlIG9mIHRoZSBldmVudCBuYW1lIHRvIGVtaXQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdCBhbmQgZXhlY3V0ZSBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gT3B0aW9uYWwgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gYmUgcGFzc2VkIHRvIGVhY2ggbGlzdGVuZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW1pdEV2ZW50KGV2dCwgYXJncyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmIGFcbiAgICAgKiBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhlIG9uZSBzZXQgaGVyZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZFxuICAgICAqIGFmdGVyIGV4ZWN1dGlvbi4gVGhpcyB2YWx1ZSBkZWZhdWx0cyB0byB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbmV3IHZhbHVlIHRvIGNoZWNrIGZvciB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uc2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gc2V0T25jZVJldHVyblZhbHVlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX29uY2VSZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWZcbiAgICAgKiB0aGUgbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoaXMgb25lIHRoZW4gaXQgc2hvdWxkIGJlIHJlbW92ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5LiBJdCB3aWxsIHJldHVybiB0cnVlIGJ5IGRlZmF1bHQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfEJvb2xlYW59IFRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGZvciBvciB0aGUgZGVmYXVsdCwgdHJ1ZS5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0T25jZVJldHVyblZhbHVlID0gZnVuY3Rpb24gX2dldE9uY2VSZXR1cm5WYWx1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoJ19vbmNlUmV0dXJuVmFsdWUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29uY2VSZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGV2ZW50cyBvYmplY3QgYW5kIGNyZWF0ZXMgb25lIGlmIHJlcXVpcmVkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZXZlbnRzIHN0b3JhZ2Ugb2JqZWN0LlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRFdmVudHMgPSBmdW5jdGlvbiBfZ2V0RXZlbnRzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRzIHx8ICh0aGlzLl9ldmVudHMgPSB7fSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJldmVydHMgdGhlIGdsb2JhbCB7QGxpbmsgRXZlbnRFbWl0dGVyfSB0byBpdHMgcHJldmlvdXMgdmFsdWUgYW5kIHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhpcyB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IE5vbiBjb25mbGljdGluZyBFdmVudEVtaXR0ZXIgY2xhc3MuXG4gICAgICovXG4gICAgRXZlbnRFbWl0dGVyLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IG9yaWdpbmFsR2xvYmFsVmFsdWU7XG4gICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgfTtcblxuICAgIC8vIEV4cG9zZSB0aGUgY2xhc3MgZWl0aGVyIHZpYSBBTUQsIENvbW1vbkpTIG9yIHRoZSBnbG9iYWwgb2JqZWN0XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKXtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBleHBvcnRzLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG59KHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdGhpcyB8fCB7fSkpO1xuIiwibW9kdWxlLmV4cG9ydHM9e1xuICAgIFwiYXV0aG9yXCI6IFwiT3BlblZpZHVcIixcbiAgICBcImRlcGVuZGVuY2llc1wiOiB7XG4gICAgICAgIFwiQHR5cGVzL25vZGVcIjogXCIxMi42LjhcIixcbiAgICAgICAgXCJAdHlwZXMvcGxhdGZvcm1cIjogXCIxLjMuMlwiLFxuICAgICAgICBcImZyZWVpY2VcIjogXCIyLjIuMlwiLFxuICAgICAgICBcImhhcmtcIjogXCIxLjIuM1wiLFxuICAgICAgICBcInBsYXRmb3JtXCI6IFwiMS4zLjVcIixcbiAgICAgICAgXCJ1dWlkXCI6IFwiMy4zLjJcIixcbiAgICAgICAgXCJ3b2xmeTg3LWV2ZW50ZW1pdHRlclwiOiBcIjUuMi42XCJcbiAgICB9LFxuICAgIFwiZGVzY3JpcHRpb25cIjogXCJPcGVuVmlkdSBCcm93c2VyXCIsXG4gICAgXCJkZXZEZXBlbmRlbmNpZXNcIjoge1xuICAgICAgICBcImJyb3dzZXJpZnlcIjogXCIxNi4zLjBcIixcbiAgICAgICAgXCJncnVudFwiOiBcIjEuMC40XCIsXG4gICAgICAgIFwiZ3J1bnQtYXV0b3ByZWZpeGVyXCI6IFwiMy4wLjRcIixcbiAgICAgICAgXCJncnVudC1jbGlcIjogXCIxLjMuMlwiLFxuICAgICAgICBcImdydW50LWNvbnRyaWItY29weVwiOiBcIjEuMC4wXCIsXG4gICAgICAgIFwiZ3J1bnQtY29udHJpYi1zYXNzXCI6IFwiMS4wLjBcIixcbiAgICAgICAgXCJncnVudC1jb250cmliLXVnbGlmeVwiOiBcIjQuMC4xXCIsXG4gICAgICAgIFwiZ3J1bnQtY29udHJpYi13YXRjaFwiOiBcIjEuMS4wXCIsXG4gICAgICAgIFwiZ3J1bnQtc3RyaW5nLXJlcGxhY2VcIjogXCIxLjMuMVwiLFxuICAgICAgICBcImdydW50LXRzXCI6IFwiNi4wLjAtYmV0YS4yMlwiLFxuICAgICAgICBcInRzaWZ5XCI6IFwiNC4wLjFcIixcbiAgICAgICAgXCJ0c2xpbnRcIjogXCI1LjE4LjBcIixcbiAgICAgICAgXCJ0eXBlZG9jXCI6IFwiMC4xNS4wXCIsXG4gICAgICAgIFwidHlwZXNjcmlwdFwiOiBcIjMuNS4zXCIsXG4gICAgICAgIFwidWdsaWZ5LWpzXCI6IFwiMy42LjBcIlxuICAgIH0sXG4gICAgXCJsaWNlbnNlXCI6IFwiQXBhY2hlLTIuMFwiLFxuICAgIFwibWFpblwiOiBcImxpYi9pbmRleC5qc1wiLFxuICAgIFwibmFtZVwiOiBcIm9wZW52aWR1LWJyb3dzZXJcIixcbiAgICBcInJlcG9zaXRvcnlcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJnaXRcIixcbiAgICAgICAgXCJ1cmxcIjogXCJnaXQ6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1XCJcbiAgICB9LFxuICAgIFwic2NyaXB0c1wiOiB7XG4gICAgICAgIFwiYnJvd3NlcmlmeVwiOiBcIlZFUlNJT049JHtWRVJTSU9OOi19OyBjZCBzcmMgJiYgLi4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvYmluL2NtZC5qcyBNYWluLnRzIC1wIFsgdHNpZnkgXSAtLWV4Y2x1ZGUga3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMgLS1kZWJ1ZyAtbyAuLi9zdGF0aWMvanMvb3BlbnZpZHUtYnJvd3Nlci0kVkVSU0lPTi5qcyAtdlwiLFxuICAgICAgICBcImJyb3dzZXJpZnktcHJvZFwiOiBcIlZFUlNJT049JHtWRVJTSU9OOi19OyBjZCBzcmMgJiYgLi4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvYmluL2NtZC5qcyAtLWRlYnVnIE1haW4udHMgLXAgWyB0c2lmeSBdIC0tZXhjbHVkZSBrdXJlbnRvLWJyb3dzZXItZXh0ZW5zaW9ucyB8IC4uL25vZGVfbW9kdWxlcy91Z2xpZnktanMvYmluL3VnbGlmeWpzIC0tc291cmNlLW1hcCBjb250ZW50PWlubGluZSAtLW91dHB1dCAuLi9zdGF0aWMvanMvb3BlbnZpZHUtYnJvd3Nlci0kVkVSU0lPTi5taW4uanNcIixcbiAgICAgICAgXCJidWlsZFwiOiBcImNkIHNyYy9PcGVuVmlkdSAmJiAuLy4uLy4uL25vZGVfbW9kdWxlcy90eXBlc2NyaXB0L2Jpbi90c2MgJiYgY2QgLi4vLi4gJiYgLi9ub2RlX21vZHVsZXMvdHlwZXNjcmlwdC9iaW4vdHNjIC0tZGVjbGFyYXRpb24gc3JjL2luZGV4LnRzIC0tb3V0RGlyIC4vbGliIC0tc291cmNlTWFwIC0tbGliIGRvbSxlczUsZXMyMDE1LnByb21pc2Usc2NyaXB0aG9zdFwiLFxuICAgICAgICBcImRvY3NcIjogXCIuL25vZGVfbW9kdWxlcy90eXBlZG9jL2Jpbi90eXBlZG9jIC0tb3B0aW9ucyAuL2NvbmZpZy90eXBlZG9jLmpzIC0tb3V0IC4vZG9jcyAuL3NyYyAmJiBybSAtcmYgLi4vLi4vb3BlbnZpZHUuaW8vYXBpL29wZW52aWR1LWJyb3dzZXIvKiAmJiBjcCAtUiAuL2RvY3MvLiAuLi8uLi9vcGVudmlkdS5pby9hcGkvb3BlbnZpZHUtYnJvd3NlclwiLFxuICAgICAgICBcInRlc3RcIjogXCJlY2hvIFxcXCJFcnJvcjogbm8gdGVzdCBzcGVjaWZpZWRcXFwiICYmIGV4aXQgMVwiXG4gICAgfSxcbiAgICBcInR5cGVzXCI6IFwibGliL2luZGV4LmQudHNcIixcbiAgICBcInZlcnNpb25cIjogXCIyLjExLjBcIlxufVxuIiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcblxuaWYgKHdpbmRvdykge1xuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0Nvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgU3RyZWFtT3B0aW9uc1NlcnZlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1N0cmVhbU9wdGlvbnNTZXJ2ZXInO1xuXG5cbi8qKlxuICogUmVwcmVzZW50cyBlYWNoIG9uZSBvZiB0aGUgdXNlcidzIGNvbm5lY3Rpb24gdG8gdGhlIHNlc3Npb24gKHRoZSBsb2NhbCBvbmUgYW5kIG90aGVyIHVzZXIncyBjb25uZWN0aW9ucykuXG4gKiBUaGVyZWZvcmUgZWFjaCBbW1Nlc3Npb25dXSBhbmQgW1tTdHJlYW1dXSBvYmplY3QgaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIENvbm5lY3Rpb25cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb24ge1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIGNvbm5lY3Rpb25cbiAgICAgKi9cbiAgICBjb25uZWN0aW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRpbWUgd2hlbiB0aGlzIGNvbm5lY3Rpb24gd2FzIGNyZWF0ZWQgaW4gT3BlblZpZHUgU2VydmVyIChVVEMgbWlsbGlzZWNvbmRzKVxuICAgICAqL1xuICAgIGNyZWF0aW9uVGltZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogRGF0YSBhc3NvY2lhdGVkIHRvIHRoaXMgY29ubmVjdGlvbiAoYW5kIHRoZXJlZm9yZSB0byBjZXJ0YWluIHVzZXIpLiBUaGlzIGlzIGFuIGltcG9ydGFudCBmaWVsZDpcbiAgICAgKiBpdCBhbGxvd3MgeW91IHRvIGJyb2FkY2FzdCBhbGwgdGhlIGluZm9ybWF0aW9uIHlvdSB3YW50IGZvciBlYWNoIHVzZXIgKGEgdXNlcm5hbWUsIGZvciBleGFtcGxlKVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcHRpb25zOiBDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJwY1Nlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgb3B0cz86IENvbm5lY3Rpb25PcHRpb25zKSB7XG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISFvcHRzKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgbXNnICs9IFwiKHJlbW90ZSkgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyBvcHRzLmlkICsgJ10nO1xuICAgICAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cztcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gb3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gb3B0cy5jcmVhdGVkQXQ7XG4gICAgICAgICAgICBpZiAob3B0cy5tZXRhZGF0YSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YSA9IG9wdHMubWV0YWRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0cy5zdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0UmVtb3RlU3RyZWFtcyhvcHRzLnN0cmVhbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBpcyBsb2NhbFxuICAgICAgICAgICAgbXNnICs9ICcobG9jYWwpJztcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmluZm8obXNnKTtcbiAgICB9XG5cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2VuZEljZUNhbmRpZGF0ZShjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZGVidWcoKCEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzID8gJ0xvY2FsJyA6ICdSZW1vdGUnKSArICdjYW5kaWRhdGUgZm9yJyArXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCwgY2FuZGlkYXRlKTtcblxuICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ29uSWNlQ2FuZGlkYXRlJywge1xuICAgICAgICAgICAgZW5kcG9pbnROYW1lOiB0aGlzLmNvbm5lY3Rpb25JZCxcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSxcbiAgICAgICAgICAgIHNkcE1pZDogY2FuZGlkYXRlLnNkcE1pZCxcbiAgICAgICAgICAgIHNkcE1MaW5lSW5kZXg6IGNhbmRpZGF0ZS5zZHBNTGluZUluZGV4XG4gICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJ1xuICAgICAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0UmVtb3RlU3RyZWFtcyhvcHRpb25zOiBTdHJlYW1PcHRpb25zU2VydmVyW10pOiB2b2lkIHtcblxuICAgICAgICAvLyBUaGlzIGlzIHJlYWR5IGZvciBzdXBwb3J0aW5nIG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb24gb2JqZWN0LiBSaWdodCBub3cgdGhlIGxvb3Agd2lsbCBhbHdheXMgcnVuIGp1c3Qgb25jZVxuICAgICAgICAvLyB0aGlzLnN0cmVhbSBzaG91bGQgYWxzbyBiZSByZXBsYWNlZCBieSBhIGNvbGxlY3Rpb24gb2Ygc3RyZWFtcyB0byBzdXBwb3J0IG11bHRpcGxlIHN0cmVhbXMgcGVyIENvbm5lY3Rpb25cbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdHMgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaWQ6IG9wdHMuaWQsXG4gICAgICAgICAgICAgICAgY3JlYXRlZEF0OiBvcHRzLmNyZWF0ZWRBdCxcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uOiB0aGlzLFxuICAgICAgICAgICAgICAgIGhhc0F1ZGlvOiBvcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIGhhc1ZpZGVvOiBvcHRzLmhhc1ZpZGVvLFxuICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiBvcHRzLmF1ZGlvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiBvcHRzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiBvcHRzLnR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgIGZyYW1lUmF0ZTogb3B0cy5mcmFtZVJhdGUsXG4gICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiAhIW9wdHMudmlkZW9EaW1lbnNpb25zID8gSlNPTi5wYXJzZShvcHRzLnZpZGVvRGltZW5zaW9ucykgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgZmlsdGVyOiAhIW9wdHMuZmlsdGVyID8gb3B0cy5maWx0ZXIgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKHRoaXMuc2Vzc2lvbiwgc3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgIHRoaXMuYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnQ29ubmVjdGlvbicgd2l0aCAnY29ubmVjdGlvbklkJyBbXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArICddIGlzIG5vdyBjb25maWd1cmVkIGZvciByZWNlaXZpbmcgU3RyZWFtcyB3aXRoIG9wdGlvbnM6ICcsIHRoaXMuc3RyZWFtLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IEZpbHRlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRmlsdGVyRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuXG5cbi8qKlxuICogKipXQVJOSU5HKio6IGV4cGVyaW1lbnRhbCBvcHRpb24uIFRoaXMgaW50ZXJmYWNlIG1heSBjaGFuZ2UgaW4gdGhlIG5lYXIgZnV0dXJlXG4gKlxuICogVmlkZW8vYXVkaW8gZmlsdGVyIGFwcGxpZWQgdG8gYSBTdHJlYW0uIFNlZSBbW1N0cmVhbS5hcHBseUZpbHRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXIge1xuXG4gICAgLyoqXG4gICAgICogVHlwZSBvZiBmaWx0ZXIgYXBwbGllZC4gVGhpcyBpcyB0aGUgbmFtZSBvZiB0aGUgcmVtb3RlIGNsYXNzIGlkZW50aWZ5aW5nIHRoZSBmaWx0ZXIgdG8gYXBwbHkgaW4gS3VyZW50byBNZWRpYSBTZXJ2ZXIuXG4gICAgICogRm9yIGV4YW1wbGU6IGBcIkZhY2VPdmVybGF5RmlsdGVyXCJgLCBgXCJHU3RyZWFtZXJGaWx0ZXJcImAuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIGdldCB0aGlzIHByb3BlcnR5IGluIGAqLmttZC5qc29uYCBmaWxlcyBkZWZpbmluZyB0aGUgS3VyZW50byBmaWx0ZXJzLiBGb3IgZXhhbXBsZSwgZm9yIEdTdHJlYW1lckZpbHRlciB0aGF0J3NcbiAgICAgKiBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL0t1cmVudG8va21zLWZpbHRlcnMvYmxvYi81M2E0NTJmYWM3MWQ2MTc5NTk1MmUzZDIyMDIxNTZjNmIwMGY2ZDY1L3NyYy9zZXJ2ZXIvaW50ZXJmYWNlL2ZpbHRlcnMuR1N0cmVhbWVyRmlsdGVyLmttZC5qc29uI0w0KVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFBhcmFtZXRlcnMgdXNlZCB0byBpbml0aWFsaXplIHRoZSBmaWx0ZXIuXG4gICAgICogVGhlc2UgY29ycmVzcG9uZCB0byB0aGUgY29uc3RydWN0b3IgcGFyYW1ldGVycyB1c2VkIGluIHRoZSBmaWx0ZXIgaW4gS3VyZW50byBNZWRpYSBTZXJ2ZXIgKGV4Y2VwdCBmb3IgYG1lZGlhUGlwZWxpbmVgIHBhcmFtZXRlciwgd2hpY2ggaXMgbmV2ZXIgbmVlZGVkKS5cbiAgICAgKlxuICAgICAqIEZvciBleGFtcGxlOiBmb3IgYGZpbHRlci50eXBlID0gXCJHU3RyZWFtZXJGaWx0ZXJcImAgY291bGQgYmUgYGZpbHRlci5vcHRpb25zID0ge1wiY29tbWFuZFwiOiBcInZpZGVvYmFsYW5jZSBzYXR1cmF0aW9uPTAuMFwifWBcbiAgICAgKlxuICAgICAqIFlvdSBjYW4gZ2V0IHRoaXMgcHJvcGVydHkgaW4gYCoua21kLmpzb25gIGZpbGVzIGRlZmluaW5nIHRoZSBLdXJlbnRvIGZpbHRlcnMuIEZvciBleGFtcGxlLCBmb3IgR1N0cmVhbWVyRmlsdGVyIHRoYXQnc1xuICAgICAqIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vS3VyZW50by9rbXMtZmlsdGVycy9ibG9iLzUzYTQ1MmZhYzcxZDYxNzk1OTUyZTNkMjIwMjE1NmM2YjAwZjZkNjUvc3JjL3NlcnZlci9pbnRlcmZhY2UvZmlsdGVycy5HU3RyZWFtZXJGaWx0ZXIua21kLmpzb24jTDEzLUwzMSlcbiAgICAgKi9cbiAgICBvcHRpb25zOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBWYWx1ZSBwYXNzZWQgdGhlIGxhc3QgdGltZSBbW0ZpbHRlci5leGVjTWV0aG9kXV0gd2FzIGNhbGxlZC4gSWYgYHVuZGVmaW5lZGAgdGhpcyBtZXRob2QgaGFzIG5vdCBiZWVuIGNhbGxlZCB5ZXQuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIHVzZSB0aGlzIHZhbHVlIHRvIGtub3cgdGhlIGN1cnJlbnQgc3RhdHVzIG9mIGFueSBhcHBsaWVkIGZpbHRlclxuICAgICAqL1xuICAgIGxhc3RFeGVjTWV0aG9kPzoge1xuICAgICAgICBtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBPYmplY3RcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhbmRsZXJzOiBPYmpNYXA8KGV2ZW50OiBGaWx0ZXJFdmVudCkgPT4gdm9pZD4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHR5cGU6IHN0cmluZywgb3B0aW9uczogT2JqZWN0KSB7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyBhIGZpbHRlciBtZXRob2QuIEF2YWlsYWJsZSBtZXRob2RzIGFyZSBzcGVjaWZpYyBmb3IgZWFjaCBmaWx0ZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSBtZXRob2QgTmFtZSBvZiB0aGUgbWV0aG9kXG4gICAgICogQHBhcmFtIHBhcmFtcyBQYXJhbWV0ZXJzIG9mIHRoZSBtZXRob2RcbiAgICAgKi9cbiAgICBleGVjTWV0aG9kKG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IE9iamVjdCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmluZm8oJ0V4ZWN1dGluZyBmaWx0ZXIgbWV0aG9kIHRvIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgbGV0IHN0cmluZ1BhcmFtcztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyYW1zICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmluZ1BhcmFtcyA9IEpTT04uc3RyaW5naWZ5KHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JNc2cgPSBcIidwYXJhbXMnIHByb3BlcnR5IG11c3QgYmUgYSBKU09OIGZvcm1hdHRlZCBvYmplY3RcIjtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvck1zZyk7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvck1zZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdHJpbmdQYXJhbXMgPSA8c3RyaW5nPnBhcmFtcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2V4ZWNGaWx0ZXJNZXRob2QnLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBtZXRob2QsIHBhcmFtczogc3RyaW5nUGFyYW1zIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGV4ZWN1dGluZyBmaWx0ZXIgbWV0aG9kIGZvciBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGV4ZWN1dGUgYSBmaWx0ZXIgbWV0aG9kXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRmlsdGVyIG1ldGhvZCBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQgb24gU3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9ICg8YW55Pk9iamVjdCkuYXNzaWduKHt9LCB0aGlzLnN0cmVhbS5maWx0ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZmlsdGVyLmxhc3RFeGVjTWV0aG9kID0geyBtZXRob2QsIHBhcmFtczogSlNPTi5wYXJzZShzdHJpbmdQYXJhbXMpIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnN0cmVhbS5zZXNzaW9uLCB0aGlzLnN0cmVhbSwgJ2ZpbHRlcicsIHRoaXMuc3RyZWFtLmZpbHRlciwgb2xkVmFsdWUsICdleGVjRmlsdGVyTWV0aG9kJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIsIHRoaXMuc3RyZWFtLCAnZmlsdGVyJywgdGhpcy5zdHJlYW0uZmlsdGVyLCBvbGRWYWx1ZSwgJ2V4ZWNGaWx0ZXJNZXRob2QnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgdG8gY2VydGFpbiBmaWx0ZXIgZXZlbnQuIEF2YWlsYWJsZSBldmVudHMgYXJlIHNwZWNpZmljIGZvciBlYWNoIGZpbHRlclxuICAgICAqXG4gICAgICogQHBhcmFtIGV2ZW50VHlwZSBFdmVudCB0byB3aGljaCBzdWJzY3JpYmUgdG8uXG4gICAgICogQHBhcmFtIGhhbmRsZXIgRnVuY3Rpb24gdG8gZXhlY3V0ZSB1cG9uIGV2ZW50IGRpc3BhdGNoZWQuIEl0IHJlY2VpdmVzIGFzIHBhcmFtZXRlciBhIFtbRmlsdGVyRXZlbnRdXSBvYmplY3RcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgZXZlbnQgbGlzdGVuZXIgd2FzIHN1Y2Nlc3NmdWxseSBhdHRhY2hlZCB0byB0aGUgZmlsdGVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBhZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEZpbHRlckV2ZW50KSA9PiB2b2lkKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnQWRkaW5nIGZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJyB0byBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2FkZEZpbHRlckV2ZW50TGlzdGVuZXInLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBldmVudFR5cGUgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgYWRkaW5nIGZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJ2ZvciBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGFkZCBhIGZpbHRlciBldmVudCBsaXN0ZW5lclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZXJzW2V2ZW50VHlwZV0gPSBoYW5kbGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICcgc3VjY2Vzc2Z1bGx5IGFwcGxpZWQgb24gU3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgY2VydGFpbiBmaWx0ZXIgZXZlbnQgbGlzdGVuZXIgcHJldmlvdXNseSBzZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnRUeXBlIEV2ZW50IHRvIHVuc3Vic2NyaWJlIGZyb20uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIGV2ZW50IGxpc3RlbmVyIHdhcyBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBmcm9tIHRoZSBmaWx0ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGluIG90aGVyIGNhc2VcbiAgICAgKi9cbiAgICByZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VHlwZTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnUmVtb3ZpbmcgZmlsdGVyIGV2ZW50IGxpc3RlbmVyIHRvIGV2ZW50ICcgKyBldmVudFR5cGUgKyAnIHRvIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAncmVtb3ZlRmlsdGVyRXZlbnRMaXN0ZW5lcicsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsIGV2ZW50VHlwZSB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciByZW1vdmluZyBmaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICdmb3IgU3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBhZGQgYSBmaWx0ZXIgZXZlbnQgbGlzdGVuZXJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuaGFuZGxlcnNbZXZlbnRUeXBlXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRmlsdGVyIGV2ZW50IGxpc3RlbmVyIHRvIGV2ZW50ICcgKyBldmVudFR5cGUgKyAnIHN1Y2Nlc3NmdWxseSByZW1vdmVkIG9uIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyU3RhdGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL0xvY2FsUmVjb3JkZXJTdGF0ZSc7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklOR1M6XG4gKiAtIFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKiAtIE9ubHkgQ2hyb21lIGFuZCBGaXJlZm94IHN1cHBvcnQgbG9jYWwgc3RyZWFtIHJlY29yZGluZ1xuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I6IEJsb2I7XG4gICAgcHJpdmF0ZSBpZDogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3U3JjOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXc6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzdHJlYW06IFN0cmVhbSkge1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBsb2NhbCByZWNvcmRpbmcgb2Ygc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgXCInIG9mIGNvbm5lY3Rpb24gJ1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyBcIidcIik7XG5cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA5JyB9O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKCd2aWRlby93ZWJtO2NvZGVjcz1oMjY0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9aDI2NCcgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCgndmlkZW8vd2VibTtjb2RlY3M9dnA4JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibTtjb2RlY3M9dnA4JyB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdVc2luZyBtaW1lVHlwZSAnICsgb3B0aW9ucy5taW1lVHlwZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignaXNUeXBlU3VwcG9ydGVkIGlzIG5vdCBzdXBwb3J0ZWQsIHVzaW5nIGRlZmF1bHQgY29kZWNzIGZvciBicm93c2VyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBzdGFydGVkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0b3AgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25wYXVzZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ud2FybmluZyA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgd2FybmluZzogJyArIGUpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFbmRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2Agb3IgYFBBVVNFRGAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYEZJTklTSEVEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdG9wcGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBzdG9wKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkgfHwgdGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQ09SRElOR1xcJyBvciBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN0b3BEZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBQQVVTRURgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSBwYXVzZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHBhdXNlKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZXN1bWUoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdQQVVTRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5wYXVzZSgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lID09PSAnU2FmYXJpJykge1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICd0cnVlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKCdcXCdMb2NhbFJlY29yZC51cGxvYWRBc0JpbmFyeSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNNdWx0aXBhcnRmaWxlKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBodHRwID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgZW5kcG9pbnQsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBoZWFkZXJzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRhYmxlID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgICAgICAgc2VuZGFibGUuYXBwZW5kKCdmaWxlJywgdGhpcy5ibG9iLCB0aGlzLmlkICsgJy53ZWJtJyk7XG5cbiAgICAgICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGh0dHAuc3RhdHVzLnRvU3RyaW5nKCkuY2hhckF0KDApID09PSAnMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWNjZXNzIHJlc3BvbnNlIGZyb20gc2VydmVyIChIVFRQIHN0YXR1cyBzdGFuZGFyZDogMlhYIGlzIHN1Y2Nlc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaHR0cC5zZW5kKHNlbmRhYmxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgb25TdG9wRGVmYXVsdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6ICd2aWRlby93ZWJtJyB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xucGxhdGZvcm1bJ2lzSW9uaWNJb3MnXSA9IChwbGF0Zm9ybS5wcm9kdWN0ID09PSAnaVBob25lJyB8fCBwbGF0Zm9ybS5wcm9kdWN0ID09PSAnaVBhZCcpICYmIHBsYXRmb3JtLnVhISEuaW5kZXhPZignU2FmYXJpJykgPT09IC0xO1xucGxhdGZvcm1bJ2lzSW9uaWNBbmRyb2lkJ10gPSBwbGF0Zm9ybS5vcyEhLmZhbWlseSA9PT0gJ0FuZHJvaWQnICYmIHBsYXRmb3JtLm5hbWUgPT0gXCJBbmRyb2lkIEJyb3dzZXJcIjtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IHBhY2thZ2VKc29uID0gcmVxdWlyZSgnLi4vLi4vcGFja2FnZS5qc29uJyk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgY29yZG92YTogYW55O1xuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBodHRwVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkdmFuY2VkQ29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gPSB7fTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdlYnJ0Y1N0YXRzSW50ZXJ2YWw6IG51bWJlciA9IDA7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBsaWJyYXJ5VmVyc2lvbjogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKClcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmxpYnJhcnlWZXJzaW9uID0gcGFja2FnZUpzb24udmVyc2lvbjtcblxuICAgIGNvbnNvbGUuaW5mbyhcIidPcGVuVmlkdScgaW5pdGlhbGl6ZWRcIik7XG4gICAgY29uc29sZS5pbmZvKFwib3BlbnZpZHUtYnJvd3NlciB2ZXJzaW9uOiBcIiArIHRoaXMubGlicmFyeVZlcnNpb24pO1xuXG4gICAgaWYgKHBsYXRmb3JtLm9zISEuZmFtaWx5ID09PSAnaU9TJyB8fCBwbGF0Zm9ybS5vcyEhLmZhbWlseSA9PT0gJ0FuZHJvaWQnKSB7XG4gICAgICAvLyBMaXN0ZW4gdG8gb3JpZW50YXRpb25jaGFuZ2Ugb25seSBvbiBtb2JpbGUgZGV2aWNlc1xuICAgICAgKDxhbnk+d2luZG93KS5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsICgpID0+IHtcbiAgICAgICAgdGhpcy5wdWJsaXNoZXJzLmZvckVhY2gocHVibGlzaGVyID0+IHtcbiAgICAgICAgICBpZiAocHVibGlzaGVyLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkICYmICEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8gJiYgISFwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdKSB7XG5cbiAgICAgICAgICAgIGxldCBhdHRlbXB0cyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IG9sZFdpZHRoID0gcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG5cbiAgICAgICAgICAgIGNvbnN0IGdldE5ld1ZpZGVvRGltZW5zaW9ucyA9ICgpOiBQcm9taXNlPHsgbmV3V2lkdGg6IG51bWJlciwgbmV3SGVpZ2h0OiBudW1iZXIgfT4gPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChwbGF0Zm9ybVsnaXNJb25pY0lvcyddKSB7XG4gICAgICAgICAgICAgICAgICAvLyBpT1MgSW9uaWMuIExpbWl0YXRpb246IG11c3QgZ2V0IG5ldyBkaW1lbnNpb25zIGZyb20gYW4gZXhpc3RpbmcgdmlkZW8gZWxlbWVudCBhbHJlYWR5IGluc2VydGVkIGludG8gRE9NXG4gICAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgbmV3V2lkdGg6IHB1Ymxpc2hlci5zdHJlYW0uc3RyZWFtTWFuYWdlci52aWRlb3NbMF0udmlkZW8udmlkZW9XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0OiBwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIudmlkZW9zWzBdLnZpZGVvLnZpZGVvSGVpZ2h0XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgLy8gUmVzdCBvZiBwbGF0Zm9ybXNcbiAgICAgICAgICAgICAgICAgIC8vIE5ldyByZXNvbHV0aW9uIGdvdCBmcm9tIGRpZmZlcmVudCBwbGFjZXMgZm9yIENocm9tZSBhbmQgRmlyZWZveC4gQ2hyb21lIG5lZWRzIGEgdmlkZW9XaWR0aCBhbmQgdmlkZW9IZWlnaHQgb2YgYSB2aWRlb0VsZW1lbnQuXG4gICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IG5lZWRzIGdldFNldHRpbmdzIGZyb20gdGhlIHZpZGVvVHJhY2tcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGZpcmVmb3hTZXR0aW5ncyA9IHB1Ymxpc2hlci5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpWzBdLmdldFNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgICBjb25zdCBuZXdXaWR0aCA9IDxudW1iZXI+KChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy53aWR0aCA6IHB1Ymxpc2hlci52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IDxudW1iZXI+KChwbGF0Zm9ybS5uYW1lISEudG9Mb3dlckNhc2UoKS5pbmRleE9mKCdmaXJlZm94JykgIT09IC0xKSA/IGZpcmVmb3hTZXR0aW5ncy5oZWlnaHQgOiBwdWJsaXNoZXIudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7IG5ld1dpZHRoLCBuZXdIZWlnaHQgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICBnZXROZXdWaWRlb0RpbWVuc2lvbnMoKS50aGVuKG5ld0RpbWVuc2lvbnMgPT4ge1xuICAgICAgICAgICAgICAgIHNlbmRTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChvbGRXaWR0aCwgb2xkSGVpZ2h0LCBuZXdEaW1lbnNpb25zLm5ld1dpZHRoLCBuZXdEaW1lbnNpb25zLm5ld0hlaWdodCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSwgNzUpO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgPSAob2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3V2lkdGgsIG5ld0hlaWdodCkgPT4ge1xuICAgICAgICAgICAgICBhdHRlbXB0cysrO1xuICAgICAgICAgICAgICBpZiAoYXR0ZW1wdHMgPiAxMCkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKG5ld1dpZHRoICE9PSBvbGRXaWR0aCB8fCBuZXdIZWlnaHQgIT09IG9sZEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgd2lkdGg6IG5ld1dpZHRoIHx8IDAsXG4gICAgICAgICAgICAgICAgICBoZWlnaHQ6IG5ld0hlaWdodCB8fCAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsXG4gICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiBwdWJsaXNoZXIuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ3ZpZGVvRGltZW5zaW9ucycsXG4gICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiBKU09OLnN0cmluZ2lmeShwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ2RldmljZVJvdGF0ZWQnXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHB1Ymxpc2hlci5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucywgeyB3aWR0aDogb2xkV2lkdGgsIGhlaWdodDogb2xkSGVpZ2h0IH0sICdkZXZpY2VSb3RhdGVkJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHB1Ymxpc2hlciwgcHVibGlzaGVyLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLCB7IHdpZHRoOiBvbGRXaWR0aCwgaGVpZ2h0OiBvbGRIZWlnaHQgfSwgJ2RldmljZVJvdGF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQocmVwZWF0VW50aWxDaGFuZ2UpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIG5ldyBzZXNzaW9uXG4gICAqL1xuICBpbml0U2Vzc2lvbigpOiBTZXNzaW9uIHtcbiAgICB0aGlzLnNlc3Npb24gPSBuZXcgU2Vzc2lvbih0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uO1xuICB9XG5cblxuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgcHVibGlzaGVyXG4gICAqXG4gICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0RpYWxvZ09wZW5lZGAgZXZlbnQsIG9ubHkgaWYgdGhlIHBvcC11cCBzaG93biBieSB0aGUgYnJvd3NlciB0byByZXF1ZXN0IHBlcm1pc3Npb25zIGZvciB0aGUgY2FtZXJhIGlzIG9wZW5lZC4gWW91IGNhbiB1c2UgdGhpcyBldmVudCB0byBhbGVydCB0aGUgdXNlciBhYm91dCBncmFudGluZyBwZXJtaXNzaW9uc1xuICAgKiBmb3IgeW91ciB3ZWJzaXRlLiBBbiBgYWNjZXNzRGlhbG9nQ2xvc2VkYCBldmVudCB3aWxsIGFsc28gYmUgZGlzcGF0Y2hlZCBhZnRlciB1c2VyIGNsaWNrcyBvbiBcIkFsbG93XCIgb3IgXCJCbG9ja1wiIGluIHRoZSBwb3AtdXAuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NBbGxvd2VkYCBvciBgYWNjZXNzRGVuaWVkYCBldmVudCBvbmNlIGl0IGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3QuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgYSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6ICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZpbHRlcjogcHJvcGVydGllcy5maWx0ZXJcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW2Vycm9yXSk7XG4gICAgICB9KTtcblxuICAgIHRoaXMucHVibGlzaGVycy5wdXNoKHB1Ymxpc2hlcik7XG4gICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICpcbiAgICogPiBXQVJOSU5HOiBldmVudHMgYGFjY2Vzc0RpYWxvZ09wZW5lZGAgYW5kIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIHdpbGwgbm90IGJlIGRpc3BhdGNoZWQgaWYgdXNpbmcgdGhpcyBtZXRob2QgaW5zdGVhZCBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG5cbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFB1Ymxpc2hlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICBsZXQgcHVibGlzaGVyOiBQdWJsaXNoZXI7XG5cbiAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShwdWJsaXNoZXIpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBsb2NhbCByZWNvcmRlciBmb3IgcmVjb3JkaW5nIHN0cmVhbXMgc3RyYWlnaHQgYXdheSBmcm9tIHRoZSBicm93c2VyXG4gICAqIEBwYXJhbSBzdHJlYW0gIFN0cmVhbSB0byByZWNvcmRcbiAgICovXG4gIGluaXRMb2NhbFJlY29yZGVyKHN0cmVhbTogU3RyZWFtKTogTG9jYWxSZWNvcmRlciB7XG4gICAgcmV0dXJuIG5ldyBMb2NhbFJlY29yZGVyKHN0cmVhbSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHVcbiAgICogQHJldHVybnMgMSBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdSwgMCBvdGhlcndpc2VcbiAgICovXG4gIGNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCk6IG51bWJlciB7XG4gICAgY29uc3QgYnJvd3NlciA9IHBsYXRmb3JtLm5hbWU7XG4gICAgY29uc3QgZmFtaWx5ID0gcGxhdGZvcm0ub3MhIS5mYW1pbHk7XG4gICAgY29uc3QgdXNlckFnZW50ID0gISFwbGF0Zm9ybS51YSA/IHBsYXRmb3JtLnVhIDogbmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgIC8vIFJlamVjdCBpUGhvbmVzIGFuZCBpUGFkcyBpZiBub3QgU2FmYXJpICgnU2FmYXJpJyBhbHNvIGNvdmVycyBJb25pYyBmb3IgaU9TKVxuICAgIGlmIChmYW1pbHkgPT09ICdpT1MnICYmIChicm93c2VyICE9PSAnU2FmYXJpJyB8fCB1c2VyQWdlbnQuaW5kZXhPZignQ3JpT1MnKSAhPT0gLTEgfHwgdXNlckFnZW50LmluZGV4T2YoJ0Z4aU9TJykgIT09IC0xKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8gQWNjZXB0OiBDaHJvbWUgKGRlc2t0b3AgYW5kIEFuZHJvaWQpLCBGaXJlZm94IChkZXNrdG9wIGFuZCBBbmRyb2lkKSwgT3BlcmEgKGRlc2t0b3AgYW5kIEFuZHJvaWQpLFxuICAgIC8vIFNhZmFyaSAoT1NYIGFuZCBpT1MpLCBJb25pYyAoQW5kcm9pZCBhbmQgaU9TKVxuICAgIGlmIChcbiAgICAgIChicm93c2VyICE9PSAnU2FmYXJpJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdDaHJvbWUgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnRmlyZWZveCcpICYmIChicm93c2VyICE9PSAnRmlyZWZveCBNb2JpbGUnKSAmJlxuICAgICAgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnT3BlcmEgTW9iaWxlJykgJiZcbiAgICAgIChicm93c2VyICE9PSAnQW5kcm9pZCBCcm93c2VyJykgJiYgKGJyb3dzZXIgIT09ICdFbGVjdHJvbicpXG4gICAgKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIHNjcmVlbi1zaGFyaW5nLiBEZXNrdG9wIENocm9tZSwgRmlyZWZveCBhbmQgT3BlcmEgc3VwcG9ydCBzY3JlZW4tc2hhcmluZ1xuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIHNjcmVlbi1zaGFyaW5nLCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTY3JlZW5TaGFyaW5nQ2FwYWJpbGl0aWVzKCk6IG51bWJlciB7XG4gICAgY29uc3QgYnJvd3NlciA9IHBsYXRmb3JtLm5hbWU7XG4gICAgY29uc3QgZmFtaWx5ID0gcGxhdGZvcm0ub3MhIS5mYW1pbHk7XG5cbiAgICAvLyBSZWplY3QgbW9iaWxlIGRldmljZXNcbiAgICBpZiAoZmFtaWx5ID09PSAnaU9TJyB8fCBmYW1pbHkgPT09ICdBbmRyb2lkJykge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgaWYgKChicm93c2VyICE9PSAnQ2hyb21lJykgJiYgKGJyb3dzZXIgIT09ICdGaXJlZm94JykgJiYgKGJyb3dzZXIgIT09ICdPcGVyYScpICYmIChicm93c2VyICE9PSAnRWxlY3Ryb24nKSkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuXG4gICAgICAgIC8vIElvbmljIEFuZHJvaWQgIGRldmljZXNcbiAgICAgICAgaWYgKHBsYXRmb3JtWydpc0lvbmljQW5kcm9pZCddICYmIGNvcmRvdmEucGx1Z2lucyAmJiBjb3Jkb3ZhLnBsdWdpbnMuRW51bWVyYXRlRGV2aWNlc1BsdWdpbikge1xuICAgICAgICAgIGNvcmRvdmEucGx1Z2lucy5FbnVtZXJhdGVEZXZpY2VzUGx1Z2luLmdldEVudW1lcmF0ZURldmljZXMoKS50aGVuKChwbHVnaW5EZXZpY2VzOiBEZXZpY2VbXSkgPT4ge1xuICAgICAgICAgICAgbGV0IHBsdWdpbkF1ZGlvRGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgICAgIGxldCB2aWRlb0RldmljZXM6IERldmljZVtdID0gW107XG4gICAgICAgICAgICBsZXQgYXVkaW9EZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICAgICAgcGx1Z2luQXVkaW9EZXZpY2VzID0gcGx1Z2luRGV2aWNlcy5maWx0ZXIoKGRldmljZTogRGV2aWNlKSA9PiBkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvaW5wdXQnKTtcbiAgICAgICAgICAgIHZpZGVvRGV2aWNlcyA9IGRldmljZUluZm9zLmZpbHRlcigoZGV2aWNlOiBEZXZpY2UpID0+IGRldmljZS5raW5kID09PSAndmlkZW9pbnB1dCcpO1xuICAgICAgICAgICAgYXVkaW9EZXZpY2VzID0gZGV2aWNlSW5mb3MuZmlsdGVyKChkZXZpY2U6IERldmljZSkgPT4gZGV2aWNlLmtpbmQgPT09ICdhdWRpb2lucHV0Jyk7XG4gICAgICAgICAgICB2aWRlb0RldmljZXMuZm9yRWFjaCgoZGV2aWNlSW5mbywgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCFkZXZpY2VJbmZvLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgbGV0IGxhYmVsID0gXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgIGxhYmVsID0gXCJGcm9udCBDYW1lcmFcIjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGluZGV4ID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICBsYWJlbCA9IFwiQmFjayBDYW1lcmFcIjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgbGFiZWwgPSBcIlVua25vd24gQ2FtZXJhXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICBraW5kOiBkZXZpY2VJbmZvLmtpbmQsXG4gICAgICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgIGxhYmVsOiBsYWJlbFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBhdWRpb0RldmljZXMuZm9yRWFjaCgoZGV2aWNlSW5mbywgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCFkZXZpY2VJbmZvLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgbGV0IGxhYmVsID0gXCJcIjtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICBjYXNlIDA6IC8vIERlZmF1bHQgTWljcm9waG9uZVxuICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICdEZWZhdWx0JztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBjYXNlIDE6IC8vIE1pY3JvcGhvbmUgKyBTcGVha2VycGhvbmVcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdE1hdGNoID0gcGx1Z2luQXVkaW9EZXZpY2VzLmZpbHRlcigoZCkgPT4gZC5sYWJlbC5pbmNsdWRlcygnQnVpbHQnKSlbMF07XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsID0gZGVmYXVsdE1hdGNoID8gZGVmYXVsdE1hdGNoLmxhYmVsIDogJ0J1aWx0LWluIE1pY3JvcGhvbmUnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgMjogLy8gSGVhZHNldCBNaWNyb3Bob25lXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpcmVkTWF0Y2ggPSBwbHVnaW5BdWRpb0RldmljZXMuZmlsdGVyKChkKSA9PiBkLmxhYmVsLmluY2x1ZGVzKCdXaXJlZCcpKVswXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpcmVkTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHdpcmVkTWF0Y2gubGFiZWw7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSAnSGVhZHNldCBlYXJwaWVjZSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpcmVsZXNzTWF0Y2ggPSBwbHVnaW5BdWRpb0RldmljZXMuZmlsdGVyKChkKSA9PiBkLmxhYmVsLmluY2x1ZGVzKCdCbHVldG9vdGgnKSlbMF07XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsID0gd2lyZWxlc3NNYXRjaCA/IHdpcmVsZXNzTWF0Y2gubGFiZWwgOiAnV2lyZWxlc3MnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsID0gXCJVbmtub3duIE1pY3JvcGhvbmVcIjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICBraW5kOiBkZXZpY2VJbmZvLmtpbmQsXG4gICAgICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgIGxhYmVsOiBsYWJlbFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgICAgbGFiZWw6IGRldmljZUluZm8ubGFiZWxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgLy8gUmVzdCBvZiBwbGF0Zm9ybXNcbiAgICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgICAgaWYgKGRldmljZUluZm8ua2luZCA9PT0gJ2F1ZGlvaW5wdXQnIHx8IGRldmljZUluZm8ua2luZCA9PT0gJ3ZpZGVvaW5wdXQnKSB7XG4gICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBnZXR0aW5nIGRldmljZXMnLCBlcnJvcik7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZTtcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKG9wdGlvbnMpXG4gICAgICAgIC50aGVuKGNvbnN0cmFpbnRzID0+IHtcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cylcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgY29uc29sZS5sb2cgPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS5kZWJ1ZyA9ICgpID0+IHsgfTtcbiAgICBjb25zb2xlLmluZm8gPSAoKSA9PiB7IH07XG4gICAgY29uc29sZS53YXJuID0gKCkgPT4geyB9O1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZVxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgYXVkaW8sIHZpZGVvO1xuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICBhdWRpbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXVkaW8gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXVkaW8gPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgfVxuXG4gICAgICBpZiAocHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICB2aWRlbyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlkZW8gPSB7XG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogNDgwXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgaWRlYWw6IDY0MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVkaWFDb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW8sXG4gICAgICAgIHZpZGVvXG4gICAgICB9O1xuXG4gICAgICBpZiAodHlwZW9mIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1lZGlhQ29uc3RyYWludHMuYXVkaW8gPSB7IGRldmljZUlkOiB7IGV4YWN0OiBtZWRpYUNvbnN0cmFpbnRzLmF1ZGlvIH0gfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lZGlhQ29uc3RyYWludHMudmlkZW8pIHtcblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3Qgd2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFsxXSk7XG4gICAgICAgICAgKG1lZGlhQ29uc3RyYWludHMudmlkZW8gYXMgYW55KS53aWR0aC5pZGVhbCA9IHdpZHRoO1xuICAgICAgICAgIChtZWRpYUNvbnN0cmFpbnRzLnZpZGVvIGFzIGFueSkuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGUpIHtcbiAgICAgICAgICAobWVkaWFDb25zdHJhaW50cy52aWRlbyBhcyBhbnkpLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICYmIHR5cGVvZiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuXG4gICAgICAgICAgaWYgKHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nIHx8XG4gICAgICAgICAgICAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSAmJiBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnd2luZG93JykgfHxcbiAgICAgICAgICAgIChwbGF0Zm9ybS5uYW1lID09PSAnRWxlY3Ryb24nICYmIHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2Uuc3RhcnRzV2l0aCgnc2NyZWVuOicpKSkge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2hlY2tTY3JlZW5TaGFyaW5nQ2FwYWJpbGl0aWVzKCkpIHtcblxuICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQsICdZb3UgY2FuIG9ubHkgc2NyZWVuIHNoYXJlIGluIGRlc2t0b3AgQ2hyb21lLCBGaXJlZm94LCBPcGVyYSBvciBFbGVjdHJvbi4gRGV0ZWN0ZWQgY2xpZW50OiAnICsgcGxhdGZvcm0ubmFtZSk7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lID09PSAnRWxlY3Ryb24nKSB7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwcmVmaXggPSBcInNjcmVlbjpcIjtcbiAgICAgICAgICAgICAgICBjb25zdCB2aWRlb1NvdXJjZVN0cmluZzogc3RyaW5nID0gcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZTtcbiAgICAgICAgICAgICAgICBjb25zdCBlbGVjdHJvblNjcmVlbklkID0gdmlkZW9Tb3VyY2VTdHJpbmcuc3Vic3RyKHZpZGVvU291cmNlU3RyaW5nLmluZGV4T2YocHJlZml4KSArIHByZWZpeC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICg8YW55Pm1lZGlhQ29uc3RyYWludHNbJ3ZpZGVvJ10pID0ge1xuICAgICAgICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlSWQ6IGVsZWN0cm9uU2NyZWVuSWRcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG5cbiAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkgJiYgIW5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddKSB7XG5cbiAgICAgICAgICAgICAgICAgIC8vIEN1c3RvbSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZSAoYW5kIE9wZXJhKSBhbmQgbm8gc3VwcG9ydCBmb3IgTWVkaWFEZXZpY2VzLmdldERpc3BsYXlNZWRpYSgpXG5cbiAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnIHx8IGVycm9yID09PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uSWQgPSB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiEuc3BsaXQoJy8nKS5wb3AoKSEhLnRyaW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbklkLCAoc3RhdHVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgKDxzdHJpbmc+dGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50cy52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGdldERpc3BsYXlNZWRpYSBzdXBwb3J0IChDaHJvbWUgPj0gNzIsIEZpcmVmb3ggPj0gNTIpXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lL09wZXJhLCBvciBpcyBGaXJlZm94IDwgNjZcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFN0cmluZyA9IHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEgPyBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKGZpcmVmb3hTdHJpbmcsIChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4dGVuc2lvblVybCA9ICEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gPyB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAncGVybWlzc2lvbi1kZW5pZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG1lZGlhQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9ICdzY3JlZW4nO1xuXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLXN0cmluZy1saXRlcmFsXG4gICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzLnZpZGVvWydkZXZpY2VJZCddID0geyBleGFjdDogcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSB9O1xuICAgICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShtZWRpYUNvbnN0cmFpbnRzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHNlbmRDbG9zZU1lc3NhZ2U6IGZhbHNlLFxuICAgICAgd3M6IHtcbiAgICAgICAgdXJpOiB0aGlzLndzVXJpLFxuICAgICAgICB1c2VTb2NrSlM6IGZhbHNlLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpXG4gICAgICB9LFxuICAgICAgcnBjOiB7XG4gICAgICAgIHJlcXVlc3RUaW1lb3V0OiAxMDAwMCxcbiAgICAgICAgcGFydGljaXBhbnRKb2luZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50Sm9pbmVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRQdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50UHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRVbnB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRVbnB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50TGVmdDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRMZWZ0LmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRFdmljdGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEV2aWN0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdGFydGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdGFydGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RvcHBlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RvcHBlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHNlbmRNZXNzYWdlOiB0aGlzLnNlc3Npb24ub25OZXdNZXNzYWdlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc3RyZWFtUHJvcGVydHlDaGFuZ2VkOiB0aGlzLnNlc3Npb24ub25TdHJlYW1Qcm9wZXJ0eUNoYW5nZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBmaWx0ZXJFdmVudERpc3BhdGNoZWQ6IHRoaXMuc2Vzc2lvbi5vbkZpbHRlckV2ZW50RGlzcGF0Y2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKVxuICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50ID0gbmV3IFJwY0J1aWxkZXIuY2xpZW50cy5Kc29uUnBjQ2xpZW50KGNvbmZpZyk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoNDEwMiwgXCJDb25uZWN0aW9uIGNsb3NlZCBieSBjbGllbnRcIik7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VuZFJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHBhcmFtczogYW55LCBjYWxsYmFjaz8pOiB2b2lkIHtcbiAgICBpZiAocGFyYW1zICYmIHBhcmFtcyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBjYWxsYmFjayA9IHBhcmFtcztcbiAgICAgIHBhcmFtcyA9IHt9O1xuICAgIH1cbiAgICBjb25zb2xlLmRlYnVnKCdTZW5kaW5nIHJlcXVlc3Q6IHttZXRob2Q6XCInICsgbWV0aG9kICsgJ1wiLCBwYXJhbXM6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgJ30nKTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuc2VuZChtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cblxuICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICBwcml2YXRlIGRpc2Nvbm5lY3RDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBjb25zb2xlLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QgKHJlY29ubmVjdGluZyknKTtcbiAgICBpZiAoIXRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RlZENhbGxiYWNrKCk6IHZvaWQge1xuICAgIGNvbnNvbGUud2FybignV2Vic29ja2V0IHJlY29ubmVjdGVkJyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIHRoaXMuc2VuZFJlcXVlc3QoJ2Nvbm5lY3QnLCB7IHNlc3Npb25JZDogdGhpcy5zZXNzaW9uLmNvbm5lY3Rpb24ucnBjU2Vzc2lvbklkIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbihcIm5ldHdvcmtEaXNjb25uZWN0XCIpO1xuICAgICAgICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSg0MTAxLCBcIlJlY29ubmVjdGlvbiBmYXVsdFwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmpzb25ScGNDbGllbnQucmVzZXRQaW5nKCk7XG4gICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzUm9vbUF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5zZXNzaW9uICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zZXNzaW9uIGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybignU2Vzc2lvbiBpbnN0YW5jZSBub3QgZm91bmQnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9QdWJsaXNoZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuXG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG4vKipcbiAqIFBhY2tzIGxvY2FsIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBjYW4gcHVibGlzaCBpdCB0byBhIHNlc3Npb24uIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBQdWJsaXNoZXIgZXh0ZW5kcyBTdHJlYW1NYW5hZ2VyIHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFB1Ymxpc2hlciBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90XG4gICAgICovXG4gICAgYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB5b3UgaGF2ZSBjYWxsZWQgW1tQdWJsaXNoZXIuc3Vic2NyaWJlVG9SZW1vdGVdXSB3aXRoIHZhbHVlIGB0cnVlYCBvciBgZmFsc2VgICgqZmFsc2UqIGJ5IGRlZmF1bHQpXG4gICAgICovXG4gICAgaXNTdWJzY3JpYmVkVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSB0byB3aGljaCB0aGUgUHVibGlzaGVyIGJlbG9uZ3NcbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uOyAvLyBJbml0aWFsaXplZCBieSBTZXNzaW9uLnB1Ymxpc2goUHVibGlzaGVyKVxuXG4gICAgcHJpdmF0ZSBhY2Nlc3NEZW5pZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG4gICAgcHJpdmF0ZSBwZXJtaXNzaW9uRGlhbG9nVGltZW91dDogTm9kZUpTLlRpbWVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlkZW9SZWZlcmVuY2U6IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWw6IE5vZGVKUy5UaW1lcjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgSUVBZGFwdGVyOiBhbnk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgb3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHN1cGVyKG5ldyBTdHJlYW0oKCEhb3BlbnZpZHUuc2Vzc2lvbikgPyBvcGVudmlkdS5zZXNzaW9uIDogbmV3IFNlc3Npb24ob3BlbnZpZHUpLCB7IHB1Ymxpc2hlclByb3BlcnRpZXM6IHByb3BlcnRpZXMsIG1lZGlhQ29uc3RyYWludHM6IHt9IH0pLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgICAgICB0aGlzLm9wZW52aWR1ID0gb3BlbnZpZHU7XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uZWUub24oJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQnLCAocmVhc29uOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCB0aGlzLnN0cmVhbSwgcmVhc29uKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiA+IF9Pbmx5IGlmIGBTZXNzaW9uLnB1Ymxpc2goUHVibGlzaGVyKWAgaGFzIGJlZW4gY2FsbGVkIGZvciB0aGlzIFB1Ymxpc2hlcl9cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwiYXVkaW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoQXVkaW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaEF1ZGlvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uICYmICEhdGhpcy5zdHJlYW0uc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hBdWRpbydcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICdhdWRpb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoQXVkaW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiA+IF9Pbmx5IGlmIGBTZXNzaW9uLnB1Ymxpc2goUHVibGlzaGVyKWAgaGFzIGJlZW4gY2FsbGVkIGZvciB0aGlzIFB1Ymxpc2hlcl9cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwidmlkZW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoVmlkZW9cImBcbiAgICAgKiBUaGUgcmVzcGVjdGl2ZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgcmVjZWl2aW5nIHRoaXMgUHVibGlzaGVyJ3Mgc3RyZWFtIHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICovXG4gICAgcHVibGlzaFZpZGVvKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uICYmICEhdGhpcy5zdHJlYW0uc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ3ZpZGVvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJ3B1Ymxpc2hWaWRlbydcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAndmlkZW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaFZpZGVvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiJ1B1Ymxpc2hlcicgaGFzIFwiICsgKHZhbHVlID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoaXMgbWV0aG9kIGJlZm9yZSBbW1Nlc3Npb24ucHVibGlzaF1dIGlmIHlvdSBwcmVmZXIgdG8gc3Vic2NyaWJlIHRvIHlvdXIgUHVibGlzaGVyJ3MgcmVtb3RlIHN0cmVhbSBpbnN0ZWFkIG9mIHVzaW5nIHRoZSBsb2NhbCBzdHJlYW0sIGFzIGFueSBvdGhlciB1c2VyIHdvdWxkIGRvLlxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvUmVtb3RlKHZhbHVlPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSA/IHZhbHVlIDogdHJ1ZTtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZWRUb1JlbW90ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnN0cmVhbS5zdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgc3VwZXIub24odHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAncmVtb3RlVmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpICYmIHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgncmVtb3RlVmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3JlbW90ZVZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFB1Ymxpc2hlciB7XG4gICAgICAgIHN1cGVyLm9uY2UodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQ3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbmNlKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBjb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgbGV0IGNvbnN0cmFpbnRzQXV4OiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge307XG4gICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxMjUwO1xuICAgICAgICAgICAgbGV0IHN0YXJ0VGltZTtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0udmlkZW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgPT09ICdTYWZhcmknKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2Uuc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0TWVkaWFTdHJlYW0obWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZVZpZGVvRWxlbWVudCh0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+dGhpcy5wcm9wZXJ0aWVzLmluc2VydE1vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2Uuc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW07XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIHN1YnNjcmliZWQgdG8gb3VyIHJlbW90ZSB3ZSBkb24ndCBzdGlsbCBzZXQgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB0aGUgdmlkZW8gZWxlbWVudHMgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gYXZvaWQgZWFybHkgJ3N0cmVhbVBsYXlpbmcnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwbGF0Zm9ybVsnaXNJb25pY0lvcyddIHx8IHBsYXRmb3JtLm5hbWUgPT09ICdTYWZhcmknKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaU9TIElvbmljIG9yIFNhZmFyaS4gTGltaXRhdGlvbjogY2Fubm90IHNldCB2aWRlb0RpbWVuc2lvbnMgZGlyZWN0bHksIGFzIHRoZSB2aWRlb1JlZmVyZW5jZSBpcyBub3QgbG9hZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgbm90IGFkZGVkIHRvIERPTS4gTXVzdCBhZGQgaXQgdG8gRE9NIGFuZCB3YWl0IGZvciB2aWRlb1dpZHRoIGFuZCB2aWRlb0hlaWdodCBwcm9wZXJ0aWVzIHRvIGJlIGRlZmluZWRcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2Uuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMudmlkZW9SZWZlcmVuY2UpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmlkZW9EaW1lbnNpb25zU2V0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGhpcy52aWRlb1JlZmVyZW5jZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb1dpZHRoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnNTZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnNTZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXN0IG9mIHBsYXRmb3Jtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggbm8gc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gY2FuIGJlIHNldCBkaXJlY3RseSBmcm9tIE1lZGlhU3RyZWFtIChnZXRTZXR0aW5ncylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPcmllbnRhdGlvbiBtdXN0IGJlIGNoZWNrZWQgZm9yIG1vYmlsZSBkZXZpY2VzICh3aWR0aCBhbmQgaGVpZ2h0IGFyZSByZXZlcnNlZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgocGxhdGZvcm0ub3MhIS5mYW1pbHkgPT09ICdpT1MnIHx8IHBsYXRmb3JtLm9zISEuZmFtaWx5ID09PSAnQW5kcm9pZCcpICYmICh3aW5kb3cuaW5uZXJIZWlnaHQgPiB3aW5kb3cuaW5uZXJXaWR0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTW9iaWxlIHBvcnRyYWl0IG1vZGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGhlaWdodCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB3aWR0aCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHdpZHRoIHx8IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdpdGggc2NyZWVuIHNoYXJlLCB2aWRlbyBkaW1lbnNpb24gbXVzdCBiZSBnb3QgZnJvbSBhIHZpZGVvIGVsZW1lbnQgKG9ubG9hZGVkbWV0YWRhdGEgZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9XaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpcmVmb3hTZXR0aW5ncyA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3V2lkdGggPSAocGxhdGZvcm0ubmFtZSA9PT0gJ0Nocm9tZScgfHwgcGxhdGZvcm0ubmFtZSA9PT0gJ09wZXJhJykgPyB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGggOiBmaXJlZm94U2V0dGluZ3Mud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld0hlaWdodCA9IChwbGF0Zm9ybS5uYW1lID09PSAnQ2hyb21lJyB8fCBwbGF0Zm9ybS5uYW1lID09PSAnT3BlcmEnKSA/IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQgOiBmaXJlZm94U2V0dGluZ3MuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5ld1dpZHRoICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGggfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdIZWlnaHQgIT09IHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHsgd2lkdGg6IHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy53aWR0aCwgaGVpZ2h0OiB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0IH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IG5ld1dpZHRoIHx8IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBuZXdIZWlnaHQgfHwgMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbS5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHk6ICd2aWRlb0RpbWVuc2lvbnMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogSlNPTi5zdHJpbmdpZnkodGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAnc2NyZWVuUmVzaXplZCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igc2VuZGluZyAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIG9sZFZhbHVlLCAnc2NyZWVuUmVzaXplZCcpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLCB0aGlzLnN0cmVhbSwgJ3ZpZGVvRGltZW5zaW9ucycsIHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucywgb2xkVmFsdWUsICdzY3JlZW5SZXNpemVkJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGdldE1lZGlhU3VjY2VzcyA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0sIGRlZmluZWRBdWRpb0NvbnN0cmFpbnQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgdGhpcy5zdHJlYW0uaXNTZW5kQXVkaW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGdldHRpbmcgZGVza3RvcCBhcyB1c2VyIG1lZGlhIGF1ZGlvIGNvbnN0cmFpbnQgbXVzdCBiZSBmYWxzZS4gTm93IHdlIGNhbiBhc2sgZm9yIGl0IGlmIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gZGVmaW5lZEF1ZGlvQ29uc3RyYWludDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIodGltZUZvckRpYWxvZ0V2ZW50KTtcblxuICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2soYXVkaW9Pbmx5U3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Vycm9yJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgT3ZlckNvbnN0cmFpbmVkRXJyb3IgaGFzIGFzIG5hbWUgcHJvcGVydHkgJ0Vycm9yJyBpbnN0ZWFkIG9mICdPdmVyQ29uc3RyYWluZWRFcnJvcidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubmFtZSA9IGVycm9yLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWUsIGVycm9yTWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdub3Rmb3VuZGVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGdldE1lZGlhRXJyb3IgPSBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yLm5hbWUgPT09ICdFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIE92ZXJDb25zdHJhaW5lZEVycm9yIGhhcyBhcyBuYW1lIHByb3BlcnR5ICdFcnJvcicgaW5zdGVhZCBvZiAnT3ZlckNvbnN0cmFpbmVkRXJyb3InXG4gICAgICAgICAgICAgICAgICAgIGVycm9yLm5hbWUgPSBlcnJvci5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSB0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSA/IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCA6IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy5hdWRpbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYWJvcnRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdHJlYWRhYmxlZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FMUkVBRFlfSU5fVVNFO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuR0VORVJJQ19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIG5ldyBjb25zdHJhaW50cyBuZWVkIHRvIGJlIGdlbmVyYXRlZC4gTm8gY29uc3RyYWludHMgbmVlZGVkIGlmXG4gICAgICAgICAgICAvLyAtIHZpZGVvIHRyYWNrIGlzIGdpdmVuIGFuZCBubyBhdWRpb1xuICAgICAgICAgICAgLy8gLSBhdWRpbyB0cmFjayBpcyBnaXZlbiBhbmQgbm8gdmlkZW9cbiAgICAgICAgICAgIC8vIC0gYm90aCB2aWRlbyBhbmQgYXVkaW8gdHJhY2tzIGFyZSBnaXZlblxuICAgICAgICAgICAgaWYgKCh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjayAmJiAhdGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlKVxuICAgICAgICAgICAgICAgIHx8ICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5wcm9wZXJ0aWVzLmF1ZGlvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjayAmJiAhdGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlKVxuICAgICAgICAgICAgICAgIHx8ICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5wcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjayAmJiB0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1lZGlhU3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gTWVkaWFTdHJlYW1UcmFja3MgYXJlIGhhbmRsZWQgd2l0aGluIGNhbGxiYWNrIC0ganVzdCBjYWxsIGNhbGxiYWNrIHdpdGggbmV3IE1lZGlhU3RyZWFtKCkgYW5kIGxldCBpdCBoYW5kbGUgdGhlIHNvdXJjZXNcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgIC8vIFJldHVybiBhcyB3ZSBkbyBub3QgbmVlZCB0byBwcm9jZXNzIGZ1cnRoZXJcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihteUNvbnN0cmFpbnRzID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50cyA9IG15Q29uc3RyYWludHM7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kVmlkZW8oKSB8fCB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXgudmlkZW8gPSBjb25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgJiYgbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10gJiYgcGxhdGZvcm0ubmFtZSAhPT0gJ0VsZWN0cm9uJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10oeyB2aWRlbzogdHJ1ZSB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNZWRpYVN1Y2Nlc3MobWVkaWFTdHJlYW0sIGRlZmluZWRBdWRpb0NvbnN0cmFpbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWVkaWFFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1lZGlhU3VjY2VzcyhtZWRpYVN0cmVhbSwgZGVmaW5lZEF1ZGlvQ29uc3RyYWludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNZWRpYUVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5OT19JTlBVVF9TT1VSQ0VfU0VULFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiUHJvcGVydGllcyAnYXVkaW9Tb3VyY2UnIGFuZCAndmlkZW9Tb3VyY2UnIGNhbm5vdCBiZSBzZXQgdG8gZmFsc2Ugb3IgbnVsbCBhdCB0aGUgc2FtZSB0aW1lIHdoZW4gY2FsbGluZyAnT3BlblZpZHUuaW5pdFB1Ymxpc2hlcidcIikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2soZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi9Db25uZWN0aW9uJztcbmltcG9ydCB7IEZpbHRlciB9IGZyb20gJy4vRmlsdGVyJztcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdSc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9DYXBhYmlsaXRpZXMnO1xuaW1wb3J0IHsgRXZlbnREaXNwYXRjaGVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9FdmVudERpc3BhdGNoZXInO1xuaW1wb3J0IHsgU2lnbmFsT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU2lnbmFsT3B0aW9ucyc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyUHJvcGVydGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3Vic2NyaWJlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Db25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBPYmpNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PYmpNYXAnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgRmlsdGVyRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9GaWx0ZXJFdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudCc7XG5pbXBvcnQgeyBSZWNvcmRpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50JztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTaWduYWxFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1NpZ25hbEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbUV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSByb2xlIG9mIHRoZSB0b2tlbiB1c2VkIHRvIGNvbm5lY3QgdG8gdGhlIFNlc3Npb24uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBPYmpNYXA8Ym9vbGVhbj4gPSB7fTtcblxuICAgIC8qKlx0XG4gICAgICogQGhpZGRlblx0XG4gICAgICovXG4gICAgaXNGaXJzdElvbmljSW9zU3Vic2NyaWJlciA9IHRydWU7XG4gICAgLyoqXHRcbiAgICAgKiBAaGlkZGVuXHRcbiAgICAgKi9cbiAgICBjb3VudERvd25Gb3JJb25pY0lvc1N1YnNjcmliZXJzQWN0aXZlID0gdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE9iak1hcDxDb25uZWN0aW9uPiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcmRpemVkIGZvcm1hdFxuICAgICAqIGFzIEpTT04gb3IgWE1MIGlzIGEgZ29vZCBpZGVhKS5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0YWRhdGEgaXMgbm90IGNvbnNpZGVyZWQgc2VjdXJlLCBhcyBpdCBpcyBnZW5lcmF0ZWQgaW4gdGhlIGNsaWVudCBzaWRlLiBUbyBwYXNzIHNlY3VyZSBkYXRhLCBhZGQgaXQgYXMgYSBwYXJhbWV0ZXIgaW4gdGhlXG4gICAgICogdG9rZW4gZ2VuZXJhdGlvbiBvcGVyYXRpb24gKHRocm91Z2ggdGhlIEFQSSBSRVNULCBvcGVudmlkdS1qYXZhLWNsaWVudCBvciBvcGVudmlkdS1ub2RlLWNsaWVudCkuXG4gICAgICpcbiAgICAgKiBPbmx5IGFmdGVyIHRoZSByZXR1cm5lZCBQcm9taXNlIGlzIHN1Y2Nlc3NmdWxseSByZXNvbHZlZCBbW1Nlc3Npb24uY29ubmVjdGlvbl1dIG9iamVjdCB3aWxsIGJlIGF2YWlsYWJsZSBhbmQgcHJvcGVybHkgZGVmaW5lZC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZmlyc3QgZGlzcGF0Y2ggb25lIG9yIG1vcmUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kOlxuICAgICAqIC0gRmlyc3Qgb25lIGZvciB5b3VyIG93biBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCwgc28geW91IGNhbiByZXRyaWV2ZSBbW1Nlc3Npb24uY29ubmVjdGlvbl1dIHByb3BlcnR5LlxuICAgICAqIC0gVGhlbiBvbmUgZm9yIGVhY2ggcmVtb3RlIENvbm5lY3Rpb24gcHJldmlvdXNseSBjb25uZWN0ZWQgdG8gdGhlIFNlc3Npb24sIGlmIGFueS4gQW55IG90aGVyIHJlbW90ZSB1c2VyIGNvbm5lY3RpbmcgdG8gdGhlIFNlc3Npb24gYWZ0ZXIgeW91IGhhdmVcbiAgICAgKiBzdWNjZXNzZnVsbHkgY29ubmVjdGVkIHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnQgd2hlbiB0aGV5IGRvIHNvLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IGZvciBlYWNoIHJlbW90ZSBhY3RpdmUgW1tQdWJsaXNoZXJdXSB0aGF0IHdhcyBhbHJlYWR5IHN0cmVhbWluZ1xuICAgICAqIHdoZW4gY29ubmVjdGluZywganVzdCBhZnRlciBkaXNwYXRjaGluZyBhbGwgcmVtb3RlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgdG8gd2hpY2ggeW91IG11c3Qgc3Vic2NyaWJlIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKlxuICAgICAqL1xuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZywgbWV0YWRhdGE/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NUb2tlbih0b2tlbik7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBFYXJseSBjb25maWd1cmF0aW9uIHRvIGRlYWN0aXZhdGUgYXV0b21hdGljIHN1YnNjcmlwdGlvbiB0byBzdHJlYW1zXG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudElkOiB0b2tlbixcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6ICEhbWV0YWRhdGEgPyB0aGlzLnN0cmluZ0NsaWVudE1ldGFkYXRhKG1ldGFkYXRhKSA6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3RBdXgodG9rZW4pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuQlJPV1NFUl9OT1RfU1VQUE9SVEVELCAnQnJvd3NlciAnICsgcGxhdGZvcm0ubmFtZSArICcgKHZlcnNpb24gJyArIHBsYXRmb3JtLnZlcnNpb24gKyAnKSBmb3IgJyArIHBsYXRmb3JtLm9zISEuZmFtaWx5ICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIGlmIHlvdSB3YW50IHRvIGNsZWFuIHRoZSBQdWJsaXNoZXIgb2JqZWN0IG9uIHlvdXIgb3duIG9yIHJlLXB1Ymxpc2ggaXQgaW4gYSBkaWZmZXJlbnQgU2Vzc2lvbiAodG8gZG8gc28gaXQgaXMgYSBtYW5kYXRvcnkgcmVxdWlyZW1lbnQgdG8gY2FsbCBgU2Vzc2lvbi51bnB1Ymxpc2goKWBcbiAgICAgKiBvci9hbmQgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBpbiB0aGUgcHJldmlvdXMgc2Vzc2lvbikuIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBkaXNjb25uZWN0ZWQgcGFydGljaXBhbnQgd2FzIHB1Ymxpc2hpbmcuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgaW4gYW55IGNhc2UuIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sZWF2ZShmYWxzZSwgJ2Rpc2Nvbm5lY3QnKTtcbiAgICB9XG5cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIGEgYHN0cmVhbWAsIGFkZGluZyBhIG5ldyBIVE1MIHZpZGVvIGVsZW1lbnQgdG8gRE9NIHdpdGggYHN1YnNjcmliZXJQcm9wZXJ0aWVzYCBzZXR0aW5ncy4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWQgaW4gdGhlIGNhbGxiYWNrIG9mIGBzdHJlYW1DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIHRoZSBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gYWRkZWQgdG8gRE9NIChvbmx5IGlmIHlvdVxuICAgICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZG9jcy9ob3ctZG8taS9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmluZm8oJ1N1YnNjcmliaW5nIHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHN0cmVhbS5zdWJzY3JpYmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZCA9IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkO1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAndW5zdWJzY3JpYmVGcm9tVmlkZW8nLFxuICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHVuc3Vic2NyaWJpbmcgZnJvbSAnICsgY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgV2ViUlRDUGVlciBjb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBudWxsJywgc3RyZWFtKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJlYW0uY29ubmVjdGlvbiAhPT0gdGhpcy5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgIFwiT25seSBtb2RlcmF0b3JzIGNhbiBmb3JjZSB1bnB1Ymxpc2ggb24gcmVtb3RlIFN0cmVhbXMgdmlhICdmb3JjZVVucHVibGlzaCcgbWV0aG9kXCIsIHN0cmVhbSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnVW5wdWJsaXNoaW5nIGxvY2FsIG1lZGlhICgnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyknKTtcblxuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyBzb21lIHVzZXIgdG8gbGVhdmUgdGhlIHNlc3Npb25cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24uZGlzY29ubmVjdF1dLCBidXQgYHJlYXNvbmAgcHJvcGVydHkgaW4gYWxsIGV2ZW50cyB3aWxsIGJlIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZSBldmljdGVkIHVzZXIgd2FzIHB1Ymxpc2hpbmcgYSBzdHJlYW0sIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IGV4Y2VwdCB0aGUgZXZpY3RlZCBvbmUgd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBmb3IgdGhlIGV2aWN0ZWQgdXNlciwgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogSWYgYW55LCB0aGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGV2aWN0ZWQgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1FdmVudF1dLCBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcGFydGljaXBhbnQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvbiBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgZm9yY2VEaXNjb25uZWN0KGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZvcmNpbmcgZGlzY29ubmVjdCBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyBvbmUgc2lnbmFsLiBgc2lnbmFsYCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiBgYGBqc29uXG4gICAgICoge2RhdGE6c3RyaW5nLCB0bzpDb25uZWN0aW9uW10sIHR5cGU6c3RyaW5nfVxuICAgICAqIGBgYFxuICAgICAqIEFsbCB1c2VycyBzdWJzY3JpYmVkIHRvIHRoYXQgc2lnbmFsIChgc2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCAuLi4pYCBvciBgc2Vzc2lvbi5vbignc2lnbmFsJywgLi4uKWAgZm9yIGFsbCBzaWduYWxzKSBhbmQgd2hvc2UgQ29ubmVjdGlvbiBvYmplY3RzIGFyZSBpbiBgdG9gIGFycmF5IHdpbGwgcmVjZWl2ZSBpdC4gVGhlaXIgbG9jYWxcbiAgICAgKiBTZXNzaW9uIG9iamVjdHMgd2lsbCBkaXNwYXRjaCBhIGBzaWduYWxgIG9yIGBzaWduYWw6dHlwZWAgZXZlbnQuIFNlZSBbW1NpZ25hbEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgbWVzc2FnZSBzdWNjZXNzZnVsbHkgcmVhY2hlZCBvcGVudmlkdS1zZXJ2ZXIgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdC4gX1RoaXMgZG9lc24ndFxuICAgICAqIG1lYW4gdGhhdCBvcGVudmlkdS1zZXJ2ZXIgY291bGQgcmVzZW5kIHRoZSBtZXNzYWdlIHRvIGFsbCB0aGUgbGlzdGVkIHJlY2VpdmVycy5fXG4gICAgICovXG4gICAgLyogdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWwgKi9cbiAgICBzaWduYWwoc2lnbmFsOiBTaWduYWxPcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc2lnbmFsTWVzc2FnZSA9IHt9O1xuXG4gICAgICAgICAgICBpZiAoc2lnbmFsLnRvICYmIHNpZ25hbC50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uSWRzLnB1c2goY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcblxuICAgICAgICAgICAgbGV0IHR5cGVBdXg6IHN0cmluZyA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnc2lnbmFsJztcbiAgICAgICAgICAgIGlmICghIXR5cGVBdXgpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZUF1eC5zdWJzdHJpbmcoMCwgNykgIT09ICdzaWduYWw6Jykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlQXV4ID0gJ3NpZ25hbDonICsgdHlwZUF1eDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSB0eXBlQXV4O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICB0aGlzLmVlLm9uKHR5cGUsIGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIHx8IHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICB0aGlzLnNwZWFraW5nRXZlbnRzRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMsIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0ciAmJiBzdHIuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyLmVuYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBlbmFibGUgaGFyayBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5yZW1vdGVDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW07XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyICYmIHN0ci5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZW5hYmxlT25jZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJyB8fCB0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgdGhpcy5zcGVha2luZ0V2ZW50c0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFscmVhZHkgYXZhaWxhYmxlIHJlbW90ZSBzdHJlYW1zLCBkaXNhYmxlIGhhcmsgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbklkIGluIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHIgPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtO1xuICAgICAgICAgICAgICAgIGlmICghIXN0cikge1xuICAgICAgICAgICAgICAgICAgICBzdHIuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKHJlc3BvbnNlOiBDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24ocmVzcG9uc2UuaWQsICcnKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0Nvbm5lY3Rpb24gJyArIHJlc3BvbnNlLmlkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tyZXNwb25zZS5pZF0gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChtc2cpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsICdSZW1vdGUgY29ubmVjdGlvbiAnICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnb25QYXJ0aWNpcGFudExlZnQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbc3RyZWFtLnN0cmVhbUlkXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmtleXModGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRmlyc3RJb25pY0lvc1N1YnNjcmliZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb3VudERvd25Gb3JJb25pY0lvc1N1YnNjcmliZXJzQWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLCBjb25uZWN0aW9uLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUGFydGljaXBhbnRQdWJsaXNoZWQocmVzcG9uc2U6IENvbm5lY3Rpb25PcHRpb25zKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgYWZ0ZXJDb25uZWN0aW9uRm91bmQgPSAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uLmNvbm5lY3Rpb25JZF0gPSBjb25uZWN0aW9uO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWRbY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWRdKSB7XG4gICAgICAgICAgICAgICAgLy8gQXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiBzdHJlYW0uc3Vic2NyaWJlKCkgaW4gXCJvblBhcnRpY2lwYW50UHVibGlzaGVkXCIgYW5kIGluIFwiam9pblJvb21cIiBycGMgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbmRpdGlvbiBpcyBmYWxzZSBpZiBvcGVudmlkdS1zZXJ2ZXIgc2VuZHMgXCJwYXJ0aWNpcGFudFB1Ymxpc2hlZFwiIGV2ZW50IHRvIGEgc3Vic2NyaWJlciBwYXJ0aWNpcGFudCB0aGF0IGhhc1xuICAgICAgICAgICAgICAgIC8vIGFscmVhZHkgc3Vic2NyaWJlZCB0byBjZXJ0YWluIHN0cmVhbSBpbiB0aGUgY2FsbGJhY2sgb2YgXCJqb2luUm9vbVwiIG1ldGhvZFxuXG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldCB0aGUgZXhpc3RpbmcgQ29ubmVjdGlvbiBjcmVhdGVkIG9uICdvblBhcnRpY2lwYW50Sm9pbmVkJyBmb3JcbiAgICAgICAgLy8gZXhpc3RpbmcgcGFydGljaXBhbnRzIG9yIGNyZWF0ZSBhIG5ldyBvbmUgZm9yIG5ldyBwYXJ0aWNpcGFudHNcbiAgICAgICAgbGV0IGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihyZXNwb25zZS5pZCwgXCJSZW1vdGUgY29ubmVjdGlvbiAnXCIgKyByZXNwb25zZS5pZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnLiBcIiArXG4gICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAudGhlbihjb24gPT4ge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IGNvbjtcbiAgICAgICAgICAgICAgICByZXNwb25zZS5tZXRhZGF0YSA9IGNvbi5kYXRhO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ub3B0aW9ucyA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uaW5pdFJlbW90ZVN0cmVhbXMocmVzcG9uc2Uuc3RyZWFtcyk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBuZXcgQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgYWZ0ZXJDb25uZWN0aW9uRm91bmQoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFVucHVibGlzaGVkKG1zZyk6IHZvaWQge1xuICAgICAgICBpZiAobXNnLmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91ciBzdHJlYW0gaGFzIGJlZW4gZm9yY2VkbHkgdW5wdWJsaXNoZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKG1zZy5yZWFzb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKG1zZy5jb25uZWN0aW9uSWQsIFwiUmVtb3RlIGNvbm5lY3Rpb24gJ1wiICsgbXNnLmNvbm5lY3Rpb25JZCArIFwiJyB1bmtub3duIHdoZW4gJ29uUGFydGljaXBhbnRVbnB1Ymxpc2hlZCcuIFwiICtcbiAgICAgICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkoT2JqZWN0LmtleXModGhpcy5yZW1vdGVDb25uZWN0aW9ucykpKVxuXG4gICAgICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIGNvbm5lY3Rpb24uc3RyZWFtLCBtc2cucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRGVsZXRpbmcgdGhlIHJlbW90ZSBzdHJlYW1cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtSWQ6IHN0cmluZyA9IGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtzdHJlYW1JZF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWQpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0ZpcnN0SW9uaWNJb3NTdWJzY3JpYmVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY291bnREb3duRm9ySW9uaWNJb3NTdWJzY3JpYmVyc0FjdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudEV2aWN0ZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGlmIChtc2cuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgbXNnLnJlYXNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXdNZXNzYWdlKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuaW5mbygnTmV3IHNpZ25hbDogJyArIEpTT04uc3RyaW5naWZ5KG1zZykpO1xuXG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihtc2cuZnJvbSwgXCJDb25uZWN0aW9uICdcIiArIG1zZy5mcm9tICsgXCInIHVua25vdyB3aGVuICdvbk5ld01lc3NhZ2UnLiBFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6IFwiXG4gICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KE9iamVjdC5rZXlzKHRoaXMucmVtb3RlQ29ubmVjdGlvbnMpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgaWYgKG1zZy50eXBlICE9PSAnc2lnbmFsJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudChtc2cudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBtc2cudHlwZSwgbXNnLmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKG1zZyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGNvbm5lY3Rpb246IENvbm5lY3Rpb24pID0+IHtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtICYmIGNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkID09PSBtc2cuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICBsZXQgb2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChtc2cucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYXVkaW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBtc2cubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5hdWRpb0FjdGl2ZSA9IG1zZy5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zZy5uZXdWYWx1ZSA9IG1zZy5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvQWN0aXZlID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBKU09OLnBhcnNlKEpTT04ucGFyc2UobXNnLm5ld1ZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0udmlkZW9EaW1lbnNpb25zID0gbXNnLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbHRlcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5maWx0ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSAoT2JqZWN0LmtleXMobXNnLm5ld1ZhbHVlKS5sZW5ndGggPiAwKSA/IG1zZy5uZXdWYWx1ZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtc2cubmV3VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5maWx0ZXIgPSBuZXcgRmlsdGVyKG1zZy5uZXdWYWx1ZS50eXBlLCBtc2cubmV3VmFsdWUub3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlci5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1zZy5uZXdWYWx1ZS5sYXN0RXhlY01ldGhvZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uZmlsdGVyLmxhc3RFeGVjTWV0aG9kID0gbXNnLm5ld1ZhbHVlLmxhc3RFeGVjTWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5maWx0ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cubmV3VmFsdWUgPSBzdHJlYW0uZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHN0cmVhbSwgbXNnLnByb3BlcnR5LCBtc2cubmV3VmFsdWUsIG9sZFZhbHVlLCBtc2cucmVhc29uKV0pO1xuICAgICAgICAgICAgICAgIGlmICghIXN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBtc2cucHJvcGVydHksIG1zZy5uZXdWYWx1ZSwgb2xkVmFsdWUsIG1zZy5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiTm8gc3RyZWFtIHdpdGggc3RyZWFtSWQgJ1wiICsgbXNnLnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIG1zZy5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKG1zZy5jb25uZWN0aW9uSWQgPT09IHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpIHtcbiAgICAgICAgICAgIC8vIFlvdXIgc3RyZWFtIGhhcyBiZWVuIGZvcmNlZGx5IGNoYW5nZWQgKGZpbHRlciBmZWF0dXJlKVxuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5jb25uZWN0aW9uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVtb3RlQ29ubmVjdGlvbihtc2cuY29ubmVjdGlvbklkLCAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIG1zZy5jb25uZWN0aW9uSWQgKyBcIiB1bmtub3duIHdoZW4gJ29uU3RyZWFtUHJvcGVydHlDaGFuZ2VkJy4gXCIgK1xuICAgICAgICAgICAgICAgICdFeGlzdGluZyByZW1vdGUgY29ubmVjdGlvbnM6ICcgKyBKU09OLnN0cmluZ2lmeShPYmplY3Qua2V5cyh0aGlzLnJlbW90ZUNvbm5lY3Rpb25zKSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlY3ZJY2VDYW5kaWRhdGUobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBtc2cuY2FuZGlkYXRlLFxuICAgICAgICAgICAgY29tcG9uZW50OiBtc2cuY29tcG9uZW50LFxuICAgICAgICAgICAgZm91bmRhdGlvbjogbXNnLmZvdW5kYXRpb24sXG4gICAgICAgICAgICBpcDogbXNnLmlwLFxuICAgICAgICAgICAgcG9ydDogbXNnLnBvcnQsXG4gICAgICAgICAgICBwcmlvcml0eTogbXNnLnByaW9yaXR5LFxuICAgICAgICAgICAgcHJvdG9jb2w6IG1zZy5wcm90b2NvbCxcbiAgICAgICAgICAgIHJlbGF0ZWRBZGRyZXNzOiBtc2cucmVsYXRlZEFkZHJlc3MsXG4gICAgICAgICAgICByZWxhdGVkUG9ydDogbXNnLnJlbGF0ZWRQb3J0LFxuICAgICAgICAgICAgc2RwTWlkOiBtc2cuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogbXNnLnNkcE1MaW5lSW5kZXgsXG4gICAgICAgICAgICB0Y3BUeXBlOiBtc2cudGNwVHlwZSxcbiAgICAgICAgICAgIHVzZXJuYW1lRnJhZ21lbnQ6IG1zZy51c2VybmFtZUZyYWdtZW50LFxuICAgICAgICAgICAgdHlwZTogbXNnLnR5cGUsXG4gICAgICAgICAgICB0b0pTT046ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBjYW5kaWRhdGU6IG1zZy5jYW5kaWRhdGUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKG1zZy5zZW5kZXJDb25uZWN0aW9uSWQsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgY29ubmVjdGlvbklkICcgKyBtc2cuc2VuZGVyQ29ubmVjdGlvbklkICsgJyBvd25pbmcgZW5kcG9pbnQgJyArIG1zZy5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBtc2cuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblNlc3Npb25DbG9zZWQobXNnKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5zZXNzaW9uSWQ7XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbihyZWFzb246IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0xvc3QgY29ubmVjdGlvbiBpbiBzZXNzaW9uICcgKyB0aGlzLnNlc3Npb25JZCArICcgd2FpdGluZyBmb3IgcmVjb25uZWN0Jyk7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbklkICYmICF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgcmVhc29uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY292ZXJlZENvbm5lY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUud2FybignUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICAvLyB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblJlY292ZXJlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKHBhcmFtcyk6IHZvaWQge1xuXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSk7XG4gICAgICAgIGNvbnN0IGVyciA9IHBhcmFtcy5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvci4gUGFyYW1zOicsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIHJlc3BvbnNlLmlkLCByZXNwb25zZS5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQocmVzcG9uc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgcmVzcG9uc2UuaWQsIHJlc3BvbnNlLm5hbWUsIHJlc3BvbnNlLnJlYXNvbildKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICogcmVzcG9uc2UgPSB7Y29ubmVjdGlvbklkOiBzdHJpbmcsIHN0cmVhbUlkOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgZGF0YTogT2JqZWN0fVxuICAgICAqL1xuICAgIG9uRmlsdGVyRXZlbnREaXNwYXRjaGVkKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZDogc3RyaW5nID0gcmVzcG9uc2UuY29ubmVjdGlvbklkO1xuICAgICAgICBjb25zdCBzdHJlYW1JZDogc3RyaW5nID0gcmVzcG9uc2Uuc3RyZWFtSWQ7XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihjb25uZWN0aW9uSWQsICdObyBjb25uZWN0aW9uIGZvdW5kIGZvciBjb25uZWN0aW9uSWQgJyArIGNvbm5lY3Rpb25JZClcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbygnRmlsdGVyIGV2ZW50IGRpc3BhdGNoZWQnKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW06IFN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5maWx0ZXIuaGFuZGxlcnNbcmVzcG9uc2UuZXZlbnRUeXBlXShuZXcgRmlsdGVyRXZlbnQoc3RyZWFtLmZpbHRlciwgcmVzcG9uc2UuZXZlbnRUeXBlLCByZXNwb25zZS5kYXRhKSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgY29uc29sZS5pbmZvKCdMZWF2aW5nIFNlc3Npb24gKGZvcmNlZD0nICsgZm9yY2VkICsgJyknKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1lvdSB3ZXJlIG5vdCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIGNvbm5lY3RBdXgodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnN0YXJ0V3MoKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGpvaW5QYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogKCEhdG9rZW4pID8gdG9rZW4gOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb246IHRoaXMuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhdGZvcm06ICEhcGxhdGZvcm0uZGVzY3JpcHRpb24gPyBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA6ICd1bmtub3duJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKVxuICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2pvaW5Sb29tJywgam9pblBhcmFtcywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgY2FwYWJpbGl0aWVzIG9iamVjdCB3aXRoIHRoZSByb2xlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXBhYmlsaXRpZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlICE9PSAnU1VCU0NSSUJFUicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlVW5wdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZURpc2Nvbm5lY3Q6IHRoaXMub3BlbnZpZHUucm9sZSA9PT0gJ01PREVSQVRPUidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCB3aXRoIHZhbHVlcyByZXR1cm5lZCBieSBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNyZWF0aW9uVGltZSA9IHJlc3BvbnNlLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGF0YSA9IHJlc3BvbnNlLm1ldGFkYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5ycGNTZXNzaW9uSWQgPSByZXNwb25zZS5zZXNzaW9uSWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHJlbW90ZSBDb25uZWN0aW9ucyB3aXRoIHZhbHVlIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbnM6IG5ldyBBcnJheTxDb25uZWN0aW9uPigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBuZXcgQXJyYXk8U3RyZWFtPigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50czogQ29ubmVjdGlvbk9wdGlvbnNbXSA9IHJlc3BvbnNlLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnRzLmZvckVhY2gocGFydGljaXBhbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gbmV3IENvbm5lY3Rpb24odGhpcywgcGFydGljaXBhbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb24uY29ubmVjdGlvbklkXSA9IGNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zQ3JlYXRlZFtjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMucHVzaChjb25uZWN0aW9uLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE93biAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIHRoaXMuY29ubmVjdGlvbiwgJycpXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgJ2Nvbm5lY3Rpb25DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBleGlzdGluZyBjb25uZWN0aW9uIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLmZvckVhY2goY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnc3RyZWFtQ3JlYXRlZCcgZXZlbnQgZm9yIGVhY2ggYWN0aXZlIHN0cmVhbSBpbiB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zdHJlYW1zLmZvckVhY2goc3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW1vdGVDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIGNvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NUb2tlbih0b2tlbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gdG9rZW4ubWF0Y2goL14od3NzP1xcOilcXC9cXC8oKFteOlxcLz8jXSopKD86XFw6KFswLTldKykpPykoW1xcL117MCwxfVtePyNdKikoXFw/W14jXSp8KSgjLip8KSQvKTtcbiAgICAgICAgaWYgKCEhbWF0Y2gpIHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHtcbiAgICAgICAgICAgICAgICBwcm90b2NvbDogbWF0Y2hbMV0sXG4gICAgICAgICAgICAgICAgaG9zdDogbWF0Y2hbMl0sXG4gICAgICAgICAgICAgICAgaG9zdG5hbWU6IG1hdGNoWzNdLFxuICAgICAgICAgICAgICAgIHBvcnQ6IG1hdGNoWzRdLFxuICAgICAgICAgICAgICAgIHBhdGhuYW1lOiBtYXRjaFs1XSxcbiAgICAgICAgICAgICAgICBzZWFyY2g6IG1hdGNoWzZdLFxuICAgICAgICAgICAgICAgIGhhc2g6IG1hdGNoWzddXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB0b2tlbi5zcGxpdCgnPycpO1xuICAgICAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSBkZWNvZGVVUkkocGFyYW1zWzFdKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnJicpXG4gICAgICAgICAgICAgICAgLm1hcChwYXJhbSA9PiBwYXJhbS5zcGxpdCgnPScpKVxuICAgICAgICAgICAgICAgIC5yZWR1Y2UoKHZhbHVlcywgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlc1trZXldID0gdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlc1xuICAgICAgICAgICAgICAgIH0sIHt9KTtcblxuICAgICAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSA8c3RyaW5nPnF1ZXJ5UGFyYW1zWydzZXNzaW9uSWQnXTtcbiAgICAgICAgICAgIGNvbnN0IHNlY3JldCA9IHF1ZXJ5UGFyYW1zWydzZWNyZXQnXTtcbiAgICAgICAgICAgIGNvbnN0IHJlY29yZGVyID0gcXVlcnlQYXJhbXNbJ3JlY29yZGVyJ107XG4gICAgICAgICAgICBjb25zdCB0dXJuVXNlcm5hbWUgPSBxdWVyeVBhcmFtc1sndHVyblVzZXJuYW1lJ107XG4gICAgICAgICAgICBjb25zdCB0dXJuQ3JlZGVudGlhbCA9IHF1ZXJ5UGFyYW1zWyd0dXJuQ3JlZGVudGlhbCddO1xuICAgICAgICAgICAgY29uc3Qgcm9sZSA9IHF1ZXJ5UGFyYW1zWydyb2xlJ107XG4gICAgICAgICAgICBjb25zdCB3ZWJydGNTdGF0c0ludGVydmFsID0gcXVlcnlQYXJhbXNbJ3dlYnJ0Y1N0YXRzSW50ZXJ2YWwnXTtcbiAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1U2VydmVyVmVyc2lvbiA9IHF1ZXJ5UGFyYW1zWyd2ZXJzaW9uJ107XG5cbiAgICAgICAgICAgIGlmICghIXNlY3JldCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VjcmV0ID0gc2VjcmV0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhcmVjb3JkZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnJlY29yZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXR1cm5Vc2VybmFtZSAmJiAhIXR1cm5DcmVkZW50aWFsKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3R1blVybCA9ICdzdHVuOicgKyB1cmwuaG9zdG5hbWUgKyAnOjM0NzgnO1xuICAgICAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIHVybC5ob3N0bmFtZSArICc6MzQ3OCc7XG4gICAgICAgICAgICAgICAgY29uc3QgdHVyblVybDIgPSB0dXJuVXJsMSArICc/dHJhbnNwb3J0PXRjcCc7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5pY2VTZXJ2ZXJzID0gW1xuICAgICAgICAgICAgICAgICAgICB7IHVybHM6IFtzdHVuVXJsXSB9LFxuICAgICAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMSwgdHVyblVybDJdLCB1c2VybmFtZTogdHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiB0dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVFVSTiB0ZW1wIGNyZWRlbnRpYWxzIFsnICsgdHVyblVzZXJuYW1lICsgJzonICsgdHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhcm9sZSkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IHJvbGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF3ZWJydGNTdGF0c0ludGVydmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS53ZWJydGNTdGF0c0ludGVydmFsID0gK3dlYnJ0Y1N0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISFvcGVudmlkdVNlcnZlclZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJvcGVudmlkdS1zZXJ2ZXIgdmVyc2lvbjogXCIgKyBvcGVudmlkdVNlcnZlclZlcnNpb24pO1xuICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVNlcnZlclZlcnNpb24gIT09IHRoaXMub3BlbnZpZHUubGlicmFyeVZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignT3BlblZpZHUgU2VydmVyICgnICsgb3BlbnZpZHVTZXJ2ZXJWZXJzaW9uICtcbiAgICAgICAgICAgICAgICAgICAgICAgICcpIGFuZCBPcGVuVmlkdSBCcm93c2VyICgnICsgdGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbiArXG4gICAgICAgICAgICAgICAgICAgICAgICAnKSB2ZXJzaW9ucyBkbyBOT1QgbWF0Y2guIFRoZXJlIG1heSBiZSBpbmNvbXBhdGliaWxpdGllcycpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gJ3dzczovLycgKyB1cmwuaG9zdCArICcvb3BlbnZpZHUnO1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5odHRwVXJpID0gJ2h0dHBzOi8vJyArIHVybC5ob3N0O1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUb2tlbiBcIicgKyB0b2tlbiArICdcIiBpcyBub3QgdmFsaWQnKVxuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuL0ZpbHRlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNQZWVyL1dlYlJ0Y1BlZXInO1xuaW1wb3J0IHsgV2ViUnRjU3RhdHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1N0YXRzL1dlYlJ0Y1N0YXRzJztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIGltcGxlbWVudHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtLiBJZiB0aGUgc3RyZWFtIGJlbG9uZ3MgdG8gYS4uLlxuICAgICAqIC0gU3Vic2NyaWJlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgb25seSBkZWZpbmVkIGFmdGVyIHN1Y2Nlc3NmdWwgZXhlY3V0aW9uIG9mIFtbU2Vzc2lvbi5wdWJsaXNoXV1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgc3RyZWFtIHdhcyBjcmVhdGVkIGluIE9wZW5WaWR1IFNlcnZlciAoVVRDIG1pbGxpc2Vjb25kcykuIERlcGVuZGluZyBvbiB0aGUgb3duZXIgb2YgdGhpcyBzdHJlYW06XG4gICAgICogLSBTdWJzY3JpYmVyIG9iamVjdDogcHJvcGVydHkgYGNyZWF0aW9uVGltZWAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBjcmVhdGlvblRpbWVgIGlzIG9ubHkgZGVmaW5lZCBhZnRlciBzdWNjZXNzZnVsIGV4ZWN1dGlvbiBvZiBbW1Nlc3Npb24ucHVibGlzaF1dXG4gICAgICovXG4gICAgY3JlYXRpb25UaW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBgXCJDQU1FUkFcImAsIGBcIlNDUkVFTlwiYCBvciBgXCJDVVNUT01cImAgKHRoZSBsYXR0ZXIgd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBpcyBhIE1lZGlhU3RyZWFtVHJhY2sgd2hlbiBjYWxsaW5nIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dKS5cbiAgICAgKiBJZiBbW2hhc1ZpZGVvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICovXG4gICAgdHlwZU9mVmlkZW8/OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogKipXQVJOSU5HKio6IGV4cGVyaW1lbnRhbCBvcHRpb24uIFRoaXMgaW50ZXJmYWNlIG1heSBjaGFuZ2UgaW4gdGhlIG5lYXIgZnV0dXJlXG4gICAgICpcbiAgICAgKiBGaWx0ZXIgYXBwbGllZCB0byB0aGUgU3RyZWFtLiBZb3UgY2FuIGFwcGx5IGZpbHRlcnMgYnkgY2FsbGluZyBbW1N0cmVhbS5hcHBseUZpbHRlcl1dLCBleGVjdXRlIG1ldGhvZHMgb2YgdGhlIGFwcGxpZWQgZmlsdGVyIHdpdGhcbiAgICAgKiBbW0ZpbHRlci5leGVjTWV0aG9kXV0gYW5kIHJlbW92ZSBpdCB3aXRoIFtbU3RyZWFtLnJlbW92ZUZpbHRlcl1dLiBCZSBhd2FyZSB0aGF0IHRoZSBjbGllbnQgY2FsbGluZyB0aGlzIG1ldGhvZHMgbXVzdCBoYXZlIHRoZVxuICAgICAqIG5lY2Vzc2FyeSBwZXJtaXNzaW9uczogdGhlIHRva2VuIG93bmVkIGJ5IHRoZSBjbGllbnQgbXVzdCBoYXZlIGJlZW4gaW5pdGlhbGl6ZWQgd2l0aCB0aGUgYXBwcm9wcmlhdGVkIGBhbGxvd2VkRmlsdGVyc2AgYXJyYXkuXG4gICAgICovXG4gICAgZmlsdGVyOiBGaWx0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJpdmF0ZSBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluYm91bmRTdHJlYW1PcHRzOiBJbmJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNwZWVjaEV2ZW50OiBhbnk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdFdmVudEVuYWJsZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVyU3RvcFNwZWFraW5nRXZlbnRFbmFibGVkID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHZvbHVtZUNoYW5nZUV2ZW50RW5hYmxlZCA9IGZhbHNlO1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5jcmVhdGlvblRpbWUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzVmlkZW87XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmF1ZGlvQWN0aXZlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy52aWRlb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvKSA/IHVuZGVmaW5lZCA6IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSAodGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGUgPT09IC0xKSA/IHVuZGVmaW5lZCA6IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9EaW1lbnNpb25zID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZpbHRlciAmJiAoT2JqZWN0LmtleXModGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIpLmxlbmd0aCA+IDApKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2QgJiYgT2JqZWN0LmtleXModGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2QpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdXRib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgUHVibGlzaGVyXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IDxPdXRib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcblxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZpbHRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIHRoaXMuZWUub24odHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgYnkgc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtSWQgKyBcIidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW1JZCArIFwiJ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICB0aGlzLmVlLm9uY2UodHlwZSwgZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZSBieSBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW1JZCArIFwiJ1wiLCBldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIG9uY2UgYnkgc3RyZWFtICdcIiArIHRoaXMuc3RyZWFtSWQgKyBcIidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgaGFuZGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGFuIGF1ZGlvL3ZpZGVvIGZpbHRlciB0byB0aGUgc3RyZWFtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHR5cGUgVHlwZSBvZiBmaWx0ZXIgYXBwbGllZC4gU2VlIFtbRmlsdGVyLnR5cGVdXVxuICAgICAqIEBwYXJhbSBvcHRpb25zIFBhcmFtZXRlcnMgdXNlZCB0byBpbml0aWFsaXplIHRoZSBmaWx0ZXIuIFNlZSBbW0ZpbHRlci5vcHRpb25zXV1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB0byB0aGUgYXBwbGllZCBmaWx0ZXIgaWYgc3VjY2VzcyBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgYXBwbHlGaWx0ZXIodHlwZTogc3RyaW5nLCBvcHRpb25zOiBPYmplY3QpOiBQcm9taXNlPEZpbHRlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdBcHBseWluZyBmaWx0ZXIgdG8gc3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIG9wdGlvbnMgPSAhIW9wdGlvbnMgPyBvcHRpb25zIDoge307XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdhcHBseUZpbHRlcicsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogdGhpcy5zdHJlYW1JZCwgdHlwZSwgb3B0aW9ucyB9LFxuICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhcHBseWluZyBmaWx0ZXIgZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBhcHBseSBhIGZpbHRlclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZpbHRlciBzdWNjZXNzZnVsbHkgYXBwbGllZCBvbiBTdHJlYW0gJyArIHRoaXMuc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWU6IEZpbHRlciA9IHRoaXMuZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIgPSBuZXcgRmlsdGVyKHR5cGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIuc3RyZWFtID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zZXNzaW9uLCB0aGlzLCAnZmlsdGVyJywgdGhpcy5maWx0ZXIsIG9sZFZhbHVlLCAnYXBwbHlGaWx0ZXInKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciwgb2xkVmFsdWUsICdhcHBseUZpbHRlcicpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuZmlsdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW4gYXVkaW8vdmlkZW8gZmlsdGVyIHByZXZpb3VzbHkgYXBwbGllZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcHJldmlvdXNseSBhcHBsaWVkIGZpbHRlciBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaW4gb3RoZXIgY2FzZVxuICAgICAqL1xuICAgIHJlbW92ZUZpbHRlcigpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKCdSZW1vdmluZyBmaWx0ZXIgb2Ygc3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAncmVtb3ZlRmlsdGVyJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHJlbW92aW5nIGZpbHRlciBmb3IgU3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHJlbW92ZSBhIGZpbHRlclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oJ0ZpbHRlciBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBmcm9tIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHRoaXMuZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciwgb2xkVmFsdWUsICdhcHBseUZpbHRlcicpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc3RyZWFtTWFuYWdlciwgdGhpcywgJ2ZpbHRlcicsIHRoaXMuZmlsdGVyLCBvbGRWYWx1ZSwgJ2FwcGx5RmlsdGVyJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TWVkaWFTdHJlYW0oKTogTWVkaWFTdHJlYW0ge1xuICAgICAgICByZXR1cm4gdGhpcy5tZWRpYVN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0TWVkaWFTdHJlYW0obWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBtZWRpYVN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdXBkYXRlTWVkaWFTdHJlYW1JblZpZGVvcygpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJUQ1BlZXJDb25uZWN0aW9uKCk6IFJUQ1BlZXJDb25uZWN0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5wYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID0gb3V0Ym91bmRTdHJlYW1PcHRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKClcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VXZWJSdGNQZWVyKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1BlZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGlzU2VuZGVyQW5kQ3VzdG9tVHJhY2s6IGJvb2xlYW4gPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmRpc3Bvc2UoaXNTZW5kZXJBbmRDdXN0b21UcmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zcGVlY2hFdmVudC5zdG9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zcGVlY2hFdmVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiV2ViUlRDUGVlciBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgc2NyZWVuID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbic7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5uYW1lID09PSAnRWxlY3Ryb24nKSB7XG4gICAgICAgICAgICBzY3JlZW4gPSB0eXBlb2YgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlLnN0YXJ0c1dpdGgoJ3NjcmVlbjonKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJiBzY3JlZW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldFNwZWVjaEV2ZW50SWZOb3RFeGlzdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLmludGVydmFsID0gKHR5cGVvZiBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gaGFya09wdGlvbnMuaW50ZXJ2YWwgOiA1MDtcbiAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50ID0gaGFyayh0aGlzLm1lZGlhU3RyZWFtLCBoYXJrT3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW5hYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0U3BlZWNoRXZlbnRJZk5vdEV4aXN0cygpO1xuICAgICAgICBpZiAoIXRoaXMucHVibGlzaGVyU3RhcnRTcGVha2luZ0V2ZW50RW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5wdWJsaXNoZXJTdGFydFNwZWFraW5nRXZlbnRFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5wdWJsaXNoZXJTdG9wU3BlYWtpbmdFdmVudEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHVibGlzaGVyU3RvcFNwZWFraW5nRXZlbnRFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VTcGVha2luZ0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy5wdWJsaXNoZXJTdGFydFNwZWFraW5nRXZlbnRFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnB1Ymxpc2hlclN0YXJ0U3BlYWtpbmdFdmVudEVuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbmNlKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNhYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5wdWJsaXNoZXJTdG9wU3BlYWtpbmdFdmVudEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHVibGlzaGVyU3RvcFNwZWFraW5nRXZlbnRFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub25jZSgnc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZVNwZWFraW5nRXZlbnRzKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlU3BlYWtpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZvbHVtZUNoYW5nZUV2ZW50RW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIC8vICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScgZXZlbnQgaXMgZW5hYmxlZC4gQ2Fubm90IHN0b3AgdGhlIGhhcmsgcHJvY2Vzc1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCdzcGVha2luZycpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNwZWVjaEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMucHVibGlzaGVyU3RhcnRTcGVha2luZ0V2ZW50RW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnB1Ymxpc2hlclN0b3BTcGVha2luZ0V2ZW50RW5hYmxlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVWb2x1bWVDaGFuZ2VFdmVudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy52b2x1bWVDaGFuZ2VFdmVudEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMudm9sdW1lQ2hhbmdlRXZlbnRFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3ZvbHVtZV9jaGFuZ2UnLCBoYXJrRXZlbnQgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlID0gdGhpcy5zcGVlY2hFdmVudC5vbGRWb2x1bWVWYWx1ZTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHsgbmV3VmFsdWU6IGhhcmtFdmVudCwgb2xkVmFsdWUgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlID0gaGFya0V2ZW50O1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnLCB2YWx1ZSldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VWb2x1bWVDaGFuZ2VFdmVudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRTcGVlY2hFdmVudElmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy52b2x1bWVDaGFuZ2VFdmVudEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMudm9sdW1lQ2hhbmdlRXZlbnRFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub25jZSgndm9sdW1lX2NoYW5nZScsIGhhcmtFdmVudCA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0geyBuZXdWYWx1ZTogaGFya0V2ZW50LCBvbGRWYWx1ZSB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2xkVm9sdW1lVmFsdWUgPSBoYXJrRXZlbnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNhYmxlVm9sdW1lQ2hhbmdlRXZlbnQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMuc3RyZWFtTWFuYWdlciwgJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJywgdmFsdWUpXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhYmxlVm9sdW1lQ2hhbmdlRXZlbnQoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24uc3BlYWtpbmdFdmVudHNFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnIGFuZC9vciBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgIGV2ZW50cyBhcmUgZW5hYmxlZC4gQ2Fubm90IHN0b3AgdGhlIGhhcmsgcHJvY2Vzc1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCd2b2x1bWVfY2hhbmdlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNwZWVjaEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMudm9sdW1lQ2hhbmdlRXZlbnRFbmFibGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWwoKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGluYm91bmQgb3B0aW9ucyB1bmRlZmluZWQgYW5kIG91dGJvdW5kIG9wdGlvbnMgZGVmaW5lZFxuICAgICAgICByZXR1cm4gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzICYmICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRTZWxlY3RlZEljZUNhbmRpZGF0ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5nZXRTZWxlY3RlZEljZUNhbmRpZGF0ZUluZm8oKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlcG9ydCA9PiByZXNvbHZlKHJlcG9ydCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0UmVtb3RlSWNlQ2FuZGlkYXRlTGlzdCgpOiBSVENJY2VDYW5kaWRhdGVbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBpbml0V2ViUnRjUGVlclNlbmQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3QgdXNlck1lZGlhQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgYXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5pc1NlbmRWaWRlbygpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBvcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IHVzZXJNZWRpYUNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIG9uaWNlY2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBsZXQgdHlwZU9mVmlkZW8gPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwdWJsaXNoVmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtLFxuICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBoYXNBdWRpbzogdGhpcy5pc1NlbmRBdWRpbygpLFxuICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHRoaXMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6IEpTT04uc3RyaW5naWZ5KHRoaXMudmlkZW9EaW1lbnNpb25zKSxcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyOiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZpbHRlclxuICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIHB1Ymxpc2hcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0Fuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIsIGZhbHNlKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IHJlc3BvbnNlLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1jcmVhdGVkLWJ5LXB1Ymxpc2hlcicsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIidQdWJsaXNoZXInIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgdG8gc2Vzc2lvblwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KG9wdGlvbnMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKS50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhwdWJsaXNoKSBTRFAgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRXZWJSdGNQZWVyUmVjZWl2ZSgpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBvZmZlckNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgIHZpZGVvOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWQuIENvbnN0cmFpbnRzIG9mIGdlbmVyYXRlIFNEUCBvZmZlclwiLFxuICAgICAgICAgICAgICAgIG9mZmVyQ29uc3RyYWludHMpO1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBvbmljZWNhbmRpZGF0ZTogdGhpcy5jb25uZWN0aW9uLnNlbmRJY2VDYW5kaWRhdGUuYmluZCh0aGlzLmNvbm5lY3Rpb24pLFxuICAgICAgICAgICAgICAgIG1lZGlhQ29uc3RyYWludHM6IG9mZmVyQ29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2VcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gc3Vic2NyaWJlIHRvICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3JlY2VpdmVWaWRlb0Zyb20nLCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gcmVjdlZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW9zIElvbmljLiBMaW1pdGF0aW9uOiBzb21lIGJ1ZyBpbiBpb3NydGMgY29yZG92YSBwbHVnaW4gbWFrZXMgaXQgbmVjZXNzYXJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0byBhZGQgYSB0aW1lb3V0IGJlZm9yZSBjYWxsaW5nIFBlZXJDb25uZWN0aW9uI3NldFJlbW90ZURlc2NyaXB0aW9uIGR1cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc29tZSB0aW1lICg0MDAgbXMpIGZyb20gdGhlIG1vbWVudCBmaXJzdCBzdWJzY3JpYmVyIHN0cmVhbSBpcyByZWNlaXZlZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5pc0ZpcnN0SW9uaWNJb3NTdWJzY3JpYmVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmlzRmlyc3RJb25pY0lvc1N1YnNjcmliZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWZ0ZXIgNDAwIG1zIElvbmljIGlPUyBzdWJzY3JpYmVycyB3b24ndCBuZWVkIHRvIHJ1blxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQZWVyQ29ubmVjdGlvbiNzZXRSZW1vdGVEZXNjcmlwdGlvbiBhZnRlciAyNTAgbXMgdGltZW91dCBhbnltb3JlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5jb3VudERvd25Gb3JJb25pY0lvc1N1YnNjcmliZXJzQWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgNDAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5lZWRzVGltZW91dE9uUHJvY2Vzc0Fuc3dlciA9IHRoaXMuc2Vzc2lvbi5jb3VudERvd25Gb3JJb25pY0lvc1N1YnNjcmliZXJzQWN0aXZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyLCBuZWVkc1RpbWVvdXRPblByb2Nlc3NBbnN3ZXIpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlUGVlclN1Y2Nlc3NmdWxseUVzdGFibGlzaGVkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmdlbmVyYXRlT2ZmZXIoKVxuICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtWydpc0lvbmljSW9zJ10pIHtcbiAgICAgICAgICAgIC8vIGlPUyBJb25pYy4gTElNSVRBVElPTjogbXVzdCB1c2UgZGVwcmVjYXRlZCBXZWJSVEMgQVBJXG4gICAgICAgICAgICBjb25zdCBwYzE6IGFueSA9IHRoaXMud2ViUnRjUGVlci5wYztcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBwYzEuZ2V0UmVtb3RlU3RyZWFtcygpWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG5ldyBNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgbGV0IHJlY2VpdmVyOiBSVENSdHBSZWNlaXZlcjtcbiAgICAgICAgICAgIGZvciAocmVjZWl2ZXIgb2YgdGhpcy53ZWJSdGNQZWVyLnBjLmdldFJlY2VpdmVycygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZXIudHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5hZGRUcmFjayhyZWNlaXZlci50cmFjayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1BlZXIgcmVtb3RlIHN0cmVhbScsIHRoaXMubWVkaWFTdHJlYW0pO1xuXG4gICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0pIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtTWFuYWdlciBpbnN0YW5jZW9mIFN1YnNjcmliZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBBcHBseSBTdWJzY3JpYmVyUHJvcGVydGllcy5zdWJzY3JpYmVUb0F1ZGlvIGFuZCBTdWJzY3JpYmVyUHJvcGVydGllcy5zdWJzY3JpYmVUb1ZpZGVvXG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAhISgoPFN1YnNjcmliZXI+dGhpcy5zdHJlYW1NYW5hZ2VyKS5wcm9wZXJ0aWVzLnN1YnNjcmliZVRvQXVkaW8pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0uZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmFibGVkID0gISEoKDxTdWJzY3JpYmVyPnRoaXMuc3RyZWFtTWFuYWdlcikucHJvcGVydGllcy5zdWJzY3JpYmVUb1ZpZGVvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZGlzcGxheU15UmVtb3RlKCkgJiYgISF0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF0gJiYgdGhpcy5zZXNzaW9uLnNwZWFraW5nRXZlbnRzRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU3BlYWtpbmdFdmVudHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzID0gbmV3IFdlYlJ0Y1N0YXRzKHRoaXMpO1xuICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLmluaXRXZWJSdGNTdGF0cygpO1xuXG4gICAgICAgIC8vVE9ETzogc2VuZCBjb21tb24gd2VicnRjIHN0YXRzIGZyb20gY2xpZW50IHRvIG9wZW52aWR1LXNlcnZlclxuICAgICAgICAvKmlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUud2VicnRjU3RhdHNJbnRlcnZhbCA+IDApIHtcbiAgICAgICAgICAgIHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmdhdGhlclN0YXRzRm9yUGVlcigpLnRoZW4oanNvblN0YXRzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYm9keSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlc3Npb25JZDogdGhpcy5zZXNzaW9uLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpY2lwYW50UHJpdmF0ZUlkOiB0aGlzLmNvbm5lY3Rpb24ucnBjU2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHM6IGpzb25TdGF0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgeGhyLm9wZW4oJ1BPU1QnLCB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaHR0cFVyaSArICcvZWxhc3RpY3NlYXJjaC93ZWJydGMtc3RhdHMnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgICAgICAgICAgICAgICAgIHhoci5zZW5kKEpTT04uc3RyaW5naWZ5KGJvZHkpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSwgdGhpcy5zZXNzaW9uLm9wZW52aWR1LndlYnJ0Y1N0YXRzSW50ZXJ2YWwgKiAxMDAwKTtcbiAgICAgICAgfSovXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wV2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMud2ViUnRjU3RhdHMgJiYgdGhpcy53ZWJSdGNTdGF0cy5pc0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5zdG9wV2ViUnRjU3RhdHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0SWNlU2VydmVyc0NvbmYoKTogUlRDSWNlU2VydmVyW10gfCB1bmRlZmluZWQge1xuICAgICAgICBsZXQgcmV0dXJuVmFsdWU7XG4gICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMgPT09ICdmcmVlaWNlJyA/XG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmljZVNlcnZlcnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnYXRoZXJTdGF0c0ZvclBlZXIoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTG9jYWwoKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gUHVibGlzaGVyIHN0cmVhbSBzdGF0c1xuXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRSVENQZWVyQ29ubmVjdGlvbigpLmdldFNlbmRlcnMoKS5mb3JFYWNoKHNlbmRlciA9PiBzZW5kZXIuZ2V0U3RhdHMoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5mb3JFYWNoKHJlcG9ydCA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNSZXBvcnRXYW50ZWQocmVwb3J0KSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaW5hbFJlcG9ydCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndHlwZSddID0gcmVwb3J0LnR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndGltZXN0YW1wJ10gPSByZXBvcnQudGltZXN0YW1wO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2lkJ10gPSByZXBvcnQuaWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvbW1vbiB0byBDaHJvbWUsIEZpcmVmb3ggYW5kIFNhZmFyaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC50eXBlID09PSAnb3V0Ym91bmQtcnRwJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0Wydzc3JjJ10gPSByZXBvcnQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnZmlyQ291bnQnXSA9IHJlcG9ydC5maXJDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncGxpQ291bnQnXSA9IHJlcG9ydC5wbGlDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbmFja0NvdW50J10gPSByZXBvcnQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydxcFN1bSddID0gcmVwb3J0LnFwU3VtO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IG1lZGlhIHR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFyZXBvcnQua2luZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSByZXBvcnQua2luZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCEhcmVwb3J0Lm1lZGlhVHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSByZXBvcnQubWVkaWFUeXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSBkb2VzIG5vdCBoYXZlICdtZWRpYVR5cGUnIGRlZmluZWQgZm9yIGluYm91bmQtcnRwLiBNdXN0IGJlIGluZmVycmVkIGZyb20gJ2lkJyBmaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSAocmVwb3J0LmlkLmluZGV4T2YoJ1ZpZGVvU3RyZWFtJykgIT09IC0xKSA/ICd2aWRlbycgOiAnYXVkaW8nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2ZyYW1lc0VuY29kZWQnXSA9IHJlcG9ydC5mcmFtZXNFbmNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydwYWNrZXRzU2VudCddID0gcmVwb3J0LnBhY2tldHNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydieXRlc1NlbnQnXSA9IHJlcG9ydC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgZm9yIENocm9tZSBhbmQgU2FmYXJpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT09ICdjYW5kaWRhdGUtcGFpcicgJiYgcmVwb3J0LnRvdGFsUm91bmRUcmlwVGltZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgZmluYWwgc2VsZWN0ZWQgY2FuZGlkYXRlIHBhaXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYXZhaWxhYmxlT3V0Z29pbmdCaXRyYXRlJ10gPSByZXBvcnQuYXZhaWxhYmxlT3V0Z29pbmdCaXRyYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydydHQnXSA9IHJlcG9ydC5jdXJyZW50Um91bmRUcmlwVGltZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYXZlcmFnZVJ0dCddID0gcmVwb3J0LnRvdGFsUm91bmRUcmlwVGltZSAvIHJlcG9ydC5yZXNwb25zZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmb3IgRmlyZWZveCA+PSA2Ni4wXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT09ICdyZW1vdGUtaW5ib3VuZC1ydHAnIHx8IHJlcG9ydC50eXBlID09PSAncmVtb3RlLW91dGJvdW5kLXJ0cCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhmaW5hbFJlcG9ydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBTdWJzY3JpYmVyIHN0cmVhbSBzdGF0c1xuXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRSVENQZWVyQ29ubmVjdGlvbigpLmdldFJlY2VpdmVycygpLmZvckVhY2gocmVjZWl2ZXIgPT4gcmVjZWl2ZXIuZ2V0U3RhdHMoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5mb3JFYWNoKHJlcG9ydCA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNSZXBvcnRXYW50ZWQocmVwb3J0KSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaW5hbFJlcG9ydCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndHlwZSddID0gcmVwb3J0LnR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndGltZXN0YW1wJ10gPSByZXBvcnQudGltZXN0YW1wO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2lkJ10gPSByZXBvcnQuaWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvbW1vbiB0byBDaHJvbWUsIEZpcmVmb3ggYW5kIFNhZmFyaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3NzcmMnXSA9IHJlcG9ydC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydmaXJDb3VudCddID0gcmVwb3J0LmZpckNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydwbGlDb3VudCddID0gcmVwb3J0LnBsaUNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WyduYWNrQ291bnQnXSA9IHJlcG9ydC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3FwU3VtJ10gPSByZXBvcnQucXBTdW07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgbWVkaWEgdHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlcG9ydC5raW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5raW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISFyZXBvcnQubWVkaWFUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5tZWRpYVR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIGRvZXMgbm90IGhhdmUgJ21lZGlhVHlwZScgZGVmaW5lZCBmb3IgaW5ib3VuZC1ydHAuIE11c3QgYmUgaW5mZXJyZWQgZnJvbSAnaWQnIGZpZWxkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IChyZXBvcnQuaWQuaW5kZXhPZignVmlkZW9TdHJlYW0nKSAhPT0gLTEpID8gJ3ZpZGVvJyA6ICdhdWRpbyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnZnJhbWVzRGVjb2RlZCddID0gcmVwb3J0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3BhY2tldHNSZWNlaXZlZCddID0gcmVwb3J0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncGFja2V0c0xvc3QnXSA9IHJlcG9ydC5wYWNrZXRzTG9zdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnaml0dGVyJ10gPSByZXBvcnQuaml0dGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydieXRlc1JlY2VpdmVkJ10gPSByZXBvcnQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmb3IgQ2hyb21lIGFuZCBTYWZhcmlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ2NhbmRpZGF0ZS1wYWlyJyAmJiByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBmaW5hbCBzZWxlY3RlZCBjYW5kaWRhdGUgcGFpclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmFpbGFibGVJbmNvbWluZ0JpdHJhdGUnXSA9IHJlcG9ydC5hdmFpbGFibGVJbmNvbWluZ0JpdHJhdGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3J0dCddID0gcmVwb3J0LmN1cnJlbnRSb3VuZFRyaXBUaW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmVyYWdlUnR0J10gPSByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lIC8gcmVwb3J0LnJlc3BvbnNlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGZvciBGaXJlZm94ID49IDY2LjBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ3JlbW90ZS1pbmJvdW5kLXJ0cCcgfHwgcmVwb3J0LnR5cGUgPT09ICdyZW1vdGUtb3V0Ym91bmQtcnRwJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhmaW5hbFJlcG9ydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNSZXBvcnRXYW50ZWQocmVwb3J0OiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHJlcG9ydC50eXBlID09PSAnaW5ib3VuZC1ydHAnICYmICF0aGlzLmlzTG9jYWwoKSB8fFxuICAgICAgICAgICAgcmVwb3J0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnICYmIHRoaXMuaXNMb2NhbCgpIHx8XG4gICAgICAgICAgICAocmVwb3J0LnR5cGUgPT09ICdjYW5kaWRhdGUtcGFpcicgJiYgcmVwb3J0Lm5vbWluYXRlZCAmJiByZXBvcnQuYnl0ZXNTZW50ID4gMCk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBWaWRlb0VsZW1lbnRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1ZpZGVvRWxlbWVudEV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcblxuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG5pbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG4vKipcbiAqIEludGVyZmFjZSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGUgbWVkaWEgc3RyZWFtcyBpbiB0aGUgSFRNTCBET00uIFRoaXMgd3JhcHMgYW55IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAqIFlvdSBjYW4gaW5zZXJ0IGFzIG1hbnkgdmlkZW8gcGxheWVycyBmbyB0aGUgc2FtZSBTdHJlYW0gYXMgeW91IHdhbnQgYnkgY2FsbGluZyBbW1N0cmVhbU1hbmFnZXIuYWRkVmlkZW9FbGVtZW50XV0gb3JcbiAqIFtbU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnRdXS5cbiAqXG4gKiBUaGUgdXNlIG9mIFN0cmVhbU1hbmFnZXIgd3JhcHBlciBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIHdoZW4geW91IGRvbid0IG5lZWQgdG8gZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFB1Ymxpc2hlciBvciBTdWJzY3JpYmVyIHN0cmVhbXMgb3IganVzdFxuICogd2FudCB0byBkaXJlY3RseSBtYW5hZ2UgeW91ciBvd24gdmlkZW8gZWxlbWVudHMgKGV2ZW4gbW9yZSB0aGFuIG9uZSB2aWRlbyBlbGVtZW50IHBlciBTdHJlYW0pLiBUaGlzIHNjZW5hcmlvIGlzIHByZXR0eSBjb21tb24gaW5cbiAqIGRlY2xhcmF0aXZlLCBNVkMgZnJvbnRlbmQgZnJhbWV3b3JrcyBzdWNoIGFzIEFuZ3VsYXIsIFJlYWN0IG9yIFZ1ZS5qc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlciBpbXBsZW1lbnRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpcnN0VmlkZW9FbGVtZW50OiBTdHJlYW1NYW5hZ2VyVmlkZW87XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY2FuUGxheUxpc3RlbmVyOiBFdmVudExpc3RlbmVyO1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ/OiBIVE1MRWxlbWVudCB8IHN0cmluZykge1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlciA9IHRoaXM7XG4gICAgICAgIHRoaXMucmVtb3RlID0gIXRoaXMuc3RyZWFtLmlzTG9jYWwoKTtcblxuICAgICAgICBpZiAoISF0YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBsZXQgdGFyZ0VsO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSB0YXJnZXRFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0YXJnRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcnN0VmlkZW9FbGVtZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpLFxuICAgICAgICAgICAgICAgICAgICBpZDogJycsXG4gICAgICAgICAgICAgICAgICAgIGNhbnBsYXlMaXN0ZW5lckFkZGVkOiBmYWxzZVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgPT09ICdTYWZhcmknKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudmlkZW8uc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNhblBsYXlMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIllvdXIgbG9jYWwgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMsICdzdHJlYW1QbGF5aW5nJywgdW5kZWZpbmVkKV0pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnXCIgKyAodGhpcy5yZW1vdGUgPyAnU3Vic2NyaWJlcicgOiAnUHVibGlzaGVyJykgKyBcIidcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnXCIgKyAodGhpcy5yZW1vdGUgPyAnU3Vic2NyaWJlcicgOiAnUHVibGlzaGVyJykgKyBcIidcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzLCAnc3RyZWFtUGxheWluZycsIHVuZGVmaW5lZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScgJiYgdGhpcy5zdHJlYW0uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVuYWJsZVZvbHVtZUNoYW5nZUV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogU3RyZWFtTWFuYWdlciB7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBldmVudCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKFwiRXZlbnQgJ1wiICsgdHlwZSArIFwiJyB0cmlnZ2VyZWQgb25jZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJyB8fCB0eXBlID09PSAndmlkZW9QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMsICdzdHJlYW1QbGF5aW5nJywgdW5kZWZpbmVkKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJyAmJiB0aGlzLnN0cmVhbS5oYXNBdWRpbykge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZW5hYmxlT25jZVZvbHVtZUNoYW5nZUV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9mZl1dXG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBTdHJlYW1NYW5hZ2VyIHtcbiAgICAgICAgaWYgKCFoYW5kbGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVlLnJlbW92ZUFsbExpc3RlbmVycyh0eXBlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZWUub2ZmKHR5cGUsIGhhbmRsZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc2FibGVWb2x1bWVDaGFuZ2VFdmVudCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2RvY3MvaG93LWRvLWkvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNMb2NhbCgpICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICBpZiAodmlkZW8uc3JjT2JqZWN0ICE9PSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKSB7XG4gICAgICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZCxcbiAgICAgICAgICAgIGNhbnBsYXlMaXN0ZW5lckFkZGVkOiBmYWxzZVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zb2xlLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgSFRNTFZpZGVvRWxlbWVudFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgbGV0IGluc01vZGUgPSAhIWluc2VydE1vZGUgPyBpbnNlcnRNb2RlIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgc3dpdGNoIChpbnNNb2RlKSB7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BRlRFUjpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFQUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQkVGT1JFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUFJFUEVORDpcbiAgICAgICAgICAgICAgICB0YXJnRWwuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5SRVBMQUNFOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEucmVwbGFjZUNoaWxkKHZpZGVvLCB0YXJnRWwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpbnNNb2RlID0gVmlkZW9JbnNlcnRNb2RlLkFQUEVORDtcbiAgICAgICAgICAgICAgICB0YXJnRWwuYXBwZW5kQ2hpbGQodmlkZW8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdjogU3RyZWFtTWFuYWdlclZpZGVvID0ge1xuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpbnNlcnRNb2RlOiBpbnNNb2RlLFxuICAgICAgICAgICAgaWQ6IHZpZGVvLmlkLFxuICAgICAgICAgICAgY2FucGxheUxpc3RlbmVyQWRkZWQ6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh2KTtcblxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodi52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSAhIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQ7XG5cbiAgICAgICAgcmV0dXJuIHZpZGVvO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGlmICghKHRoaXMuc3RyZWFtLmlzTG9jYWwoKSAmJiB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkpIHtcbiAgICAgICAgICAgIC8vIEF2b2lkIHNldHRpbmcgdGhlIE1lZGlhU3RyZWFtIGludG8gdGhlIHNyY09iamVjdCBpZiByZW1vdGUgc3Vic2NyaXB0aW9uIGJlZm9yZSBwdWJsaXNoaW5nXG4gICAgICAgICAgICBpZiAodmlkZW8uc3JjT2JqZWN0ICE9PSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgc3JjT2JqZWN0IGFscmVhZHkgc2V0IGRvbid0IGRvIGl0IGFnYWluXG4gICAgICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2aWRlby5hdXRvcGxheSA9IHRydWU7XG4gICAgICAgIHZpZGVvLmNvbnRyb2xzID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgPT09ICdTYWZhcmknKSB7XG4gICAgICAgICAgICB2aWRlby5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJ3RydWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcdFxuICAgICAgICAgICAgaWYgKCF0aGlzLmlkICYmICEhdGhpcy50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pZCA9IHZpZGVvLmlkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh2aWRlby5zdHlsZS50cmFuc2Zvcm0gPT09ICdyb3RhdGVZKDE4MGRlZyknICYmICF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgcm90YXRlZCBhbmQgbm93IGlzIHNldCB0byBub3QgbWlycm9yXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVNaXJyb3JWaWRlbyh2aWRlbyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvciAmJiAhdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIGxpc3RlbmVyLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKCdjYW5wbGF5JywgdGhpcy5jYW5QbGF5TGlzdGVuZXIpO1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLmNhbnBsYXlMaXN0ZW5lckFkZGVkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoISFzdHJlYW1NYW5hZ2VyVmlkZW8udGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVtb3ZlIGZyb20gRE9NIHZpZGVvcyBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIgKHRob3NlIGdlbmVyYXRlZCBieSBwYXNzaW5nIGEgdmFsaWQgdGFyZ2V0RWxlbWVudCBpbiBPcGVuVmlkdS5pbml0UHVibGlzaGVyXG4gICAgICAgICAgICAgICAgLy8gYW5kIFNlc3Npb24uc3Vic2NyaWJlIG9yIHRob3NlIGNyZWF0ZWQgYnkgU3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQpLiBBbGwgdGhpcyB2aWRlb3MgdHJpZ2dlcmVkIGEgdmlkZW9FbGVtZW50Q3JlYXRlZCBldmVudFxuICAgICAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnROb2RlIS5yZW1vdmVDaGlsZChzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnREZXN0cm95ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSZW1vdmUgc3JjT2JqZWN0IGZyb20gdGhlIHZpZGVvXG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8udmlkZW8uc3JjT2JqZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBmcm9tIGNvbGxlY3Rpb24gb2YgdmlkZW9zIGV2ZXJ5IHZpZGVvIG1hbmFnZWQgYnkgT3BlblZpZHUgQnJvd3NlclxuICAgICAgICAgICAgdGhpcy52aWRlb3MuZmlsdGVyKHYgPT4gIXYudGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNhc3NvY2lhdGVWaWRlbyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgZGlzYXNzb2NpYXRlZCA9IGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMudmlkZW9zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbaV0udmlkZW8gPT09IHZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbaV0udmlkZW8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgZGlzYXNzb2NpYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAoIXRoaXMudmlkZW9zWzBdLmNhbnBsYXlMaXN0ZW5lckFkZGVkKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uYWRkRXZlbnRMaXN0ZW5lcignY2FucGxheScsIHRoaXMuY2FuUGxheUxpc3RlbmVyKTtcbiAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLmNhbnBsYXlMaXN0ZW5lckFkZGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB1cGRhdGVNZWRpYVN0cmVhbShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgICAgICAgICAgaWYgKHBsYXRmb3JtWydpc0lvbmljSW9zJ10pIHtcbiAgICAgICAgICAgICAgICAvLyBpT1MgSW9uaWMuIExJTUlUQVRJT046IG11c3QgcmVpbnNlcnQgdGhlIHZpZGVvIGluIHRoZSBET00gZm9yXG4gICAgICAgICAgICAgICAgLy8gdGhlIG1lZGlhIHN0cmVhbSB0byBiZSB1cGRhdGVkXG4gICAgICAgICAgICAgICAgY29uc3QgdlBhcmVudCA9IHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1ZpZGVvID0gc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvO1xuICAgICAgICAgICAgICAgIHZQYXJlbnQhIS5yZXBsYWNlQ2hpbGQobmV3VmlkZW8sIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvID0gbmV3VmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oc3RyZWFtTWFuYWdlclZpZGVvOiBTdHJlYW1NYW5hZ2VyVmlkZW8pIHtcbiAgICAgICAgdGhpcy52aWRlb3MucHVzaChzdHJlYW1NYW5hZ2VyVmlkZW8pO1xuICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5pbmRleE9mKHRoaXMpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5wdXNoKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICBpZiAoIXBsYXRmb3JtWydpc0lvbmljSW9zJ10pIHtcbiAgICAgICAgICAgIHZpZGVvLnN0eWxlLnRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgICAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW92ZU1pcnJvclZpZGVvKHZpZGVvKTogdm9pZCB7XG4gICAgICAgIHZpZGVvLnN0eWxlLnRyYW5zZm9ybSA9ICd1bnNldCc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICd1bnNldCc7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5cblxuLyoqXG4gKiBQYWNrcyByZW1vdGUgbWVkaWEgc3RyZWFtcy4gUGFydGljaXBhbnRzIGF1dG9tYXRpY2FsbHkgcmVjZWl2ZSB0aGVtIHdoZW4gb3RoZXJzIHB1Ymxpc2ggdGhlaXIgc3RyZWFtcy4gSW5pdGlhbGl6ZWQgd2l0aCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gbWV0aG9kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJzY3JpYmVyIGV4dGVuZHMgU3RyZWFtTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXM7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc3RyZWFtOiBTdHJlYW0sIHRhcmdFbDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKSB7XG4gICAgICAgIHN1cGVyKHN0cmVhbSwgdGFyZ0VsKTtcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gdGhpcy50YXJnZXRFbGVtZW50O1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgb3IgdW5zdWJzY3JpYmUgZnJvbSB0aGUgYXVkaW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBzdWJzY3JpYmUgdG8gdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnN1YnNjcmliZSBmcm9tIGl0XG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9BdWRpbyh2YWx1ZTogYm9vbGVhbik6IFN1YnNjcmliZXIge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidTdWJzY3JpYmVyJyBoYXMgXCIgKyAodmFsdWUgPyAnc3Vic2NyaWJlZCB0bycgOiAndW5zdWJzY3JpYmVkIGZyb20nKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgb3IgdW5zdWJzY3JpYmUgZnJvbSB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBzdWJzY3JpYmUgdG8gdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnN1YnNjcmliZSBmcm9tIGl0XG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9WaWRlbyh2YWx1ZTogYm9vbGVhbik6IFN1YnNjcmliZXIge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIidTdWJzY3JpYmVyJyBoYXMgXCIgKyAodmFsdWUgPyAnc3Vic2NyaWJlZCB0bycgOiAndW5zdWJzY3JpYmVkIGZyb20nKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmV4cG9ydCBlbnVtIExvY2FsUmVjb3JkZXJTdGF0ZSB7XG4gICAgUkVBRFkgPSAnUkVBRFknLFxuICAgIFJFQ09SRElORyA9ICdSRUNPUkRJTkcnLFxuICAgIFBBVVNFRCA9ICdQQVVTRUQnLFxuICAgIEZJTklTSEVEID0gJ0ZJTklTSEVEJ1xufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBEZWZpbmVzIHByb3BlcnR5IFtbT3BlblZpZHVFcnJvci5uYW1lXV1cbiAqL1xuZXhwb3J0IGVudW0gT3BlblZpZHVFcnJvck5hbWUge1xuXG4gICAgLyoqXG4gICAgICogQnJvd3NlciBpcyBub3Qgc3VwcG9ydGVkIGJ5IE9wZW5WaWR1LlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbU2Vzc2lvbi5jb25uZWN0XV1cbiAgICAgKi9cbiAgICBCUk9XU0VSX05PVF9TVVBQT1JURUQgPSAnQlJPV1NFUl9OT1RfU1VQUE9SVEVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIHRoZSByZXF1aXJlZCBpbnB1dCBkZXZpY2Ugd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSBpcyBwcm9iYWJseSBiZWluZyB1c2VkIGJ5IG90aGVyIHByb2Nlc3Mgd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgaXQuXG4gICAgICogQWNjdXJhY3kgb2YgdGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGdyYW50ZWQgZm9yIENocm9tZSBhbmQgRmlyZWZveCBjbGllbnRzLiBcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FMUkVBRFlfSU5fVVNFID0gXCJERVZJQ0VfQUxSRUFEWV9JTl9VU0VcIixcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIGNhcHR1cmUgc29tZSBkZXNrdG9wIHNjcmVlbiB3aGVuIHRoZSBicm93c2VyIGFza2VkIGZvciB0aGVtLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgPSAnU0NSRUVOX0NBUFRVUkVfREVOSUVEJyxcblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBzY3JlZW4gc2hhcmluZy5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEID0gJ1NDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZSBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gaXMgaW5zdGFsbGVkIGJ1dCBpcyBkaXNhYmxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCA9ICdTQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE5vIHZpZGVvIGlucHV0IGRldmljZSBmb3VuZCB3aXRoIHRoZSBwcm92aWRlZCBkZXZpY2VJZCAocHJvcGVydHkgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlXV0pXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgICAqL1xuICAgIElOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQgPSAnSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCcsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAgICovXG4gICAgUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1IgPSAnUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1InLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNsaWVudCB0cmllZCB0byBjYWxsIGEgbWV0aG9kIHdpdGhvdXQgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb25zLiBUaGlzIGNhbiBvY2N1ciBmb3IgbWV0aG9kcyBbW1Nlc3Npb24ucHVibGlzaF1dLFxuICAgICAqIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dLCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV0sIFtbU3RyZWFtLmFwcGx5RmlsdGVyXV0sIFtbU3RyZWFtLnJlbW92ZUZpbHRlcl1dXG4gICAgICovXG4gICAgT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQgPSAnT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogX05vdCBpbiB1c2UgeWV0X1xuICAgICAqL1xuICAgIE9QRU5WSURVX05PVF9DT05ORUNURUQgPSAnT1BFTlZJRFVfTk9UX0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBfTm90IGluIHVzZSB5ZXRfXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgY29ubmVjdGlvbkNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqXG4gICAgICogRm9yIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnQgYW4gZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEZpbHRlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0ZpbHRlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciB8IEZpbHRlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIgfCBGaWx0ZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgZXZlbnQuIFRoZSBmb2xsb3dpbmcgZXZlbnRzIGhhdmUgYSBkZWZhdWx0IGJlaGF2aW9yOlxuICAgICAqXG4gICAgICogLSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gb2JqZWN0LCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFdlYlJUQ1BlZXIgY29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBlYWNoIFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGAgaW4gbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBvclxuICAgICAqIGJ5IGNhbGxpbmcgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAtIGBzdHJlYW1EZXN0cm95ZWRgOlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IGEgW1tQdWJsaXNoZXJdXSAoKnlvdSogaGF2ZSB1bnB1Ymxpc2hlZCk6IGF1dG9tYXRpY2FsbHkgc3RvcHMgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyLCBlaXRoZXIgYnkgcGFzc2luZyBhIHZhbGlkIHBhcmFtZXRlciBhcyBgdGFyZ2V0RWxlbWVudGBcbiAgICAgKiBpbiBtZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgYnkgY2FsbGluZyBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiAgIC0gSWYgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSAoKm90aGVyIHVzZXIqIGhhcyB1bnB1Ymxpc2hlZCk6IGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmVzIHRoZSBwcm9wZXIgU3Vic2NyaWJlciBvYmplY3QgZnJvbSB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBXZWJSVENQZWVyIGNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhhdCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciwgZWl0aGVyIGJ5IHBhc3NpbmcgYSB2YWxpZCBwYXJhbWV0ZXIgYXMgYHRhcmdldEVsZW1lbnRgIGluIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gb3JcbiAgICAgKiBieSBjYWxsaW5nIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSkuIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICovXG4gICAgcHJldmVudERlZmF1bHQoKSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgICAgICB0aGlzLmNhbGxEZWZhdWx0QmVoYXZpb3IgPSAoKSA9PiB7IH07XG4gICAgICAgIHRoaXMuaGFzQmVlblByZXZlbnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFic3RyYWN0IGNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbSc7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9GaWx0ZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVyeSBldmVudCBkaXNwYXRjaGVkIGJ5IGF1ZGlvL3ZpZGVvIHN0cmVhbSBmaWx0ZXJzLiBZb3UgY2FuIHN1YnNjcmliZSB0byBmaWx0ZXIgZXZlbnRzIGJ5IGNhbGxpbmcgW1tGaWx0ZXIuYWRkRXZlbnRMaXN0ZW5lcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXJFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIERhdGEgb2YgdGhlIGV2ZW50XG4gICAgICovXG4gICAgZGF0YTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogRmlsdGVyLCBldmVudFR5cGU6IHN0cmluZywgZGF0YTogT2JqZWN0KSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIGV2ZW50VHlwZSk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcHVibGlzaGVyU3RhcnRTcGVha2luZ2A6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHB1Ymxpc2hlclN0b3BTcGVha2luZ2A6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqXG4gKiBNb3JlIGluZm9ybWF0aW9uOlxuICogLSBUaGlzIGV2ZW50cyB3aWxsIG9ubHkgYmUgdHJpZ2dlcmVkIGZvciAqKnJlbW90ZSBzdHJlYW1zIHRoYXQgaGF2ZSBhdWRpbyB0cmFja3MqKiAoW1tTdHJlYW0uaGFzQXVkaW9dXSBtdXN0IGJlIHRydWUpXG4gKiAtIEJvdGggZXZlbnRzIHNoYXJlIHRoZSBzYW1lIGxpZmVjeWNsZS4gVGhhdCBtZWFucyB0aGF0IHlvdSBjYW4gc3Vic2NyaWJlIHRvIG9ubHkgb25lIG9mIHRoZW0gaWYgeW91IHdhbnQsIGJ1dCBpZiB5b3UgY2FsbCBgU2Vzc2lvbi5vZmYoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpYCxcbiAqIGtlZXAgaW4gbWluZCB0aGF0IHRoaXMgd2lsbCBhbHNvIGludGVybmFsbHkgcmVtb3ZlIGFueSAncHVibGlzaGVyU3RhcnRTcGVha2luZycgZXZlbnRcbiAqIC0gWW91IGNhbiBmdXJ0aGVyIGNvbmZpZ3VyZSBob3cgdGhlIGV2ZW50cyBhcmUgZGlzcGF0Y2hlZCBieSBzZXR0aW5nIHByb3BlcnR5IGBwdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnNgIGluIHRoZSBjYWxsIG9mIFtbT3BlblZpZHUuc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgY2xpZW50IHRoYXQgc3RhcnRlZCBvciBzdG9wcGVkIHNwZWFraW5nXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBzdHJlYW1JZCBvZiB0aGUgU3RyZWFtIGFmZmVjdGVkIGJ5IHRoZSBzcGVha2luZyBldmVudFxuICAgICAqL1xuICAgIHN0cmVhbUlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHN0cmVhbUlkOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuc3RyZWFtSWQgPSBzdHJlYW1JZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHJlY29yZGluZ1N0YXJ0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKiAtIGByZWNvcmRpbmdTdG9wcGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgUmVjb3JkaW5nRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIElEIGdlbmVyYXRlZCBpbiBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHJlY29yZGluZyBuYW1lIHlvdSBzdXBwbGllZCB0byBvcGVudmlkdS1zZXJ2ZXIuIEZvciBleGFtcGxlLCB0byBuYW1lIHlvdXIgcmVjb3JkaW5nIGZpbGUgTVlfUkVDT1JESU5HOlxuICAgICAqIC0gV2l0aCAqKkFQSSBSRVNUKio6IFBPU1QgdG8gYC9hcGkvcmVjb3JkaW5ncy9zdGFydGAgcGFzc2luZyBKU09OIGJvZHkgYHtcInNlc3Npb25cIjpcInNlc3Npb25JZFwiLFwibmFtZVwiOlwiTVlfUkVDT1JESU5HXCJ9YFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LWphdmEtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCBuZXcgUmVjb3JkaW5nUHJvcGVydGllcy5CdWlsZGVyKCkubmFtZShcIk1ZX1JFQ09SRElOR1wiKS5idWlsZCgpKWBcbiAgICAgKiAtIFdpdGggKipvcGVudmlkdS1ub2RlLWNsaWVudCoqOiBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCBcIk1ZX1JFQ09SRElOR1wiKWAgb3IgYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwge25hbWU6IFwiTVlfUkVDT1JESU5HXCJ9KWBcbiAgICAgKlxuICAgICAqIElmIG5vIG5hbWUgaXMgc3VwcGxpZWQsIHRoaXMgcHJvcGVydHkgd2lsbCBiZSB1bmRlZmluZWQgYW5kIHRoZSByZWNvcmRlZCBmaWxlIHdpbGwgYmUgbmFtZWQgYWZ0ZXIgcHJvcGVydHkgW1tpZF1dXG4gICAgICovXG4gICAgbmFtZT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEZvciAncmVjb3JkaW5nU3RvcHBlZCcgZXZlbnQ6XG4gICAgICogLSBcInJlY29yZGluZ1N0b3BwZWRCeVNlcnZlclwiOiB0aGUgcmVjb3JkaW5nIGhhcyBiZWVuIGdyYWNlZnVsbHkgc3RvcHBlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiYXV0b21hdGljU3RvcFwiOiBzZWUgW0F1dG9tYXRpYyBzdG9wIG9mIHJlY29yZGluZ3NdKGh0dHBzOi8vb3BlbnZpZHUuaW8vZG9jcy9hZHZhbmNlZC1mZWF0dXJlcy9yZWNvcmRpbmcvI2F1dG9tYXRpYy1zdG9wLW9mLXJlY29yZGluZ3MpXG4gICAgICogLSBcIm1lZGlhU2VydmVyRGlzY29ubmVjdFwiOiBPcGVuVmlkdSBNZWRpYSBTZXJ2ZXIgaGFzIGNyYXNoZWQgb3IgbG9zdCBpdHMgY29ubmVjdGlvbi4gQSBuZXcgbWVkaWEgc2VydmVyIGluc3RhbmNlIGlzIGFjdGl2ZSBhbmQgdGhlIHJlY29yZGluZyBoYXMgYmVlbiBzdG9wcGVkIChubyBtZWRpYSBzdHJlYW1zIGFyZSBhdmFpbGFibGUgaW4gdGhlIG5ldyBtZWRpYSBzZXJ2ZXIpXG4gICAgICpcbiAgICAgKiBGb3IgJ3JlY29yZGluZ1N0YXJ0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbj86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nLCByZWFzb24/OiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgaWYgKG5hbWUgIT09IGlkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB5b3UgaGF2ZSBjYWxsZWQgYFNlc3Npb24uZGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcIjogeW91IGhhdmUgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogeW91ciBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHRydWUsIHRhcmdldCwgJ3Nlc3Npb25EaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7XG5cbiAgICAgICAgY29uc29sZS5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW9yIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuXG4gICAgICAgIGNvbnN0IHNlc3Npb24gPSA8U2Vzc2lvbj50aGlzLnRhcmdldDtcblxuICAgICAgICAvLyBEaXNwb3NlIGFuZCBkZWxldGUgYWxsIHJlbW90ZSBDb25uZWN0aW9uc1xuICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb25JZCBpbiBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICBpZiAoISFzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgaWYgKHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zW2Nvbm5lY3Rpb25JZF0uc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSBzZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkW3Nlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5zdHJlYW0uc3RyZWFtSWRdO1xuICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnNbY29ubmVjdGlvbklkXS5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1tjb25uZWN0aW9uSWRdO1xuICAgICAgICB9XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHNpZ25hbGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV1cbiAqIC0gYHNpZ25hbDpUWVBFYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXVxuICovXG5leHBvcnQgY2xhc3MgU2lnbmFsRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBzaWduYWwgKGNhbiBiZSBlbXB0eSkuXG4gICAgICpcbiAgICAgKiBUaGUgY2xpZW50IG11c3QgYmUgc3Vic2NyaWJlZCB0byBgU2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCBmdW5jdGlvbihzaWduYWxFdmVudCkgey4uLn0pYCB0byByZWNlaXZlIHRoaXMgb2JqZWN0IGluIHRoZSBjYWxsYmFjay5cbiAgICAgKlxuICAgICAqIFN1YnNjcmliaW5nIHRvIGBTZXNzaW9uLm9uKCdzaWduYWwnLCBmdW5jdGlvbihzaWduYWxFdmVudCkgey4uLn0pYCB3aWxsIHRyaWdnZXIgYWxsIHR5cGVzIG9mIHNpZ25hbHMuXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG1lc3NhZ2Ugb2YgdGhlIHNpZ25hbCAoY2FuIGJlIGVtdHB5KVxuICAgICAqL1xuICAgIGRhdGE6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzZW50IHRoZSBzaWduYWxcbiAgICAgKi9cbiAgICBmcm9tOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBkYXRhOiBzdHJpbmcsIGZyb206IENvbm5lY3Rpb24pIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuZnJvbSA9IGZyb207XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuXG5cbi8qKlxuICogRGVmaW5lcyB0aGUgZm9sbG93aW5nIGV2ZW50czpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1B1Ymxpc2hlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1FdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbSBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEZvciAnc3RyZWFtRGVzdHJveWVkJyBldmVudDpcbiAgICAgKiAtIFwidW5wdWJsaXNoXCI6IG1ldGhvZCBgU2Vzc2lvbi51bnB1Ymxpc2goKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImRpc2Nvbm5lY3RcIjogbWV0aG9kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaGFzIGJlZW4gY2FsbGVkXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlVc2VyXCI6IHNvbWUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmZvcmNlVW5wdWJsaXNoKClgIG92ZXIgdGhlIFN0cmVhbVxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgIG92ZXIgdGhlIFN0cmVhbVxuICAgICAqIC0gXCJmb3JjZVVucHVibGlzaEJ5U2VydmVyXCI6IHRoZSB1c2VyJ3Mgc3RyZWFtIGhhcyBiZWVuIHVucHVibGlzaGVkIGZyb20gdGhlIFNlc3Npb24gYnkgdGhlIGFwcGxpY2F0aW9uXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHRoZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHVzZXIncyBuZXR3b3JrIGNvbm5lY3Rpb24gaGFzIGRyb3BwZWRcbiAgICAgKiAtIFwibWVkaWFTZXJ2ZXJEaXNjb25uZWN0XCI6IE9wZW5WaWR1IE1lZGlhIFNlcnZlciBoYXMgY3Jhc2hlZCBvciBsb3N0IGl0cyBjb25uZWN0aW9uLiBBIG5ldyBtZWRpYSBzZXJ2ZXIgaW5zdGFuY2UgaXMgYWN0aXZlIGFuZCBubyBtZWRpYSBzdHJlYW1zIGFyZSBhdmFpbGFibGUgaW4gdGhlIG1lZGlhIHNlcnZlclxuICAgICAqXG4gICAgICogRm9yICdzdHJlYW1DcmVhdGVkJyBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24gfCBQdWJsaXNoZXIsIHR5cGU6IHN0cmluZywgc3RyZWFtOiBTdHJlYW0sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGNhbmNlbGFibGUsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3N0cmVhbURlc3Ryb3llZCcpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBjb25zb2xlLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtLnNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWRbdGhpcy5zdHJlYW0uc3RyZWFtSWRdO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9uc1t0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZF07XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ub3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgc3RyZWFtUGxheWluZ2A6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKSB3aGVuZXZlciBpdHMgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nIChvbmUgb2YgaXRzIHZpZGVvcyBoYXMgbWVkaWFcbiAqIGFuZCBoYXMgYmVndW4gdG8gcGxheSkuIFRoaXMgZXZlbnQgd2lsbCBiZSBkaXNwYXRjaGVkIHdoZW4gdGhlc2UgMyBjb25kaXRpb25zIGFyZSBtZXQgMSkgVGhlIFN0cmVhbU1hbmFnZXIgaGFzIG5vIHZpZGVvIGFzc29jaWF0ZWQgaW4gdGhlIERPTSAyKSBJdCBpcyBhc3NvY2lhdGVkIHRvIG9uZSB2aWRlbyAzKSBUaGF0IHZpZGVvIHN0YXJ0cyBwbGF5aW5nXG4gKiAtIGBzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZWA6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKSB3aGVuIHRoZSB2b2x1bWUgb2YgaXRzIFN0cmVhbSdzIGF1ZGlvIHRyYWNrXG4gKiBjaGFuZ2VzLiBPbmx5IGFwcGxpZXMgaWYgW1tTdHJlYW0uaGFzQXVkaW9dXSBpcyBgdHJ1ZWAuIFRoZSBmcmVxdWVuY3kgdGhpcyBldmVudCBpcyBmaXJlZCB3aXRoIGlzIGRlZmluZWQgYnkgcHJvcGVydHkgYGludGVydmFsYCBvZlxuICogW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbi5wdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnNdXSAoZGVmYXVsdCA1MG1zKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogRm9yIGBzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZWAgZXZlbnQ6XG4gICAgICogLSBge25ld1ZhbHVlOiBudW1iZXIsIG9sZFZhbHVlOiBudW1iZXJ9YDogbmV3IGFuZCBvbGQgYXVkaW8gdm9sdW1lIHZhbHVlcy4gVGhlc2UgdmFsdWVzIGFyZSBiZXR3ZWVuIC0xMDAgKHNpbGVuY2UpIGFuZCAwIChsb3VkZXN0IHBvc3NpYmxlIHZvbHVtZSkuXG4gICAgICogVGhleSBhcmUgbm90IGV4YWN0IGFuZCBkZXBlbmQgb24gaG93IHRoZSBicm93c2VyIGlzIG1hbmFnaW5nIHRoZSBhdWRpbyB0cmFjaywgYnV0IC0xMDAgYW5kIDAgY2FuIGJlIHRha2VuIGFzIGxpbWl0IHZhbHVlcy5cbiAgICAgKiBcbiAgICAgKiBGb3IgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIHZhbHVlOiBPYmplY3QgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcsIHZhbHVlOiBPYmplY3QgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIGV2ZW50IGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYXMgd2VsbCBhcyBieSBbW1N0cmVhbU1hbmFnZXJdXSAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pLlxuICogVGhpcyBldmVudCBpcyBmaXJlZCB3aGVuIGFueSByZW1vdGUgc3RyZWFtIChvd25lZCBieSBhIFN1YnNjcmliZXIpIG9yIGxvY2FsIHN0cmVhbSAob3duZWQgYnkgYSBQdWJsaXNoZXIpIHVuZGVyZ29lc1xuICogYW55IGNoYW5nZSBpbiBhbnkgb2YgaXRzIG11dGFibGUgcHJvcGVydGllcyAoc2VlIFtbY2hhbmdlZFByb3BlcnR5XV0pLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHdob3NlIHByb3BlcnR5IGhhcyBjaGFuZ2VkLiBZb3UgY2FuIGFsd2F5cyBpZGVudGlmeSB0aGUgdXNlciBwdWJsaXNoaW5nIHRoZSBjaGFuZ2VkIHN0cmVhbSBieSBjb25zdWx0aW5nIHByb3BlcnR5IFtbU3RyZWFtLmNvbm5lY3Rpb25dXVxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHByb3BlcnR5IG9mIHRoZSBzdHJlYW0gdGhhdCBjaGFuZ2VkLiBUaGlzIHZhbHVlIGlzIGVpdGhlciBgXCJ2aWRlb0FjdGl2ZVwiYCwgYFwiYXVkaW9BY3RpdmVcImAsIGBcInZpZGVvRGltZW5zaW9uc1wiYCBvciBgXCJmaWx0ZXJcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgIG9yIGBcInNjcmVlblJlc2l6ZWRcImBcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciwgc3RyZWFtOiBTdHJlYW0sIGNoYW5nZWRQcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogT2JqZWN0LCBvbGRWYWx1ZTogT2JqZWN0LCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMTkgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8vKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9kb2NzL2hvdy1kby1pL21hbmFnZS12aWRlb3MpIHNlY3Rpb24uXG4gKiAtIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgOiBkaXNwYXRjaGVkIGJ5IFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dIHdoZW5ldmVyIGFuIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiByZW1vdmVkIGZyb20gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpXG57XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaylcbiAge1xuICAgIGZvcih2YXIga2V5IGluIHNvdXJjZXMpXG4gICAge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24oaWQsIHNvdXJjZSlcbiAge1xuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGlkLCBzb3VyY2UpXG4gIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm47XG5cbiAgICBkZWxldGUgaWRzW2lkXTtcblxuICAgIC8vIENoZWNrIGl0J3MgZW1wdHlcbiAgICBmb3IodmFyIGkgaW4gaWRzKXtyZXR1cm4gZmFsc2V9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24odmFsdWUsIGlkLCBzb3VyY2UpXG4gIHtcbiAgICBpZih2YWx1ZSA9PSB1bmRlZmluZWQpXG4gICAgICByZXR1cm4gdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbihpZCwgc291cmNlKVxue1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjtcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgSnNvblJwY0NsaWVudCAgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuRGF0ZS5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZTtcbn07XG5cbnZhciBQSU5HX0lOVEVSVkFMID0gNTAwMDtcblxudmFyIFJFQ09OTkVDVElORyA9ICdSRUNPTk5FQ1RJTkcnO1xudmFyIENPTk5FQ1RFRCA9ICdDT05ORUNURUQnO1xudmFyIERJU0NPTk5FQ1RFRCA9ICdESVNDT05ORUNURUQnO1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKlxuICogaGVhcnRiZWF0OiBpbnRlcnZhbCBpbiBtcyBmb3IgZWFjaCBoZWFydGJlYXQgbWVzc2FnZSxcbiAqIHNlbmRDbG9zZU1lc3NhZ2UgOiB0cnVlIC8gZmFsc2UsIGJlZm9yZSBjbG9zaW5nIHRoZSBjb25uZWN0aW9uLCBpdCBzZW5kcyBhIGNsb3NlU2Vzc2lvbiBtZXNzYWdlXG4gKiA8cHJlPlxuICogd3MgOiB7XG4gKiBcdHVyaSA6IFVSSSB0byBjb25udGVjdCB0byxcbiAqICB1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuICogXHRvbmNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiBjb25uZWN0aW9uIGlzIHN1Y2Nlc3NmdWwsXG4gKiBcdG9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0IChtYXggcmV0cmllcyBmb3IgcmVjb25uZWN0aW5nIHJlYWNoZWQpLFxuICogXHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcbiAqIFx0b25yZWNvbm5lY3RlZCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IHN1Y2Nlc3NmdWxseSByZWNvbm5lY3RzLFxuICogXHRvbmVycm9yIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZXJlIGlzIGFuIGVycm9yXG4gKiB9LFxuICogcnBjIDoge1xuICogXHRyZXF1ZXN0VGltZW91dCA6IHRpbWVvdXQgZm9yIGEgcmVxdWVzdCxcbiAqIFx0c2Vzc2lvblN0YXR1c0NoYW5nZWQ6IGNhbGxiYWNrIG1ldGhvZCBmb3IgY2hhbmdlcyBpbiBzZXNzaW9uIHN0YXR1cyxcbiAqIFx0bWVkaWFSZW5lZ290aWF0aW9uOiBtZWRpYVJlbmVnb3RpYXRpb25cbiAqIH1cbiAqIDwvcHJlPlxuICovXG5mdW5jdGlvbiBKc29uUnBjQ2xpZW50KGNvbmZpZ3VyYXRpb24pIHtcblxuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciB3c0NvbmZpZyA9IGNvbmZpZ3VyYXRpb24ud3M7XG5cbiAgICB2YXIgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiA9IC0xO1xuXG4gICAgdmFyIHBpbmdOZXh0TnVtID0gMDtcbiAgICB2YXIgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICB2YXIgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgdmFyIHBpbmdJbnRlcnZhbDtcblxuICAgIHZhciBzdGF0dXMgPSBESVNDT05ORUNURUQ7XG5cbiAgICB2YXIgb25yZWNvbm5lY3RpbmcgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGluZztcbiAgICB2YXIgb25yZWNvbm5lY3RlZCA9IHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQ7XG4gICAgdmFyIG9uY29ubmVjdGVkID0gd3NDb25maWcub25jb25uZWN0ZWQ7XG4gICAgdmFyIG9uZXJyb3IgPSB3c0NvbmZpZy5vbmVycm9yO1xuXG4gICAgY29uZmlndXJhdGlvbi5ycGMucHVsbCA9IGZ1bmN0aW9uIChwYXJhbXMsIHJlcXVlc3QpIHtcbiAgICAgICAgcmVxdWVzdC5yZXBseShudWxsLCBcInB1c2hcIik7XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVElORyAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gUkVDT05ORUNUSU5HKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBSRUNPTk5FQ1RJTkcgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RJTkcgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzdG9wUGluZygpO1xuXG4gICAgICAgIHN0YXR1cyA9IFJFQ09OTkVDVElORztcbiAgICAgICAgaWYgKG9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGluZygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25yZWNvbm5lY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcblxuICAgICAgICBpZiAob25yZWNvbm5lY3RlZCkge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25jb25uZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05DT05ORUNURUQgbWVzc2FnZS4gSWdub3JpbmcgaXRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc3RhdHVzID0gQ09OTkVDVEVEO1xuXG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHVzZVBpbmcoKTtcblxuICAgICAgICBpZiAob25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9uY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmVycm9yID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTkVSUk9SIC0tLS0tLS0tLS0tXCIpO1xuXG4gICAgICAgIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgICAgICBzdG9wUGluZygpO1xuXG4gICAgICAgIGlmIChvbmVycm9yKSB7XG4gICAgICAgICAgICBvbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uKHdzQ29uZmlnKTtcblxuICAgIExvZ2dlci5kZWJ1ZygnQ29ubmVjdGluZyB3ZWJzb2NrZXQgdG8gVVJJOiAnICsgd3NDb25maWcudXJpKTtcblxuICAgIHZhciBycGNCdWlsZGVyT3B0aW9ucyA9IHtcbiAgICAgICAgcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5yZXF1ZXN0VGltZW91dCxcbiAgICAgICAgcGluZ19yZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLmhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0XG4gICAgfTtcblxuICAgIHZhciBycGMgPSBuZXcgUnBjQnVpbGRlcihScGNCdWlsZGVyLnBhY2tlcnMuSnNvblJQQywgcnBjQnVpbGRlck9wdGlvbnMsIHdzLFxuICAgICAgICBmdW5jdGlvbiAocmVxdWVzdCkge1xuXG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1JlY2VpdmVkIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjb25maWd1cmF0aW9uLnJwY1tyZXF1ZXN0Lm1ldGhvZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIk1ldGhvZCBcIiArIHJlcXVlc3QubWV0aG9kICsgXCIgbm90IHJlZ2lzdGVyZWQgaW4gY2xpZW50XCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMocmVxdWVzdC5wYXJhbXMsIHJlcXVlc3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcignRXhjZXB0aW9uIHByb2Nlc3NpbmcgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB0aGlzLnNlbmQgPSBmdW5jdGlvbiAobWV0aG9kLCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChtZXRob2QgIT09ICdwaW5nJykge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKCdSZXF1ZXN0OiBtZXRob2Q6JyArIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlcXVlc3RUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgICAgICBycGMuZW5jb2RlKG1ldGhvZCwgcGFyYW1zLCBmdW5jdGlvbiAoZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1I6XCIgKyBlcnJvci5tZXNzYWdlICsgXCIgaW4gUmVxdWVzdDogbWV0aG9kOlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCArIFwiIHBhcmFtczpcIiArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyBcIiByZXF1ZXN0OlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3QpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRVJST1IgREFUQTpcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yLmRhdGEpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdFRpbWUgPSByZXF1ZXN0VGltZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT0gdW5kZWZpbmVkICYmIHJlc3VsdC52YWx1ZSAhPT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVzcG9uc2U6ICcgKyBKU09OLnN0cmluZ2lmeShyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIm5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBcIiArIHBpbmdOZXh0TnVtICsgJyAob2xkPScgK1xuICAgICAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiArICcpJyk7XG4gICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSBwaW5nTmV4dE51bTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZW5kUGluZygpIHtcbiAgICAgICAgaWYgKGVuYWJsZWRQaW5ncykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG51bGw7XG4gICAgICAgICAgICBpZiAocGluZ05leHROdW0gPT0gMCB8fCBwaW5nTmV4dE51bSA9PSBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbDogY29uZmlndXJhdGlvbi5oZWFydGJlYXQgfHwgUElOR19JTlRFUlZBTFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwaW5nTmV4dE51bSsrO1xuXG4gICAgICAgICAgICBzZWxmLnNlbmQoJ3BpbmcnLCBwYXJhbXMsIChmdW5jdGlvbiAocGluZ051bSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoZXJyb3IsIHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkVycm9yIGluIHBpbmcgcmVxdWVzdCAjXCIgKyBwaW5nTnVtICsgXCIgKFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5tZXNzYWdlICsgXCIpXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBpbmdOdW0gPiBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlNlcnZlciBkaWQgbm90IHJlc3BvbmQgdG8gcGluZyBtZXNzYWdlICNcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpbmdOdW0gKyBcIi4gUmVjb25uZWN0aW5nLi4uIFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkocGluZ05leHROdW0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlRyeWluZyB0byBzZW5kIHBpbmcsIGJ1dCBwaW5nIGlzIG5vdCBlbmFibGVkXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBJZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0IGhhcyBhbnkgdmFsdWUsIHRoZSBwaW5nLXBvbmcgd2lsbCB3b3JrIHdpdGggdGhlIGludGVydmFsXG4gICAgICogb2YgY29uZmlndXJhdGlvbi5oZWFyYmVhdFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVzZVBpbmcoKSB7XG4gICAgICAgIGlmICghcGluZ1BvbmdTdGFydGVkKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTdGFydGluZyBwaW5nIChpZiBjb25maWd1cmVkKVwiKVxuICAgICAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0ICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHBpbmdJbnRlcnZhbCA9IHNldEludGVydmFsKHNlbmRQaW5nLCBjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCk7XG4gICAgICAgICAgICAgICAgc2VuZFBpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0b3BQaW5nKCkge1xuICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgcGluZ05leHROdW0gPSAtMTtcbiAgICAgICAgcnBjLmNhbmNlbCgpO1xuICAgIH1cblxuICAgIHRoaXMuY2xvc2UgPSBmdW5jdGlvbiAoY29kZSwgcmVhc29uKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NpbmcgIHdpdGggY29kZTogXCIgKyBjb2RlICsgXCIgYmVjYXVzZTogXCIgKyByZWFzb24pO1xuXG4gICAgICAgIGlmIChwaW5nSW50ZXJ2YWwgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDbGVhcmluZyBwaW5nIGludGVydmFsXCIpO1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChwaW5nSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5zZW5kQ2xvc2VNZXNzYWdlKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZW5kaW5nIGNsb3NlIG1lc3NhZ2VcIilcbiAgICAgICAgICAgIHRoaXMuc2VuZCgnY2xvc2VTZXNzaW9uJywgbnVsbCwgZnVuY3Rpb24gKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyBjbG9zZSBtZXNzYWdlOiBcIiArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdzLmNsb3NlKGNvZGUsIHJlYXNvbik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdzLmNsb3NlKGNvZGUsIHJlYXNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24gKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZXNldFBpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHBpbmdOZXh0TnVtID0gMDtcbiAgICAgICAgdXNlUGluZygpO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpzb25ScGNDbGllbnQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uICA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5cbmV4cG9ydHMuV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiAgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBCcm93c2VyV2ViU29ja2V0ID0gZ2xvYmFsLldlYlNvY2tldCB8fCBnbG9iYWwuTW96V2ViU29ja2V0O1xuXG52YXIgTG9nZ2VyID0gY29uc29sZTtcblxuLyoqXG4gKiBHZXQgZWl0aGVyIHRoZSBgV2ViU29ja2V0YCBvciBgTW96V2ViU29ja2V0YCBnbG9iYWxzXG4gKiBpbiB0aGUgYnJvd3NlciBvciB0cnkgdG8gcmVzb2x2ZSBXZWJTb2NrZXQtY29tcGF0aWJsZVxuICogaW50ZXJmYWNlIGV4cG9zZWQgYnkgYHdzYCBmb3IgTm9kZS1saWtlIGVudmlyb25tZW50LlxuICovXG5cbi8qdmFyIFdlYlNvY2tldCA9IEJyb3dzZXJXZWJTb2NrZXQ7XG5pZiAoIVdlYlNvY2tldCAmJiB0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgIHRyeSB7XG4gICAgICAgIFdlYlNvY2tldCA9IHJlcXVpcmUoJ3dzJyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG59Ki9cblxuLy92YXIgU29ja0pTID0gcmVxdWlyZSgnc29ja2pzLWNsaWVudCcpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcblx0XHR1cmkgOiB3c1VyaSxcblx0XHR1c2VTb2NrSlMgOiB0cnVlICh1c2UgU29ja0pTKSAvIGZhbHNlICh1c2UgV2ViU29ja2V0KSBieSBkZWZhdWx0LFxuXHRcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcblx0XHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCAobWF4IHJldHJpZXMgZm9yIHJlY29ubmVjdGluZyByZWFjaGVkKSxcblx0XHRvbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcblx0XHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG5cdH07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcblxuICAgIHZhciBjbG9zaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXI7XG4gICAgdmFyIHdzVXJpID0gY29uZmlnLnVyaTtcbiAgICB2YXIgdXNlU29ja0pTID0gY29uZmlnLnVzZVNvY2tKUztcbiAgICB2YXIgcmVjb25uZWN0aW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZm9yY2luZ0Rpc2Nvbm5lY3Rpb24gPSBmYWxzZTtcblxuICAgIHZhciB3cztcblxuICAgIGlmICh1c2VTb2NrSlMpIHtcbiAgICAgICAgd3MgPSBuZXcgU29ja0pTKHdzVXJpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuICAgIH1cblxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSk7XG4gICAgICAgIGlmIChjb25maWcub25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIGNvbmZpZy5vbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uZXJyb3IgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmVycm9yKFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsIGVycm9yKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9nQ29ubmVjdGVkKHdzLCB3c1VyaSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiV2ViU29ja2V0IGNvbm5lY3RlZCB0byBcIiArIHdzVXJpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlY2x5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdFRvU2FtZVVyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFRvU2FtZVVyaSAoYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzICsgXCIsIG1heD1cIiArIG1heFJldHJpZXMgKyBcIilcIik7XG5cbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcIlRyeWluZyB0byByZWNvbm5lY3RUb05ld1VyaSB3aGVuIHJlY29ubmVjdGluZy4uLiBJZ25vcmluZyB0aGlzIHJlY29ubmVjdGlvbi5cIilcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb3JjaW5nRGlzY29ubmVjdGlvbikge1xuICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm5ld1dzVXJpT25SZWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjb25maWcubmV3V3NVcmlPblJlY29ubmVjdGlvbihmdW5jdGlvbiAoZXJyb3IsIG5ld1dzVXJpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgbmV3V3NVcmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0VG9OZXdVcmkobWF4UmV0cmllcywgbnVtUmV0cmllcywgd3NVcmkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBUZXN0IHJldHJpZXMuIEhvdyB0byBmb3JjZSBub3QgY29ubmVjdGlvbj9cbiAgICBmdW5jdGlvbiByZWNvbm5lY3RUb05ld1VyaShtYXhSZXRyaWVzLCBudW1SZXRyaWVzLCByZWNvbm5lY3RXc1VyaSkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJSZWNvbm5lY3Rpb24gYXR0ZW1wdCAjXCIgKyBudW1SZXRyaWVzKTtcblxuICAgICAgICB3cy5jbG9zZSgpO1xuXG4gICAgICAgIHdzVXJpID0gcmVjb25uZWN0V3NVcmkgfHwgd3NVcmk7XG5cbiAgICAgICAgdmFyIG5ld1dzO1xuICAgICAgICBpZiAodXNlU29ja0pTKSB7XG4gICAgICAgICAgICBuZXdXcyA9IG5ldyBTb2NrSlMod3NVcmkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3V3MgPSBuZXcgV2ViU29ja2V0KHdzVXJpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1dzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGVkIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCIpO1xuICAgICAgICAgICAgbG9nQ29ubmVjdGVkKG5ld1dzLCB3c1VyaSk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3V3Mub25jbG9zZSA9IHJlY29ubmVjdGlvbk9uQ2xvc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG9uRXJyb3JPckNsb3NlID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBMb2dnZXIud2FybihcIlJlY29ubmVjdGlvbiBlcnJvcjogXCIsIGVycm9yKTtcblxuICAgICAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IG1heFJldHJpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLm9uZGlzY29ubmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBjb25maWcub25kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKG1heFJldHJpZXMsIG51bVJldHJpZXMgKyAxKTtcbiAgICAgICAgICAgICAgICB9LCBSRVRSWV9USU1FX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBuZXdXcy5vbmVycm9yID0gb25FcnJvck9yQ2xvc2U7XG5cbiAgICAgICAgd3MgPSBuZXdXcztcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjbG9zaW5nID0gdHJ1ZTtcbiAgICAgICAgd3MuY2xvc2UoKTtcbiAgICB9O1xuXG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24gKG1pbGxpcykge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJUZXN0aW5nOiBGb3JjZSBXZWJTb2NrZXQgY2xvc2VcIik7XG5cbiAgICAgICAgaWYgKG1pbGxpcykge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogQ2hhbmdlIHdzVXJpIGZvciBcIiArIG1pbGxpcyArIFwiIG1pbGxpcyB0byBzaW11bGF0ZSBuZXQgZmFpbHVyZVwiKTtcbiAgICAgICAgICAgIHZhciBnb29kV3NVcmkgPSB3c1VyaTtcbiAgICAgICAgICAgIHdzVXJpID0gXCJ3c3M6Ly8yMS4yMzQuMTIuMzQuNDo0NDMvXCI7XG5cbiAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gdHJ1ZTtcblxuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVGVzdGluZzogUmVjb3ZlciBnb29kIHdzVXJpIFwiICsgZ29vZFdzVXJpKTtcbiAgICAgICAgICAgICAgICB3c1VyaSA9IGdvb2RXc1VyaTtcblxuICAgICAgICAgICAgICAgIGZvcmNpbmdEaXNjb25uZWN0aW9uID0gZmFsc2U7XG5cbiAgICAgICAgICAgIH0sIG1pbGxpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB3cy5jbG9zZSgpO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0VG9TYW1lVXJpKE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gKHR5cGUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYoT2JqZWN0LmRlZmluZVByb3BlcnR5KVxue1xuICB0cnlcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfVxuICBjYXRjaChlKVxuICB7XG4gICAgZGVmaW5lUHJvcGVydHlfSUU4ID0gdHJ1ZVxuICB9XG59XG5cbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmRcbmlmICghRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQpIHtcbiAgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyAgID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgZlRvQmluZCA9IHRoaXMsXG4gICAgICAgIGZOT1AgICAgPSBmdW5jdGlvbigpIHt9LFxuICAgICAgICBmQm91bmQgID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXNcbiAgICAgICAgICAgICAgICAgPyB0aGlzXG4gICAgICAgICAgICAgICAgIDogb1RoaXMsXG4gICAgICAgICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKVxue1xuICBpZighcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yKHZhciBrZXkgaW4gcmVzcG9uc2VNZXRob2RzKVxuICB7XG4gICAgdmFyIHZhbHVlID0gcmVzcG9uc2VNZXRob2RzW2tleV07XG5cbiAgICBpZih0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9XG4gICAgICB7XG4gICAgICAgIHJlc3BvbnNlOiB2YWx1ZVxuICAgICAgfVxuICB9O1xuXG4gIHJldHVybiByZXNwb25zZU1ldGhvZHM7XG59O1xuXG5mdW5jdGlvbiB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpXG57XG4gIGlmKCF0cmFuc3BvcnQpIHJldHVybjtcblxuICAvLyBUcmFuc3BvcnQgYXMgYSBmdW5jdGlvblxuICBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge3NlbmQ6IHRyYW5zcG9ydH07XG5cbiAgLy8gV2ViU29ja2V0ICYgRGF0YUNoYW5uZWxcbiAgaWYodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYodHJhbnNwb3J0LndyaXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICB0cmFuc3BvcnQuc2VuZCA9IHRyYW5zcG9ydC53cml0ZTtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG5cbiAgLy8gVHJhbnNwb3J0cyB0aGF0IG9ubHkgY2FuIHJlY2VpdmUgbWVzc2FnZXMsIGJ1dCBub3Qgc2VuZFxuICBpZih0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcylcbntcbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9XG4gIGVsc2VcbiAge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge3ZhbHVlOiBtZXRob2QsIGVudW1lcmFibGU6IHRydWV9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHt2YWx1ZTogcGFyYW1zLCBlbnVtZXJhYmxlOiB0cnVlfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdClcbntcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZighcGFja2VyLnBhY2sgfHwgIXBhY2tlci51bnBhY2spXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgaW52YWxpZCcpO1xuXG4gIHZhciByZXNwb25zZU1ldGhvZHMgPSB1bmlmeVJlc3BvbnNlTWV0aG9kcyhwYWNrZXIucmVzcG9uc2VNZXRob2RzKTtcblxuXG4gIGlmKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAge1xuICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgICA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZihvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICB7XG4gICAgaWYodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zICAgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gIHtcbiAgICBpZihvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIGlmKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYoZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIHRoaXMucGVlcklEID0gb3B0aW9ucy5wZWVySURcbiAgZWxzZVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAncGVlcklEJywge3ZhbHVlOiBvcHRpb25zLnBlZXJJRH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpXG4gIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uKClcbiAge1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cbiAgdGhpcy5zZXRUcmFuc3BvcnQgPSBmdW5jdGlvbih2YWx1ZSlcbiAge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZih0cmFuc3BvcnQpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYodmFsdWUpXG4gICAge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZih2YWx1ZS5hZGRMaXN0ZW5lcilcbiAgICAgICAgdmFsdWUuYWRkTGlzdGVuZXIoJ2RhdGEnLCB0cmFuc3BvcnRNZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICB9XG5cbiAgaWYoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCAgICAgID0gb3B0aW9ucy5yZXF1ZXN0X3RpbWVvdXQgICAgICB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCAgICAgPSBvcHRpb25zLnJlc3BvbnNlX3RpbWVvdXQgICAgIHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCAgID0gb3B0aW9ucy5kdXBsaWNhdGVzX3RpbWVvdXQgICB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuICB2YXIgcHJvY2Vzc2VkUmVzcG9uc2VzID0gbmV3IE1hcHBlcigpO1xuXG4gIHZhciBtZXNzYWdlMktleSA9IHt9O1xuXG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgZHVwbGljYXRlIHJlcXVlc3QgbGF0ZXJcbiAgICovXG4gIGZ1bmN0aW9uIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGRlc3QpXG4gIHtcbiAgICB2YXIgcmVzcG9uc2UgPVxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgICAge1xuICAgICAgICByZXNwb25zZXMucmVtb3ZlKGlkLCBkZXN0KTtcbiAgICAgIH0sXG4gICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pXG4gIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICB9LFxuICAgIGR1cGxpY2F0ZXNfdGltZW91dCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuc2V0KHRpbWVvdXQsIGFjaywgZnJvbSk7XG4gIH07XG5cblxuICAvKipcbiAgICogUmVwcmVzZW50YXRpb24gb2YgYSBSUEMgcmVxdWVzdFxuICAgKlxuICAgKiBAY2xhc3NcbiAgICogQGV4dGVuZHMgUnBjTm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaWQgLSBpZGVudGlmaWVyIG9mIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBbZnJvbV0gLSBzb3VyY2Ugb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gUnBjUmVxdWVzdChtZXRob2QsIHBhcmFtcywgaWQsIGZyb20sIHRyYW5zcG9ydClcbiAge1xuICAgIFJwY05vdGlmaWNhdGlvbi5jYWxsKHRoaXMsIG1ldGhvZCwgcGFyYW1zKTtcblxuICAgIHRoaXMuZ2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24oKVxuICAgIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24odmFsdWUpXG4gICAge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsXG4gICAgICB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZighKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSlcbiAgICB7XG4gICAgICBpZihkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydClcbiAgICB7XG4gICAgICAvLyBGaXggb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAgaWYoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgICB7XG4gICAgICAgIGlmKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb25cbiAgICAgIHx8IHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgICAge1xuICAgICAgICBpZih0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmKGZyb20gIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICBlcnJvci5kZXN0ID0gZnJvbTtcblxuICAgICAgICBpZihyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZihlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKVxuICAgICAge1xuICAgICAgICBpZihzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHtcbiAgICAgICAgICBpZihlcnJvcilcbiAgICAgICAgICAgIGVycm9yLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXN1bHQuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJvdG9jb2wgaW5kaWNhdGVzIHRoYXQgcmVzcG9uc2VzIGhhcyBvd24gcmVxdWVzdCBtZXRob2RzXG4gICAgICAgIGlmKHJlc3BvbnNlTWV0aG9kKVxuICAgICAgICB7XG4gICAgICAgICAgaWYocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgPyByZXNwb25zZU1ldGhvZC5lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICA6IHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9XG4gICAgICAgICAge1xuICAgICAgICAgICAgZXJyb3I6ICBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7cmVzdWx0OiBudWxsfSwgaWQpO1xuXG4gICAgICAvLyBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGEgZHVwbGljYXRlZCByZXF1ZXN0IGxhdGVyXG4gICAgICBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBmcm9tKTtcblxuICAgICAgLy8gUmV0dXJuIHRoZSBzdG9yZWQgcmVzcG9uc2Ugc28gaXQgY2FuIGJlIGRpcmVjdGx5IHNlbmQgYmFja1xuICAgICAgdHJhbnNwb3J0ID0gdHJhbnNwb3J0IHx8IHRoaXMuZ2V0VHJhbnNwb3J0KCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcblxuICAgICAgaWYodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKVxuICB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmKCFyZXF1ZXN0KSByZXR1cm47XG5cbiAgICBjbGVhclRpbWVvdXQocmVxdWVzdC50aW1lb3V0KTtcblxuICAgIC8vIFN0YXJ0IGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGtleS5pZCwga2V5LmRlc3QpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBbGxvdyB0byBjYW5jZWwgYSByZXF1ZXN0IGFuZCBkb24ndCB3YWl0IGZvciBhIHJlc3BvbnNlXG4gICAqXG4gICAqIElmIGBtZXNzYWdlYCBpcyBub3QgZ2l2ZW4sIGNhbmNlbCBhbGwgdGhlIHJlcXVlc3RcbiAgICovXG4gIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24obWVzc2FnZSlcbiAge1xuICAgIGlmKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IodmFyIG1lc3NhZ2UgaW4gbWVzc2FnZTJLZXkpXG4gICAgICBjYW5jZWwobWVzc2FnZSk7XG4gIH07XG5cblxuICB0aGlzLmNsb3NlID0gZnVuY3Rpb24oKVxuICB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICB0cmFuc3BvcnQuY2xvc2UoNDAwMywgXCJDYW5jZWwgcmVxdWVzdFwiKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbihyZXNwb25zZSlcbiAgICB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKVxuICB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZihwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCAgICAgID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zICAgID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGVsc2UgaWYoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHtcbiAgICAgIGlmKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IGRlc3Q7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ICAgICAgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZWxzZSBpZih0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICB7XG4gICAgICBpZihjYWxsYmFjayAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrICA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKVxuICAgIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZGVzdCA9IGRlc3Q7XG4gICAgfTtcblxuICAgIC8vIEVuY29kZSBtZXNzYWdlXG4gICAgdmFyIG1lc3NhZ2UgPVxuICAgIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYoY2FsbGJhY2spXG4gICAge1xuICAgICAgdmFyIGlkID0gcmVxdWVzdElEKys7XG4gICAgICB2YXIgcmV0cmllZCA9IDA7XG5cbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG5cbiAgICAgIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IsIHJlc3VsdClcbiAgICAgIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9XG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6ICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6ICAgICAgICBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJ0ID0gKG1ldGhvZCA9PT0gJ3BpbmcnID8gcGluZ19yZXF1ZXN0X3RpbWVvdXQgOiByZXF1ZXN0X3RpbWVvdXQpO1xuICAgICAgICByZXF1ZXN0LnRpbWVvdXQgPSBzZXRUaW1lb3V0KHRpbWVvdXQsIHJ0Kk1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtpZDogaWQsIGRlc3Q6IGRlc3R9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9O1xuXG4gICAgICBmdW5jdGlvbiByZXRyeSh0cmFuc3BvcnQpXG4gICAgICB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQrJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpXG4gICAgICB7XG4gICAgICAgIGlmKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZih0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24obWVzc2FnZSwgdHJhbnNwb3J0KVxuICB7XG4gICAgaWYoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeVxuICAgIHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBjYXRjaChlKVxuICAgIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkICAgICA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayAgICA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZihpZCA9PSB1bmRlZmluZWQgJiYgYWNrID09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKVxuICAgIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgYSB0cmFuc3BvcnQgYW5kIGl0J3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QsIHJlcGx5IGlubWVkaWF0bHlcbiAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKTtcbiAgICAgIGlmKHRyYW5zcG9ydClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG4gICAgICAgIGlmKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdClcbiAgICB7XG4gICAgICByZXF1ZXN0LmNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBkdXBsaWNhdGVkUmVzcG9uc2UodGltZW91dClcbiAgICB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZihtZXRob2QpXG4gICAge1xuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgICAgaWYoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRClcbiAgICAgIHtcbiAgICAgICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYocmVxdWVzdClcbiAgICAgICAge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZihtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLnJlc3BvbnNlKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBudWxsLCBwYXJhbXMpO1xuXG4gICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXF1ZXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkUmVzcG9uc2VzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yICA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgdmFyIHJlc3VsdCA9IG1lc3NhZ2UucmVzdWx0O1xuXG4gICAgLy8gSWdub3JlIHJlc3BvbnNlcyBub3Qgc2VuZCB0byB1c1xuICAgIGlmKGVycm9yICAmJiBlcnJvci5kZXN0ICAmJiBlcnJvci5kZXN0ICAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmKCFyZXF1ZXN0KVxuICAgIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZihwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzO1xuIiwiLyoqXG4gKiBKc29uUlBDIDIuMCBwYWNrZXJcbiAqL1xuXG4vKipcbiAqIFBhY2sgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG1lc3NhZ2UgLSBvYmplY3QgdG8gYmUgcGFja2FnZWQuIEl0IHJlcXVpcmVzIHRvIGhhdmUgYWxsIHRoZVxuICogICBmaWVsZHMgbmVlZGVkIGJ5IHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIHRoYXQgaXQncyBnb2luZyB0byBiZSBnZW5lcmF0ZWRcbiAqXG4gKiBAcmV0dXJuIHtTdHJpbmd9IC0gdGhlIHN0cmluZ2lmaWVkIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqL1xuZnVuY3Rpb24gcGFjayhtZXNzYWdlLCBpZClcbntcbiAgdmFyIHJlc3VsdCA9XG4gIHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZihtZXNzYWdlLm1ldGhvZClcbiAge1xuICAgIHJlc3VsdC5tZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcblxuICAgIGlmKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZihpZCAhPSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihtZXNzYWdlLmVycm9yKVxuICAgIHtcbiAgICAgIGlmKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWRcIik7XG5cbiAgICAgIHJlc3VsdC5lcnJvciA9IG1lc3NhZ2UuZXJyb3I7XG4gICAgfVxuICAgIGVsc2UgaWYobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpXG57XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYodmVyc2lvbiAhPT0gJzIuMCcpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgSnNvblJQQyB2ZXJzaW9uICdcIiArIHZlcnNpb24gKyBcIic6IFwiICsgbWVzc2FnZSk7XG5cbiAgLy8gUmVzcG9uc2VcbiAgaWYocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpXG4gIHtcbiAgICBpZihyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIrbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgID0gcmVzdWx0LmVycm9yICAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmKHJlc3VsdF9kZWZpbmVkICYmIGVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkOiBcIittZXNzYWdlKTtcblxuICAgIGlmKCFyZXN1bHRfZGVmaW5lZCAmJiAhZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJObyByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZDogXCIrbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgICA9IHBhY2s7XG5leHBvcnRzLnVucGFjayA9IHVucGFjaztcbiIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5mdW5jdGlvbiB1bnBhY2sobWVzc2FnZSlcbntcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5cbmV4cG9ydHMucGFjayAgID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrO1xuIiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgID0gWG1sUlBDO1xuIiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG4gICAgXG4gICAgaWYobWljcm9zb2Z0RWRnZSkge1xuICAgICAgICBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShzY3JlZW5fY29uc3RyYWludHMpLnRoZW4ob25TdWNjZXNzKWNhdGNoKG9uRmFpbHVyZSk7XG4gICAgfVxufSwgJ3Bhc3Mgc2Vjb25kIHBhcmFtZXRlciBvbmx5IGlmIHlvdSB3YW50IHN5c3RlbSBhdWRpbycpO1xuKi9cblxud2luZG93LmdldFNjcmVlbklkID0gZnVuY3Rpb24gKGZpcmVmb3hTdHJpbmcsIGNhbGxiYWNrLCBjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignRWRnZScpICE9PSAtMSAmJiAoISFuYXZpZ2F0b3IubXNTYXZlT3JPcGVuQmxvYiB8fCAhIW5hdmlnYXRvci5tc1NhdmVCbG9iKSkge1xuICAgICAgICAvLyBtaWNyb3NvZnQgZWRnZSA9PiBuYXZpZ2F0b3IuZ2V0RGlzcGxheU1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MsIG9uRmFpbHVyZSk7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZm9yIEZpcmVmb3g6XG4gICAgLy8gc291cmNlSWQgPT0gJ2ZpcmVmb3gnXG4gICAgLy8gc2NyZWVuX2NvbnN0cmFpbnRzID0gey4uLn1cbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsICdmaXJlZm94Jywge1xuICAgICAgICAgICAgdmlkZW86IHtcbiAgICAgICAgICAgICAgICBtb3pNZWRpYVNvdXJjZTogZmlyZWZveFN0cmluZyxcbiAgICAgICAgICAgICAgICBtZWRpYVNvdXJjZTogZmlyZWZveFN0cmluZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG5cbiAgICBmdW5jdGlvbiBvbklGcmFtZUNhbGxiYWNrKGV2ZW50KSB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soJ3Blcm1pc3Npb24tZGVuaWVkJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCwgZ2V0U2NyZWVuQ29uc3RyYWludHMobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBldmVudC5kYXRhLmNhblJlcXVlc3RBdWRpb1RyYWNrKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzLCBudWxsLCBnZXRTY3JlZW5Db25zdHJhaW50cyhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykpO1xuXG4gICAgICAgICAgICAvLyB0aGlzIGV2ZW50IGxpc3RlbmVyIGlzIG5vIG1vcmUgbmVlZGVkXG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldFNvdXJjZUlkTWVzc2FnZSwgMTAwKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSwgMTAwKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhlcnJvciwgc291cmNlSWQsIGNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IGVycm9yID8gJ3NjcmVlbicgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGggPiAxOTIwID8gd2luZG93LnNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICAgICAgbWF4SGVpZ2h0OiB3aW5kb3cuc2NyZWVuLmhlaWdodCA+IDEwODAgPyB3aW5kb3cuc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoISFjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICAvLyBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2VJZCA9IHNvdXJjZUlkO1xuXG4gICAgICAgIGlmIChzY3JlZW5fY29uc3RyYWludHMuYXVkaW8gJiYgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeSkge1xuICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLmF1ZGlvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2NyZWVuX2NvbnN0cmFpbnRzO1xufVxuXG5mdW5jdGlvbiBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpZnJhbWUuaXNMb2FkZWQpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFjdXN0b21fcGFyYW1ldGVyKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZDogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIGlmICghIWN1c3RvbV9wYXJhbWV0ZXIuZm9yRWFjaCkge1xuICAgICAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICAgICBjYXB0dXJlQ3VzdG9tU291cmNlSWQ6IGN1c3RvbV9wYXJhbWV0ZXJcbiAgICAgICAgfSwgJyonKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVTb3VyY2VJZFdpdGhBdWRpbzogdHJ1ZVxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbn1cblxudmFyIGlmcmFtZTtcblxuLy8gdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIFJUQ011bHRpQ29ubmVjdGlvbiB2M1xud2luZG93LmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgbG9hZElGcmFtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldFNjcmVlbklkKGZ1bmN0aW9uIChlcnJvciwgc291cmNlSWQsIHNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB0cnVlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNjcmVlbl9jb25zdHJhaW50cy52aWRlbyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gbG9hZElGcmFtZShsb2FkQ2FsbGJhY2spIHtcbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICAgIGxvYWRDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgaWZyYW1lLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWZyYW1lLmlzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgfTtcbiAgICBpZnJhbWUuc3JjID0gJ2h0dHBzOi8vb3BlbnZpZHUuZ2l0aHViLmlvL29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24vJztcbiAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAoZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZENoaWxkKGlmcmFtZSk7XG59XG5cbndpbmRvdy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICBpZiAoISFuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGNhbGxiYWNrKCdpbnN0YWxsZWQtZW5hYmxlZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cyk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xufTtcblxuZnVuY3Rpb24gcG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UoKSB7XG4gICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgbG9hZElGcmFtZShwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlLCAxMDApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM6IHRydWVcbiAgICB9LCAnKicpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbklkID0gZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG52YXIgaXNGaXJlZm94ID0gdHlwZW9mIHdpbmRvdy5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNPcGVyYSA9ICEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwO1xudmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmIChldmVudC5vcmlnaW4gIT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIG9uTWVzc2FnZUNhbGxiYWNrKGV2ZW50LmRhdGEpO1xufSk7XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiIFxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgfVxuXG4gICAgLy8gbm93IGludm9raW5nIG5hdGl2ZSBnZXRVc2VyTWVkaWEgQVBJXG4gICAgY2FsbGJhY2sobnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbn1cblxuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50cyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzO1xuZXhwb3J0cy5nZXRTY3JlZW5Db25zdHJhaW50c1dpdGhBdWRpbyA9IGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvO1xuZXhwb3J0cy5pc0Nocm9tZUV4dGVuc2lvbkF2YWlsYWJsZSA9IGlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlO1xuZXhwb3J0cy5nZXRDaHJvbWVFeHRlbnNpb25TdGF0dXMgPSBnZXRDaHJvbWVFeHRlbnNpb25TdGF0dXM7XG5leHBvcnRzLmdldFNvdXJjZUlkID0gZ2V0U291cmNlSWQ7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDE5IE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgZnJlZWljZSA9IHJlcXVpcmUoJ2ZyZWVpY2UnKTtcbmltcG9ydCB1dWlkID0gcmVxdWlyZSgndXVpZCcpO1xuaW1wb3J0IHBsYXRmb3JtID0gcmVxdWlyZSgncGxhdGZvcm0nKTtcblxuZXhwb3J0IGludGVyZmFjZSBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbiB7XG4gICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICBhdWRpbzogYm9vbGVhbixcbiAgICAgICAgdmlkZW86IGJvb2xlYW5cbiAgICB9O1xuICAgIHNpbXVsY2FzdDogYm9vbGVhbjtcbiAgICBvbmljZWNhbmRpZGF0ZTogKGV2ZW50KSA9PiB2b2lkO1xuICAgIGljZVNlcnZlcnM6IFJUQ0ljZVNlcnZlcltdIHwgdW5kZWZpbmVkO1xuICAgIG1lZGlhU3RyZWFtPzogTWVkaWFTdHJlYW07XG4gICAgbW9kZT86ICdzZW5kb25seScgfCAncmVjdm9ubHknIHwgJ3NlbmRyZWN2JztcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuXG4gICAgcGM6IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIGxvY2FsQ2FuZGlkYXRlc1F1ZXVlOiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuXG4gICAgaWNlQ2FuZGlkYXRlTGlzdDogUlRDSWNlQ2FuZGlkYXRlW10gPSBbXTtcblxuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9ICghIXRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzICYmIHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDApID8gdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgOiBmcmVlaWNlKCk7XG5cbiAgICAgICAgdGhpcy5wYyA9IG5ldyBSVENQZWVyQ29ubmVjdGlvbih7IGljZVNlcnZlcnM6IHRoaXMuY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzIH0pO1xuICAgICAgICB0aGlzLmlkID0gISFjb25maWd1cmF0aW9uLmlkID8gY29uZmlndXJhdGlvbi5pZCA6IHV1aWQudjQoKTtcblxuICAgICAgICB0aGlzLnBjLm9uaWNlY2FuZGlkYXRlID0gZXZlbnQgPT4ge1xuICAgICAgICAgICAgaWYgKCEhZXZlbnQuY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUgPSBldmVudC5jYW5kaWRhdGU7XG4gICAgICAgICAgICAgICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW5kaWRhdGVnYXRoZXJpbmdkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5vbmljZWNhbmRpZGF0ZShldmVudC5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbmRpZGF0ZWdhdGhlcmluZ2RvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnBjLm9uc2lnbmFsaW5nc3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAodGhpcy5pY2VDYW5kaWRhdGVMaXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoPFJUQ0ljZUNhbmRpZGF0ZT50aGlzLmljZUNhbmRpZGF0ZUxpc3Quc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuc3RhcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGNyZWF0ZXMgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZVxuICAgICAqIHByb3BlcnRpZXMgcmVjZWl2ZWQgaW4gdGhlIGNvbnN0cnVjdG9yLiBJdCBzdGFydHMgdGhlIFNEUCBuZWdvdGlhdGlvblxuICAgICAqIHByb2Nlc3M6IGdlbmVyYXRlcyB0aGUgU0RQIG9mZmVyIGFuZCBpbnZva2VzIHRoZSBvbnNkcG9mZmVyIGNhbGxiYWNrLiBUaGlzXG4gICAgICogY2FsbGJhY2sgaXMgZXhwZWN0ZWQgdG8gc2VuZCB0aGUgU0RQIG9mZmVyLCBpbiBvcmRlciB0byBvYnRhaW4gYW4gU0RQXG4gICAgICogYW5zd2VyIGZyb20gYW5vdGhlciBwZWVyLlxuICAgICAqL1xuICAgIHN0YXJ0KCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1RoZSBwZWVyIGNvbm5lY3Rpb24gb2JqZWN0IGlzIGluIFwiY2xvc2VkXCIgc3RhdGUuIFRoaXMgaXMgbW9zdCBsaWtlbHkgZHVlIHRvIGFuIGludm9jYXRpb24gb2YgdGhlIGRpc3Bvc2UgbWV0aG9kIGJlZm9yZSBhY2NlcHRpbmcgaW4gdGhlIGRpYWxvZ3VlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBpZiAocGxhdGZvcm1bJ2lzSW9uaWNJb3MnXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpT1MgSW9uaWMuIExJTUlUQVRJT046IG11c3QgdXNlIGRlcHJlY2F0ZWQgV2ViUlRDIEFQSVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYzI6IGFueSA9IHRoaXMucGM7XG4gICAgICAgICAgICAgICAgICAgIHBjMi5hZGRTdHJlYW0odGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHRyYWNrIG9mIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbS5nZXRUcmFja3MoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRUcmFjayh0cmFjaywgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSh2aWRlb1NvdXJjZUlzTWVkaWFTdHJlYW1UcmFjazogYm9vbGVhbikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgIGlmIChwbGF0Zm9ybVsnaXNJb25pY0lvcyddKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlPUyBJb25pYy4gTElNSVRBVElPTjogbXVzdCB1c2UgZGVwcmVjYXRlZCBXZWJSVEMgQVBJXG4gICAgICAgICAgICAgICAgICAgIC8vIFN0b3Agc2VuZGVycyBkZXByZWNhdGVkXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBjMTogYW55ID0gdGhpcy5wYztcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzZW5kZXIgb2YgcGMxLmdldExvY2FsU3RyZWFtcygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXZpZGVvU291cmNlSXNNZWRpYVN0cmVhbVRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZGVyLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBjMS5yZW1vdmVTdHJlYW0oc2VuZGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBTdG9wIHJlY2VpdmVycyBkZXByZWNhdGVkXG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmVjZWl2ZXIgb2YgcGMxLmdldFJlbW90ZVN0cmVhbXMoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVjZWl2ZXIudHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlci5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdG9wIHNlbmRlcnNcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzZW5kZXIgb2YgdGhpcy5wYy5nZXRTZW5kZXJzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmlkZW9Tb3VyY2VJc01lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFzZW5kZXIudHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZGVyLnRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLnJlbW92ZVRyYWNrKHNlbmRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gU3RvcCByZWNlaXZlcnNcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZWNlaXZlciBvZiB0aGlzLnBjLmdldFJlY2VpdmVycygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFyZWNlaXZlci50cmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2VpdmVyLnRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucGMuY2xvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0V4Y2VwdGlvbiBkaXNwb3Npbmcgd2VicnRjIHBlZXIgJyArIGVycik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0aGF0IGNyZWF0ZXMgYW4gb2ZmZXIsIHNldHMgaXQgYXMgbG9jYWwgZGVzY3JpcHRpb24gYW5kIHJldHVybnMgdGhlIG9mZmVyIHBhcmFtXG4gICAgICogdG8gc2VuZCB0byBPcGVuVmlkdSBTZXJ2ZXIgKHdpbGwgYmUgdGhlIHJlbW90ZSBkZXNjcmlwdGlvbiBvZiBvdGhlciBwZWVyKVxuICAgICAqL1xuICAgIGdlbmVyYXRlT2ZmZXIoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxldCBvZmZlckF1ZGlvLCBvZmZlclZpZGVvID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gQ29uc3RyYWludHMgbXVzdCBoYXZlIGJvdGggYmxvY2tzXG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIG9mZmVyQXVkaW8gPSAodHlwZW9mIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gOiB0cnVlO1xuICAgICAgICAgICAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMudmlkZW8gOiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBjb25zdHJhaW50czogUlRDT2ZmZXJPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIG9mZmVyVG9SZWNlaXZlQXVkaW86ICh0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gJ3NlbmRvbmx5JyAmJiBvZmZlckF1ZGlvKSxcbiAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09ICdzZW5kb25seScgJiYgb2ZmZXJWaWRlbylcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1JUQ1BlZXJDb25uZWN0aW9uIGNvbnN0cmFpbnRzOiAnICsgSlNPTi5zdHJpbmdpZnkoY29uc3RyYWludHMpKTtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUgPT09ICdTYWZhcmknICYmIHBsYXRmb3JtLnVhISEuaW5kZXhPZignU2FmYXJpJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gU2FmYXJpIChleGNsdWRpbmcgSW9uaWMpLCBhdCBsZWFzdCBvbiBpT1MganVzdCBzZWVtcyB0byBzdXBwb3J0IHVuaWZpZWQgcGxhbiwgd2hlcmVhcyBpbiBvdGhlciBicm93c2VycyBpcyBub3QgeWV0IHJlYWR5IGFuZCBjb25zaWRlcmVkIGV4cGVyaW1lbnRhbFxuICAgICAgICAgICAgICAgIGlmIChvZmZlckF1ZGlvKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkVHJhbnNjZWl2ZXIoJ2F1ZGlvJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9mZmVyVmlkZW8pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRUcmFuc2NlaXZlcigndmlkZW8nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb246IHRoaXMuY29uZmlndXJhdGlvbi5tb2RlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBjXG4gICAgICAgICAgICAgICAgICAgIC5jcmVhdGVPZmZlcigpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKG9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0NyZWF0ZWQgU0RQIG9mZmVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxEZXNjcmlwdGlvbiA9IHRoaXMucGMubG9jYWxEZXNjcmlwdGlvbjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBSZXN0IG9mIHBsYXRmb3Jtc1xuICAgICAgICAgICAgICAgIHRoaXMucGMuY3JlYXRlT2ZmZXIoY29uc3RyYWludHMpLnRoZW4ob2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdDcmVhdGVkIFNEUCBvZmZlcicpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2NhbERlc2NyaXB0aW9uID0gdGhpcy5wYy5sb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhbG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoJ0xvY2FsIGRlc2NyaXB0aW9uIHNldCcsIGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIGludm9rZWQgd2hlbiBhIFNEUCBhbnN3ZXIgaXMgcmVjZWl2ZWQuIEZpbmFsIHN0ZXAgaW4gU0RQIG5lZ290aWF0aW9uLCB0aGUgcGVlclxuICAgICAqIGp1c3QgbmVlZHMgdG8gc2V0IHRoZSBhbnN3ZXIgYXMgaXRzIHJlbW90ZSBkZXNjcmlwdGlvblxuICAgICAqL1xuICAgIHByb2Nlc3NBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcsIG5lZWRzVGltZW91dE9uUHJvY2Vzc0Fuc3dlcjogYm9vbGVhbik6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdTRFAgYW5zd2VyIHJlY2VpdmVkLCBzZXR0aW5nIHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtWydpc0lvbmljSW9zJ10pIHtcbiAgICAgICAgICAgICAgICAvLyBJb25pYyBpT1MgcGxhdGZvcm1cbiAgICAgICAgICAgICAgICBpZiAobmVlZHNUaW1lb3V0T25Qcm9jZXNzQW5zd2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIDQwMCBtcyBoYXZlIG5vdCBlbGFwc2VkIHlldCBzaW5jZSBmaXJzdCByZW1vdGUgc3RyZWFtIHRyaWdnZXJlZCBTdHJlYW0jaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlXG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5pbmZvKCdzZXRSZW1vdGVEZXNjcmlwdGlvbiBydW4gYWZ0ZXIgdGltZW91dCBmb3IgSW9uaWMgaU9TIGRldmljZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKGFuc3dlcikpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMjUwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyA0MDAgbXMgaGF2ZSBlbGFwc2VkXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24obmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbihhbnN3ZXIpKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZXN0IG9mIHBsYXRmb3Jtc1xuICAgICAgICAgICAgICAgIHRoaXMucGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKS50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKCdSZW1vdGUgSUNFIGNhbmRpZGF0ZSByZWNlaXZlZCcsIGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZS5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdQZWVyQ29ubmVjdGlvbiBvYmplY3QgaXMgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzdGFibGUnOlxuICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnBjLnJlbW90ZURlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKS5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5wdXNoKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbn1cblxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclJlY3Zvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRvbmx5IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRvbmx5JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2ViUnRjUGVlclNlbmRyZWN2IGV4dGVuZHMgV2ViUnRjUGVlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgY29uZmlndXJhdGlvbi5tb2RlID0gJ3NlbmRyZWN2JztcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XG4gICAgfVxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAxOSBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pby8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCBwbGF0Zm9ybSA9IHJlcXVpcmUoJ3BsYXRmb3JtJyk7XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzRW5hYmxlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNJbnRlcnZhbElkOiBOb2RlSlMuVGltZXI7XG4gICAgcHJpdmF0ZSBzdGF0c0ludGVydmFsID0gMTtcbiAgICBwcml2YXRlIHN0YXRzOiBhbnkgPSB7XG4gICAgICAgIGluYm91bmQ6IHtcbiAgICAgICAgICAgIGF1ZGlvOiB7XG4gICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IDAsXG4gICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAwLFxuICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAwLFxuICAgICAgICAgICAgICAgIGZyYW1lc0RlY29kZWQ6IDAsXG4gICAgICAgICAgICAgICAgbmFja0NvdW50OiAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogMCxcbiAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogMCxcbiAgICAgICAgICAgICAgICBmcmFtZXNFbmNvZGVkOiAwLFxuICAgICAgICAgICAgICAgIG5hY2tDb3VudDogMFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHsgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnZWxhc3Rlc3QtaW5zdHJ1bWVudGF0aW9uJyk7XG5cbiAgICAgICAgaWYgKCEhZWxhc3Rlc3RJbnN0cnVtZW50YXRpb24pIHtcbiAgICAgICAgICAgIC8vIEVsYXNUZXN0IGluc3RydW1lbnRhdGlvbiBvYmplY3QgZm91bmQgaW4gbG9jYWwgc3RvcmFnZVxuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYlJ0YyBzdGF0cyBlbmFibGVkIGZvciBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgY29uc3QgaW5zdHJ1bWVudGF0aW9uID0gSlNPTi5wYXJzZShlbGFzdGVzdEluc3RydW1lbnRhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWwgPSBpbnN0cnVtZW50YXRpb24ud2VicnRjLmludGVydmFsOyAgLy8gSW50ZXJ2YWwgaW4gc2Vjb25kc1xuXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2xvY2FsU3RvcmFnZSBpdGVtOiAnICsgSlNPTi5zdHJpbmdpZnkoaW5zdHJ1bWVudGF0aW9uKSk7XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHNJbnRlcnZhbElkID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoaW5zdHJ1bWVudGF0aW9uKTtcbiAgICAgICAgICAgIH0sIHRoaXMuc3RhdHNJbnRlcnZhbCAqIDEwMDApO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlLmRlYnVnKCdXZWJSdGMgc3RhdHMgbm90IGVuYWJsZWQnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RvcFdlYlJ0Y1N0YXRzKCkge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWJSdGMgc3RhdHMgc3RvcHBlZCBmb3IgZGlzcG9zZWQgc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICcgb2YgY29ubmVjdGlvbiAnICsgdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNlbGVjdGVkSWNlQ2FuZGlkYXRlSW5mbygpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5nZXRTdGF0c0Fnbm9zdGljKHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCksXG4gICAgICAgICAgICAgICAgKHN0YXRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICgocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignQ2hyb21lJykgIT09IC0xKSB8fCAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignT3BlcmEnKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbG9jYWxDYW5kaWRhdGVJZCwgcmVtb3RlQ2FuZGlkYXRlSWQsIGdvb2dDYW5kaWRhdGVQYWlyO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9jYWxDYW5kaWRhdGVzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZW1vdGVDYW5kaWRhdGVzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBzdGF0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXQgPSBzdGF0c1trZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0LnR5cGUgPT09ICdsb2NhbGNhbmRpZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVzW3N0YXQuaWRdID0gc3RhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXQudHlwZSA9PT0gJ3JlbW90ZWNhbmRpZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlc1tzdGF0LmlkXSA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0LnR5cGUgPT09ICdnb29nQ2FuZGlkYXRlUGFpcicgJiYgKHN0YXQuZ29vZ0FjdGl2ZUNvbm5lY3Rpb24gPT09ICd0cnVlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29vZ0NhbmRpZGF0ZVBhaXIgPSBzdGF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbENhbmRpZGF0ZUlkID0gc3RhdC5sb2NhbENhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDYW5kaWRhdGVJZCA9IHN0YXQucmVtb3RlQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbmFsTG9jYWxDYW5kaWRhdGUgPSBsb2NhbENhbmRpZGF0ZXNbbG9jYWxDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFmaW5hbExvY2FsQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kID0gY2FuZExpc3QuZmlsdGVyKChjOiBSVENJY2VDYW5kaWRhdGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICghIWMuY2FuZGlkYXRlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUuaXBBZGRyZXNzKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsTG9jYWxDYW5kaWRhdGUucG9ydE51bWJlcikgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnByaW9yaXR5KSA+PSAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbExvY2FsQ2FuZGlkYXRlLnJhdyA9ICEhY2FuZFswXSA/IGNhbmRbMF0uY2FuZGlkYXRlIDogJ0VSUk9SOiBDYW5ub3QgZmluZCBsb2NhbCBjYW5kaWRhdGUgaW4gbGlzdCBvZiBzZW50IElDRSBjYW5kaWRhdGVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIGxvY2FsIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9IHJlbW90ZUNhbmRpZGF0ZXNbcmVtb3RlQ2FuZGlkYXRlSWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZmluYWxSZW1vdGVDYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kTGlzdCA9IHRoaXMuc3RyZWFtLmdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kID0gY2FuZExpc3QuZmlsdGVyKChjOiBSVENJY2VDYW5kaWRhdGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICghIWMuY2FuZGlkYXRlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLmlwQWRkcmVzcykgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wb3J0TnVtYmVyKSA+PSAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjLmNhbmRpZGF0ZS5pbmRleE9mKGZpbmFsUmVtb3RlQ2FuZGlkYXRlLnByaW9yaXR5KSA+PSAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZS5yYXcgPSAhIWNhbmRbMF0gPyBjYW5kWzBdLmNhbmRpZGF0ZSA6ICdFUlJPUjogQ2Fubm90IGZpbmQgcmVtb3RlIGNhbmRpZGF0ZSBpbiBsaXN0IG9mIHJlY2VpdmVkIElDRSBjYW5kaWRhdGVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSByZW1vdGUgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29vZ0NhbmRpZGF0ZVBhaXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGU6IGZpbmFsTG9jYWxDYW5kaWRhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlOiBmaW5hbFJlbW90ZUNhbmRpZGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoJ1NlbGVjdGVkIElDRSBjYW5kaWRhdGUgaW5mbyBvbmx5IGF2YWlsYWJsZSBmb3IgQ2hyb21lJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KGluc3RydW1lbnRhdGlvbik6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHNlbmRQb3N0ID0gKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGh0dHA6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjb25zdCB1cmw6IHN0cmluZyA9IGluc3RydW1lbnRhdGlvbi53ZWJydGMuaHR0cEVuZHBvaW50O1xuICAgICAgICAgICAgaHR0cC5vcGVuKCdQT1NUJywgdXJsLCB0cnVlKTtcblxuICAgICAgICAgICAgaHR0cC5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuXG4gICAgICAgICAgICBodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHsgLy8gQ2FsbCBhIGZ1bmN0aW9uIHdoZW4gdGhlIHN0YXRlIGNoYW5nZXMuXG4gICAgICAgICAgICAgICAgaWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWJSdGMgc3RhdHMgc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gJyArIHVybCArICcgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHR0cC5zZW5kKGpzb24pO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGYgPSAoc3RhdHMpID0+IHtcblxuICAgICAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5mb3JFYWNoKChzdGF0KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoKHN0YXQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdm9pZCBmaXJlZm94IGVtcHR5IG91dGJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5uYWNrQ291bnQgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlzUmVtb3RlID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQuaWQuc3RhcnRzV2l0aCgnaW5ib3VuZCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5yZW1vdGVJZC5zdGFydHNXaXRoKCdpbmJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX2luYm91bmRfJyArIHN0YXQubWVkaWFUeXBlICsgJ18nICsgc3RhdC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgaml0ID0gc3RhdC5qaXR0ZXIgKiAxMDAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRyaWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGppdHRlcjogaml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogKHN0YXQucGFja2V0c1JlY2VpdmVkIC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNMb3N0OiAoc3RhdC5wYWNrZXRzTG9zdCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogJ2J5dGVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiAncGFja2V0cycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6ICdwYWNrZXRzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0Lm1lZGlhVHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldHJpY3NbJ2ZyYW1lc0RlY29kZWQnXSA9IChzdGF0LmZyYW1lc0RlY29kZWQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8uZnJhbWVzRGVjb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5uYWNrQ291bnQgLSB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRGVjb2RlZCddID0gJ2ZyYW1lcyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLmZyYW1lc0RlY29kZWQgPSBzdGF0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCA9IHN0YXQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCA9IHN0YXQucGFja2V0c0xvc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb24gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXhlYyc6IGluc3RydW1lbnRhdGlvbi5leGVjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb21wb25lbnQnOiBpbnN0cnVtZW50YXRpb24uY29tcG9uZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZXRfdHlwZSc6IG1ldHJpY0lkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1fdHlwZSc6ICdjb21wb3NlZF9tZXRyaWNzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGpzb25bbWV0cmljSWRdID0gbWV0cmljcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKHN0YXQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXZvaWQgZmlyZWZveCBlbXB0eSBpbmJvdW5kLXJ0cCBzdGF0aXN0aWNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdC5pc1JlbW90ZSA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0LmlkLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ291dGJvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQ6IChzdGF0LmJ5dGVzU2VudCAtIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5pdHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNTZW50OiAncGFja2V0cydcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzWydmcmFtZXNFbmNvZGVkJ10gPSAoc3RhdC5mcmFtZXNFbmNvZGVkIC0gdGhpcy5zdGF0cy5vdXRib3VuZC52aWRlby5mcmFtZXNFbmNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bml0c1snZnJhbWVzRW5jb2RlZCddID0gJ2ZyYW1lcyc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMub3V0Ym91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzU2VudCA9IHN0YXQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoc3RhdC50aW1lc3RhbXApLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY29tcG9uZW50JzogaW5zdHJ1bWVudGF0aW9uLmNvbXBvbmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtJzogJ3dlYlJ0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V0X3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3RyZWFtX3R5cGUnOiAnY29tcG9zZWRfbWV0cmljcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3VuaXRzJzogdW5pdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBqc29uW21ldHJpY0lkXSA9IG1ldHJpY3M7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQb3N0KEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignQ2hyb21lJykgIT09IC0xKSB8fCAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignT3BlcmEnKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoc3RhdHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXQgPSBzdGF0c1trZXldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAnc3NyYycpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGpzb24gPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCdieXRlc1JlY2VpdmVkJyBpbiBzdGF0ICYmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3RhdC5tZWRpYVR5cGUgPT09ICdhdWRpbycgJiYgJ2F1ZGlvT3V0cHV0TGV2ZWwnIGluIHN0YXQpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHN0YXQubWVkaWFUeXBlID09PSAndmlkZW8nICYmICdxcFN1bScgaW4gc3RhdClcbiAgICAgICAgICAgICAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbmJvdW5kLXJ0cFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY0lkID0gJ3dlYnJ0Y19pbmJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQ6IChzdGF0LmJ5dGVzUmVjZWl2ZWQgLSB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLmJ5dGVzUmVjZWl2ZWQpIC8gdGhpcy5zdGF0c0ludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6IHN0YXQuZ29vZ0ppdHRlckJ1ZmZlck1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzUmVjZWl2ZWQ6IChzdGF0LnBhY2tldHNSZWNlaXZlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1JlY2VpdmVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c0xvc3Q6IChzdGF0LnBhY2tldHNMb3N0IC0gdGhpcy5zdGF0cy5pbmJvdW5kW3N0YXQubWVkaWFUeXBlXS5wYWNrZXRzTG9zdCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1JlY2VpdmVkOiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXI6ICdtcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNSZWNlaXZlZDogJ3BhY2tldHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzTG9zdDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRGVjb2RlZCddID0gKHN0YXQuZnJhbWVzRGVjb2RlZCAtIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkKSAvIHRoaXMuc3RhdHNJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snbmFja0NvdW50J10gPSAoc3RhdC5nb29nTmFja3NTZW50IC0gdGhpcy5zdGF0cy5pbmJvdW5kLnZpZGVvLm5hY2tDb3VudCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNEZWNvZGVkJ10gPSAnZnJhbWVzJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHNbJ25hY2tDb3VudCddID0gJ3BhY2tldHMnO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZC52aWRlby5mcmFtZXNEZWNvZGVkID0gc3RhdC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmQudmlkZW8ubmFja0NvdW50ID0gc3RhdC5nb29nTmFja3NTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNSZWNlaXZlZCA9IHN0YXQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLmluYm91bmRbc3RhdC5tZWRpYVR5cGVdLnBhY2tldHNSZWNlaXZlZCA9IHN0YXQucGFja2V0c1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdHMuaW5ib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c0xvc3QgPSBzdGF0LnBhY2tldHNMb3N0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V0X3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgnYnl0ZXNTZW50JyBpbiBzdGF0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3V0Ym91bmQtcnRwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWV0cmljSWQgPSAnd2VicnRjX291dGJvdW5kXycgKyBzdGF0Lm1lZGlhVHlwZSArICdfJyArIHN0YXQuc3NyYztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzU2VudDogKHN0YXQuYnl0ZXNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50KSAvIHRoaXMuc3RhdHNJbnRlcnZhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2V0c1NlbnQ6IChzdGF0LnBhY2tldHNTZW50IC0gdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQpIC8gdGhpcy5zdGF0c0ludGVydmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bml0cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNTZW50OiAnYnl0ZXMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzU2VudDogJ3BhY2tldHMnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdC5tZWRpYVR5cGUgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0cmljc1snZnJhbWVzRW5jb2RlZCddID0gKHN0YXQuZnJhbWVzRW5jb2RlZCAtIHRoaXMuc3RhdHMub3V0Ym91bmQudmlkZW8uZnJhbWVzRW5jb2RlZCkgLyB0aGlzLnN0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzWydmcmFtZXNFbmNvZGVkJ10gPSAnZnJhbWVzJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRzLm91dGJvdW5kLnZpZGVvLmZyYW1lc0VuY29kZWQgPSBzdGF0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0uYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0cy5vdXRib3VuZFtzdGF0Lm1lZGlhVHlwZV0ucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0B0aW1lc3RhbXAnOiBuZXcgRGF0ZShzdGF0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V4ZWMnOiBpbnN0cnVtZW50YXRpb24uZXhlYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbXBvbmVudCc6IGluc3RydW1lbnRhdGlvbi5jb21wb25lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW0nOiAnd2ViUnRjJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2V0X3R5cGUnOiBtZXRyaWNJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbV90eXBlJzogJ2NvbXBvc2VkX21ldHJpY3MnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndW5pdHMnOiB1bml0c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNvblttZXRyaWNJZF0gPSBtZXRyaWNzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFBvc3QoSlNPTi5zdHJpbmdpZnkoanNvbikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuZ2V0U3RhdHNBZ25vc3RpYyh0aGlzLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpLCBmLCAoZXJyb3IpID0+IHsgY29uc29sZS5sb2coZXJyb3IpOyB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YW5kYXJkaXplUmVwb3J0KHJlc3BvbnNlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlKTtcbiAgICAgICAgY29uc3Qgc3RhbmRhcmRSZXBvcnQgPSB7fTtcblxuICAgICAgICBpZiAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignRmlyZWZveCcpICE9PSAtMSkge1xuICAgICAgICAgICAgT2JqZWN0LmtleXMocmVzcG9uc2UpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZVtrZXldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzcG9uc2UucmVzdWx0KCkuZm9yRWFjaChyZXBvcnQgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhbmRhcmRTdGF0cyA9IHtcbiAgICAgICAgICAgICAgICBpZDogcmVwb3J0LmlkLFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogcmVwb3J0LnRpbWVzdGFtcCxcbiAgICAgICAgICAgICAgICB0eXBlOiByZXBvcnQudHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlcG9ydC5uYW1lcygpLmZvckVhY2goKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBzdGFuZGFyZFN0YXRzW25hbWVdID0gcmVwb3J0LnN0YXQobmFtZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHN0YW5kYXJkUmVwb3J0W3N0YW5kYXJkU3RhdHMuaWRdID0gc3RhbmRhcmRTdGF0cztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHN0YW5kYXJkUmVwb3J0O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U3RhdHNBZ25vc3RpYyhwYywgc3VjY2Vzc0NiLCBmYWlsdXJlQ2IpIHtcbiAgICAgICAgaWYgKHBsYXRmb3JtLm5hbWUhLmluZGV4T2YoJ0ZpcmVmb3gnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGdldFN0YXRzIHRha2VzIGFyZ3MgaW4gZGlmZmVyZW50IG9yZGVyIGluIENocm9tZSBhbmQgRmlyZWZveFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKG51bGwpLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZmFpbHVyZUNiKTtcbiAgICAgICAgfSBlbHNlIGlmICgocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignQ2hyb21lJykgIT09IC0xKSB8fCAocGxhdGZvcm0ubmFtZSEuaW5kZXhPZignT3BlcmEnKSAhPT0gLTEpKSB7XG4gICAgICAgICAgICAvLyBJbiBDaHJvbWUsIHRoZSBmaXJzdCB0d28gYXJndW1lbnRzIGFyZSByZXZlcnNlZFxuICAgICAgICAgICAgcmV0dXJuIHBjLmdldFN0YXRzKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuc3RhbmRhcmRpemVSZXBvcnQocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYihyZXBvcnQpO1xuICAgICAgICAgICAgfSwgbnVsbCwgZmFpbHVyZUNiKTtcbiAgICAgICAgfVxuICAgIH1cblxufSJdfQ==
|