12155 lines
1.6 MiB
12155 lines
1.6 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.
|
|
|
|
'use strict';
|
|
|
|
var R = typeof Reflect === 'object' ? Reflect : null
|
|
var ReflectApply = R && typeof R.apply === 'function'
|
|
? R.apply
|
|
: function ReflectApply(target, receiver, args) {
|
|
return Function.prototype.apply.call(target, receiver, args);
|
|
}
|
|
|
|
var ReflectOwnKeys
|
|
if (R && typeof R.ownKeys === 'function') {
|
|
ReflectOwnKeys = R.ownKeys
|
|
} else if (Object.getOwnPropertySymbols) {
|
|
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
return Object.getOwnPropertyNames(target)
|
|
.concat(Object.getOwnPropertySymbols(target));
|
|
};
|
|
} else {
|
|
ReflectOwnKeys = function ReflectOwnKeys(target) {
|
|
return Object.getOwnPropertyNames(target);
|
|
};
|
|
}
|
|
|
|
function ProcessEmitWarning(warning) {
|
|
if (console && console.warn) console.warn(warning);
|
|
}
|
|
|
|
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
|
|
return value !== value;
|
|
}
|
|
|
|
function EventEmitter() {
|
|
EventEmitter.init.call(this);
|
|
}
|
|
module.exports = EventEmitter;
|
|
module.exports.once = once;
|
|
|
|
// Backwards-compat with node 0.10.x
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
EventEmitter.prototype._events = undefined;
|
|
EventEmitter.prototype._eventsCount = 0;
|
|
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;
|
|
|
|
function checkListener(listener) {
|
|
if (typeof listener !== 'function') {
|
|
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
enumerable: true,
|
|
get: function() {
|
|
return defaultMaxListeners;
|
|
},
|
|
set: function(arg) {
|
|
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
|
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
|
|
}
|
|
defaultMaxListeners = arg;
|
|
}
|
|
});
|
|
|
|
EventEmitter.init = function() {
|
|
|
|
if (this._events === undefined ||
|
|
this._events === Object.getPrototypeOf(this)._events) {
|
|
this._events = Object.create(null);
|
|
this._eventsCount = 0;
|
|
}
|
|
|
|
this._maxListeners = this._maxListeners || undefined;
|
|
};
|
|
|
|
// 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 || NumberIsNaN(n)) {
|
|
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
|
|
}
|
|
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);
|
|
};
|
|
|
|
EventEmitter.prototype.emit = function emit(type) {
|
|
var args = [];
|
|
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
|
|
var doError = (type === 'error');
|
|
|
|
var events = this._events;
|
|
if (events !== undefined)
|
|
doError = (doError && events.error === undefined);
|
|
else if (!doError)
|
|
return false;
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (doError) {
|
|
var er;
|
|
if (args.length > 0)
|
|
er = args[0];
|
|
if (er instanceof Error) {
|
|
// Note: The comments on the `throw` lines are intentional, they show
|
|
// up in Node's output if this results in an unhandled exception.
|
|
throw er; // Unhandled 'error' event
|
|
}
|
|
// At least give some kind of context to the user
|
|
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
|
|
err.context = er;
|
|
throw err; // Unhandled 'error' event
|
|
}
|
|
|
|
var handler = events[type];
|
|
|
|
if (handler === undefined)
|
|
return false;
|
|
|
|
if (typeof handler === 'function') {
|
|
ReflectApply(handler, this, args);
|
|
} else {
|
|
var len = handler.length;
|
|
var listeners = arrayClone(handler, len);
|
|
for (var i = 0; i < len; ++i)
|
|
ReflectApply(listeners[i], this, args);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
function _addListener(target, type, listener, prepend) {
|
|
var m;
|
|
var events;
|
|
var existing;
|
|
|
|
checkListener(listener);
|
|
|
|
events = target._events;
|
|
if (events === undefined) {
|
|
events = target._events = Object.create(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 !== undefined) {
|
|
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 === undefined) {
|
|
// 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];
|
|
// If we've already got an array, just append.
|
|
} else if (prepend) {
|
|
existing.unshift(listener);
|
|
} else {
|
|
existing.push(listener);
|
|
}
|
|
|
|
// Check for listener leak
|
|
m = _getMaxListeners(target);
|
|
if (m > 0 && existing.length > m && !existing.warned) {
|
|
existing.warned = true;
|
|
// No error code for this since it is a Warning
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
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;
|
|
ProcessEmitWarning(w);
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (arguments.length === 0)
|
|
return this.listener.call(this.target);
|
|
return this.listener.apply(this.target, arguments);
|
|
}
|
|
}
|
|
|
|
function _onceWrap(target, type, listener) {
|
|
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
|
|
var wrapped = onceWrapper.bind(state);
|
|
wrapped.listener = listener;
|
|
state.wrapFn = wrapped;
|
|
return wrapped;
|
|
}
|
|
|
|
EventEmitter.prototype.once = function once(type, listener) {
|
|
checkListener(listener);
|
|
this.on(type, _onceWrap(this, type, listener));
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.prependOnceListener =
|
|
function prependOnceListener(type, listener) {
|
|
checkListener(listener);
|
|
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;
|
|
|
|
checkListener(listener);
|
|
|
|
events = this._events;
|
|
if (events === undefined)
|
|
return this;
|
|
|
|
list = events[type];
|
|
if (list === undefined)
|
|
return this;
|
|
|
|
if (list === listener || list.listener === listener) {
|
|
if (--this._eventsCount === 0)
|
|
this._events = Object.create(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 !== undefined)
|
|
this.emit('removeListener', type, originalListener || listener);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
|
|
EventEmitter.prototype.removeAllListeners =
|
|
function removeAllListeners(type) {
|
|
var listeners, events, i;
|
|
|
|
events = this._events;
|
|
if (events === undefined)
|
|
return this;
|
|
|
|
// not listening for removeListener, no need to emit
|
|
if (events.removeListener === undefined) {
|
|
if (arguments.length === 0) {
|
|
this._events = Object.create(null);
|
|
this._eventsCount = 0;
|
|
} else if (events[type] !== undefined) {
|
|
if (--this._eventsCount === 0)
|
|
this._events = Object.create(null);
|
|
else
|
|
delete events[type];
|
|
}
|
|
return this;
|
|
}
|
|
|
|
// emit removeListener for all listeners on all events
|
|
if (arguments.length === 0) {
|
|
var keys = Object.keys(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 = Object.create(null);
|
|
this._eventsCount = 0;
|
|
return this;
|
|
}
|
|
|
|
listeners = events[type];
|
|
|
|
if (typeof listeners === 'function') {
|
|
this.removeListener(type, listeners);
|
|
} else if (listeners !== undefined) {
|
|
// 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 === undefined)
|
|
return [];
|
|
|
|
var evlistener = events[type];
|
|
if (evlistener === undefined)
|
|
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 !== undefined) {
|
|
var evlistener = events[type];
|
|
|
|
if (typeof evlistener === 'function') {
|
|
return 1;
|
|
} else if (evlistener !== undefined) {
|
|
return evlistener.length;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EventEmitter.prototype.eventNames = function eventNames() {
|
|
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
|
|
};
|
|
|
|
function arrayClone(arr, n) {
|
|
var copy = new Array(n);
|
|
for (var i = 0; i < n; ++i)
|
|
copy[i] = arr[i];
|
|
return copy;
|
|
}
|
|
|
|
function spliceOne(list, index) {
|
|
for (; index + 1 < list.length; index++)
|
|
list[index] = list[index + 1];
|
|
list.pop();
|
|
}
|
|
|
|
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 once(emitter, name) {
|
|
return new Promise(function (resolve, reject) {
|
|
function errorListener(err) {
|
|
emitter.removeListener(name, resolver);
|
|
reject(err);
|
|
}
|
|
|
|
function resolver() {
|
|
if (typeof emitter.removeListener === 'function') {
|
|
emitter.removeListener('error', errorListener);
|
|
}
|
|
resolve([].slice.call(arguments));
|
|
};
|
|
|
|
eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
|
|
if (name !== 'error') {
|
|
addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
|
|
}
|
|
});
|
|
}
|
|
|
|
function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
|
|
if (typeof emitter.on === 'function') {
|
|
eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
|
|
}
|
|
}
|
|
|
|
function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
|
|
if (typeof emitter.on === 'function') {
|
|
if (flags.once) {
|
|
emitter.once(name, listener);
|
|
} else {
|
|
emitter.on(name, listener);
|
|
}
|
|
} else if (typeof emitter.addEventListener === 'function') {
|
|
// EventTarget does not have `error` event semantics like Node
|
|
// EventEmitters, we do not listen for `error` events here.
|
|
emitter.addEventListener(name, function wrapListener(arg) {
|
|
// IE does not have builtin `{ once: true }` support so we
|
|
// have to do it manually.
|
|
if (flags.once) {
|
|
emitter.removeEventListener(name, wrapListener);
|
|
}
|
|
listener(arg);
|
|
});
|
|
} else {
|
|
throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
|
|
}
|
|
}
|
|
|
|
},{}],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":8}],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":25}],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){
|
|
/*
|
|
* JSNLog 2.30.0
|
|
* Open source under the MIT License.
|
|
* Copyright 2012-2017 Mattijs Perdeck All rights reserved.
|
|
*/
|
|
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 (Object.prototype.hasOwnProperty.call(b, 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 __());
|
|
};
|
|
})();
|
|
function JL(loggerName) {
|
|
// If name is empty, return the root logger
|
|
if (!loggerName) {
|
|
return JL.__;
|
|
}
|
|
// Implements Array.reduce. JSNLog supports IE8+ and reduce is not supported in that browser.
|
|
// Same interface as the standard reduce, except that
|
|
if (!Array.prototype.reduce) {
|
|
Array.prototype.reduce = function (callback, initialValue) {
|
|
var previousValue = initialValue;
|
|
for (var i = 0; i < this.length; i++) {
|
|
previousValue = callback(previousValue, this[i], i, this);
|
|
}
|
|
return previousValue;
|
|
};
|
|
}
|
|
var accumulatedLoggerName = '';
|
|
var logger = ('.' + loggerName).split('.').reduce(function (prev, curr, idx, arr) {
|
|
// if loggername is a.b.c, than currentLogger will be set to the loggers
|
|
// root (prev: JL, curr: '')
|
|
// a (prev: JL.__, curr: 'a')
|
|
// a.b (prev: JL.__.__a, curr: 'b')
|
|
// a.b.c (prev: JL.__.__a.__a.b, curr: 'c')
|
|
// Note that when a new logger name is encountered (such as 'a.b.c'),
|
|
// a new logger object is created and added as a property to the parent ('a.b').
|
|
// The root logger is added as a property of the JL object itself.
|
|
// It is essential that the name of the property containing the child logger
|
|
// contains the full 'path' name of the child logger ('a.b.c') instead of
|
|
// just the bit after the last period ('c').
|
|
// This is because the parent inherits properties from its ancestors.
|
|
// So if the root has a child logger 'c' (stored in a property 'c' of the root logger),
|
|
// then logger 'a.b' has that same property 'c' through inheritance.
|
|
// The names of the logger properties start with __, so the root logger
|
|
// (which has name ''), has a nice property name '__'.
|
|
// accumulatedLoggerName evaluates false ('' is falsy) in first iteration when prev is the root logger.
|
|
// accumulatedLoggerName will be the logger name corresponding with the logger in currentLogger.
|
|
// Keep in mind that the currentLogger may not be defined yet, so can't get the name from
|
|
// the currentLogger object itself.
|
|
if (accumulatedLoggerName) {
|
|
accumulatedLoggerName += '.' + curr;
|
|
}
|
|
else {
|
|
accumulatedLoggerName = curr;
|
|
}
|
|
var currentLogger = prev['__' + accumulatedLoggerName];
|
|
// If the currentLogger (or the actual logger being sought) does not yet exist,
|
|
// create it now.
|
|
if (currentLogger === undefined) {
|
|
// Set the prototype of the Logger constructor function to the parent of the logger
|
|
// to be created. This way, __proto of the new logger object will point at the parent.
|
|
// When logger.level is evaluated and is not present, the JavaScript runtime will
|
|
// walk down the prototype chain to find the first ancestor with a level property.
|
|
//
|
|
// Note that prev at this point refers to the parent logger.
|
|
JL.Logger.prototype = prev;
|
|
currentLogger = new JL.Logger(accumulatedLoggerName);
|
|
prev['__' + accumulatedLoggerName] = currentLogger;
|
|
}
|
|
return currentLogger;
|
|
}, JL.__);
|
|
return logger;
|
|
}
|
|
(function (JL) {
|
|
// Initialise requestId to empty string. If you don't do this and the user
|
|
// does not set it via setOptions, then the JSNLog-RequestId header will
|
|
// have value "undefined", which doesn't look good in a log.
|
|
//
|
|
// Note that you always want to send a requestId as part of log requests,
|
|
// otherwise the server side component doesn't know this is a log request
|
|
// and may create a new request id for the log request, causing confusion
|
|
// in the log.
|
|
JL.requestId = '';
|
|
// Number uniquely identifying every log entry within the request.
|
|
JL.entryId = 0;
|
|
// Allow property injection of these classes, to enable unit testing
|
|
JL._createXMLHttpRequest = function () { return new XMLHttpRequest(); };
|
|
JL._getTime = function () { return (new Date).getTime(); };
|
|
JL._console = console;
|
|
// ----- private variables
|
|
JL._appenderNames = [];
|
|
/**
|
|
Copies the value of a property from one object to the other.
|
|
This is used to copy property values as part of setOption for loggers and appenders.
|
|
|
|
Because loggers inherit property values from their parents, it is important never to
|
|
create a property on a logger if the intent is to inherit from the parent.
|
|
|
|
Copying rules:
|
|
1) if the from property is undefined (for example, not mentioned in a JSON object), the
|
|
to property is not affected at all.
|
|
2) if the from property is null, the to property is deleted (so the logger will inherit from
|
|
its parent).
|
|
3) Otherwise, the from property is copied to the to property.
|
|
*/
|
|
function copyProperty(propertyName, from, to) {
|
|
if (from[propertyName] === undefined) {
|
|
return;
|
|
}
|
|
if (from[propertyName] === null) {
|
|
delete to[propertyName];
|
|
return;
|
|
}
|
|
to[propertyName] = from[propertyName];
|
|
}
|
|
/**
|
|
Returns true if a log should go ahead.
|
|
Does not check level.
|
|
|
|
@param filters
|
|
Filters that determine whether a log can go ahead.
|
|
*/
|
|
function allow(filters) {
|
|
// If enabled is not null or undefined, then if it is false, then return false
|
|
// Note that undefined==null (!)
|
|
if (!(JL.enabled == null)) {
|
|
if (!JL.enabled) {
|
|
return false;
|
|
}
|
|
}
|
|
// If the regex contains a bug, that will throw an exception.
|
|
// Ignore this, and pass the log item (better too much than too little).
|
|
try {
|
|
if (filters.userAgentRegex) {
|
|
if (!new RegExp(filters.userAgentRegex).test(navigator.userAgent)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
catch (e) { }
|
|
try {
|
|
if (filters.ipRegex && JL.clientIP) {
|
|
if (!new RegExp(filters.ipRegex).test(JL.clientIP)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
catch (e) { }
|
|
return true;
|
|
}
|
|
/**
|
|
Returns true if a log should go ahead, based on the message.
|
|
|
|
@param filters
|
|
Filters that determine whether a log can go ahead.
|
|
|
|
@param message
|
|
Message to be logged.
|
|
*/
|
|
function allowMessage(filters, message) {
|
|
// If the regex contains a bug, that will throw an exception.
|
|
// Ignore this, and pass the log item (better too much than too little).
|
|
try {
|
|
if (filters.disallow) {
|
|
if (new RegExp(filters.disallow).test(message)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
catch (e) { }
|
|
return true;
|
|
}
|
|
// If logObject is a function, the function is evaluated (without parameters)
|
|
// and the result returned.
|
|
// Otherwise, logObject itself is returned.
|
|
function stringifyLogObjectFunction(logObject) {
|
|
if (typeof logObject == "function") {
|
|
if (logObject instanceof RegExp) {
|
|
return logObject.toString();
|
|
}
|
|
else {
|
|
return logObject();
|
|
}
|
|
}
|
|
return logObject;
|
|
}
|
|
var StringifiedLogObject = /** @class */ (function () {
|
|
// * msg -
|
|
// if the logObject is a scalar (after possible function evaluation), this is set to
|
|
// string representing the scalar. Otherwise it is left undefined.
|
|
// * meta -
|
|
// if the logObject is an object (after possible function evaluation), this is set to
|
|
// that object. Otherwise it is left undefined.
|
|
// * finalString -
|
|
// This is set to the string representation of logObject (after possible function evaluation),
|
|
// regardless of whether it is an scalar or an object. An object is stringified to a JSON string.
|
|
// Note that you can't call this field "final", because as some point this was a reserved
|
|
// JavaScript keyword and using final trips up some minifiers.
|
|
function StringifiedLogObject(msg, meta, finalString) {
|
|
this.msg = msg;
|
|
this.meta = meta;
|
|
this.finalString = finalString;
|
|
}
|
|
return StringifiedLogObject;
|
|
}());
|
|
// Takes a logObject, which can be
|
|
// * a scalar
|
|
// * an object
|
|
// * a parameterless function, which returns the scalar or object to log.
|
|
// Returns a stringifiedLogObject
|
|
function stringifyLogObject(logObject) {
|
|
// Note that this works if logObject is null.
|
|
// typeof null is object.
|
|
// JSON.stringify(null) returns "null".
|
|
var actualLogObject = stringifyLogObjectFunction(logObject);
|
|
var finalString;
|
|
// Note that typeof actualLogObject should not be "function", because that has
|
|
// been resolved with stringifyLogObjectFunction.
|
|
switch (typeof actualLogObject) {
|
|
case "string":
|
|
return new StringifiedLogObject(actualLogObject, null, actualLogObject);
|
|
case "number":
|
|
finalString = actualLogObject.toString();
|
|
return new StringifiedLogObject(finalString, null, finalString);
|
|
case "boolean":
|
|
finalString = actualLogObject.toString();
|
|
return new StringifiedLogObject(finalString, null, finalString);
|
|
case "undefined":
|
|
return new StringifiedLogObject("undefined", null, "undefined");
|
|
case "object":
|
|
if ((actualLogObject instanceof RegExp) ||
|
|
(actualLogObject instanceof String) ||
|
|
(actualLogObject instanceof Number) ||
|
|
(actualLogObject instanceof Boolean)) {
|
|
finalString = actualLogObject.toString();
|
|
return new StringifiedLogObject(finalString, null, finalString);
|
|
}
|
|
else {
|
|
if (typeof JL.serialize === 'function') {
|
|
finalString = JL.serialize.call(this, actualLogObject);
|
|
}
|
|
else {
|
|
finalString = JSON.stringify(actualLogObject);
|
|
}
|
|
// Set the msg field to "" instead of null. Some Winston transports
|
|
// assume that the msg field is not null.
|
|
return new StringifiedLogObject("", actualLogObject, finalString);
|
|
}
|
|
default:
|
|
return new StringifiedLogObject("unknown", null, "unknown");
|
|
}
|
|
}
|
|
function setOptions(options) {
|
|
copyProperty("enabled", options, this);
|
|
copyProperty("maxMessages", options, this);
|
|
copyProperty("defaultAjaxUrl", options, this);
|
|
copyProperty("clientIP", options, this);
|
|
copyProperty("requestId", options, this);
|
|
copyProperty("defaultBeforeSend", options, this);
|
|
copyProperty("serialize", options, this);
|
|
return this;
|
|
}
|
|
JL.setOptions = setOptions;
|
|
function getAllLevel() { return -2147483648; }
|
|
JL.getAllLevel = getAllLevel;
|
|
function getTraceLevel() { return 1000; }
|
|
JL.getTraceLevel = getTraceLevel;
|
|
function getDebugLevel() { return 2000; }
|
|
JL.getDebugLevel = getDebugLevel;
|
|
function getInfoLevel() { return 3000; }
|
|
JL.getInfoLevel = getInfoLevel;
|
|
function getWarnLevel() { return 4000; }
|
|
JL.getWarnLevel = getWarnLevel;
|
|
function getErrorLevel() { return 5000; }
|
|
JL.getErrorLevel = getErrorLevel;
|
|
function getFatalLevel() { return 6000; }
|
|
JL.getFatalLevel = getFatalLevel;
|
|
function getOffLevel() { return 2147483647; }
|
|
JL.getOffLevel = getOffLevel;
|
|
function levelToString(level) {
|
|
if (level <= 1000) {
|
|
return "trace";
|
|
}
|
|
if (level <= 2000) {
|
|
return "debug";
|
|
}
|
|
if (level <= 3000) {
|
|
return "info";
|
|
}
|
|
if (level <= 4000) {
|
|
return "warn";
|
|
}
|
|
if (level <= 5000) {
|
|
return "error";
|
|
}
|
|
return "fatal";
|
|
}
|
|
// ---------------------
|
|
var Exception = /** @class */ (function () {
|
|
// data replaces message. It takes not just strings, but also objects and functions, just like the log function.
|
|
// internally, the string representation is stored in the message property (inherited from Error)
|
|
//
|
|
// inner: inner exception. Can be null or undefined.
|
|
function Exception(data, inner) {
|
|
this.inner = inner;
|
|
this.name = "JL.Exception";
|
|
this.message = stringifyLogObject(data).finalString;
|
|
}
|
|
return Exception;
|
|
}());
|
|
JL.Exception = Exception;
|
|
// Derive Exception from Error (a Host object), so browsers
|
|
// are more likely to produce a stack trace for it in their console.
|
|
//
|
|
// Note that instanceof against an object created with this constructor
|
|
// will return true in these cases:
|
|
// <object> instanceof JL.Exception);
|
|
// <object> instanceof Error);
|
|
Exception.prototype = new Error();
|
|
// ---------------------
|
|
var LogItem = /** @class */ (function () {
|
|
// l: level
|
|
// m: message
|
|
// n: logger name
|
|
// t (timeStamp) is number of milliseconds since 1 January 1970 00:00:00 UTC
|
|
// u: number uniquely identifying this entry for this request.
|
|
//
|
|
// Keeping the property names really short, because they will be sent in the
|
|
// JSON payload to the server.
|
|
function LogItem(l, m, n, t, u) {
|
|
this.l = l;
|
|
this.m = m;
|
|
this.n = n;
|
|
this.t = t;
|
|
this.u = u;
|
|
}
|
|
return LogItem;
|
|
}());
|
|
JL.LogItem = LogItem;
|
|
function newLogItem(levelNbr, message, loggerName) {
|
|
JL.entryId++;
|
|
return new LogItem(levelNbr, message, loggerName, JL._getTime(), JL.entryId);
|
|
}
|
|
function clearTimer(timer) {
|
|
if (timer.id) {
|
|
clearTimeout(timer.id);
|
|
timer.id = null;
|
|
}
|
|
}
|
|
function setTimer(timer, timeoutMs, callback) {
|
|
var that = this;
|
|
if (!timer.id) {
|
|
timer.id = setTimeout(function () {
|
|
// use call to ensure that the this as used inside sendBatch when it runs is the
|
|
// same this at this point.
|
|
callback.call(that);
|
|
}, timeoutMs);
|
|
}
|
|
}
|
|
var Appender = /** @class */ (function () {
|
|
// sendLogItems takes an array of log items. It will be called when
|
|
// the appender has items to process (such as, send to the server).
|
|
// sendLogItems will call successCallback after the items have been successfully sent.
|
|
//
|
|
// Note that after sendLogItems returns, the appender may truncate
|
|
// the LogItem array, so the function has to copy the content of the array
|
|
// in some fashion (eg. serialize) before returning.
|
|
function Appender(appenderName, sendLogItems) {
|
|
this.appenderName = appenderName;
|
|
this.sendLogItems = sendLogItems;
|
|
this.level = JL.getTraceLevel();
|
|
// set to super high level, so if user increases level, level is unlikely to get
|
|
// above sendWithBufferLevel
|
|
this.sendWithBufferLevel = 2147483647;
|
|
this.storeInBufferLevel = -2147483648;
|
|
this.bufferSize = 0; // buffering switch off by default
|
|
this.batchSize = 1;
|
|
this.maxBatchSize = 20;
|
|
this.batchTimeout = 2147483647;
|
|
this.sendTimeout = 5000;
|
|
// Holds all log items with levels higher than storeInBufferLevel
|
|
// but lower than level. These items may never be sent.
|
|
this.buffer = [];
|
|
// Holds all items that we do want to send, until we have a full
|
|
// batch (as determined by batchSize).
|
|
this.batchBuffer = [];
|
|
// Holds the id of the timer implementing the batch timeout.
|
|
// Can be null.
|
|
// This is an object, so it can be passed to a method that updated the timer variable.
|
|
this.batchTimeoutTimer = { id: null };
|
|
// Holds the id of the timer implementing the send timeout.
|
|
// Can be null.
|
|
this.sendTimeoutTimer = { id: null };
|
|
// Number of log items that has been skipped due to batch buffer at max size,
|
|
// since appender creation or since creation of the last "skipped" warning log entry.
|
|
this.nbrLogItemsSkipped = 0;
|
|
// Will be 0 if no log request is outstanding at the moment.
|
|
// Otherwise the number of log items in the outstanding request.
|
|
this.nbrLogItemsBeingSent = 0;
|
|
var emptyNameErrorMessage = "Trying to create an appender without a name or with an empty name";
|
|
// This evaluates to true if appenderName is either null or undefined!
|
|
// Do not check here if the name is "", because that would stop you creating the
|
|
// default appender.
|
|
if (appenderName == undefined) {
|
|
throw emptyNameErrorMessage;
|
|
}
|
|
if (JL._appenderNames.indexOf(appenderName) != -1) {
|
|
// If user passed in "", that will now have been picked up as a duplicate
|
|
// because default appender also uses "".
|
|
if (!appenderName) {
|
|
throw emptyNameErrorMessage;
|
|
}
|
|
throw "Multiple appenders use the same name " + appenderName;
|
|
}
|
|
JL._appenderNames.push(appenderName);
|
|
}
|
|
Appender.prototype.addLogItemsToBuffer = function (logItems) {
|
|
// If the batch buffer has reached its maximum limit,
|
|
// skip the log item and increase the "skipped items" counter.
|
|
if (this.batchBuffer.length >= this.maxBatchSize) {
|
|
this.nbrLogItemsSkipped += logItems.length;
|
|
return;
|
|
}
|
|
// If maxMessages is not null or undefined, then decrease it by the batch size.
|
|
// This can result in a negative maxMessages.
|
|
// Note that undefined==null (!)
|
|
//
|
|
// Note that we may be sending more messages than the maxMessages limit allows,
|
|
// if we stored trace messages. Rationale is the buffer for trace messages is limited,
|
|
// and if we cut off at exactly maxMessages, we'd also loose the high severity message
|
|
// that caused the trace messages to be sent (unless we cater for this specifically, which
|
|
// is more complexity).
|
|
//
|
|
// If there are multiple appenders sending the same message, maxMessage will be decreased
|
|
// by each appender for the same message. This is:
|
|
// 1) only appenders know whether a message will actually be sent (based on storeInBufferLevel),
|
|
// so the loggers couldn't do this update;
|
|
// 2) if you have multiple appenders hitting the same server, this may be what you want.
|
|
//
|
|
// In most cases there is only 1 appender, so this then doesn't matter.
|
|
if (!(JL.maxMessages == null)) {
|
|
if (JL.maxMessages < 1) {
|
|
return;
|
|
}
|
|
JL.maxMessages -= logItems.length;
|
|
}
|
|
this.batchBuffer = this.batchBuffer.concat(logItems);
|
|
// If this is the first item in the buffer, set the timer
|
|
// to ensure it will be sent within the timeout period.
|
|
// If it is not the first item, leave the timer alone so to not to
|
|
// increase the timeout for the first item.
|
|
//
|
|
// To determine if this is the first item, look at the timer variable.
|
|
// Do not look at the buffer length, because we also put items in the buffer
|
|
// via a concat (bypassing this function).
|
|
//
|
|
// The setTimer method only sets the timer if it is not already running.
|
|
var that = this;
|
|
setTimer(this.batchTimeoutTimer, this.batchTimeout, function () {
|
|
that.sendBatch.call(that);
|
|
});
|
|
};
|
|
;
|
|
Appender.prototype.batchBufferHasOverdueMessages = function () {
|
|
for (var i = 0; i < this.batchBuffer.length; i++) {
|
|
var messageAgeMs = JL._getTime() - this.batchBuffer[i].t;
|
|
if (messageAgeMs > this.batchTimeout) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
// Returns true if no more message will ever be added to the batch buffer,
|
|
// but the batch buffer has messages now - so if there are not enough to make up a batch,
|
|
// and there is no batch timeout, then they will never be sent. This is especially important if
|
|
// maxMessages was reached while jsnlog.js was retrying sending messages to the server.
|
|
Appender.prototype.batchBufferHasStrandedMessage = function () {
|
|
return (!(JL.maxMessages == null)) && (JL.maxMessages < 1) && (this.batchBuffer.length > 0);
|
|
};
|
|
Appender.prototype.sendBatchIfComplete = function () {
|
|
if ((this.batchBuffer.length >= this.batchSize) ||
|
|
this.batchBufferHasOverdueMessages() ||
|
|
this.batchBufferHasStrandedMessage()) {
|
|
this.sendBatch();
|
|
}
|
|
};
|
|
Appender.prototype.onSendingEnded = function () {
|
|
clearTimer(this.sendTimeoutTimer);
|
|
this.nbrLogItemsBeingSent = 0;
|
|
this.sendBatchIfComplete();
|
|
};
|
|
Appender.prototype.setOptions = function (options) {
|
|
copyProperty("level", options, this);
|
|
copyProperty("ipRegex", options, this);
|
|
copyProperty("userAgentRegex", options, this);
|
|
copyProperty("disallow", options, this);
|
|
copyProperty("sendWithBufferLevel", options, this);
|
|
copyProperty("storeInBufferLevel", options, this);
|
|
copyProperty("bufferSize", options, this);
|
|
copyProperty("batchSize", options, this);
|
|
copyProperty("maxBatchSize", options, this);
|
|
copyProperty("batchTimeout", options, this);
|
|
copyProperty("sendTimeout", options, this);
|
|
if (this.bufferSize < this.buffer.length) {
|
|
this.buffer.length = this.bufferSize;
|
|
}
|
|
if (this.maxBatchSize < this.batchSize) {
|
|
throw new JL.Exception({
|
|
"message": "maxBatchSize cannot be smaller than batchSize",
|
|
"maxBatchSize": this.maxBatchSize,
|
|
"batchSize": this.batchSize
|
|
});
|
|
}
|
|
return this;
|
|
};
|
|
/**
|
|
Called by a logger to log a log item.
|
|
If in response to this call one or more log items need to be processed
|
|
(eg., sent to the server), this method calls this.sendLogItems
|
|
with an array with all items to be processed.
|
|
|
|
Note that the name and parameters of this function must match those of the log function of
|
|
a Winston transport object, so that users can use these transports as appenders.
|
|
That is why there are many parameters that are not actually used by this function.
|
|
|
|
level - string with the level ("trace", "debug", etc.) Only used by Winston transports.
|
|
msg - human readable message. Undefined if the log item is an object. Only used by Winston transports.
|
|
meta - log object. Always defined, because at least it contains the logger name. Only used by Winston transports.
|
|
callback - function that is called when the log item has been logged. Only used by Winston transports.
|
|
levelNbr - level as a number. Not used by Winston transports.
|
|
message - log item. If the user logged an object, this is the JSON string. Not used by Winston transports.
|
|
loggerName: name of the logger. Not used by Winston transports.
|
|
*/
|
|
Appender.prototype.log = function (level, msg, meta, callback, levelNbr, message, loggerName) {
|
|
var logItem;
|
|
if (!allow(this)) {
|
|
return;
|
|
}
|
|
if (!allowMessage(this, message)) {
|
|
return;
|
|
}
|
|
if (levelNbr < this.storeInBufferLevel) {
|
|
// Ignore the log item completely
|
|
return;
|
|
}
|
|
logItem = newLogItem(levelNbr, message, loggerName);
|
|
if (levelNbr < this.level) {
|
|
// Store in the hold buffer. Do not send.
|
|
if (this.bufferSize > 0) {
|
|
this.buffer.push(logItem);
|
|
// If we exceeded max buffer size, remove oldest item
|
|
if (this.buffer.length > this.bufferSize) {
|
|
this.buffer.shift();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
// Want to send the item
|
|
this.addLogItemsToBuffer([logItem]);
|
|
if (levelNbr >= this.sendWithBufferLevel) {
|
|
// Want to send the contents of the buffer.
|
|
//
|
|
// Send the buffer AFTER sending the high priority item.
|
|
// If you were to send the high priority item after the buffer,
|
|
// if we're close to maxMessages or maxBatchSize,
|
|
// then the trace messages in the buffer could crowd out the actual high priority item.
|
|
if (this.buffer.length) {
|
|
this.addLogItemsToBuffer(this.buffer);
|
|
this.buffer.length = 0;
|
|
}
|
|
}
|
|
this.sendBatchIfComplete();
|
|
};
|
|
;
|
|
// Processes the batch buffer
|
|
//
|
|
// Make this public, so it can be called from outside the library,
|
|
// when the page is unloaded.
|
|
Appender.prototype.sendBatch = function () {
|
|
// Do not clear the batch timer if you don't go ahead here because
|
|
// a send is already in progress. Otherwise the messages that were stopped from going out
|
|
// may get ignored because the batch timer never went off.
|
|
if (this.nbrLogItemsBeingSent > 0) {
|
|
return;
|
|
}
|
|
clearTimer(this.batchTimeoutTimer);
|
|
if (this.batchBuffer.length == 0) {
|
|
return;
|
|
}
|
|
// Decided at this point to send contents of the buffer
|
|
this.nbrLogItemsBeingSent = this.batchBuffer.length;
|
|
var that = this;
|
|
setTimer(this.sendTimeoutTimer, this.sendTimeout, function () {
|
|
that.onSendingEnded.call(that);
|
|
});
|
|
this.sendLogItems(this.batchBuffer, function () {
|
|
// Log entries have been successfully sent to server
|
|
// Remove the first (nbrLogItemsBeingSent) items in the batch buffer, because they are the ones
|
|
// that were sent.
|
|
that.batchBuffer.splice(0, that.nbrLogItemsBeingSent);
|
|
// If items had to be skipped, add a WARN message
|
|
if (that.nbrLogItemsSkipped > 0) {
|
|
that.batchBuffer.push(newLogItem(getWarnLevel(), "Lost " + that.nbrLogItemsSkipped + " messages. Either connection with the server was down or logging was disabled via the enabled option. Reduce lost messages by increasing the ajaxAppender option maxBatchSize.", that.appenderName));
|
|
that.nbrLogItemsSkipped = 0;
|
|
}
|
|
that.onSendingEnded.call(that);
|
|
});
|
|
};
|
|
return Appender;
|
|
}());
|
|
JL.Appender = Appender;
|
|
// ---------------------
|
|
var AjaxAppender = /** @class */ (function (_super) {
|
|
__extends(AjaxAppender, _super);
|
|
function AjaxAppender(appenderName) {
|
|
return _super.call(this, appenderName, AjaxAppender.prototype.sendLogItemsAjax) || this;
|
|
}
|
|
AjaxAppender.prototype.setOptions = function (options) {
|
|
copyProperty("url", options, this);
|
|
copyProperty("beforeSend", options, this);
|
|
_super.prototype.setOptions.call(this, options);
|
|
return this;
|
|
};
|
|
AjaxAppender.prototype.sendLogItemsAjax = function (logItems, successCallback) {
|
|
// JSON.stringify is only supported on IE8+
|
|
// Use try-catch in case we get an exception here.
|
|
//
|
|
// The "r" field is now obsolete. When writing a server side component,
|
|
// read the HTTP header "JSNLog-RequestId"
|
|
// to get the request id.
|
|
//
|
|
// The .Net server side component
|
|
// now uses the JSNLog-RequestId HTTP Header, because this allows it to
|
|
// detect whether the incoming request has a request id.
|
|
// If the request id were in the json payload, it would have to read the json
|
|
// from the stream, interfering with normal non-logging requests.
|
|
//
|
|
// To see what characters you can use in the HTTP header, visit:
|
|
// http://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions/3561399#3561399
|
|
//
|
|
// It needs this ability, so users of NLog can set a requestId variable in NLog
|
|
// before the server side component tries to log the client side log message
|
|
// through an NLog logger.
|
|
// Unlike Log4Net, NLog doesn't allow you to register an object whose ToString()
|
|
// is only called when it tries to log something, so the requestId has to be
|
|
// determined right at the start of request processing.
|
|
try {
|
|
// Do not send logs, if JL.enabled is set to false.
|
|
//
|
|
// Do not call successCallback here. After each timeout, jsnlog will retry sending the message.
|
|
// If jsnlog gets re-enabled, it will then log the number of messages logged.
|
|
// If it doesn't get re-enabled, amount of cpu cycles wasted is minimal.
|
|
if (!allow(this)) {
|
|
return;
|
|
}
|
|
// If a request is in progress, abort it.
|
|
// Otherwise, it may call the success callback, which will be very confusing.
|
|
// It may also stop the inflight request from resulting in a log at the server.
|
|
if (this.xhr && (this.xhr.readyState != 0) && (this.xhr.readyState != 4)) {
|
|
this.xhr.abort();
|
|
}
|
|
// Because a react-native XMLHttpRequest cannot be reused it needs to be recreated with each request
|
|
this.xhr = JL._createXMLHttpRequest();
|
|
// Only determine the url right before you send a log request.
|
|
// Do not set the url when constructing the appender.
|
|
//
|
|
// This is because the server side component sets defaultAjaxUrl
|
|
// in a call to setOptions, AFTER the JL object and the default appender
|
|
// have been created.
|
|
var ajaxUrl = "/jsnlog.logger";
|
|
// This evaluates to true if defaultAjaxUrl is null or undefined
|
|
if (!(JL.defaultAjaxUrl == null)) {
|
|
ajaxUrl = JL.defaultAjaxUrl;
|
|
}
|
|
if (this.url) {
|
|
ajaxUrl = this.url;
|
|
}
|
|
this.xhr.open('POST', ajaxUrl);
|
|
this.xhr.setRequestHeader('Content-Type', 'application/json');
|
|
this.xhr.setRequestHeader('JSNLog-RequestId', JL.requestId);
|
|
var that = this;
|
|
this.xhr.onreadystatechange = function () {
|
|
// On most browsers, if the request fails (eg. internet is gone),
|
|
// it will set xhr.readyState == 4 and xhr.status != 200 (0 if request could not be sent) immediately.
|
|
// However, Edge and IE will not change the readyState at all if the internet goes away while waiting
|
|
// for a response.
|
|
// Some servers will return a 204 (success, no content) when the JSNLog endpoint
|
|
// returns the empty response. So check on any code in the 2.. range, not just 200.
|
|
if ((that.xhr.readyState == 4) && (that.xhr.status >= 200 && that.xhr.status < 300)) {
|
|
successCallback();
|
|
}
|
|
};
|
|
var json = {
|
|
r: JL.requestId,
|
|
lg: logItems
|
|
};
|
|
// call beforeSend callback
|
|
// first try the callback on the appender
|
|
// then the global defaultBeforeSend callback
|
|
if (typeof this.beforeSend === 'function') {
|
|
this.beforeSend.call(this, this.xhr, json);
|
|
}
|
|
else if (typeof JL.defaultBeforeSend === 'function') {
|
|
JL.defaultBeforeSend.call(this, this.xhr, json);
|
|
}
|
|
var finalmsg = JSON.stringify(json);
|
|
this.xhr.send(finalmsg);
|
|
}
|
|
catch (e) { }
|
|
};
|
|
return AjaxAppender;
|
|
}(Appender));
|
|
JL.AjaxAppender = AjaxAppender;
|
|
// ---------------------
|
|
var ConsoleAppender = /** @class */ (function (_super) {
|
|
__extends(ConsoleAppender, _super);
|
|
function ConsoleAppender(appenderName) {
|
|
return _super.call(this, appenderName, ConsoleAppender.prototype.sendLogItemsConsole) || this;
|
|
}
|
|
ConsoleAppender.prototype.clog = function (logEntry) {
|
|
JL._console.log(logEntry);
|
|
};
|
|
ConsoleAppender.prototype.cerror = function (logEntry) {
|
|
if (JL._console.error) {
|
|
JL._console.error(logEntry);
|
|
}
|
|
else {
|
|
this.clog(logEntry);
|
|
}
|
|
};
|
|
ConsoleAppender.prototype.cwarn = function (logEntry) {
|
|
if (JL._console.warn) {
|
|
JL._console.warn(logEntry);
|
|
}
|
|
else {
|
|
this.clog(logEntry);
|
|
}
|
|
};
|
|
ConsoleAppender.prototype.cinfo = function (logEntry) {
|
|
if (JL._console.info) {
|
|
JL._console.info(logEntry);
|
|
}
|
|
else {
|
|
this.clog(logEntry);
|
|
}
|
|
};
|
|
// IE11 has a console.debug function. But its console doesn't have
|
|
// the option to show/hide debug messages (the same way Chrome and FF do),
|
|
// even though it does have such buttons for Error, Warn, Info.
|
|
//
|
|
// For now, this means that debug messages can not be hidden on IE.
|
|
// Live with this, seeing that it works fine on FF and Chrome, which
|
|
// will be much more popular with developers.
|
|
ConsoleAppender.prototype.cdebug = function (logEntry) {
|
|
if (JL._console.debug) {
|
|
JL._console.debug(logEntry);
|
|
}
|
|
else {
|
|
this.cinfo(logEntry);
|
|
}
|
|
};
|
|
ConsoleAppender.prototype.sendLogItemsConsole = function (logItems, successCallback) {
|
|
try {
|
|
// Do not send logs, if JL.enabled is set to false
|
|
//
|
|
// Do not call successCallback here. After each timeout, jsnlog will retry sending the message.
|
|
// If jsnlog gets re-enabled, it will then log the number of messages logged.
|
|
// If it doesn't get re-enabled, amount of cpu cycles wasted is minimal.
|
|
if (!allow(this)) {
|
|
return;
|
|
}
|
|
if (!JL._console) {
|
|
return;
|
|
}
|
|
var i;
|
|
for (i = 0; i < logItems.length; ++i) {
|
|
var li = logItems[i];
|
|
var msg = li.n + ": " + li.m;
|
|
// Only log the timestamp if we're on the server
|
|
// (window is undefined). On the browser, the user
|
|
// sees the log entry probably immediately, so in that case
|
|
// the timestamp is clutter.
|
|
if (typeof window === 'undefined') {
|
|
msg = new Date(li.t) + " | " + msg;
|
|
}
|
|
if (li.l <= JL.getDebugLevel()) {
|
|
this.cdebug(msg);
|
|
}
|
|
else if (li.l <= JL.getInfoLevel()) {
|
|
this.cinfo(msg);
|
|
}
|
|
else if (li.l <= JL.getWarnLevel()) {
|
|
this.cwarn(msg);
|
|
}
|
|
else {
|
|
this.cerror(msg);
|
|
}
|
|
}
|
|
}
|
|
catch (e) {
|
|
}
|
|
successCallback();
|
|
};
|
|
return ConsoleAppender;
|
|
}(Appender));
|
|
JL.ConsoleAppender = ConsoleAppender;
|
|
// --------------------
|
|
var Logger = /** @class */ (function () {
|
|
function Logger(loggerName) {
|
|
this.loggerName = loggerName;
|
|
// Create seenRexes, otherwise this logger will use the seenRexes
|
|
// of its parent via the prototype chain.
|
|
this.seenRegexes = [];
|
|
}
|
|
Logger.prototype.setOptions = function (options) {
|
|
copyProperty("level", options, this);
|
|
copyProperty("userAgentRegex", options, this);
|
|
copyProperty("disallow", options, this);
|
|
copyProperty("ipRegex", options, this);
|
|
copyProperty("appenders", options, this);
|
|
copyProperty("onceOnly", options, this);
|
|
// Reset seenRegexes, in case onceOnly has been changed.
|
|
this.seenRegexes = [];
|
|
return this;
|
|
};
|
|
// Turns an exception into an object that can be sent to the server.
|
|
Logger.prototype.buildExceptionObject = function (e) {
|
|
var excObject = {};
|
|
if (e.stack) {
|
|
excObject.stack = e.stack;
|
|
}
|
|
else {
|
|
excObject.e = e;
|
|
}
|
|
if (e.message) {
|
|
excObject.message = e.message;
|
|
}
|
|
if (e.name) {
|
|
excObject.name = e.name;
|
|
}
|
|
if (e.data) {
|
|
excObject.data = e.data;
|
|
}
|
|
if (e.inner) {
|
|
excObject.inner = this.buildExceptionObject(e.inner);
|
|
}
|
|
return excObject;
|
|
};
|
|
// Logs a log item.
|
|
// Parameter e contains an exception (or null or undefined).
|
|
//
|
|
// Reason that processing exceptions is done at this low level is that
|
|
// 1) no need to spend the cpu cycles if the logger is switched off
|
|
// 2) fatalException takes both a logObject and an exception, and the logObject
|
|
// may be a function that should only be executed if the logger is switched on.
|
|
//
|
|
// If an exception is passed in, the contents of logObject is attached to the exception
|
|
// object in a new property logData.
|
|
// The resulting exception object is than worked into a message to the server.
|
|
//
|
|
// If there is no exception, logObject itself is worked into the message to the server.
|
|
Logger.prototype.log = function (level, logObject, e) {
|
|
var i = 0;
|
|
var compositeMessage;
|
|
var excObject;
|
|
// If we can't find any appenders, do nothing
|
|
if (!this.appenders) {
|
|
return this;
|
|
}
|
|
if (((level >= this.level)) && allow(this)) {
|
|
if (e) {
|
|
excObject = this.buildExceptionObject(e);
|
|
excObject.logData = stringifyLogObjectFunction(logObject);
|
|
}
|
|
else {
|
|
excObject = logObject;
|
|
}
|
|
compositeMessage = stringifyLogObject(excObject);
|
|
if (allowMessage(this, compositeMessage.finalString)) {
|
|
// See whether message is a duplicate
|
|
if (this.onceOnly) {
|
|
i = this.onceOnly.length - 1;
|
|
while (i >= 0) {
|
|
if (new RegExp(this.onceOnly[i]).test(compositeMessage.finalString)) {
|
|
if (this.seenRegexes[i]) {
|
|
return this;
|
|
}
|
|
this.seenRegexes[i] = true;
|
|
}
|
|
i--;
|
|
}
|
|
}
|
|
// Pass message to all appenders
|
|
// Note that these appenders could be Winston transports
|
|
// https://github.com/flatiron/winston
|
|
compositeMessage.meta = compositeMessage.meta || {};
|
|
// Note that if the user is logging an object, compositeMessage.meta will hold a reference to that object.
|
|
// Do not add fields to compositeMessage.meta, otherwise the user's object will get that field out of the blue.
|
|
i = this.appenders.length - 1;
|
|
while (i >= 0) {
|
|
this.appenders[i].log(levelToString(level), compositeMessage.msg, compositeMessage.meta, function () { }, level, compositeMessage.finalString, this.loggerName);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
Logger.prototype.trace = function (logObject) { return this.log(getTraceLevel(), logObject); };
|
|
Logger.prototype.debug = function (logObject) { return this.log(getDebugLevel(), logObject); };
|
|
Logger.prototype.info = function (logObject) { return this.log(getInfoLevel(), logObject); };
|
|
Logger.prototype.warn = function (logObject) { return this.log(getWarnLevel(), logObject); };
|
|
Logger.prototype.error = function (logObject) { return this.log(getErrorLevel(), logObject); };
|
|
Logger.prototype.fatal = function (logObject) { return this.log(getFatalLevel(), logObject); };
|
|
Logger.prototype.fatalException = function (logObject, e) { return this.log(getFatalLevel(), logObject, e); };
|
|
return Logger;
|
|
}());
|
|
JL.Logger = Logger;
|
|
function createAjaxAppender(appenderName) {
|
|
return new AjaxAppender(appenderName);
|
|
}
|
|
JL.createAjaxAppender = createAjaxAppender;
|
|
function createConsoleAppender(appenderName) {
|
|
return new ConsoleAppender(appenderName);
|
|
}
|
|
JL.createConsoleAppender = createConsoleAppender;
|
|
// -----------------------
|
|
// In the browser, the default appender is the AjaxAppender.
|
|
// Under nodejs (where there is no "window"), use the ConsoleAppender instead.
|
|
//
|
|
// Do NOT create an AjaxAppender object if you are not on a browser (that is, window is not defined).
|
|
// That would try to create an XmlHttpRequest object, which will crash outside a browser.
|
|
var defaultAppender;
|
|
if (typeof window !== 'undefined') {
|
|
defaultAppender = new AjaxAppender("");
|
|
}
|
|
else {
|
|
defaultAppender = new ConsoleAppender("");
|
|
}
|
|
// Create root logger
|
|
//
|
|
// Note that this is the parent of all other loggers.
|
|
// Logger "x" will be stored at
|
|
// JL.__.x
|
|
// Logger "x.y" at
|
|
// JL.__.x.y
|
|
JL.__ = new JL.Logger("");
|
|
JL.__.setOptions({
|
|
level: JL.getDebugLevel(),
|
|
appenders: [defaultAppender]
|
|
});
|
|
})(JL || (JL = {}));
|
|
if (typeof exports !== 'undefined') {
|
|
// Allows SystemJs to import jsnlog.js. See
|
|
// https://github.com/mperdeck/jsnlog.js/issues/56
|
|
exports.__esModule = true;
|
|
exports.JL = JL;
|
|
}
|
|
// Support AMD module format
|
|
var define;
|
|
if (typeof define == 'function' && define.amd) {
|
|
define('jsnlog', [], function () {
|
|
return JL;
|
|
});
|
|
}
|
|
// If the __jsnlog_configure global function has been
|
|
// created, call it now. This allows you to create a global function
|
|
// setting logger options etc. inline in the page before jsnlog.js
|
|
// has been loaded.
|
|
if (typeof __jsnlog_configure == 'function') {
|
|
__jsnlog_configure(JL);
|
|
}
|
|
// Create onerror handler to log uncaught exceptions to the server side log, but only if there
|
|
// is no such handler already.
|
|
// Must use "typeof window" here, because in NodeJs, window is not defined at all, so cannot refer to window in any way.
|
|
if (typeof window !== 'undefined' && !window.onerror) {
|
|
window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {
|
|
// Send object with all data to server side log, using severity fatal,
|
|
// from logger "onerrorLogger"
|
|
//
|
|
// Use errorMsg.message if available, so Angular 4 template errors will be logged.
|
|
// See https://github.com/mperdeck/jsnlog.js/pull/68
|
|
JL("onerrorLogger").fatalException({
|
|
"msg": "Uncaught Exception",
|
|
"errorMsg": errorMsg ? (errorMsg.message || errorMsg) : '',
|
|
"url": url,
|
|
"line number": lineNumber, "column": column
|
|
}, errorObj);
|
|
// Tell browser to run its own error handler as well
|
|
return false;
|
|
};
|
|
}
|
|
// Deal with unhandled exceptions thrown in promises
|
|
if (typeof window !== 'undefined' && !window.onunhandledrejection) {
|
|
window.onunhandledrejection = function (event) {
|
|
// Send object with all data to server side log, using severity fatal,
|
|
// from logger "onerrorLogger".
|
|
// Need to check both event.reason.message and event.message,
|
|
// because SystemJs wraps exceptions and throws a new object which doesn't have a reason property.
|
|
// See https://github.com/systemjs/systemjs/issues/1309
|
|
JL("onerrorLogger").fatalException({
|
|
"msg": "unhandledrejection",
|
|
"errorMsg": event.reason ? event.reason.message : event.message || null
|
|
}, event.reason);
|
|
};
|
|
}
|
|
|
|
},{}],8:[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;
|
|
};
|
|
|
|
},{}],9:[function(require,module,exports){
|
|
(function (global){(function (){
|
|
/*!
|
|
* Platform.js v1.3.6
|
|
* Copyright 2014-2020 Benjamin Tan
|
|
* Copyright 2011-2013 John-David Dalton
|
|
* Available under MIT license
|
|
*/
|
|
;(function() {
|
|
'use strict';
|
|
|
|
/** Used to determine if values are of the language type `Object`. */
|
|
var objectTypes = {
|
|
'function': true,
|
|
'object': true
|
|
};
|
|
|
|
/** Used as a reference to the global object. */
|
|
var root = (objectTypes[typeof window] && window) || this;
|
|
|
|
/** Backup possible global object. */
|
|
var oldRoot = root;
|
|
|
|
/** Detect free variable `exports`. */
|
|
var freeExports = objectTypes[typeof exports] && exports;
|
|
|
|
/** Detect free variable `module`. */
|
|
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
|
|
|
|
/** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
|
|
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
|
|
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
|
|
root = freeGlobal;
|
|
}
|
|
|
|
/**
|
|
* Used as the maximum length of an array-like object.
|
|
* See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
|
|
* for more details.
|
|
*/
|
|
var maxSafeInteger = Math.pow(2, 53) - 1;
|
|
|
|
/** Regular expression to detect Opera. */
|
|
var reOpera = /\bOpera/;
|
|
|
|
/** Possible global object. */
|
|
var thisBinding = this;
|
|
|
|
/** Used for native method references. */
|
|
var objectProto = Object.prototype;
|
|
|
|
/** Used to check for own properties of an object. */
|
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
|
|
/** Used to resolve the internal `[[Class]]` of values. */
|
|
var toString = objectProto.toString;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Capitalizes a string value.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to capitalize.
|
|
* @returns {string} The capitalized string.
|
|
*/
|
|
function capitalize(string) {
|
|
string = String(string);
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
}
|
|
|
|
/**
|
|
* A utility function to clean up the OS name.
|
|
*
|
|
* @private
|
|
* @param {string} os The OS name to clean up.
|
|
* @param {string} [pattern] A `RegExp` pattern matching the OS name.
|
|
* @param {string} [label] A label for the OS.
|
|
*/
|
|
function cleanupOS(os, pattern, label) {
|
|
// Platform tokens are defined at:
|
|
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
|
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
|
var data = {
|
|
'10.0': '10',
|
|
'6.4': '10 Technical Preview',
|
|
'6.3': '8.1',
|
|
'6.2': '8',
|
|
'6.1': 'Server 2008 R2 / 7',
|
|
'6.0': 'Server 2008 / Vista',
|
|
'5.2': 'Server 2003 / XP 64-bit',
|
|
'5.1': 'XP',
|
|
'5.01': '2000 SP1',
|
|
'5.0': '2000',
|
|
'4.0': 'NT',
|
|
'4.90': 'ME'
|
|
};
|
|
// Detect Windows version from platform tokens.
|
|
if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
|
|
(data = data[/[\d.]+$/.exec(os)])) {
|
|
os = 'Windows ' + data;
|
|
}
|
|
// Correct character case and cleanup string.
|
|
os = String(os);
|
|
|
|
if (pattern && label) {
|
|
os = os.replace(RegExp(pattern, 'i'), label);
|
|
}
|
|
|
|
os = format(
|
|
os.replace(/ ce$/i, ' CE')
|
|
.replace(/\bhpw/i, 'web')
|
|
.replace(/\bMacintosh\b/, 'Mac OS')
|
|
.replace(/_PowerPC\b/i, ' OS')
|
|
.replace(/\b(OS X) [^ \d]+/i, '$1')
|
|
.replace(/\bMac (OS X)\b/, '$1')
|
|
.replace(/\/(\d)/, ' $1')
|
|
.replace(/_/g, '.')
|
|
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
|
|
.replace(/\bx86\.64\b/gi, 'x86_64')
|
|
.replace(/\b(Windows Phone) OS\b/, '$1')
|
|
.replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
|
|
.split(' on ')[0]
|
|
);
|
|
|
|
return os;
|
|
}
|
|
|
|
/**
|
|
* An iteration utility for arrays and objects.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} object The object to iterate over.
|
|
* @param {Function} callback The function called per iteration.
|
|
*/
|
|
function each(object, callback) {
|
|
var index = -1,
|
|
length = object ? object.length : 0;
|
|
|
|
if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
|
|
while (++index < length) {
|
|
callback(object[index], index, object);
|
|
}
|
|
} else {
|
|
forOwn(object, callback);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Trim and conditionally capitalize string values.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to format.
|
|
* @returns {string} The formatted string.
|
|
*/
|
|
function format(string) {
|
|
string = trim(string);
|
|
return /^(?:webOS|i(?:OS|P))/.test(string)
|
|
? string
|
|
: capitalize(string);
|
|
}
|
|
|
|
/**
|
|
* Iterates over an object's own properties, executing the `callback` for each.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} callback The function executed per own property.
|
|
*/
|
|
function forOwn(object, callback) {
|
|
for (var key in object) {
|
|
if (hasOwnProperty.call(object, key)) {
|
|
callback(object[key], key, object);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the internal `[[Class]]` of a value.
|
|
*
|
|
* @private
|
|
* @param {*} value The value.
|
|
* @returns {string} The `[[Class]]`.
|
|
*/
|
|
function getClassOf(value) {
|
|
return value == null
|
|
? capitalize(value)
|
|
: toString.call(value).slice(8, -1);
|
|
}
|
|
|
|
/**
|
|
* Host objects can return type values that are different from their actual
|
|
* data type. The objects we are concerned with usually return non-primitive
|
|
* types of "object", "function", or "unknown".
|
|
*
|
|
* @private
|
|
* @param {*} object The owner of the property.
|
|
* @param {string} property The property to check.
|
|
* @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
|
|
*/
|
|
function isHostType(object, property) {
|
|
var type = object != null ? typeof object[property] : 'number';
|
|
return !/^(?:boolean|number|string|undefined)$/.test(type) &&
|
|
(type == 'object' ? !!object[property] : true);
|
|
}
|
|
|
|
/**
|
|
* Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to qualify.
|
|
* @returns {string} The qualified string.
|
|
*/
|
|
function qualify(string) {
|
|
return String(string).replace(/([ -])(?!$)/g, '$1?');
|
|
}
|
|
|
|
/**
|
|
* A bare-bones `Array#reduce` like utility function.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} callback The function called per iteration.
|
|
* @returns {*} The accumulated result.
|
|
*/
|
|
function reduce(array, callback) {
|
|
var accumulator = null;
|
|
each(array, function(value, index) {
|
|
accumulator = callback(accumulator, value, index, array);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* Removes leading and trailing whitespace from a string.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to trim.
|
|
* @returns {string} The trimmed string.
|
|
*/
|
|
function trim(string) {
|
|
return String(string).replace(/^ +| +$/g, '');
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a new platform object.
|
|
*
|
|
* @memberOf platform
|
|
* @param {Object|string} [ua=navigator.userAgent] The user agent string or
|
|
* context object.
|
|
* @returns {Object} A platform object.
|
|
*/
|
|
function parse(ua) {
|
|
|
|
/** The environment context object. */
|
|
var context = root;
|
|
|
|
/** Used to flag when a custom context is provided. */
|
|
var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
|
|
|
|
// Juggle arguments.
|
|
if (isCustomContext) {
|
|
context = ua;
|
|
ua = null;
|
|
}
|
|
|
|
/** Browser navigator object. */
|
|
var nav = context.navigator || {};
|
|
|
|
/** Browser user agent string. */
|
|
var userAgent = nav.userAgent || '';
|
|
|
|
ua || (ua = userAgent);
|
|
|
|
/** Used to flag when `thisBinding` is the [ModuleScope]. */
|
|
var isModuleScope = isCustomContext || thisBinding == oldRoot;
|
|
|
|
/** Used to detect if browser is like Chrome. */
|
|
var likeChrome = isCustomContext
|
|
? !!nav.likeChrome
|
|
: /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
|
|
|
|
/** Internal `[[Class]]` value shortcuts. */
|
|
var objectClass = 'Object',
|
|
airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
|
|
enviroClass = isCustomContext ? objectClass : 'Environment',
|
|
javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
|
|
phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
|
|
|
|
/** Detect Java environments. */
|
|
var java = /\bJava/.test(javaClass) && context.java;
|
|
|
|
/** Detect Rhino. */
|
|
var rhino = java && getClassOf(context.environment) == enviroClass;
|
|
|
|
/** A character to represent alpha. */
|
|
var alpha = java ? 'a' : '\u03b1';
|
|
|
|
/** A character to represent beta. */
|
|
var beta = java ? 'b' : '\u03b2';
|
|
|
|
/** Browser document object. */
|
|
var doc = context.document || {};
|
|
|
|
/**
|
|
* Detect Opera browser (Presto-based).
|
|
* http://www.howtocreate.co.uk/operaStuff/operaObject.html
|
|
* http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
|
|
*/
|
|
var opera = context.operamini || context.opera;
|
|
|
|
/** Opera `[[Class]]`. */
|
|
var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
|
|
? operaClass
|
|
: (opera = null);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/** Temporary variable used over the script's lifetime. */
|
|
var data;
|
|
|
|
/** The CPU architecture. */
|
|
var arch = ua;
|
|
|
|
/** Platform description array. */
|
|
var description = [];
|
|
|
|
/** Platform alpha/beta indicator. */
|
|
var prerelease = null;
|
|
|
|
/** A flag to indicate that environment features should be used to resolve the platform. */
|
|
var useFeatures = ua == userAgent;
|
|
|
|
/** The browser/environment version. */
|
|
var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
|
|
|
|
/** A flag to indicate if the OS ends with "/ Version" */
|
|
var isSpecialCasedOS;
|
|
|
|
/* Detectable layout engines (order is important). */
|
|
var layout = getLayout([
|
|
{ 'label': 'EdgeHTML', 'pattern': 'Edge' },
|
|
'Trident',
|
|
{ 'label': 'WebKit', 'pattern': 'AppleWebKit' },
|
|
'iCab',
|
|
'Presto',
|
|
'NetFront',
|
|
'Tasman',
|
|
'KHTML',
|
|
'Gecko'
|
|
]);
|
|
|
|
/* Detectable browser names (order is important). */
|
|
var name = getName([
|
|
'Adobe AIR',
|
|
'Arora',
|
|
'Avant Browser',
|
|
'Breach',
|
|
'Camino',
|
|
'Electron',
|
|
'Epiphany',
|
|
'Fennec',
|
|
'Flock',
|
|
'Galeon',
|
|
'GreenBrowser',
|
|
'iCab',
|
|
'Iceweasel',
|
|
'K-Meleon',
|
|
'Konqueror',
|
|
'Lunascape',
|
|
'Maxthon',
|
|
{ 'label': 'Microsoft Edge', 'pattern': '(?:Edge|Edg|EdgA|EdgiOS)' },
|
|
'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',
|
|
'Vivaldi',
|
|
'Waterfox',
|
|
'WebPositive',
|
|
{ 'label': 'Yandex Browser', 'pattern': 'YaBrowser' },
|
|
{ 'label': 'UC Browser', 'pattern': 'UCBrowser' },
|
|
'Opera Mini',
|
|
{ 'label': 'Opera Mini', 'pattern': 'OPiOS' },
|
|
'Opera',
|
|
{ 'label': 'Opera', 'pattern': 'OPR' },
|
|
'Chromium',
|
|
'Chrome',
|
|
{ 'label': 'Chrome', 'pattern': '(?:HeadlessChrome)' },
|
|
{ '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 },
|
|
'Alcatel': {},
|
|
'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': {},
|
|
'Huawei': {},
|
|
'Lenovo': {},
|
|
'LG': {},
|
|
'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
|
|
'Motorola': { 'Xoom': 1 },
|
|
'Nintendo': { 'Wii U': 1, 'Wii': 1 },
|
|
'Nokia': { 'Lumia': 1 },
|
|
'Oppo': {},
|
|
'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
|
|
'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 },
|
|
'Xiaomi': { 'Mi': 1, 'Redmi': 1 }
|
|
});
|
|
|
|
/* Detectable operating systems (order is important). */
|
|
var os = getOS([
|
|
'Windows Phone',
|
|
'KaiOS',
|
|
'Android',
|
|
'CentOS',
|
|
{ 'label': 'Chrome OS', 'pattern': 'CrOS' },
|
|
'Debian',
|
|
{ 'label': 'DragonFly BSD', 'pattern': 'DragonFly' },
|
|
'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 Android products.
|
|
// Browsers on Android devices typically provide their product IDS after "Android;"
|
|
// up to "Build" or ") AppleWebKit".
|
|
// Example:
|
|
// "Mozilla/5.0 (Linux; Android 8.1.0; Moto G (5) Plus) AppleWebKit/537.36
|
|
// (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36"
|
|
if (/\bAndroid\b/.test(os) && !product &&
|
|
(data = /\bAndroid[^;]*;(.*?)(?:Build|\) AppleWebKit)\b/i.exec(ua))) {
|
|
product = trim(data[1])
|
|
// Replace any language codes (eg. "en-US").
|
|
.replace(/^[a-z]{2}-[a-z]{2};\s*/i, '')
|
|
|| null;
|
|
}
|
|
// Detect product names that contain their manufacturer's name.
|
|
if (manufacturer && !product) {
|
|
product = getProduct([manufacturer]);
|
|
} else if (manufacturer && product) {
|
|
product = product
|
|
.replace(RegExp('^(' + qualify(manufacturer) + ')[-_.\\s]', 'i'), manufacturer + ' ')
|
|
.replace(RegExp('^(' + qualify(manufacturer) + ')[-_.]?(\\w)', 'i'), manufacturer + ' $2');
|
|
}
|
|
// 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' && /^Linux\b/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 UC Browser speed mode.
|
|
else if (name == 'UC Browser' && /\bUCWEB\b/.test(ua)) {
|
|
description.push('speed mode');
|
|
}
|
|
// 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|Edg|EdgA|EdgiOS|FxiOS|HeadlessChrome|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$)|UCBrowser|YaBrowser)',
|
|
'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|KaiOS)\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] = (/\b(?:Headless)?Chrome\/([\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 : data < 602 ? 9 : data < 604 ? 10 : data < 606 ? 11 : data < 608 ? 12 : '12');
|
|
} 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;
|
|
} else if (name == 'Chrome' && /\bHeadlessChrome/i.test(ua)) {
|
|
description.unshift('headless');
|
|
}
|
|
}
|
|
// 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;
|
|
}
|
|
}
|
|
// Newer versions of SRWare Iron uses the Chrome tag to indicate its version number.
|
|
else if (/\bSRWare Iron\b/.test(name) && !version) {
|
|
version = getVersion('Chrome');
|
|
}
|
|
// Strip incorrect OS versions.
|
|
if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
|
|
ua.indexOf('/' + data + '-') > -1) {
|
|
os = trim(os.replace(data, ''));
|
|
}
|
|
// Ensure OS does not include the browser name.
|
|
if (os && os.indexOf(name) != -1 && !RegExp(name + ' OS').test(os)) {
|
|
os = os.replace(RegExp(' *' + qualify(name) + ' *'), '');
|
|
}
|
|
// 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|SRWare Iron|Vivaldi|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", "Linux", "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)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
|
|
},{}],10:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "v1", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _v.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "v3", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _v2.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "v4", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _v3.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "v5", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _v4.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "NIL", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _nil.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "version", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _version.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "validate", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _validate.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "stringify", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _stringify.default;
|
|
}
|
|
});
|
|
Object.defineProperty(exports, "parse", {
|
|
enumerable: true,
|
|
get: function () {
|
|
return _parse.default;
|
|
}
|
|
});
|
|
|
|
var _v = _interopRequireDefault(require("./v1.js"));
|
|
|
|
var _v2 = _interopRequireDefault(require("./v3.js"));
|
|
|
|
var _v3 = _interopRequireDefault(require("./v4.js"));
|
|
|
|
var _v4 = _interopRequireDefault(require("./v5.js"));
|
|
|
|
var _nil = _interopRequireDefault(require("./nil.js"));
|
|
|
|
var _version = _interopRequireDefault(require("./version.js"));
|
|
|
|
var _validate = _interopRequireDefault(require("./validate.js"));
|
|
|
|
var _stringify = _interopRequireDefault(require("./stringify.js"));
|
|
|
|
var _parse = _interopRequireDefault(require("./parse.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
},{"./nil.js":12,"./parse.js":13,"./stringify.js":17,"./v1.js":18,"./v3.js":19,"./v4.js":21,"./v5.js":22,"./validate.js":23,"./version.js":24}],11:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
/*
|
|
* Browser-compatible JavaScript MD5
|
|
*
|
|
* Modification of JavaScript MD5
|
|
* https://github.com/blueimp/JavaScript-MD5
|
|
*
|
|
* Copyright 2011, Sebastian Tschan
|
|
* https://blueimp.net
|
|
*
|
|
* Licensed under the MIT license:
|
|
* https://opensource.org/licenses/MIT
|
|
*
|
|
* Based on
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for more info.
|
|
*/
|
|
function md5(bytes) {
|
|
if (typeof bytes === 'string') {
|
|
const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
|
|
|
|
bytes = new Uint8Array(msg.length);
|
|
|
|
for (let i = 0; i < msg.length; ++i) {
|
|
bytes[i] = msg.charCodeAt(i);
|
|
}
|
|
}
|
|
|
|
return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8));
|
|
}
|
|
/*
|
|
* Convert an array of little-endian words to an array of bytes
|
|
*/
|
|
|
|
|
|
function md5ToHexEncodedArray(input) {
|
|
const output = [];
|
|
const length32 = input.length * 32;
|
|
const hexTab = '0123456789abcdef';
|
|
|
|
for (let i = 0; i < length32; i += 8) {
|
|
const x = input[i >> 5] >>> i % 32 & 0xff;
|
|
const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16);
|
|
output.push(hex);
|
|
}
|
|
|
|
return output;
|
|
}
|
|
/**
|
|
* Calculate output length with padding and bit length
|
|
*/
|
|
|
|
|
|
function getOutputLength(inputLength8) {
|
|
return (inputLength8 + 64 >>> 9 << 4) + 14 + 1;
|
|
}
|
|
/*
|
|
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
|
*/
|
|
|
|
|
|
function wordsToMd5(x, len) {
|
|
/* append padding */
|
|
x[len >> 5] |= 0x80 << len % 32;
|
|
x[getOutputLength(len) - 1] = len;
|
|
let a = 1732584193;
|
|
let b = -271733879;
|
|
let c = -1732584194;
|
|
let d = 271733878;
|
|
|
|
for (let i = 0; i < x.length; i += 16) {
|
|
const olda = a;
|
|
const oldb = b;
|
|
const oldc = c;
|
|
const oldd = d;
|
|
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
|
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
|
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
|
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
|
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
|
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
|
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
|
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
|
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
|
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
|
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
|
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
|
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
|
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
|
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
|
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
|
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
|
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
|
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
|
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
|
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
|
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
|
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
|
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
|
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
|
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
|
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
|
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
|
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
|
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
|
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
|
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
|
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
|
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
|
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
|
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
|
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
|
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
|
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
|
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
|
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
|
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
|
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
|
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
|
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
|
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
|
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
|
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
|
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
|
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
|
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
|
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
|
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
|
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
|
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
|
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
|
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
|
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
|
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
|
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
|
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
|
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
|
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
|
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
|
a = safeAdd(a, olda);
|
|
b = safeAdd(b, oldb);
|
|
c = safeAdd(c, oldc);
|
|
d = safeAdd(d, oldd);
|
|
}
|
|
|
|
return [a, b, c, d];
|
|
}
|
|
/*
|
|
* Convert an array bytes to an array of little-endian words
|
|
* Characters >255 have their high-byte silently ignored.
|
|
*/
|
|
|
|
|
|
function bytesToWords(input) {
|
|
if (input.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
const length8 = input.length * 8;
|
|
const output = new Uint32Array(getOutputLength(length8));
|
|
|
|
for (let i = 0; i < length8; i += 8) {
|
|
output[i >> 5] |= (input[i / 8] & 0xff) << i % 32;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
|
|
|
|
function safeAdd(x, y) {
|
|
const lsw = (x & 0xffff) + (y & 0xffff);
|
|
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return msw << 16 | lsw & 0xffff;
|
|
}
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left.
|
|
*/
|
|
|
|
|
|
function bitRotateLeft(num, cnt) {
|
|
return num << cnt | num >>> 32 - cnt;
|
|
}
|
|
/*
|
|
* These functions implement the four basic operations the algorithm uses.
|
|
*/
|
|
|
|
|
|
function md5cmn(q, a, b, x, s, t) {
|
|
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
|
}
|
|
|
|
function md5ff(a, b, c, d, x, s, t) {
|
|
return md5cmn(b & c | ~b & d, a, b, x, s, t);
|
|
}
|
|
|
|
function md5gg(a, b, c, d, x, s, t) {
|
|
return md5cmn(b & d | c & ~d, a, b, x, s, t);
|
|
}
|
|
|
|
function md5hh(a, b, c, d, x, s, t) {
|
|
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
|
}
|
|
|
|
function md5ii(a, b, c, d, x, s, t) {
|
|
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
|
|
}
|
|
|
|
var _default = md5;
|
|
exports.default = _default;
|
|
},{}],12:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
var _default = '00000000-0000-0000-0000-000000000000';
|
|
exports.default = _default;
|
|
},{}],13:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _validate = _interopRequireDefault(require("./validate.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function parse(uuid) {
|
|
if (!(0, _validate.default)(uuid)) {
|
|
throw TypeError('Invalid UUID');
|
|
}
|
|
|
|
let v;
|
|
const arr = new Uint8Array(16); // Parse ########-....-....-....-............
|
|
|
|
arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24;
|
|
arr[1] = v >>> 16 & 0xff;
|
|
arr[2] = v >>> 8 & 0xff;
|
|
arr[3] = v & 0xff; // Parse ........-####-....-....-............
|
|
|
|
arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8;
|
|
arr[5] = v & 0xff; // Parse ........-....-####-....-............
|
|
|
|
arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8;
|
|
arr[7] = v & 0xff; // Parse ........-....-....-####-............
|
|
|
|
arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8;
|
|
arr[9] = v & 0xff; // Parse ........-....-....-....-############
|
|
// (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes)
|
|
|
|
arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff;
|
|
arr[11] = v / 0x100000000 & 0xff;
|
|
arr[12] = v >>> 24 & 0xff;
|
|
arr[13] = v >>> 16 & 0xff;
|
|
arr[14] = v >>> 8 & 0xff;
|
|
arr[15] = v & 0xff;
|
|
return arr;
|
|
}
|
|
|
|
var _default = parse;
|
|
exports.default = _default;
|
|
},{"./validate.js":23}],14:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
|
|
exports.default = _default;
|
|
},{}],15:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = rng;
|
|
// Unique ID creation requires a high quality random # generator. In the browser we therefore
|
|
// require the crypto API and do not support built-in fallback to lower quality random number
|
|
// generators (like Math.random()).
|
|
let getRandomValues;
|
|
const rnds8 = new Uint8Array(16);
|
|
|
|
function rng() {
|
|
// lazy load so that environments that need to polyfill have a chance to do so
|
|
if (!getRandomValues) {
|
|
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
|
|
// find the complete implementation of crypto (msCrypto) on IE11.
|
|
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
|
|
|
|
if (!getRandomValues) {
|
|
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
}
|
|
}
|
|
|
|
return getRandomValues(rnds8);
|
|
}
|
|
},{}],16:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
// Adapted from Chris Veness' SHA1 code at
|
|
// http://www.movable-type.co.uk/scripts/sha1.html
|
|
function f(s, x, y, z) {
|
|
switch (s) {
|
|
case 0:
|
|
return x & y ^ ~x & z;
|
|
|
|
case 1:
|
|
return x ^ y ^ z;
|
|
|
|
case 2:
|
|
return x & y ^ x & z ^ y & z;
|
|
|
|
case 3:
|
|
return x ^ y ^ z;
|
|
}
|
|
}
|
|
|
|
function ROTL(x, n) {
|
|
return x << n | x >>> 32 - n;
|
|
}
|
|
|
|
function sha1(bytes) {
|
|
const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
|
|
const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
|
|
|
|
if (typeof bytes === 'string') {
|
|
const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
|
|
|
|
bytes = [];
|
|
|
|
for (let i = 0; i < msg.length; ++i) {
|
|
bytes.push(msg.charCodeAt(i));
|
|
}
|
|
} else if (!Array.isArray(bytes)) {
|
|
// Convert Array-like to Array
|
|
bytes = Array.prototype.slice.call(bytes);
|
|
}
|
|
|
|
bytes.push(0x80);
|
|
const l = bytes.length / 4 + 2;
|
|
const N = Math.ceil(l / 16);
|
|
const M = new Array(N);
|
|
|
|
for (let i = 0; i < N; ++i) {
|
|
const arr = new Uint32Array(16);
|
|
|
|
for (let j = 0; j < 16; ++j) {
|
|
arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3];
|
|
}
|
|
|
|
M[i] = arr;
|
|
}
|
|
|
|
M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32);
|
|
M[N - 1][14] = Math.floor(M[N - 1][14]);
|
|
M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff;
|
|
|
|
for (let i = 0; i < N; ++i) {
|
|
const W = new Uint32Array(80);
|
|
|
|
for (let t = 0; t < 16; ++t) {
|
|
W[t] = M[i][t];
|
|
}
|
|
|
|
for (let t = 16; t < 80; ++t) {
|
|
W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
|
|
}
|
|
|
|
let a = H[0];
|
|
let b = H[1];
|
|
let c = H[2];
|
|
let d = H[3];
|
|
let e = H[4];
|
|
|
|
for (let t = 0; t < 80; ++t) {
|
|
const s = Math.floor(t / 20);
|
|
const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;
|
|
e = d;
|
|
d = c;
|
|
c = ROTL(b, 30) >>> 0;
|
|
b = a;
|
|
a = T;
|
|
}
|
|
|
|
H[0] = H[0] + a >>> 0;
|
|
H[1] = H[1] + b >>> 0;
|
|
H[2] = H[2] + c >>> 0;
|
|
H[3] = H[3] + d >>> 0;
|
|
H[4] = H[4] + e >>> 0;
|
|
}
|
|
|
|
return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff];
|
|
}
|
|
|
|
var _default = sha1;
|
|
exports.default = _default;
|
|
},{}],17:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _validate = _interopRequireDefault(require("./validate.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
/**
|
|
* Convert array of 16 byte values to UUID string format of the form:
|
|
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
*/
|
|
const byteToHex = [];
|
|
|
|
for (let i = 0; i < 256; ++i) {
|
|
byteToHex.push((i + 0x100).toString(16).substr(1));
|
|
}
|
|
|
|
function stringify(arr, offset = 0) {
|
|
// Note: Be careful editing this code! It's been tuned for performance
|
|
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
|
|
const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
|
|
// of the following:
|
|
// - One or more input array values don't map to a hex octet (leading to
|
|
// "undefined" in the uuid)
|
|
// - Invalid input values for the RFC `version` or `variant` fields
|
|
|
|
if (!(0, _validate.default)(uuid)) {
|
|
throw TypeError('Stringified UUID is invalid');
|
|
}
|
|
|
|
return uuid;
|
|
}
|
|
|
|
var _default = stringify;
|
|
exports.default = _default;
|
|
},{"./validate.js":23}],18:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _rng = _interopRequireDefault(require("./rng.js"));
|
|
|
|
var _stringify = _interopRequireDefault(require("./stringify.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
// **`v1()` - Generate time-based UUID**
|
|
//
|
|
// Inspired by https://github.com/LiosK/UUID.js
|
|
// and http://docs.python.org/library/uuid.html
|
|
let _nodeId;
|
|
|
|
let _clockseq; // Previous uuid creation time
|
|
|
|
|
|
let _lastMSecs = 0;
|
|
let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details
|
|
|
|
function v1(options, buf, offset) {
|
|
let i = buf && offset || 0;
|
|
const b = buf || new Array(16);
|
|
options = options || {};
|
|
let node = options.node || _nodeId;
|
|
let 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) {
|
|
const seedBytes = options.random || (options.rng || _rng.default)();
|
|
|
|
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.
|
|
|
|
|
|
let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock
|
|
// cycle to simulate higher resolution clock
|
|
|
|
let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)
|
|
|
|
const 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`
|
|
|
|
const 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`
|
|
|
|
const 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 (let n = 0; n < 6; ++n) {
|
|
b[i + n] = node[n];
|
|
}
|
|
|
|
return buf || (0, _stringify.default)(b);
|
|
}
|
|
|
|
var _default = v1;
|
|
exports.default = _default;
|
|
},{"./rng.js":15,"./stringify.js":17}],19:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _v = _interopRequireDefault(require("./v35.js"));
|
|
|
|
var _md = _interopRequireDefault(require("./md5.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
const v3 = (0, _v.default)('v3', 0x30, _md.default);
|
|
var _default = v3;
|
|
exports.default = _default;
|
|
},{"./md5.js":11,"./v35.js":20}],20:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = _default;
|
|
exports.URL = exports.DNS = void 0;
|
|
|
|
var _stringify = _interopRequireDefault(require("./stringify.js"));
|
|
|
|
var _parse = _interopRequireDefault(require("./parse.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function stringToBytes(str) {
|
|
str = unescape(encodeURIComponent(str)); // UTF8 escape
|
|
|
|
const bytes = [];
|
|
|
|
for (let i = 0; i < str.length; ++i) {
|
|
bytes.push(str.charCodeAt(i));
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
|
exports.DNS = DNS;
|
|
const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
|
|
exports.URL = URL;
|
|
|
|
function _default(name, version, hashfunc) {
|
|
function generateUUID(value, namespace, buf, offset) {
|
|
if (typeof value === 'string') {
|
|
value = stringToBytes(value);
|
|
}
|
|
|
|
if (typeof namespace === 'string') {
|
|
namespace = (0, _parse.default)(namespace);
|
|
}
|
|
|
|
if (namespace.length !== 16) {
|
|
throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)');
|
|
} // Compute hash of namespace and value, Per 4.3
|
|
// Future: Use spread syntax when supported on all platforms, e.g. `bytes =
|
|
// hashfunc([...namespace, ... value])`
|
|
|
|
|
|
let bytes = new Uint8Array(16 + value.length);
|
|
bytes.set(namespace);
|
|
bytes.set(value, namespace.length);
|
|
bytes = hashfunc(bytes);
|
|
bytes[6] = bytes[6] & 0x0f | version;
|
|
bytes[8] = bytes[8] & 0x3f | 0x80;
|
|
|
|
if (buf) {
|
|
offset = offset || 0;
|
|
|
|
for (let i = 0; i < 16; ++i) {
|
|
buf[offset + i] = bytes[i];
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
return (0, _stringify.default)(bytes);
|
|
} // Function#name is not settable on some platforms (#270)
|
|
|
|
|
|
try {
|
|
generateUUID.name = name; // eslint-disable-next-line no-empty
|
|
} catch (err) {} // For CommonJS default export support
|
|
|
|
|
|
generateUUID.DNS = DNS;
|
|
generateUUID.URL = URL;
|
|
return generateUUID;
|
|
}
|
|
},{"./parse.js":13,"./stringify.js":17}],21:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _rng = _interopRequireDefault(require("./rng.js"));
|
|
|
|
var _stringify = _interopRequireDefault(require("./stringify.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function v4(options, buf, offset) {
|
|
options = options || {};
|
|
|
|
const rnds = options.random || (options.rng || _rng.default)(); // 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) {
|
|
offset = offset || 0;
|
|
|
|
for (let i = 0; i < 16; ++i) {
|
|
buf[offset + i] = rnds[i];
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
return (0, _stringify.default)(rnds);
|
|
}
|
|
|
|
var _default = v4;
|
|
exports.default = _default;
|
|
},{"./rng.js":15,"./stringify.js":17}],22:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _v = _interopRequireDefault(require("./v35.js"));
|
|
|
|
var _sha = _interopRequireDefault(require("./sha1.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
const v5 = (0, _v.default)('v5', 0x50, _sha.default);
|
|
var _default = v5;
|
|
exports.default = _default;
|
|
},{"./sha1.js":16,"./v35.js":20}],23:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _regex = _interopRequireDefault(require("./regex.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function validate(uuid) {
|
|
return typeof uuid === 'string' && _regex.default.test(uuid);
|
|
}
|
|
|
|
var _default = validate;
|
|
exports.default = _default;
|
|
},{"./regex.js":14}],24:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _validate = _interopRequireDefault(require("./validate.js"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function version(uuid) {
|
|
if (!(0, _validate.default)(uuid)) {
|
|
throw TypeError('Invalid UUID');
|
|
}
|
|
|
|
return parseInt(uuid.substr(14, 1), 16);
|
|
}
|
|
|
|
var _default = version;
|
|
exports.default = _default;
|
|
},{"./validate.js":23}],25:[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);
|
|
|
|
},{}],26:[function(require,module,exports){
|
|
/*!
|
|
* EventEmitter v5.2.9 - 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 || {}));
|
|
|
|
},{}],27:[function(require,module,exports){
|
|
module.exports={
|
|
"author": "OpenVidu",
|
|
"dependencies": {
|
|
"freeice": "2.2.2",
|
|
"hark": "1.2.3",
|
|
"jsnlog": "2.30.0",
|
|
"platform": "1.3.6",
|
|
"uuid": "8.3.2",
|
|
"wolfy87-eventemitter": "5.2.9"
|
|
},
|
|
"description": "OpenVidu Browser",
|
|
"devDependencies": {
|
|
"@types/node": "15.12.2",
|
|
"@types/platform": "1.3.3",
|
|
"browserify": "17.0.0",
|
|
"grunt": "1.4.1",
|
|
"grunt-cli": "1.4.3",
|
|
"grunt-contrib-copy": "1.0.0",
|
|
"grunt-contrib-sass": "2.0.0",
|
|
"grunt-contrib-uglify": "5.0.1",
|
|
"grunt-contrib-watch": "1.1.0",
|
|
"grunt-postcss": "0.9.0",
|
|
"grunt-string-replace": "1.3.1",
|
|
"grunt-ts": "6.0.0-beta.22",
|
|
"terser": "5.7.0",
|
|
"tsify": "5.0.4",
|
|
"tslint": "6.1.3",
|
|
"typedoc": "0.19.2",
|
|
"typescript": "4.0.7"
|
|
},
|
|
"license": "Apache-2.0",
|
|
"main": "lib/index.js",
|
|
"name": "openvidu-browser",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git://github.com/OpenVidu/openvidu"
|
|
},
|
|
"scripts": {
|
|
"browserify": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && 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:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --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 --target es5 --lib dom,es5,es2015.promise,scripthost",
|
|
"docs": "./generate-docs.sh"
|
|
},
|
|
"types": "lib/index.d.ts",
|
|
"version": "2.19.0"
|
|
}
|
|
|
|
},{}],28:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var OpenVidu_1 = require("./OpenVidu/OpenVidu");
|
|
var jsnlog_1 = require("jsnlog");
|
|
if (window) {
|
|
window['OpenVidu'] = OpenVidu_1.OpenVidu;
|
|
}
|
|
jsnlog_1.JL.setOptions({ enabled: false });
|
|
|
|
},{"./OpenVidu/OpenVidu":33,"jsnlog":7}],29:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Connection = void 0;
|
|
var Stream_1 = require("./Stream");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var Connection = (function () {
|
|
function Connection(session, connectionOptions) {
|
|
this.session = session;
|
|
this.disposed = false;
|
|
var msg = "'Connection' created ";
|
|
if (!!connectionOptions.role) {
|
|
this.localOptions = connectionOptions;
|
|
this.connectionId = this.localOptions.id;
|
|
this.creationTime = this.localOptions.createdAt;
|
|
this.data = this.localOptions.metadata;
|
|
this.rpcSessionId = this.localOptions.sessionId;
|
|
this.role = this.localOptions.role;
|
|
this.record = this.localOptions.record;
|
|
msg += '(local)';
|
|
}
|
|
else {
|
|
this.remoteOptions = connectionOptions;
|
|
this.connectionId = this.remoteOptions.id;
|
|
this.creationTime = this.remoteOptions.createdAt;
|
|
if (this.remoteOptions.metadata) {
|
|
this.data = this.remoteOptions.metadata;
|
|
}
|
|
if (this.remoteOptions.streams) {
|
|
this.initRemoteStreams(this.remoteOptions.streams);
|
|
}
|
|
msg += "(remote) with 'connectionId' [" + this.remoteOptions.id + ']';
|
|
}
|
|
logger.info(msg);
|
|
}
|
|
Connection.prototype.sendIceCandidate = function (candidate) {
|
|
var _this = this;
|
|
logger.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) {
|
|
logger.error('Error sending ICE candidate: ' + JSON.stringify(error));
|
|
_this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, ExceptionEvent_1.ExceptionEventName.ICE_CANDIDATE_ERROR, _this.session, "There was an unexpected error on the server-side processing an ICE candidate generated and sent by the client-side", 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);
|
|
});
|
|
logger.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;
|
|
|
|
},{"../OpenViduInternal/Events/ExceptionEvent":45,"../OpenViduInternal/Logger/OpenViduLogger":66,"./Stream":36}],30:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EventDispatcher = void 0;
|
|
var EventEmitter = require("wolfy87-eventemitter");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var EventDispatcher = (function () {
|
|
function EventDispatcher() {
|
|
this.userHandlerArrowHandler = new WeakMap();
|
|
this.ee = new EventEmitter();
|
|
}
|
|
EventDispatcher.prototype.off = function (type, handler) {
|
|
if (!handler) {
|
|
this.ee.removeAllListeners(type);
|
|
}
|
|
else {
|
|
var arrowHandler = this.userHandlerArrowHandler.get(handler);
|
|
if (!!arrowHandler) {
|
|
this.ee.off(type, arrowHandler);
|
|
}
|
|
this.userHandlerArrowHandler.delete(handler);
|
|
}
|
|
return this;
|
|
};
|
|
EventDispatcher.prototype.onAux = function (type, message, handler) {
|
|
var arrowHandler = function (event) {
|
|
if (event) {
|
|
logger.info(message, event);
|
|
}
|
|
else {
|
|
logger.info(message);
|
|
}
|
|
handler(event);
|
|
};
|
|
this.userHandlerArrowHandler.set(handler, arrowHandler);
|
|
this.ee.on(type, arrowHandler);
|
|
return this;
|
|
};
|
|
EventDispatcher.prototype.onceAux = function (type, message, handler) {
|
|
var _this = this;
|
|
var arrowHandler = function (event) {
|
|
if (event) {
|
|
logger.info(message, event);
|
|
}
|
|
else {
|
|
logger.info(message);
|
|
}
|
|
handler(event);
|
|
_this.userHandlerArrowHandler.delete(handler);
|
|
};
|
|
this.userHandlerArrowHandler.set(handler, arrowHandler);
|
|
this.ee.once(type, arrowHandler);
|
|
return this;
|
|
};
|
|
return EventDispatcher;
|
|
}());
|
|
exports.EventDispatcher = EventDispatcher;
|
|
|
|
},{"../OpenViduInternal/Logger/OpenViduLogger":66,"wolfy87-eventemitter":26}],31:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Filter = void 0;
|
|
var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
|
|
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var Filter = (function () {
|
|
function Filter(type, options) {
|
|
this.handlers = new Map();
|
|
this.type = type;
|
|
this.options = options;
|
|
}
|
|
Filter.prototype.execMethod = function (method, params) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
logger.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";
|
|
logger.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) {
|
|
logger.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 {
|
|
logger.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) {
|
|
logger.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) {
|
|
logger.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.set(eventType, handler);
|
|
logger.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) {
|
|
logger.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) {
|
|
logger.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 {
|
|
_this.handlers.delete(eventType);
|
|
logger.info('Filter event listener to event ' + eventType + ' successfully removed on Stream ' + _this.stream.streamId);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
return Filter;
|
|
}());
|
|
exports.Filter = Filter;
|
|
|
|
},{"../OpenViduInternal/Enums/OpenViduError":40,"../OpenViduInternal/Events/StreamPropertyChangedEvent":54,"../OpenViduInternal/Logger/OpenViduLogger":66}],32:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.LocalRecorder = void 0;
|
|
var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var LocalRecorder = (function () {
|
|
function LocalRecorder(stream) {
|
|
this.stream = stream;
|
|
this.chunks = [];
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
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 (mimeType) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
try {
|
|
if (typeof MediaRecorder === 'undefined') {
|
|
logger.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'));
|
|
}
|
|
logger.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'");
|
|
var options = {};
|
|
if (typeof MediaRecorder.isTypeSupported === 'function') {
|
|
if (!!mimeType) {
|
|
if (!MediaRecorder.isTypeSupported(mimeType)) {
|
|
reject(new Error('mimeType "' + mimeType + '" is not supported'));
|
|
}
|
|
options = { mimeType: mimeType };
|
|
}
|
|
else {
|
|
logger.log('No mimeType parameter provided. Using default codecs');
|
|
}
|
|
}
|
|
else {
|
|
logger.warn('MediaRecorder#isTypeSupported is not supported. Using default codecs');
|
|
}
|
|
_this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options);
|
|
_this.mediaRecorder.start(10);
|
|
}
|
|
catch (err) {
|
|
reject(err);
|
|
}
|
|
_this.mediaRecorder.ondataavailable = function (e) {
|
|
_this.chunks.push(e.data);
|
|
};
|
|
_this.mediaRecorder.onerror = function (e) {
|
|
logger.error('MediaRecorder error: ', e);
|
|
};
|
|
_this.mediaRecorder.onstart = function () {
|
|
logger.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')');
|
|
};
|
|
_this.mediaRecorder.onstop = function () {
|
|
_this.onStopDefault();
|
|
};
|
|
_this.mediaRecorder.onpause = function () {
|
|
logger.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')');
|
|
};
|
|
_this.mediaRecorder.onresume = function () {
|
|
logger.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')');
|
|
};
|
|
_this.mediaRecorder.onwarning = function (e) {
|
|
logger.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;
|
|
resolve();
|
|
}
|
|
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;
|
|
resolve();
|
|
}
|
|
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.isSafariBrowser()) {
|
|
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 () {
|
|
logger.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":39,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Utils/Platform":70}],33:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OpenVidu = void 0;
|
|
var LocalRecorder_1 = require("./LocalRecorder");
|
|
var Publisher_1 = require("./Publisher");
|
|
var Session_1 = require("./Session");
|
|
var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent");
|
|
var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent");
|
|
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
|
|
var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto");
|
|
var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing");
|
|
var OpenViduLoggerConfiguration_1 = require("../OpenViduInternal/Logger/OpenViduLoggerConfiguration");
|
|
var EventEmitter = require("wolfy87-eventemitter");
|
|
var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc");
|
|
var packageJson = require('../../package.json');
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var OpenVidu = (function () {
|
|
function OpenVidu() {
|
|
var _this = this;
|
|
this.masterNodeHasCrashed = false;
|
|
this.publishers = [];
|
|
this.secret = '';
|
|
this.recorder = false;
|
|
this.advancedConfiguration = {};
|
|
this.webrtcStatsInterval = -1;
|
|
this.sendBrowserLogs = OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.disabled;
|
|
this.isPro = false;
|
|
this.ee = new EventEmitter();
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
this.libraryVersion = packageJson.version;
|
|
logger.info("OpenVidu initialized");
|
|
logger.info('Platform detected: ' + platform.getDescription());
|
|
logger.info('openvidu-browser version: ' + this.libraryVersion);
|
|
if (platform.isMobileDevice() || platform.isReactNative()) {
|
|
this.onOrientationChanged(function () {
|
|
_this.publishers.forEach(function (publisher) {
|
|
if (publisher.stream.isLocalStreamPublished && !!publisher.stream && !!publisher.stream.hasVideo) {
|
|
_this.sendNewVideoDimensionsIfRequired(publisher, 'deviceRotated', 75, 10);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
OpenVidu.prototype.onOrientationChanged = function (handler) {
|
|
window.addEventListener('orientationchange', handler);
|
|
};
|
|
OpenVidu.prototype.sendNewVideoDimensionsIfRequired = function (publisher, reason, WAIT_INTERVAL, MAX_ATTEMPTS) {
|
|
var _this = this;
|
|
var attempts = 0;
|
|
var oldWidth = publisher.stream.videoDimensions.width;
|
|
var oldHeight = publisher.stream.videoDimensions.height;
|
|
var repeatUntilChangeOrMaxAttempts = setInterval(function () {
|
|
attempts++;
|
|
if (attempts > MAX_ATTEMPTS) {
|
|
clearTimeout(repeatUntilChangeOrMaxAttempts);
|
|
}
|
|
publisher.getVideoDimensions(publisher.stream.getMediaStream()).then(function (newDimensions) {
|
|
if (newDimensions.width !== oldWidth || newDimensions.height !== oldHeight) {
|
|
clearTimeout(repeatUntilChangeOrMaxAttempts);
|
|
_this.sendVideoDimensionsChangedEvent(publisher, reason, oldWidth, oldHeight, newDimensions.width, newDimensions.height);
|
|
}
|
|
});
|
|
}, WAIT_INTERVAL);
|
|
};
|
|
OpenVidu.prototype.sendVideoDimensionsChangedEvent = function (publisher, reason, oldWidth, oldHeight, newWidth, newHeight) {
|
|
var _this = this;
|
|
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: reason
|
|
}, function (error, response) {
|
|
if (error) {
|
|
logger.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 }, reason)]);
|
|
publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, reason)]);
|
|
_this.session.sendVideoData(publisher);
|
|
}
|
|
});
|
|
};
|
|
;
|
|
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 () {
|
|
if (platform.isIPhoneOrIPad()) {
|
|
if (platform.isIOSWithSafari() || platform.isIonicIos() ||
|
|
platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() ||
|
|
platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isOperaBrowser() ||
|
|
platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() ||
|
|
platform.isSafariBrowser() || platform.isAndroidBrowser() || platform.isElectron() || platform.isSamsungBrowser()) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
};
|
|
OpenVidu.prototype.checkScreenSharingCapabilities = function () {
|
|
return platform.canScreenShare();
|
|
};
|
|
OpenVidu.prototype.getDevices = function () {
|
|
return new Promise(function (resolve, reject) {
|
|
navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
|
|
var _a;
|
|
var devices = [];
|
|
if (platform.isIonicAndroid() && typeof cordova != "undefined" && ((_a = cordova === null || cordova === void 0 ? void 0 : cordova.plugins) === null || _a === void 0 ? void 0 : _a.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) {
|
|
logger.error('Error getting devices', error);
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
OpenVidu.prototype.getUserMedia = function (options) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var askForAudioStreamOnly = function (previousMediaStream, constraints) {
|
|
var definedAudioConstraint = ((constraints.audio === undefined) ? true : constraints.audio);
|
|
var constraintsAux = { audio: definedAudioConstraint, video: false };
|
|
navigator.mediaDevices.getUserMedia(constraintsAux)
|
|
.then(function (audioOnlyStream) {
|
|
previousMediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]);
|
|
resolve(previousMediaStream);
|
|
})
|
|
.catch(function (error) {
|
|
previousMediaStream.getAudioTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
previousMediaStream.getVideoTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
reject(_this.generateAudioDeviceError(error, constraintsAux));
|
|
});
|
|
};
|
|
_this.generateMediaConstraints(options).then(function (myConstraints) {
|
|
var _a, _b;
|
|
if (!!myConstraints.videoTrack && !!myConstraints.audioTrack ||
|
|
!!myConstraints.audioTrack && ((_a = myConstraints.constraints) === null || _a === void 0 ? void 0 : _a.video) === false ||
|
|
!!myConstraints.videoTrack && ((_b = myConstraints.constraints) === null || _b === void 0 ? void 0 : _b.audio) === false) {
|
|
resolve(_this.addAlreadyProvidedTracks(myConstraints, new MediaStream()));
|
|
}
|
|
else {
|
|
if (!!myConstraints.videoTrack) {
|
|
delete myConstraints.constraints.video;
|
|
}
|
|
if (!!myConstraints.audioTrack) {
|
|
delete myConstraints.constraints.audio;
|
|
}
|
|
var mustAskForAudioTrackLater_1 = false;
|
|
if (typeof options.videoSource === 'string') {
|
|
if (options.videoSource === 'screen' ||
|
|
options.videoSource === 'window' ||
|
|
(platform.isElectron() && options.videoSource.startsWith('screen:'))) {
|
|
mustAskForAudioTrackLater_1 = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false);
|
|
if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
|
|
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
|
.then(function (mediaStream) {
|
|
_this.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
|
if (mustAskForAudioTrackLater_1) {
|
|
askForAudioStreamOnly(mediaStream, myConstraints.constraints);
|
|
return;
|
|
}
|
|
else {
|
|
resolve(mediaStream);
|
|
}
|
|
})
|
|
.catch(function (error) {
|
|
var errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED;
|
|
var errorMessage = error.toString();
|
|
reject(new OpenViduError_1.OpenViduError(errorName, errorMessage));
|
|
});
|
|
return;
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
var constraintsAux = mustAskForAudioTrackLater_1 ? { video: myConstraints.constraints.video } : myConstraints.constraints;
|
|
navigator.mediaDevices.getUserMedia(constraintsAux)
|
|
.then(function (mediaStream) {
|
|
_this.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
|
if (mustAskForAudioTrackLater_1) {
|
|
askForAudioStreamOnly(mediaStream, myConstraints.constraints);
|
|
return;
|
|
}
|
|
else {
|
|
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 () {
|
|
logger.enableProdMode();
|
|
};
|
|
OpenVidu.prototype.setAdvancedConfiguration = function (configuration) {
|
|
this.advancedConfiguration = configuration;
|
|
};
|
|
OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var myConstraints = {
|
|
audioTrack: undefined,
|
|
videoTrack: undefined,
|
|
constraints: {
|
|
audio: undefined,
|
|
video: undefined
|
|
}
|
|
};
|
|
var audioSource = publisherProperties.audioSource;
|
|
var videoSource = publisherProperties.videoSource;
|
|
if (audioSource === null || audioSource === false) {
|
|
myConstraints.constraints.audio = false;
|
|
}
|
|
if (videoSource === null || videoSource === false) {
|
|
myConstraints.constraints.video = false;
|
|
}
|
|
if (myConstraints.constraints.audio === false && myConstraints.constraints.video === false) {
|
|
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"));
|
|
}
|
|
if (typeof MediaStreamTrack !== 'undefined' && audioSource instanceof MediaStreamTrack) {
|
|
myConstraints.audioTrack = audioSource;
|
|
}
|
|
if (typeof MediaStreamTrack !== 'undefined' && videoSource instanceof MediaStreamTrack) {
|
|
myConstraints.videoTrack = videoSource;
|
|
}
|
|
if (audioSource === undefined) {
|
|
myConstraints.constraints.audio = true;
|
|
}
|
|
if (videoSource === undefined) {
|
|
myConstraints.constraints.video = {
|
|
width: {
|
|
ideal: 640
|
|
},
|
|
height: {
|
|
ideal: 480
|
|
}
|
|
};
|
|
}
|
|
if (videoSource !== null && videoSource !== false) {
|
|
if (!!publisherProperties.resolution) {
|
|
var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x');
|
|
var idealWidth = Number(widthAndHeight[0]);
|
|
var idealHeight = Number(widthAndHeight[1]);
|
|
myConstraints.constraints.video = {
|
|
width: {
|
|
ideal: idealWidth
|
|
},
|
|
height: {
|
|
ideal: idealHeight
|
|
}
|
|
};
|
|
}
|
|
if (!!publisherProperties.frameRate) {
|
|
myConstraints.constraints.video.frameRate = { ideal: publisherProperties.frameRate };
|
|
}
|
|
}
|
|
_this.configureDeviceIdOrScreensharing(myConstraints, publisherProperties, resolve, reject);
|
|
resolve(myConstraints);
|
|
});
|
|
};
|
|
OpenVidu.prototype.startWs = function (onConnectSucces) {
|
|
var config = {
|
|
heartbeat: 5000,
|
|
ws: {
|
|
uri: this.wsUri + '?sessionId=' + this.session.sessionId,
|
|
onconnected: onConnectSucces,
|
|
ondisconnect: this.disconnectCallback.bind(this),
|
|
onreconnecting: this.reconnectingCallback.bind(this),
|
|
onreconnected: this.reconnectedCallback.bind(this),
|
|
ismasternodecrashed: this.isMasterNodeCrashed.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),
|
|
connectionPropertyChanged: this.session.onConnectionPropertyChanged.bind(this.session),
|
|
networkQualityLevelChanged: this.session.onNetworkQualityLevelChangedChanged.bind(this.session),
|
|
filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session),
|
|
iceCandidate: this.session.recvIceCandidate.bind(this.session),
|
|
mediaError: this.session.onMediaError.bind(this.session),
|
|
masterNodeCrashedNotification: this.onMasterNodeCrashedNotification.bind(this),
|
|
forciblyReconnectSubscriber: this.session.onForciblyReconnectSubscriber.bind(this.session)
|
|
}
|
|
};
|
|
this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
|
|
};
|
|
OpenVidu.prototype.onMasterNodeCrashedNotification = function (response) {
|
|
console.error('Master Node has crashed');
|
|
this.masterNodeHasCrashed = true;
|
|
this.session.onLostConnection("nodeCrashed");
|
|
this.jsonRpcClient.close(4103, "Master Node has crashed");
|
|
};
|
|
OpenVidu.prototype.getWsReadyState = function () {
|
|
return this.jsonRpcClient.getReadyState();
|
|
};
|
|
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 = {};
|
|
}
|
|
logger.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.generateAudioDeviceError = function (error, constraints) {
|
|
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();
|
|
return new OpenViduError_1.OpenViduError(errorName, errorMessage);
|
|
case 'notallowederror':
|
|
errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED;
|
|
errorMessage = error.toString();
|
|
return new OpenViduError_1.OpenViduError(errorName, errorMessage);
|
|
case 'overconstrainederror':
|
|
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 + "'";
|
|
}
|
|
return new OpenViduError_1.OpenViduError(errorName, errorMessage);
|
|
case 'notreadableerror':
|
|
errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ALREADY_IN_USE;
|
|
errorMessage = error.toString();
|
|
return (new OpenViduError_1.OpenViduError(errorName, errorMessage));
|
|
default:
|
|
return new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_GENERIC_ERROR, error.toString());
|
|
}
|
|
};
|
|
OpenVidu.prototype.addAlreadyProvidedTracks = function (myConstraints, mediaStream) {
|
|
if (!!myConstraints.videoTrack) {
|
|
mediaStream.addTrack(myConstraints.videoTrack);
|
|
}
|
|
if (!!myConstraints.audioTrack) {
|
|
mediaStream.addTrack(myConstraints.audioTrack);
|
|
}
|
|
return mediaStream;
|
|
};
|
|
OpenVidu.prototype.configureDeviceIdOrScreensharing = function (myConstraints, publisherProperties, resolve, reject) {
|
|
var _this = this;
|
|
var audioSource = publisherProperties.audioSource;
|
|
var videoSource = publisherProperties.videoSource;
|
|
if (typeof audioSource === 'string') {
|
|
myConstraints.constraints.audio = { deviceId: { exact: audioSource } };
|
|
}
|
|
if (typeof videoSource === 'string') {
|
|
if (!this.isScreenShare(videoSource)) {
|
|
this.setVideoSource(myConstraints, videoSource);
|
|
}
|
|
else {
|
|
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, Safari (>=13.0), Edge (>= 80) or Electron. Detected client: ' + platform.getName() + ' ' + platform.getVersion());
|
|
logger.error(error);
|
|
reject(error);
|
|
}
|
|
else {
|
|
if (platform.isElectron()) {
|
|
var prefix = "screen:";
|
|
var videoSourceString = videoSource;
|
|
var electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length);
|
|
myConstraints.constraints.video = {
|
|
mandatory: {
|
|
chromeMediaSource: 'desktop',
|
|
chromeMediaSourceId: electronScreenId
|
|
}
|
|
};
|
|
resolve(myConstraints);
|
|
}
|
|
else {
|
|
if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) && !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');
|
|
logger.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');
|
|
logger.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);
|
|
logger.error(error_3);
|
|
reject(error_3);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
myConstraints.constraints.video = screenConstraints;
|
|
resolve(myConstraints);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
else {
|
|
if (navigator.mediaDevices['getDisplayMedia']) {
|
|
resolve(myConstraints);
|
|
}
|
|
else {
|
|
var firefoxString = (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? 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 err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl);
|
|
logger.error(err);
|
|
reject(err);
|
|
}
|
|
else if (error === 'installed-disabled') {
|
|
var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension');
|
|
logger.error(err);
|
|
reject(err);
|
|
}
|
|
else if (error === 'permission-denied') {
|
|
var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop');
|
|
logger.error(err);
|
|
reject(err);
|
|
}
|
|
else {
|
|
var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, 'Unknown error when accessing screen share');
|
|
logger.error(err);
|
|
logger.error(error);
|
|
reject(err);
|
|
}
|
|
}
|
|
else {
|
|
myConstraints.constraints.video = screenConstraints.video;
|
|
resolve(myConstraints);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
OpenVidu.prototype.setVideoSource = function (myConstraints, videoSource) {
|
|
if (!myConstraints.constraints.video) {
|
|
myConstraints.constraints.video = {};
|
|
}
|
|
myConstraints.constraints.video['deviceId'] = { exact: videoSource };
|
|
};
|
|
OpenVidu.prototype.disconnectCallback = function () {
|
|
logger.warn('Websocket connection lost');
|
|
if (this.isRoomAvailable()) {
|
|
this.session.onLostConnection('networkDisconnect');
|
|
}
|
|
else {
|
|
alert('Connection error. Please reload page.');
|
|
}
|
|
};
|
|
OpenVidu.prototype.reconnectingCallback = function () {
|
|
logger.warn('Websocket connection lost (reconnecting)');
|
|
if (!this.isRoomAvailable()) {
|
|
alert('Connection error. Please reload page.');
|
|
}
|
|
else {
|
|
this.session.emitEvent('reconnecting', []);
|
|
}
|
|
};
|
|
OpenVidu.prototype.reconnectedCallback = function () {
|
|
var _this = this;
|
|
logger.warn('Websocket reconnected');
|
|
if (this.isRoomAvailable()) {
|
|
if (!!this.session.connection) {
|
|
this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, function (error, response) {
|
|
if (!!error) {
|
|
if (_this.isMasterNodeCrashed()) {
|
|
logger.warn('Master Node has crashed!');
|
|
}
|
|
else {
|
|
logger.error(error);
|
|
logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
|
|
_this.session.onLostConnection("networkDisconnect");
|
|
_this.jsonRpcClient.close(4101, "Reconnection fault");
|
|
}
|
|
}
|
|
else {
|
|
_this.jsonRpcClient.resetPing();
|
|
_this.session.onRecoveredConnection();
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
logger.warn('There was no previous connection when running reconnection callback');
|
|
var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this.session, 'networkDisconnect');
|
|
this.session.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
|
|
sessionDisconnectEvent.callDefaultBehavior();
|
|
}
|
|
}
|
|
else {
|
|
alert('Connection error. Please reload page.');
|
|
}
|
|
};
|
|
OpenVidu.prototype.isMasterNodeCrashed = function () {
|
|
return this.masterNodeHasCrashed;
|
|
};
|
|
OpenVidu.prototype.isRoomAvailable = function () {
|
|
if (this.session !== undefined && this.session instanceof Session_1.Session) {
|
|
return true;
|
|
}
|
|
else {
|
|
logger.warn('Session instance not found');
|
|
return false;
|
|
}
|
|
};
|
|
OpenVidu.prototype.isScreenShare = function (videoSource) {
|
|
return videoSource === 'screen' ||
|
|
videoSource === 'window' ||
|
|
(platform.isElectron() && videoSource.startsWith('screen:'));
|
|
};
|
|
return OpenVidu;
|
|
}());
|
|
exports.OpenVidu = OpenVidu;
|
|
|
|
},{"../../package.json":27,"../OpenViduInternal/Enums/OpenViduError":40,"../OpenViduInternal/Enums/VideoInsertMode":41,"../OpenViduInternal/Events/SessionDisconnectedEvent":50,"../OpenViduInternal/Events/StreamPropertyChangedEvent":54,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":61,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Logger/OpenViduLoggerConfiguration":67,"../OpenViduInternal/ScreenSharing/Screen-Capturing":69,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":68,"../OpenViduInternal/Utils/Platform":70,"./LocalRecorder":32,"./Publisher":34,"./Session":35,"wolfy87-eventemitter":26}],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 (Object.prototype.hasOwnProperty.call(b, 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 __());
|
|
};
|
|
})();
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Publisher = void 0;
|
|
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 OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var 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;
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
_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) {
|
|
var affectedMediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream();
|
|
affectedMediaStream.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) {
|
|
logger.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.session.sendVideoData(_this.stream.streamManager);
|
|
}
|
|
});
|
|
}
|
|
this.stream.audioActive = value;
|
|
logger.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream');
|
|
}
|
|
};
|
|
Publisher.prototype.publishVideo = function (value) {
|
|
var _this = this;
|
|
if (this.stream.videoActive !== value) {
|
|
var affectedMediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream();
|
|
affectedMediaStream.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) {
|
|
logger.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.session.sendVideoData(_this.stream.streamManager);
|
|
}
|
|
});
|
|
}
|
|
this.stream.videoActive = value;
|
|
logger.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.replaceTrack = function (track) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var replaceTrackInMediaStream, replaceTrackInRtcRtpSender, trackOriginalEnabledValue, error_1;
|
|
var _this = this;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
replaceTrackInMediaStream = function () {
|
|
return new Promise(function (resolve, reject) {
|
|
var mediaStream = _this.stream.displayMyRemote() ? _this.stream.localMediaStreamWhenSubscribedToRemote : _this.stream.getMediaStream();
|
|
var removedTrack;
|
|
if (track.kind === 'video') {
|
|
removedTrack = mediaStream.getVideoTracks()[0];
|
|
}
|
|
else {
|
|
removedTrack = mediaStream.getAudioTracks()[0];
|
|
}
|
|
mediaStream.removeTrack(removedTrack);
|
|
removedTrack.stop();
|
|
mediaStream.addTrack(track);
|
|
if (track.kind === 'video' && _this.stream.isLocalStreamPublished) {
|
|
_this.openvidu.sendNewVideoDimensionsIfRequired(_this, 'trackReplaced', 50, 30);
|
|
_this.session.sendVideoData(_this.stream.streamManager, 5, true, 5);
|
|
}
|
|
resolve();
|
|
});
|
|
};
|
|
replaceTrackInRtcRtpSender = function () {
|
|
return new Promise(function (resolve, reject) {
|
|
var senders = _this.stream.getRTCPeerConnection().getSenders();
|
|
var sender;
|
|
if (track.kind === 'video') {
|
|
sender = senders.find(function (s) { return !!s.track && s.track.kind === 'video'; });
|
|
if (!sender) {
|
|
reject(new Error('There\'s no replaceable track for that kind of MediaStreamTrack in this Publisher object'));
|
|
return;
|
|
}
|
|
}
|
|
else if (track.kind === 'audio') {
|
|
sender = senders.find(function (s) { return !!s.track && s.track.kind === 'audio'; });
|
|
if (!sender) {
|
|
reject(new Error('There\'s no replaceable track for that kind of MediaStreamTrack in this Publisher object'));
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
reject(new Error('Unknown track kind ' + track.kind));
|
|
return;
|
|
}
|
|
sender.replaceTrack(track).then(function () {
|
|
resolve();
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
trackOriginalEnabledValue = track.enabled;
|
|
if (track.kind === 'video') {
|
|
track.enabled = this.stream.videoActive;
|
|
}
|
|
else if (track.kind === 'audio') {
|
|
track.enabled = this.stream.audioActive;
|
|
}
|
|
_a.label = 1;
|
|
case 1:
|
|
_a.trys.push([1, 7, , 8]);
|
|
if (!this.stream.isLocalStreamPublished) return [3, 4];
|
|
return [4, replaceTrackInRtcRtpSender()];
|
|
case 2:
|
|
_a.sent();
|
|
return [4, replaceTrackInMediaStream()];
|
|
case 3: return [2, _a.sent()];
|
|
case 4: return [4, replaceTrackInMediaStream()];
|
|
case 5: return [2, _a.sent()];
|
|
case 6: return [3, 8];
|
|
case 7:
|
|
error_1 = _a.sent();
|
|
track.enabled = trackOriginalEnabledValue;
|
|
throw error_1;
|
|
case 8: return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Publisher.prototype.initialize = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var constraints = {};
|
|
var constraintsAux = {};
|
|
var timeForDialogEvent = 1500;
|
|
var startTime;
|
|
var errorCallback = function (openViduError) {
|
|
_this.accessDenied = true;
|
|
_this.accessAllowed = false;
|
|
logger.error("Publisher initialization failed. " + openViduError.name + ": " + openViduError.message);
|
|
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.initializeVideoReference(mediaStream);
|
|
if (!_this.stream.displayMyRemote()) {
|
|
_this.stream.updateMediaStreamInVideos();
|
|
}
|
|
delete _this.firstVideoElement;
|
|
if (_this.stream.isSendVideo()) {
|
|
_this.getVideoDimensions(mediaStream).then(function (dimensions) {
|
|
_this.stream.videoDimensions = {
|
|
width: dimensions.width,
|
|
height: dimensions.height
|
|
};
|
|
if (_this.stream.isSendScreen()) {
|
|
_this.screenShareResizeInterval = setInterval(function () {
|
|
var settings = mediaStream.getVideoTracks()[0].getSettings();
|
|
var newWidth = settings.width;
|
|
var newHeight = settings.height;
|
|
if (_this.stream.isLocalStreamPublished &&
|
|
(newWidth !== _this.stream.videoDimensions.width || newHeight !== _this.stream.videoDimensions.height)) {
|
|
_this.openvidu.sendVideoDimensionsChangedEvent(_this, 'screenResized', _this.stream.videoDimensions.width, _this.stream.videoDimensions.height, newWidth || 0, newHeight || 0);
|
|
}
|
|
}, 650);
|
|
}
|
|
_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);
|
|
mediaStream.getAudioTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
mediaStream.getVideoTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
errorCallback(_this.openvidu.generateAudioDeviceError(error, constraints));
|
|
return;
|
|
});
|
|
}
|
|
else {
|
|
successCallback(mediaStream);
|
|
}
|
|
};
|
|
var getMediaError = function (error) {
|
|
logger.error("getMediaError: " + error.toString());
|
|
_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;
|
|
}
|
|
};
|
|
_this.openvidu.generateMediaConstraints(_this.properties)
|
|
.then(function (myConstraints) {
|
|
var _a, _b;
|
|
if (!!myConstraints.videoTrack && !!myConstraints.audioTrack ||
|
|
!!myConstraints.audioTrack && ((_a = myConstraints.constraints) === null || _a === void 0 ? void 0 : _a.video) === false ||
|
|
!!myConstraints.videoTrack && ((_b = myConstraints.constraints) === null || _b === void 0 ? void 0 : _b.audio) === false) {
|
|
successCallback(_this.openvidu.addAlreadyProvidedTracks(myConstraints, new MediaStream()));
|
|
return;
|
|
}
|
|
constraints = myConstraints.constraints;
|
|
var outboundStreamOptions = {
|
|
mediaConstraints: constraints,
|
|
publisherProperties: _this.properties
|
|
};
|
|
_this.stream.setOutboundStreamOptions(outboundStreamOptions);
|
|
var definedAudioConstraint = ((constraints.audio === undefined) ? true : constraints.audio);
|
|
constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint;
|
|
constraintsAux.video = constraints.video;
|
|
startTime = Date.now();
|
|
_this.setPermissionDialogTimer(timeForDialogEvent);
|
|
if (_this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
|
|
navigator.mediaDevices['getDisplayMedia']({ video: true })
|
|
.then(function (mediaStream) {
|
|
_this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
|
getMediaSuccess(mediaStream, definedAudioConstraint);
|
|
})
|
|
.catch(function (error) {
|
|
getMediaError(error);
|
|
});
|
|
}
|
|
else {
|
|
navigator.mediaDevices.getUserMedia(constraintsAux)
|
|
.then(function (mediaStream) {
|
|
_this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
|
|
getMediaSuccess(mediaStream, definedAudioConstraint);
|
|
})
|
|
.catch(function (error) {
|
|
getMediaError(error);
|
|
});
|
|
}
|
|
})
|
|
.catch(function (error) {
|
|
errorCallback(error);
|
|
});
|
|
});
|
|
};
|
|
Publisher.prototype.getVideoDimensions = function (mediaStream) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var requiresDomInsertion = platform.isIonicIos() || platform.isIOSWithSafari();
|
|
var loadedmetadataListener;
|
|
var resolveDimensions = function () {
|
|
var width;
|
|
var height;
|
|
if (typeof _this.stream.getMediaStream().getVideoTracks()[0].getSettings === 'function') {
|
|
var settings = _this.stream.getMediaStream().getVideoTracks()[0].getSettings();
|
|
width = settings.width || _this.videoReference.videoWidth;
|
|
height = settings.height || _this.videoReference.videoHeight;
|
|
}
|
|
else {
|
|
logger.warn('MediaStreamTrack does not have getSettings method on ' + platform.getDescription());
|
|
width = _this.videoReference.videoWidth;
|
|
height = _this.videoReference.videoHeight;
|
|
}
|
|
if (loadedmetadataListener != null) {
|
|
_this.videoReference.removeEventListener('loadedmetadata', loadedmetadataListener);
|
|
}
|
|
if (requiresDomInsertion) {
|
|
document.body.removeChild(_this.videoReference);
|
|
}
|
|
resolve({ width: width, height: height });
|
|
};
|
|
if (_this.videoReference.readyState >= 1) {
|
|
resolveDimensions();
|
|
}
|
|
else {
|
|
loadedmetadataListener = function () {
|
|
if (!_this.videoReference.videoWidth) {
|
|
var interval_1 = setInterval(function () {
|
|
if (!!_this.videoReference.videoWidth) {
|
|
clearInterval(interval_1);
|
|
resolveDimensions();
|
|
}
|
|
}, 40);
|
|
}
|
|
else {
|
|
resolveDimensions();
|
|
}
|
|
};
|
|
_this.videoReference.addEventListener('loadedmetadata', loadedmetadataListener);
|
|
if (requiresDomInsertion) {
|
|
document.body.appendChild(_this.videoReference);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Publisher.prototype.reestablishStreamPlayingEvent = function () {
|
|
if (this.ee.getListeners('streamPlaying').length > 0) {
|
|
this.addPlayEventToFirstVideo();
|
|
}
|
|
};
|
|
Publisher.prototype.initializeVideoReference = function (mediaStream) {
|
|
this.videoReference = document.createElement('video');
|
|
this.videoReference.setAttribute('muted', 'true');
|
|
this.videoReference.style.display = 'none';
|
|
if (platform.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) {
|
|
this.videoReference.setAttribute('playsinline', 'true');
|
|
}
|
|
this.stream.setMediaStream(mediaStream);
|
|
if (!!this.firstVideoElement) {
|
|
this.createVideoElement(this.firstVideoElement.targetElement, this.properties.insertMode);
|
|
}
|
|
this.videoReference.srcObject = mediaStream;
|
|
};
|
|
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":40,"../OpenViduInternal/Events/StreamEvent":52,"../OpenViduInternal/Events/StreamPropertyChangedEvent":54,"../OpenViduInternal/Events/VideoElementEvent":55,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Utils/Platform":70,"./Session":35,"./Stream":36,"./StreamManager":37}],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 (Object.prototype.hasOwnProperty.call(b, 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 __());
|
|
};
|
|
})();
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Session = void 0;
|
|
var Connection_1 = require("./Connection");
|
|
var Filter_1 = require("./Filter");
|
|
var Subscriber_1 = require("./Subscriber");
|
|
var EventDispatcher_1 = require("./EventDispatcher");
|
|
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 ConnectionPropertyChangedEvent_1 = require("../OpenViduInternal/Events/ConnectionPropertyChangedEvent");
|
|
var NetworkQualityLevelChangedEvent_1 = require("../OpenViduInternal/Events/NetworkQualityLevelChangedEvent");
|
|
var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError");
|
|
var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var Session = (function (_super) {
|
|
__extends(Session, _super);
|
|
function Session(openvidu) {
|
|
var _this = _super.call(this) || this;
|
|
_this.streamManagers = [];
|
|
_this.remoteStreamsCreated = new Map();
|
|
_this.remoteConnections = new Map();
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
_this.openvidu = openvidu;
|
|
return _this;
|
|
}
|
|
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.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' 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 = undefined;
|
|
if (!!param3 && (typeof param3 === 'function')) {
|
|
completionHandler = param3;
|
|
}
|
|
else if (!!param4) {
|
|
completionHandler = param4;
|
|
}
|
|
if (!this.sessionConnected()) {
|
|
if (completionHandler !== undefined) {
|
|
completionHandler(this.notConnectedError());
|
|
}
|
|
throw this.notConnectedError();
|
|
}
|
|
logger.info('Subscribing to ' + stream.connection.connectionId);
|
|
stream.subscribe()
|
|
.then(function () {
|
|
logger.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) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
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 _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
else {
|
|
var connectionId_1 = subscriber.stream.connection.connectionId;
|
|
logger.info('Unsubscribing from ' + connectionId_1);
|
|
_this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) {
|
|
if (error) {
|
|
logger.error('Error unsubscribing from ' + connectionId_1);
|
|
reject(error);
|
|
}
|
|
else {
|
|
logger.info('Unsubscribed correctly from ' + connectionId_1);
|
|
subscriber.stream.streamManager.removeAllVideos();
|
|
subscriber.stream.disposeWebRtcPeer();
|
|
subscriber.stream.disposeMediaStream();
|
|
resolve();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|
|
Session.prototype.publish = function (publisher) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
publisher.session = _this;
|
|
publisher.stream.session = _this;
|
|
if (!publisher.stream.publishedOnce) {
|
|
_this.connection.addStream(publisher.stream);
|
|
publisher.stream.publish()
|
|
.then(function () {
|
|
_this.sendVideoData(publisher, 8, true, 5);
|
|
resolve();
|
|
})
|
|
.catch(function (error) {
|
|
reject(error);
|
|
});
|
|
}
|
|
else {
|
|
publisher.initialize()
|
|
.then(function () {
|
|
_this.connection.addStream(publisher.stream);
|
|
publisher.reestablishStreamPlayingEvent();
|
|
publisher.stream.publish()
|
|
.then(function () {
|
|
_this.sendVideoData(publisher, 8, true, 5);
|
|
resolve();
|
|
})
|
|
.catch(function (error) {
|
|
reject(error);
|
|
});
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
}
|
|
});
|
|
};
|
|
Session.prototype.unpublish = function (publisher) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
throw _this.notConnectedError();
|
|
}
|
|
var stream = publisher.stream;
|
|
if (!stream.connection) {
|
|
reject(new Error('The associated Connection object of this Publisher is null'));
|
|
}
|
|
else if (stream.connection !== _this.connection) {
|
|
reject(new Error('The associated Connection object of this Publisher is not your local Connection.' +
|
|
"Only moderators can force unpublish on remote Streams via 'forceUnpublish' method"));
|
|
}
|
|
else {
|
|
logger.info('Unpublishing local media (' + stream.connection.connectionId + ')');
|
|
_this.openvidu.sendRequest('unpublishVideo', function (error, response) {
|
|
if (error) {
|
|
reject(error);
|
|
}
|
|
else {
|
|
logger.info('Media unpublished correctly');
|
|
stream.disposeWebRtcPeer();
|
|
if (stream.connection.stream == stream) {
|
|
delete stream.connection.stream;
|
|
}
|
|
var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish');
|
|
publisher.emitEvent('streamDestroyed', [streamEvent]);
|
|
streamEvent.callDefaultBehavior();
|
|
resolve();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|
|
Session.prototype.forceDisconnect = function (connection) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
logger.info('Forcing disconnect for connection ' + connection.connectionId);
|
|
_this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) {
|
|
if (error) {
|
|
logger.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 {
|
|
logger.info('Forcing disconnect correctly for Connection ' + connection.connectionId);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Session.prototype.forceUnpublish = function (stream) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
logger.info('Forcing unpublish for stream ' + stream.streamId);
|
|
_this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) {
|
|
if (error) {
|
|
logger.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 {
|
|
logger.info('Forcing unpublish correctly for Stream ' + stream.streamId);
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Session.prototype.signal = function (signal) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.sessionConnected()) {
|
|
reject(_this.notConnectedError());
|
|
}
|
|
var signalMessage = {};
|
|
if (signal.to && signal.to.length > 0) {
|
|
var connectionIds_1 = [];
|
|
signal.to.forEach(function (connection) {
|
|
if (!!connection.connectionId) {
|
|
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) {
|
|
var _a, _b, _c, _d;
|
|
_super.prototype.onAux.call(this, type, "Event '" + type + "' triggered by 'Session'", handler);
|
|
if (type === 'publisherStartSpeaking') {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) {
|
|
remoteConnection.stream.enableHarkSpeakingEvent();
|
|
}
|
|
});
|
|
if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.hasAudio)) {
|
|
this.connection.stream.enableHarkSpeakingEvent();
|
|
}
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) {
|
|
remoteConnection.stream.enableHarkStoppedSpeakingEvent();
|
|
}
|
|
});
|
|
if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.hasAudio)) {
|
|
this.connection.stream.enableHarkStoppedSpeakingEvent();
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
Session.prototype.once = function (type, handler) {
|
|
var _a, _b, _c, _d;
|
|
_super.prototype.onceAux.call(this, type, "Event '" + type + "' triggered once by 'Session'", handler);
|
|
if (type === 'publisherStartSpeaking') {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) {
|
|
remoteConnection.stream.enableOnceHarkSpeakingEvent();
|
|
}
|
|
});
|
|
if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.hasAudio)) {
|
|
this.connection.stream.enableOnceHarkSpeakingEvent();
|
|
}
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) {
|
|
remoteConnection.stream.enableOnceHarkStoppedSpeakingEvent();
|
|
}
|
|
});
|
|
if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.hasAudio)) {
|
|
this.connection.stream.enableOnceHarkStoppedSpeakingEvent();
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
Session.prototype.off = function (type, handler) {
|
|
var _this = this;
|
|
var _a, _b, _c, _d;
|
|
_super.prototype.off.call(this, type, handler);
|
|
if (type === 'publisherStartSpeaking') {
|
|
if (!this.anySpeechEventListenerEnabled('publisherStartSpeaking', false)) {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.streamManager)) {
|
|
if (!_this.anySpeechEventListenerEnabled('publisherStartSpeaking', false, remoteConnection.stream.streamManager)) {
|
|
remoteConnection.stream.disableHarkSpeakingEvent(false);
|
|
}
|
|
}
|
|
});
|
|
if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.streamManager)) {
|
|
if (!this.anySpeechEventListenerEnabled('publisherStartSpeaking', false, this.connection.stream.streamManager)) {
|
|
this.connection.stream.disableHarkSpeakingEvent(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
if (!this.anySpeechEventListenerEnabled('publisherStopSpeaking', false)) {
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a;
|
|
if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.streamManager)) {
|
|
if (!_this.anySpeechEventListenerEnabled('publisherStopSpeaking', false, remoteConnection.stream.streamManager)) {
|
|
remoteConnection.stream.disableHarkStoppedSpeakingEvent(false);
|
|
}
|
|
}
|
|
});
|
|
if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.streamManager)) {
|
|
if (!this.anySpeechEventListenerEnabled('publisherStopSpeaking', false, this.connection.stream.streamManager)) {
|
|
this.connection.stream.disableHarkStoppedSpeakingEvent(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
Session.prototype.onParticipantJoined = function (event) {
|
|
var _this = this;
|
|
this.getConnection(event.id, '')
|
|
.then(function (connection) {
|
|
logger.warn('Connection ' + connection.connectionId + ' already exists in connections list');
|
|
})
|
|
.catch(function (openViduError) {
|
|
var connection = new Connection_1.Connection(_this, event);
|
|
_this.remoteConnections.set(event.id, connection);
|
|
_this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]);
|
|
});
|
|
};
|
|
Session.prototype.onParticipantLeft = function (event) {
|
|
var _this = this;
|
|
this.getRemoteConnection(event.connectionId, 'onParticipantLeft').then(function (connection) {
|
|
if (!!connection.stream) {
|
|
var stream = connection.stream;
|
|
var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, event.reason);
|
|
_this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
|
streamEvent.callDefaultBehavior();
|
|
_this.remoteStreamsCreated.delete(stream.streamId);
|
|
}
|
|
_this.remoteConnections.delete(connection.connectionId);
|
|
_this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, event.reason)]);
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
};
|
|
Session.prototype.onParticipantPublished = function (event) {
|
|
var _this = this;
|
|
var afterConnectionFound = function (connection) {
|
|
_this.remoteConnections.set(connection.connectionId, connection);
|
|
if (!_this.remoteStreamsCreated.get(connection.stream.streamId)) {
|
|
_this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]);
|
|
}
|
|
_this.remoteStreamsCreated.set(connection.stream.streamId, true);
|
|
};
|
|
var connection;
|
|
this.getRemoteConnection(event.id, 'onParticipantPublished')
|
|
.then(function (con) {
|
|
connection = con;
|
|
event.metadata = con.data;
|
|
connection.remoteOptions = event;
|
|
connection.initRemoteStreams(event.streams);
|
|
afterConnectionFound(connection);
|
|
})
|
|
.catch(function (openViduError) {
|
|
connection = new Connection_1.Connection(_this, event);
|
|
afterConnectionFound(connection);
|
|
});
|
|
};
|
|
Session.prototype.onParticipantUnpublished = function (event) {
|
|
var _this = this;
|
|
if (event.connectionId === this.connection.connectionId) {
|
|
this.stopPublisherStream(event.reason);
|
|
}
|
|
else {
|
|
this.getRemoteConnection(event.connectionId, 'onParticipantUnpublished')
|
|
.then(function (connection) {
|
|
var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, event.reason);
|
|
_this.ee.emitEvent('streamDestroyed', [streamEvent]);
|
|
streamEvent.callDefaultBehavior();
|
|
var streamId = connection.stream.streamId;
|
|
_this.remoteStreamsCreated.delete(streamId);
|
|
connection.removeStream(streamId);
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
}
|
|
};
|
|
Session.prototype.onParticipantEvicted = function (event) {
|
|
if (event.connectionId === this.connection.connectionId) {
|
|
if (!!this.sessionId && !this.connection.disposed) {
|
|
this.leave(true, event.reason);
|
|
}
|
|
}
|
|
};
|
|
Session.prototype.onNewMessage = function (event) {
|
|
var _this = this;
|
|
logger.info('New signal: ' + JSON.stringify(event));
|
|
var strippedType = !!event.type ? event.type.replace(/^(signal:)/, '') : undefined;
|
|
if (!!event.from) {
|
|
this.getConnection(event.from, "Connection '" + event.from + "' unknown when 'onNewMessage'. Existing remote connections: "
|
|
+ JSON.stringify(this.remoteConnections.keys()) + '. Existing local connection: ' + this.connection.connectionId)
|
|
.then(function (connection) {
|
|
_this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, strippedType, event.data, connection)]);
|
|
if (!!event.type && event.type !== 'signal') {
|
|
_this.ee.emitEvent(event.type, [new SignalEvent_1.SignalEvent(_this, strippedType, event.data, connection)]);
|
|
}
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
}
|
|
else {
|
|
this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(this, strippedType, event.data, undefined)]);
|
|
if (!!event.type && event.type !== 'signal') {
|
|
this.ee.emitEvent(event.type, [new SignalEvent_1.SignalEvent(this, strippedType, event.data, undefined)]);
|
|
}
|
|
}
|
|
};
|
|
Session.prototype.onStreamPropertyChanged = function (event) {
|
|
var _this = this;
|
|
var callback = function (connection) {
|
|
if (!!connection.stream && connection.stream.streamId === event.streamId) {
|
|
var stream = connection.stream;
|
|
var oldValue = void 0;
|
|
switch (event.property) {
|
|
case 'audioActive':
|
|
oldValue = stream.audioActive;
|
|
event.newValue = event.newValue === 'true';
|
|
stream.audioActive = event.newValue;
|
|
break;
|
|
case 'videoActive':
|
|
oldValue = stream.videoActive;
|
|
event.newValue = event.newValue === 'true';
|
|
stream.videoActive = event.newValue;
|
|
break;
|
|
case 'videoDimensions':
|
|
oldValue = stream.videoDimensions;
|
|
event.newValue = JSON.parse(JSON.parse(event.newValue));
|
|
stream.videoDimensions = event.newValue;
|
|
break;
|
|
case 'filter':
|
|
oldValue = stream.filter;
|
|
event.newValue = (Object.keys(event.newValue).length > 0) ? event.newValue : undefined;
|
|
if (event.newValue !== undefined) {
|
|
stream.filter = new Filter_1.Filter(event.newValue.type, event.newValue.options);
|
|
stream.filter.stream = stream;
|
|
if (event.newValue.lastExecMethod) {
|
|
stream.filter.lastExecMethod = event.newValue.lastExecMethod;
|
|
}
|
|
}
|
|
else {
|
|
delete stream.filter;
|
|
}
|
|
event.newValue = stream.filter;
|
|
break;
|
|
}
|
|
_this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, event.property, event.newValue, oldValue, event.reason)]);
|
|
if (!!stream.streamManager) {
|
|
stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, event.property, event.newValue, oldValue, event.reason)]);
|
|
}
|
|
}
|
|
else {
|
|
logger.error("No stream with streamId '" + event.streamId + "' found for connection '" + event.connectionId + "' on 'streamPropertyChanged' event");
|
|
}
|
|
};
|
|
if (event.connectionId === this.connection.connectionId) {
|
|
callback(this.connection);
|
|
}
|
|
else {
|
|
this.getRemoteConnection(event.connectionId, 'onStreamPropertyChanged')
|
|
.then(function (connection) {
|
|
callback(connection);
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
}
|
|
};
|
|
Session.prototype.onConnectionPropertyChanged = function (event) {
|
|
var oldValue;
|
|
switch (event.property) {
|
|
case 'role':
|
|
oldValue = this.connection.role.slice();
|
|
this.connection.role = event.newValue;
|
|
this.connection.localOptions.role = event.newValue;
|
|
break;
|
|
case 'record':
|
|
oldValue = this.connection.record;
|
|
event.newValue = event.newValue === 'true';
|
|
this.connection.record = event.newValue;
|
|
this.connection.localOptions.record = event.newValue;
|
|
break;
|
|
}
|
|
this.ee.emitEvent('connectionPropertyChanged', [new ConnectionPropertyChangedEvent_1.ConnectionPropertyChangedEvent(this, this.connection, event.property, event.newValue, oldValue)]);
|
|
};
|
|
Session.prototype.onNetworkQualityLevelChangedChanged = function (event) {
|
|
var _this = this;
|
|
if (event.connectionId === this.connection.connectionId) {
|
|
this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent_1.NetworkQualityLevelChangedEvent(this, event.newValue, event.oldValue, this.connection)]);
|
|
}
|
|
else {
|
|
this.getConnection(event.connectionId, 'Connection not found for connectionId ' + event.connectionId)
|
|
.then(function (connection) {
|
|
_this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent_1.NetworkQualityLevelChangedEvent(_this, event.newValue, event.oldValue, connection)]);
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
}
|
|
};
|
|
Session.prototype.recvIceCandidate = function (event) {
|
|
var candidate = {
|
|
candidate: event.candidate,
|
|
sdpMid: event.sdpMid,
|
|
sdpMLineIndex: event.sdpMLineIndex,
|
|
component: null,
|
|
foundation: null,
|
|
port: null,
|
|
priority: null,
|
|
protocol: null,
|
|
relatedAddress: null,
|
|
relatedPort: null,
|
|
tcpType: null,
|
|
usernameFragment: null,
|
|
type: null,
|
|
toJSON: function () {
|
|
return { candidate: event.candidate };
|
|
}
|
|
};
|
|
this.getConnection(event.senderConnectionId, 'Connection not found for connectionId ' + event.senderConnectionId + ' owning endpoint ' + event.endpointName + '. Ice candidate will be ignored: ' + candidate)
|
|
.then(function (connection) {
|
|
var stream = connection.stream;
|
|
stream.getWebRtcPeer().addIceCandidate(candidate).catch(function (error) {
|
|
logger.error('Error adding candidate for ' + stream.streamId
|
|
+ ' stream of endpoint ' + event.endpointName + ': ' + error);
|
|
});
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
});
|
|
};
|
|
Session.prototype.onSessionClosed = function (msg) {
|
|
logger.info('Session closed: ' + JSON.stringify(msg));
|
|
var s = msg.sessionId;
|
|
if (s !== undefined) {
|
|
this.ee.emitEvent('session-closed', [{
|
|
session: s
|
|
}]);
|
|
}
|
|
else {
|
|
logger.warn('Session undefined on session closed', msg);
|
|
}
|
|
};
|
|
Session.prototype.onLostConnection = function (reason) {
|
|
logger.warn('Lost connection in Session ' + this.sessionId);
|
|
if (!!this.sessionId && !!this.connection && !this.connection.disposed) {
|
|
this.leave(true, reason);
|
|
}
|
|
};
|
|
Session.prototype.onRecoveredConnection = function () {
|
|
logger.info('Recovered connection in Session ' + this.sessionId);
|
|
this.reconnectBrokenStreams();
|
|
this.ee.emitEvent('reconnected', []);
|
|
};
|
|
Session.prototype.onMediaError = function (event) {
|
|
logger.error('Media error: ' + JSON.stringify(event));
|
|
var err = event.error;
|
|
if (err) {
|
|
this.ee.emitEvent('error-media', [{
|
|
error: err
|
|
}]);
|
|
}
|
|
else {
|
|
logger.warn('Received undefined media error:', event);
|
|
}
|
|
};
|
|
Session.prototype.onRecordingStarted = function (event) {
|
|
this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', event.id, event.name)]);
|
|
};
|
|
Session.prototype.onRecordingStopped = function (event) {
|
|
this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', event.id, event.name, event.reason)]);
|
|
};
|
|
Session.prototype.onFilterEventDispatched = function (event) {
|
|
var _this = this;
|
|
var connectionId = event.connectionId;
|
|
this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId)
|
|
.then(function (connection) {
|
|
var _a;
|
|
logger.info('Filter event dispatched');
|
|
var stream = connection.stream;
|
|
(_a = stream.filter.handlers.get(event.eventType)) === null || _a === void 0 ? void 0 : _a.call(_this, new FilterEvent_1.FilterEvent(stream.filter, event.eventType, event.data));
|
|
});
|
|
};
|
|
Session.prototype.onForciblyReconnectSubscriber = function (event) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
_this.getRemoteConnection(event.connectionId, 'onForciblyReconnectSubscriber')
|
|
.then(function (connection) {
|
|
if (!!connection.stream && connection.stream.streamId === event.streamId) {
|
|
var stream_1 = connection.stream;
|
|
if (stream_1.setupReconnectionEventEmitter(resolve, reject)) {
|
|
if (stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] != null) {
|
|
stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] = event;
|
|
reject('Ongoing forced subscriber reconnection');
|
|
}
|
|
else {
|
|
stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] = event;
|
|
var callback_1 = function () {
|
|
var eventAux = stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'];
|
|
delete stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'];
|
|
_this.onForciblyReconnectSubscriber(eventAux);
|
|
};
|
|
stream_1.reconnectionEventEmitter.once('success', function () {
|
|
callback_1();
|
|
});
|
|
stream_1.reconnectionEventEmitter.once('error', function () {
|
|
callback_1();
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
stream_1.completeWebRtcPeerReceive(true, true, event.sdpOffer)
|
|
.then(function () { return stream_1.finalResolveForSubscription(true, resolve); })
|
|
.catch(function (error) { return stream_1.finalRejectForSubscription(true, "Error while forcibly reconnecting remote stream " + event.streamId + ": " + error.toString(), reject); });
|
|
}
|
|
else {
|
|
var errMsg = "No stream with streamId '" + event.streamId + "' found for connection '" + event.connectionId + "' on 'streamPropertyChanged' event";
|
|
logger.error(errMsg);
|
|
reject(errMsg);
|
|
}
|
|
})
|
|
.catch(function (openViduError) {
|
|
logger.error(openViduError);
|
|
reject(openViduError);
|
|
});
|
|
});
|
|
};
|
|
Session.prototype.reconnectBrokenStreams = function () {
|
|
logger.info('Re-establishing media connections...');
|
|
var someReconnection = false;
|
|
if (!!this.connection.stream && this.connection.stream.streamIceConnectionStateBroken()) {
|
|
logger.warn('Re-establishing Publisher ' + this.connection.stream.streamId);
|
|
this.connection.stream.initWebRtcPeerSend(true);
|
|
someReconnection = true;
|
|
}
|
|
this.remoteConnections.forEach(function (remoteConnection) {
|
|
if (!!remoteConnection.stream && remoteConnection.stream.streamIceConnectionStateBroken()) {
|
|
logger.warn('Re-establishing Subscriber ' + remoteConnection.stream.streamId);
|
|
remoteConnection.stream.initWebRtcPeerReceive(true);
|
|
someReconnection = true;
|
|
}
|
|
});
|
|
if (!someReconnection) {
|
|
logger.info('There were no media streams in need of a reconnection');
|
|
}
|
|
};
|
|
Session.prototype.emitEvent = function (type, eventArray) {
|
|
this.ee.emitEvent(type, eventArray);
|
|
};
|
|
Session.prototype.leave = function (forced, reason) {
|
|
var _this = this;
|
|
forced = !!forced;
|
|
logger.info('Leaving Session (forced=' + forced + ')');
|
|
this.stopVideoDataIntervals();
|
|
if (!!this.connection) {
|
|
if (!this.connection.disposed && !forced) {
|
|
this.openvidu.sendRequest('leaveRoom', function (error, response) {
|
|
if (error) {
|
|
logger.error("leaveRoom error: " + JSON.stringify(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 {
|
|
logger.warn('You were not connected to the session ' + this.sessionId);
|
|
}
|
|
logger.flush();
|
|
};
|
|
Session.prototype.initializeParams = function (token) {
|
|
var joinParams = {
|
|
token: (!!token) ? token : '',
|
|
session: this.sessionId,
|
|
platform: !!platform.getDescription() ? platform.getDescription() : 'unknown',
|
|
metadata: !!this.options.metadata ? this.options.metadata : '',
|
|
secret: this.openvidu.getSecret(),
|
|
recorder: this.openvidu.getRecorder()
|
|
};
|
|
return joinParams;
|
|
};
|
|
Session.prototype.sendVideoData = function (streamManager, intervalSeconds, doInterval, maxLoops) {
|
|
var _this = this;
|
|
var _a, _b;
|
|
if (intervalSeconds === void 0) { intervalSeconds = 1; }
|
|
if (doInterval === void 0) { doInterval = false; }
|
|
if (maxLoops === void 0) { maxLoops = 1; }
|
|
if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() ||
|
|
platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() || platform.isElectron() ||
|
|
(platform.isSafariBrowser() && !platform.isIonicIos()) || platform.isAndroidBrowser() ||
|
|
platform.isSamsungBrowser() || platform.isIonicAndroid() || platform.isIOSWithSafari()) {
|
|
var obtainAndSendVideo_1 = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
var pc, statsMap, arr_1;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
pc = streamManager.stream.getRTCPeerConnection();
|
|
if (!(pc.connectionState === 'connected')) return [3, 2];
|
|
return [4, pc.getStats()];
|
|
case 1:
|
|
statsMap = _a.sent();
|
|
arr_1 = [];
|
|
statsMap.forEach(function (stats) {
|
|
if (("frameWidth" in stats) && ("frameHeight" in stats) && (arr_1.length === 0)) {
|
|
arr_1.push(stats);
|
|
}
|
|
});
|
|
if (arr_1.length > 0) {
|
|
this.openvidu.sendRequest('videoData', {
|
|
height: arr_1[0].frameHeight,
|
|
width: arr_1[0].frameWidth,
|
|
videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false,
|
|
audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false
|
|
}, function (error, response) {
|
|
if (error) {
|
|
logger.error("Error sending 'videoData' event", error);
|
|
}
|
|
});
|
|
}
|
|
_a.label = 2;
|
|
case 2: return [2];
|
|
}
|
|
});
|
|
}); };
|
|
if (doInterval) {
|
|
var loops_1 = 1;
|
|
this.videoDataInterval = setInterval(function () {
|
|
if (loops_1 < maxLoops) {
|
|
loops_1++;
|
|
obtainAndSendVideo_1();
|
|
}
|
|
else {
|
|
clearInterval(_this.videoDataInterval);
|
|
}
|
|
}, intervalSeconds * 1000);
|
|
}
|
|
else {
|
|
this.videoDataTimeout = setTimeout(obtainAndSendVideo_1, intervalSeconds * 1000);
|
|
}
|
|
}
|
|
else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isIonicIos() || platform.isReactNative()) {
|
|
this.openvidu.sendRequest('videoData', {
|
|
height: ((_a = streamManager.stream.videoDimensions) === null || _a === void 0 ? void 0 : _a.height) || 0,
|
|
width: ((_b = streamManager.stream.videoDimensions) === null || _b === void 0 ? void 0 : _b.width) || 0,
|
|
videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false,
|
|
audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false
|
|
}, function (error, response) {
|
|
if (error) {
|
|
logger.error("Error sending 'videoData' event", error);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
logger.error('Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu for Network Quality');
|
|
}
|
|
};
|
|
Session.prototype.sessionConnected = function () {
|
|
return this.connection != null;
|
|
};
|
|
Session.prototype.notConnectedError = function () {
|
|
return new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_NOT_CONNECTED, "There is no connection to the session. Method 'Session.connect' must be successfully completed first");
|
|
};
|
|
Session.prototype.anySpeechEventListenerEnabled = function (event, onlyOnce, streamManager) {
|
|
var handlersInSession = this.ee.getListeners(event);
|
|
if (onlyOnce) {
|
|
handlersInSession = handlersInSession.filter(function (h) { return h.once; });
|
|
}
|
|
var listenersInSession = handlersInSession.length;
|
|
if (listenersInSession > 0)
|
|
return true;
|
|
var listenersInStreamManager = 0;
|
|
if (!!streamManager) {
|
|
var handlersInStreamManager = streamManager.ee.getListeners(event);
|
|
if (onlyOnce) {
|
|
handlersInStreamManager = handlersInStreamManager.filter(function (h) { return h.once; });
|
|
}
|
|
listenersInStreamManager = handlersInStreamManager.length;
|
|
}
|
|
return listenersInStreamManager > 0;
|
|
};
|
|
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 = _this.initializeParams(token);
|
|
_this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) {
|
|
if (!!error) {
|
|
reject(error);
|
|
}
|
|
else {
|
|
_this.processJoinRoomResponse(response);
|
|
OpenViduLogger_1.OpenViduLogger.configureJSNLog(_this.openvidu, token);
|
|
_this.connection = new Connection_1.Connection(_this, response);
|
|
var events_1 = {
|
|
connections: new Array(),
|
|
streams: new Array()
|
|
};
|
|
var existingParticipants = response.value;
|
|
existingParticipants.forEach(function (remoteConnectionOptions) {
|
|
var connection = new Connection_1.Connection(_this, remoteConnectionOptions);
|
|
_this.remoteConnections.set(connection.connectionId, connection);
|
|
events_1.connections.push(connection);
|
|
if (!!connection.stream) {
|
|
_this.remoteStreamsCreated.set(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.stopVideoDataIntervals = function () {
|
|
clearInterval(this.videoDataInterval);
|
|
clearTimeout(this.videoDataTimeout);
|
|
};
|
|
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.get(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, operation) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var connection = _this.remoteConnections.get(connectionId);
|
|
if (!!connection) {
|
|
resolve(connection);
|
|
}
|
|
else {
|
|
var errorMessage = 'Remote connection ' + connectionId + " unknown when '" + operation + "'. " +
|
|
'Existing remote connections: ' + JSON.stringify(_this.remoteConnections.keys());
|
|
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 webrtcStatsInterval = queryParams['webrtcStatsInterval'];
|
|
var sendBrowserLogs = queryParams['sendBrowserLogs'];
|
|
if (!!secret) {
|
|
this.openvidu.secret = secret;
|
|
}
|
|
if (!!recorder) {
|
|
this.openvidu.recorder = true;
|
|
}
|
|
if (!!webrtcStatsInterval) {
|
|
this.openvidu.webrtcStatsInterval = +webrtcStatsInterval;
|
|
}
|
|
if (!!sendBrowserLogs) {
|
|
this.openvidu.sendBrowserLogs = sendBrowserLogs;
|
|
}
|
|
this.openvidu.isPro = !!webrtcStatsInterval && !!sendBrowserLogs;
|
|
this.openvidu.wsUri = 'wss://' + url.host + '/openvidu';
|
|
this.openvidu.httpUri = 'https://' + url.host;
|
|
}
|
|
else {
|
|
logger.error('Token "' + token + '" is not valid');
|
|
}
|
|
};
|
|
Session.prototype.processJoinRoomResponse = function (opts) {
|
|
this.sessionId = opts.session;
|
|
if (opts.coturnIp != null && opts.turnUsername != null && opts.turnCredential != null) {
|
|
var turnUrl1 = 'turn:' + opts.coturnIp + ':3478';
|
|
this.openvidu.iceServers = [
|
|
{ urls: [turnUrl1], username: opts.turnUsername, credential: opts.turnCredential }
|
|
];
|
|
logger.log("STUN/TURN server IP: " + opts.coturnIp);
|
|
logger.log('TURN temp credentials [' + opts.turnUsername + ':' + opts.turnCredential + ']');
|
|
}
|
|
this.openvidu.role = opts.role;
|
|
this.openvidu.finalUserId = opts.finalUserId;
|
|
this.openvidu.mediaServer = opts.mediaServer;
|
|
this.capabilities = {
|
|
subscribe: true,
|
|
publish: this.openvidu.role !== 'SUBSCRIBER',
|
|
forceUnpublish: this.openvidu.role === 'MODERATOR',
|
|
forceDisconnect: this.openvidu.role === 'MODERATOR'
|
|
};
|
|
logger.info("openvidu-server version: " + opts.version);
|
|
if (opts.version !== this.openvidu.libraryVersion) {
|
|
logger.warn('OpenVidu Server (' + opts.version +
|
|
') and OpenVidu Browser (' + this.openvidu.libraryVersion +
|
|
') versions do NOT match. There may be incompatibilities');
|
|
}
|
|
};
|
|
return Session;
|
|
}(EventDispatcher_1.EventDispatcher));
|
|
exports.Session = Session;
|
|
|
|
},{"../OpenViduInternal/Enums/OpenViduError":40,"../OpenViduInternal/Enums/VideoInsertMode":41,"../OpenViduInternal/Events/ConnectionEvent":42,"../OpenViduInternal/Events/ConnectionPropertyChangedEvent":43,"../OpenViduInternal/Events/FilterEvent":46,"../OpenViduInternal/Events/NetworkQualityLevelChangedEvent":47,"../OpenViduInternal/Events/RecordingEvent":49,"../OpenViduInternal/Events/SessionDisconnectedEvent":50,"../OpenViduInternal/Events/SignalEvent":51,"../OpenViduInternal/Events/StreamEvent":52,"../OpenViduInternal/Events/StreamPropertyChangedEvent":54,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Utils/Platform":70,"./Connection":29,"./EventDispatcher":30,"./Filter":31,"./Subscriber":38}],36:[function(require,module,exports){
|
|
"use strict";
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Stream = void 0;
|
|
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 ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent");
|
|
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 OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var hark = require("hark");
|
|
var EventEmitter = require("wolfy87-eventemitter");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var Stream = (function () {
|
|
function Stream(session, options) {
|
|
var _this = this;
|
|
this.isSubscribeToRemote = false;
|
|
this.isLocalStreamReadyToPublish = false;
|
|
this.isLocalStreamPublished = false;
|
|
this.publishedOnce = false;
|
|
this.harkSpeakingEnabled = false;
|
|
this.harkSpeakingEnabledOnce = false;
|
|
this.harkStoppedSpeakingEnabled = false;
|
|
this.harkStoppedSpeakingEnabledOnce = false;
|
|
this.harkVolumeChangeEnabled = false;
|
|
this.harkVolumeChangeEnabledOnce = false;
|
|
this.ee = new EventEmitter();
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
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);
|
|
logger.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']');
|
|
});
|
|
}
|
|
Stream.prototype.reconnect = function () {
|
|
return this.reconnectStream('API');
|
|
};
|
|
Stream.prototype.applyFilter = function (type, options) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (!_this.session.sessionConnected()) {
|
|
reject(_this.session.notConnectedError());
|
|
}
|
|
logger.info('Applying filter to stream ' + _this.streamId);
|
|
options = options != null ? options : {};
|
|
var optionsString = options;
|
|
if (typeof optionsString !== 'string') {
|
|
optionsString = JSON.stringify(optionsString);
|
|
}
|
|
_this.session.openvidu.sendRequest('applyFilter', { streamId: _this.streamId, type: type, options: optionsString }, function (error, response) {
|
|
if (error) {
|
|
logger.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 {
|
|
logger.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) {
|
|
if (!_this.session.sessionConnected()) {
|
|
reject(_this.session.notConnectedError());
|
|
}
|
|
logger.info('Removing filter of stream ' + _this.streamId);
|
|
_this.session.openvidu.sendRequest('removeFilter', { streamId: _this.streamId }, function (error, response) {
|
|
if (error) {
|
|
logger.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 {
|
|
logger.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.getRTCPeerConnection = function () {
|
|
return this.webRtcPeer.pc;
|
|
};
|
|
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.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(false)
|
|
.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(false)
|
|
.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 () {
|
|
var webrtcId;
|
|
if (!!this.webRtcPeer) {
|
|
this.webRtcPeer.dispose();
|
|
webrtcId = this.webRtcPeer.getId();
|
|
}
|
|
this.stopWebRtcStats();
|
|
logger.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "RTCPeerConnection with id [" + webrtcId + "] 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;
|
|
}
|
|
if (this.localMediaStreamWhenSubscribedToRemote) {
|
|
this.localMediaStreamWhenSubscribedToRemote.getAudioTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
this.localMediaStreamWhenSubscribedToRemote.getVideoTracks().forEach(function (track) {
|
|
track.stop();
|
|
});
|
|
delete this.localMediaStreamWhenSubscribedToRemote;
|
|
}
|
|
if (!!this.speechEvent) {
|
|
if (!!this.speechEvent.stop) {
|
|
this.speechEvent.stop();
|
|
}
|
|
delete this.speechEvent;
|
|
}
|
|
logger.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.isElectron()) {
|
|
screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' &&
|
|
this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:');
|
|
}
|
|
return !!this.outboundStreamOpts && screen;
|
|
};
|
|
Stream.prototype.enableHarkSpeakingEvent = function () {
|
|
var _this = this;
|
|
this.setHarkListenerIfNotExists();
|
|
if (!this.harkSpeakingEnabled) {
|
|
this.harkSpeakingEnabled = true;
|
|
this.speechEvent.on('speaking', function () {
|
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
_this.streamManager.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
_this.harkSpeakingEnabledOnce = false;
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.enableOnceHarkSpeakingEvent = function () {
|
|
var _this = this;
|
|
this.setHarkListenerIfNotExists();
|
|
if (!this.harkSpeakingEnabledOnce) {
|
|
this.harkSpeakingEnabledOnce = true;
|
|
this.speechEvent.once('speaking', function () {
|
|
if (_this.harkSpeakingEnabledOnce) {
|
|
_this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
_this.streamManager.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStartSpeaking', _this.connection, _this.streamId)]);
|
|
}
|
|
_this.disableHarkSpeakingEvent(true);
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.disableHarkSpeakingEvent = function (disabledByOnce) {
|
|
if (!!this.speechEvent) {
|
|
this.harkSpeakingEnabledOnce = false;
|
|
if (disabledByOnce) {
|
|
if (this.harkSpeakingEnabled) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
this.harkSpeakingEnabled = false;
|
|
}
|
|
if (this.harkVolumeChangeEnabled ||
|
|
this.harkVolumeChangeEnabledOnce ||
|
|
this.harkStoppedSpeakingEnabled ||
|
|
this.harkStoppedSpeakingEnabledOnce) {
|
|
this.speechEvent.off('speaking');
|
|
}
|
|
else {
|
|
this.speechEvent.stop();
|
|
delete this.speechEvent;
|
|
}
|
|
}
|
|
};
|
|
Stream.prototype.enableHarkStoppedSpeakingEvent = function () {
|
|
var _this = this;
|
|
this.setHarkListenerIfNotExists();
|
|
if (!this.harkStoppedSpeakingEnabled) {
|
|
this.harkStoppedSpeakingEnabled = true;
|
|
this.speechEvent.on('stopped_speaking', function () {
|
|
_this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
|
_this.streamManager.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
|
_this.harkStoppedSpeakingEnabledOnce = false;
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.enableOnceHarkStoppedSpeakingEvent = function () {
|
|
var _this = this;
|
|
this.setHarkListenerIfNotExists();
|
|
if (!this.harkStoppedSpeakingEnabledOnce) {
|
|
this.harkStoppedSpeakingEnabledOnce = true;
|
|
this.speechEvent.once('stopped_speaking', function () {
|
|
if (_this.harkStoppedSpeakingEnabledOnce) {
|
|
_this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
|
_this.streamManager.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStopSpeaking', _this.connection, _this.streamId)]);
|
|
}
|
|
_this.disableHarkStoppedSpeakingEvent(true);
|
|
});
|
|
}
|
|
};
|
|
Stream.prototype.disableHarkStoppedSpeakingEvent = function (disabledByOnce) {
|
|
if (!!this.speechEvent) {
|
|
this.harkStoppedSpeakingEnabledOnce = false;
|
|
if (disabledByOnce) {
|
|
if (this.harkStoppedSpeakingEnabled) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
this.harkStoppedSpeakingEnabled = false;
|
|
}
|
|
if (this.harkVolumeChangeEnabled ||
|
|
this.harkVolumeChangeEnabledOnce ||
|
|
this.harkSpeakingEnabled ||
|
|
this.harkSpeakingEnabledOnce) {
|
|
this.speechEvent.off('stopped_speaking');
|
|
}
|
|
else {
|
|
this.speechEvent.stop();
|
|
delete this.speechEvent;
|
|
}
|
|
}
|
|
};
|
|
Stream.prototype.enableHarkVolumeChangeEvent = function (force) {
|
|
var _this = this;
|
|
if (this.setHarkListenerIfNotExists()) {
|
|
if (!this.harkVolumeChangeEnabled || force) {
|
|
this.harkVolumeChangeEnabled = 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)]);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
this.harkVolumeChangeEnabled = true;
|
|
}
|
|
};
|
|
Stream.prototype.enableOnceHarkVolumeChangeEvent = function (force) {
|
|
var _this = this;
|
|
if (this.setHarkListenerIfNotExists()) {
|
|
if (!this.harkVolumeChangeEnabledOnce || force) {
|
|
this.harkVolumeChangeEnabledOnce = true;
|
|
this.speechEvent.once('volume_change', function (harkEvent) {
|
|
var oldValue = _this.speechEvent.oldVolumeValue;
|
|
var value = { newValue: harkEvent, oldValue: oldValue };
|
|
_this.speechEvent.oldVolumeValue = harkEvent;
|
|
_this.disableHarkVolumeChangeEvent(true);
|
|
_this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent_1.StreamManagerEvent(_this.streamManager, 'streamAudioVolumeChange', value)]);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
this.harkVolumeChangeEnabledOnce = true;
|
|
}
|
|
};
|
|
Stream.prototype.disableHarkVolumeChangeEvent = function (disabledByOnce) {
|
|
if (!!this.speechEvent) {
|
|
this.harkVolumeChangeEnabledOnce = false;
|
|
if (disabledByOnce) {
|
|
if (this.harkVolumeChangeEnabled) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
this.harkVolumeChangeEnabled = false;
|
|
}
|
|
if (this.harkSpeakingEnabled ||
|
|
this.harkSpeakingEnabledOnce ||
|
|
this.harkStoppedSpeakingEnabled ||
|
|
this.harkStoppedSpeakingEnabledOnce) {
|
|
this.speechEvent.off('volume_change');
|
|
}
|
|
else {
|
|
this.speechEvent.stop();
|
|
delete this.speechEvent;
|
|
}
|
|
}
|
|
};
|
|
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.streamIceConnectionStateBroken = function () {
|
|
if (!this.getWebRtcPeer() || !this.getRTCPeerConnection()) {
|
|
return false;
|
|
}
|
|
if (this.isLocal() && !!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) {
|
|
logger.warn("OpenVidu Browser advanced configuration option \"forceMediaReconnectionAfterNetworkDrop\" is enabled. Stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") will force a reconnection");
|
|
return true;
|
|
}
|
|
var iceConnectionState = this.getRTCPeerConnection().iceConnectionState;
|
|
return iceConnectionState !== 'connected' && iceConnectionState !== 'completed';
|
|
};
|
|
Stream.prototype.setHarkListenerIfNotExists = function () {
|
|
if (!!this.mediaStream) {
|
|
if (!this.speechEvent) {
|
|
var harkOptions = !!this.harkOptions ? this.harkOptions : (this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {});
|
|
harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 100;
|
|
harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
|
|
this.speechEvent = hark(this.mediaStream, harkOptions);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
Stream.prototype.setupReconnectionEventEmitter = function (resolve, reject) {
|
|
if (this.reconnectionEventEmitter == undefined) {
|
|
this.reconnectionEventEmitter = new EventEmitter();
|
|
return false;
|
|
}
|
|
else {
|
|
console.warn("Trying to reconnect stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") but an ongoing reconnection process is active. Waiting for response...");
|
|
this.reconnectionEventEmitter.once('success', function () {
|
|
resolve();
|
|
});
|
|
this.reconnectionEventEmitter.once('error', function (error) {
|
|
reject(error);
|
|
});
|
|
return true;
|
|
}
|
|
};
|
|
Stream.prototype.initWebRtcPeerSend = function (reconnect) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (reconnect) {
|
|
if (_this.setupReconnectionEventEmitter(resolve, reject)) {
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
_this.initHarkEvents();
|
|
}
|
|
var finalResolve = function () {
|
|
var _a;
|
|
if (reconnect) {
|
|
(_a = _this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('success');
|
|
delete _this.reconnectionEventEmitter;
|
|
}
|
|
resolve();
|
|
};
|
|
var finalReject = function (error) {
|
|
var _a;
|
|
if (reconnect) {
|
|
(_a = _this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('error', [error]);
|
|
delete _this.reconnectionEventEmitter;
|
|
}
|
|
reject(error);
|
|
};
|
|
var successOfferCallback = function (sdpOfferParam) {
|
|
logger.debug('Sending SDP offer to publish as '
|
|
+ _this.streamId, sdpOfferParam);
|
|
var method = reconnect ? 'reconnectStream' : 'publishVideo';
|
|
var params;
|
|
if (reconnect) {
|
|
params = {
|
|
stream: _this.streamId,
|
|
sdpString: sdpOfferParam
|
|
};
|
|
}
|
|
else {
|
|
var typeOfVideo = '';
|
|
if (_this.isSendVideo()) {
|
|
typeOfVideo = (typeof MediaStreamTrack !== 'undefined' && _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) ? 'CUSTOM' : (_this.isSendScreen() ? 'SCREEN' : 'CAMERA');
|
|
}
|
|
params = {
|
|
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,
|
|
sdpOffer: sdpOfferParam
|
|
};
|
|
}
|
|
_this.session.openvidu.sendRequest(method, params, function (error, response) {
|
|
if (error) {
|
|
if (error.code === 401) {
|
|
finalReject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish"));
|
|
}
|
|
else {
|
|
finalReject('Error on publishVideo: ' + JSON.stringify(error));
|
|
}
|
|
}
|
|
else {
|
|
_this.webRtcPeer.processRemoteAnswer(response.sdpAnswer)
|
|
.then(function () {
|
|
_this.streamId = response.id;
|
|
_this.creationTime = response.createdAt;
|
|
_this.isLocalStreamPublished = true;
|
|
_this.publishedOnce = true;
|
|
if (_this.displayMyRemote()) {
|
|
_this.localMediaStreamWhenSubscribedToRemote = _this.mediaStream;
|
|
_this.remotePeerSuccessfullyEstablished(reconnect);
|
|
}
|
|
if (reconnect) {
|
|
_this.ee.emitEvent('stream-reconnected-by-publisher', []);
|
|
}
|
|
else {
|
|
_this.ee.emitEvent('stream-created-by-publisher', []);
|
|
}
|
|
_this.initWebRtcStats();
|
|
logger.info("'Publisher' (" + _this.streamId + ") successfully " + (reconnect ? "reconnected" : "published") + " to session");
|
|
finalResolve();
|
|
})
|
|
.catch(function (error) {
|
|
finalReject(error);
|
|
});
|
|
}
|
|
});
|
|
};
|
|
var config = {
|
|
mediaConstraints: {
|
|
audio: _this.hasAudio,
|
|
video: _this.hasVideo,
|
|
},
|
|
simulcast: _this.session.openvidu.advancedConfiguration.enableSimulcastExperimental || false,
|
|
onIceCandidate: _this.connection.sendIceCandidate.bind(_this.connection),
|
|
onIceConnectionStateException: function (exceptionName, message, data) { _this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, exceptionName, _this, message, data)]); },
|
|
iceServers: _this.getIceServersConf(),
|
|
mediaStream: _this.mediaStream,
|
|
mediaServer: _this.session.openvidu.mediaServer
|
|
};
|
|
if (reconnect) {
|
|
_this.disposeWebRtcPeer();
|
|
}
|
|
if (_this.displayMyRemote()) {
|
|
_this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(config);
|
|
}
|
|
else {
|
|
_this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(config);
|
|
}
|
|
_this.webRtcPeer.addIceConnectionStateChangeListener('publisher of ' + _this.connection.connectionId);
|
|
_this.webRtcPeer.createOffer().then(function (sdpOffer) {
|
|
_this.webRtcPeer.processLocalOffer(sdpOffer)
|
|
.then(function () {
|
|
successOfferCallback(sdpOffer.sdp);
|
|
}).catch(function (error) {
|
|
finalReject(new Error('(publish) SDP process local offer error: ' + JSON.stringify(error)));
|
|
});
|
|
}).catch(function (error) {
|
|
finalReject(new Error('(publish) SDP create offer error: ' + JSON.stringify(error)));
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.finalResolveForSubscription = function (reconnect, resolve) {
|
|
var _a;
|
|
logger.info("'Subscriber' (" + this.streamId + ") successfully " + (reconnect ? "reconnected" : "subscribed"));
|
|
this.remotePeerSuccessfullyEstablished(reconnect);
|
|
this.initWebRtcStats();
|
|
if (reconnect) {
|
|
(_a = this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('success');
|
|
delete this.reconnectionEventEmitter;
|
|
}
|
|
resolve();
|
|
};
|
|
Stream.prototype.finalRejectForSubscription = function (reconnect, error, reject) {
|
|
var _a;
|
|
logger.error("Error for 'Subscriber' (" + this.streamId + ") while trying to " + (reconnect ? "reconnect" : "subscribe") + ": " + error.toString());
|
|
if (reconnect) {
|
|
(_a = this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('error', [error]);
|
|
delete this.reconnectionEventEmitter;
|
|
}
|
|
reject(error);
|
|
};
|
|
Stream.prototype.initWebRtcPeerReceive = function (reconnect) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if (reconnect) {
|
|
if (_this.setupReconnectionEventEmitter(resolve, reject)) {
|
|
return;
|
|
}
|
|
}
|
|
if (_this.session.openvidu.mediaServer === 'mediasoup') {
|
|
_this.initWebRtcPeerReceiveFromServer(reconnect)
|
|
.then(function () { return _this.finalResolveForSubscription(reconnect, resolve); })
|
|
.catch(function (error) { return _this.finalRejectForSubscription(reconnect, error, reject); });
|
|
}
|
|
else {
|
|
_this.initWebRtcPeerReceiveFromClient(reconnect)
|
|
.then(function () { return _this.finalResolveForSubscription(reconnect, resolve); })
|
|
.catch(function (error) { return _this.finalRejectForSubscription(reconnect, error, reject); });
|
|
}
|
|
});
|
|
};
|
|
Stream.prototype.initWebRtcPeerReceiveFromClient = function (reconnect) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
_this.completeWebRtcPeerReceive(reconnect, false).then(function (response) {
|
|
_this.webRtcPeer.processRemoteAnswer(response.sdpAnswer)
|
|
.then(function () { return resolve(); }).catch(function (error) { return reject(error); });
|
|
}).catch(function (error) { return reject(error); });
|
|
});
|
|
};
|
|
Stream.prototype.initWebRtcPeerReceiveFromServer = function (reconnect) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
_this.session.openvidu.sendRequest('prepareReceiveVideoFrom', { sender: _this.streamId, reconnect: reconnect }, function (error, response) {
|
|
if (error) {
|
|
reject(new Error('Error on prepareReceiveVideoFrom: ' + JSON.stringify(error)));
|
|
}
|
|
else {
|
|
_this.completeWebRtcPeerReceive(reconnect, false, response.sdpOffer)
|
|
.then(function () { return resolve(); }).catch(function (error) { return reject(error); });
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.completeWebRtcPeerReceive = function (reconnect, forciblyReconnect, sdpOfferByServer) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
logger.debug("'Session.subscribe(Stream)' called");
|
|
var sendSdpToServer = function (sdpString) {
|
|
logger.debug("Sending local SDP " + (!!sdpOfferByServer ? 'answer' : 'offer') + " to subscribe to " + _this.streamId, sdpString);
|
|
var method = reconnect ? 'reconnectStream' : 'receiveVideoFrom';
|
|
var params = {};
|
|
params[reconnect ? 'stream' : 'sender'] = _this.streamId;
|
|
if (!!sdpOfferByServer) {
|
|
params[reconnect ? 'sdpString' : 'sdpAnswer'] = sdpString;
|
|
}
|
|
else {
|
|
params['sdpOffer'] = sdpString;
|
|
}
|
|
if (reconnect) {
|
|
params['forciblyReconnect'] = forciblyReconnect;
|
|
}
|
|
_this.session.openvidu.sendRequest(method, params, function (error, response) {
|
|
if (error) {
|
|
reject(new Error('Error on ' + method + ' : ' + JSON.stringify(error)));
|
|
}
|
|
else {
|
|
resolve(response);
|
|
}
|
|
});
|
|
};
|
|
var config = {
|
|
mediaConstraints: {
|
|
audio: _this.hasAudio,
|
|
video: _this.hasVideo,
|
|
},
|
|
simulcast: false,
|
|
onIceCandidate: _this.connection.sendIceCandidate.bind(_this.connection),
|
|
onIceConnectionStateException: function (exceptionName, message, data) { _this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, exceptionName, _this, message, data)]); },
|
|
iceServers: _this.getIceServersConf(),
|
|
mediaServer: _this.session.openvidu.mediaServer
|
|
};
|
|
if (reconnect) {
|
|
_this.disposeWebRtcPeer();
|
|
}
|
|
_this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(config);
|
|
_this.webRtcPeer.addIceConnectionStateChangeListener(_this.streamId);
|
|
if (!!sdpOfferByServer) {
|
|
_this.webRtcPeer.processRemoteOffer(sdpOfferByServer).then(function () {
|
|
_this.webRtcPeer.createAnswer().then(function (sdpAnswer) {
|
|
_this.webRtcPeer.processLocalAnswer(sdpAnswer).then(function () {
|
|
sendSdpToServer(sdpAnswer.sdp);
|
|
}).catch(function (error) {
|
|
reject(new Error('(subscribe) SDP process local answer error: ' + JSON.stringify(error)));
|
|
});
|
|
}).catch(function (error) {
|
|
reject(new Error('(subscribe) SDP create answer error: ' + JSON.stringify(error)));
|
|
});
|
|
}).catch(function (error) {
|
|
reject(new Error('(subscribe) SDP process remote offer error: ' + JSON.stringify(error)));
|
|
});
|
|
}
|
|
else {
|
|
_this.webRtcPeer.createOffer().then(function (sdpOffer) {
|
|
_this.webRtcPeer.processLocalOffer(sdpOffer).then(function () {
|
|
sendSdpToServer(sdpOffer.sdp);
|
|
}).catch(function (error) {
|
|
reject(new Error('(subscribe) SDP process local offer error: ' + JSON.stringify(error)));
|
|
});
|
|
}).catch(function (error) {
|
|
reject(new Error('(subscribe) SDP create offer error: ' + JSON.stringify(error)));
|
|
});
|
|
}
|
|
});
|
|
};
|
|
Stream.prototype.remotePeerSuccessfullyEstablished = function (reconnect) {
|
|
if (reconnect && this.mediaStream != null) {
|
|
this.disposeMediaStream();
|
|
}
|
|
this.mediaStream = new MediaStream();
|
|
var receiver;
|
|
for (var _i = 0, _a = this.webRtcPeer.pc.getReceivers(); _i < _a.length; _i++) {
|
|
receiver = _a[_i];
|
|
if (!!receiver.track) {
|
|
this.mediaStream.addTrack(receiver.track);
|
|
}
|
|
}
|
|
logger.debug('Peer remote stream', this.mediaStream);
|
|
if (!!this.mediaStream) {
|
|
if (this.streamManager instanceof Subscriber_1.Subscriber) {
|
|
if (!!this.mediaStream.getAudioTracks()[0]) {
|
|
var enabled = reconnect ? this.audioActive : !!(this.streamManager.properties.subscribeToAudio);
|
|
this.mediaStream.getAudioTracks()[0].enabled = enabled;
|
|
}
|
|
if (!!this.mediaStream.getVideoTracks()[0]) {
|
|
var enabled = reconnect ? this.videoActive : !!(this.streamManager.properties.subscribeToVideo);
|
|
this.mediaStream.getVideoTracks()[0].enabled = enabled;
|
|
}
|
|
}
|
|
this.updateMediaStreamInVideos();
|
|
this.initHarkEvents();
|
|
}
|
|
};
|
|
Stream.prototype.initHarkEvents = function () {
|
|
if (!!this.mediaStream.getAudioTracks()[0]) {
|
|
if (this.session.anySpeechEventListenerEnabled('publisherStartSpeaking', true, this.streamManager)) {
|
|
this.enableOnceHarkSpeakingEvent();
|
|
}
|
|
if (this.session.anySpeechEventListenerEnabled('publisherStartSpeaking', false, this.streamManager)) {
|
|
this.enableHarkSpeakingEvent();
|
|
}
|
|
if (this.session.anySpeechEventListenerEnabled('publisherStopSpeaking', true, this.streamManager)) {
|
|
this.enableOnceHarkStoppedSpeakingEvent();
|
|
}
|
|
if (this.session.anySpeechEventListenerEnabled('publisherStopSpeaking', false, this.streamManager)) {
|
|
this.enableHarkStoppedSpeakingEvent();
|
|
}
|
|
if (this.harkVolumeChangeEnabledOnce) {
|
|
this.enableOnceHarkVolumeChangeEvent(true);
|
|
}
|
|
if (this.harkVolumeChangeEnabled) {
|
|
this.enableHarkVolumeChangeEvent(true);
|
|
}
|
|
}
|
|
};
|
|
Stream.prototype.onIceConnectionStateExceptionHandler = function (exceptionName, message, data) {
|
|
switch (exceptionName) {
|
|
case ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED:
|
|
this.onIceConnectionFailed();
|
|
break;
|
|
case ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED:
|
|
this.onIceConnectionDisconnected();
|
|
break;
|
|
}
|
|
this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(this.session, exceptionName, this, message, data)]);
|
|
};
|
|
Stream.prototype.onIceConnectionFailed = function () {
|
|
logger.log("[ICE_CONNECTION_FAILED] Handling ICE_CONNECTION_FAILED event. Reconnecting stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ")");
|
|
this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED);
|
|
};
|
|
Stream.prototype.onIceConnectionDisconnected = function () {
|
|
var _this = this;
|
|
logger.log("[ICE_CONNECTION_DISCONNECTED] Handling ICE_CONNECTION_DISCONNECTED event. Waiting for ICE to be restored and reconnect stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") if not possible");
|
|
var timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000;
|
|
this.awaitWebRtcPeerConnectionState(timeout).then(function (state) {
|
|
switch (state) {
|
|
case 'failed':
|
|
logger.warn("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream " + _this.streamId + " (" + (_this.isLocal() ? 'Publisher' : 'Subscriber') + ") is now failed after ICE_CONNECTION_DISCONNECTED");
|
|
break;
|
|
case 'connected':
|
|
case 'completed':
|
|
logger.log("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream " + _this.streamId + " (" + (_this.isLocal() ? 'Publisher' : 'Subscriber') + ") automatically restored after ICE_CONNECTION_DISCONNECTED. Current ICE connection state: " + state);
|
|
break;
|
|
case 'closed':
|
|
case 'checking':
|
|
case 'new':
|
|
case 'disconnected':
|
|
logger.warn("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream " + _this.streamId + " (" + (_this.isLocal() ? 'Publisher' : 'Subscriber') + ") couldn't be restored after ICE_CONNECTION_DISCONNECTED event. Current ICE connection state after " + timeout + " ms: " + state);
|
|
_this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED);
|
|
break;
|
|
}
|
|
});
|
|
};
|
|
Stream.prototype.reconnectStreamAndLogResultingIceConnectionState = function (event) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var finalIceStateAfterReconnection, error_1;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
_a.trys.push([0, 2, , 3]);
|
|
return [4, this.reconnectStreamAndReturnIceConnectionState(event)];
|
|
case 1:
|
|
finalIceStateAfterReconnection = _a.sent();
|
|
switch (finalIceStateAfterReconnection) {
|
|
case 'connected':
|
|
case 'completed':
|
|
logger.log("[" + event + "] Stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") successfully reconnected after " + event + ". Current ICE connection state: " + finalIceStateAfterReconnection);
|
|
break;
|
|
default:
|
|
logger.error("[" + event + "] Stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") failed to reconnect after " + event + ". Current ICE connection state: " + finalIceStateAfterReconnection);
|
|
break;
|
|
}
|
|
return [3, 3];
|
|
case 2:
|
|
error_1 = _a.sent();
|
|
logger.error("[" + event + "] Error reconnecting stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") after " + event + ": " + error_1);
|
|
return [3, 3];
|
|
case 3: return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.reconnectStreamAndReturnIceConnectionState = function (event) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var timeout, error_2;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
logger.log("[" + event + "] Reconnecting stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") after event " + event);
|
|
_a.label = 1;
|
|
case 1:
|
|
_a.trys.push([1, 3, , 4]);
|
|
return [4, this.reconnectStream(event)];
|
|
case 2:
|
|
_a.sent();
|
|
timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000;
|
|
return [2, this.awaitWebRtcPeerConnectionState(timeout)];
|
|
case 3:
|
|
error_2 = _a.sent();
|
|
logger.warn("[" + event + "] Error reconnecting stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + "). Reason: " + error_2);
|
|
return [2, this.awaitWebRtcPeerConnectionState(1)];
|
|
case 4: return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.reconnectStream = function (event) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var isWsConnected, errorMsg;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0: return [4, this.isWebsocketConnected(event, 3000)];
|
|
case 1:
|
|
isWsConnected = _a.sent();
|
|
if (isWsConnected) {
|
|
logger.log("[" + event + "] Trying to reconnect stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") and the websocket is opened");
|
|
if (this.isLocal()) {
|
|
return [2, this.initWebRtcPeerSend(true)];
|
|
}
|
|
else {
|
|
return [2, this.initWebRtcPeerReceive(true)];
|
|
}
|
|
}
|
|
else {
|
|
errorMsg = "[" + event + "] Trying to reconnect stream " + this.streamId + " (" + (this.isLocal() ? 'Publisher' : 'Subscriber') + ") but the websocket wasn't opened";
|
|
logger.error(errorMsg);
|
|
throw Error(errorMsg);
|
|
}
|
|
return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
Stream.prototype.isWebsocketConnected = function (event, msResponseTimeout) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var wsReadyState = _this.session.openvidu.getWsReadyState();
|
|
if (wsReadyState === 1) {
|
|
var responseTimeout_1 = setTimeout(function () {
|
|
console.warn("[" + event + "] Websocket timeout of " + msResponseTimeout + "ms");
|
|
resolve(false);
|
|
}, msResponseTimeout);
|
|
_this.session.openvidu.sendRequest('echo', {}, function (error, response) {
|
|
clearTimeout(responseTimeout_1);
|
|
if (!!error) {
|
|
console.warn("[" + event + "] Websocket 'echo' returned error: " + error);
|
|
resolve(false);
|
|
}
|
|
else {
|
|
resolve(true);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
console.warn("[" + event + "] Websocket readyState is " + wsReadyState);
|
|
resolve(false);
|
|
}
|
|
});
|
|
};
|
|
Stream.prototype.awaitWebRtcPeerConnectionState = function (timeout) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var state, interval, intervals, i;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
state = this.getRTCPeerConnection().iceConnectionState;
|
|
interval = 150;
|
|
intervals = Math.ceil(timeout / interval);
|
|
i = 0;
|
|
_a.label = 1;
|
|
case 1:
|
|
if (!(i < intervals)) return [3, 4];
|
|
state = this.getRTCPeerConnection().iceConnectionState;
|
|
if (state === 'connected' || state === 'completed') {
|
|
return [3, 4];
|
|
}
|
|
return [4, new Promise(function (resolve) { return setTimeout(resolve, interval); })];
|
|
case 2:
|
|
_a.sent();
|
|
_a.label = 3;
|
|
case 3:
|
|
i++;
|
|
return [3, 1];
|
|
case 4: return [2, state];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
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') {
|
|
}
|
|
logger.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') {
|
|
}
|
|
logger.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":40,"../OpenViduInternal/Events/ExceptionEvent":45,"../OpenViduInternal/Events/PublisherSpeakingEvent":48,"../OpenViduInternal/Events/StreamManagerEvent":53,"../OpenViduInternal/Events/StreamPropertyChangedEvent":54,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Utils/Platform":70,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":71,"../OpenViduInternal/WebRtcStats/WebRtcStats":72,"./Filter":31,"./Subscriber":38,"hark":5,"wolfy87-eventemitter":26}],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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.StreamManager = void 0;
|
|
var EventDispatcher_1 = require("./EventDispatcher");
|
|
var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent");
|
|
var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent");
|
|
var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var Platform_1 = require("../OpenViduInternal/Utils/Platform");
|
|
var ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var StreamManager = (function (_super) {
|
|
__extends(StreamManager, _super);
|
|
function StreamManager(stream, targetElement) {
|
|
var _this = _super.call(this) || this;
|
|
_this.videos = [];
|
|
_this.lazyLaunchVideoElementCreatedEvent = false;
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
_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.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) {
|
|
_this.firstVideoElement.video.setAttribute('playsinline', 'true');
|
|
}
|
|
_this.targetElement = targEl;
|
|
_this.element = targEl;
|
|
}
|
|
}
|
|
_this.canPlayListener = function () {
|
|
_this.deactivateStreamPlayingEventExceptionTimeout();
|
|
if (_this.remote) {
|
|
logger.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')]);
|
|
}
|
|
else {
|
|
if (!_this.stream.displayMyRemote()) {
|
|
logger.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 {
|
|
logger.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')]);
|
|
}
|
|
}
|
|
_this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this, 'streamPlaying', undefined)]);
|
|
};
|
|
return _this;
|
|
}
|
|
StreamManager.prototype.on = function (type, handler) {
|
|
_super.prototype.onAux.call(this, type, "Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler);
|
|
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 (this.stream.hasAudio) {
|
|
if (type === 'publisherStartSpeaking') {
|
|
this.stream.enableHarkSpeakingEvent();
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
this.stream.enableHarkStoppedSpeakingEvent();
|
|
}
|
|
if (type === 'streamAudioVolumeChange') {
|
|
this.stream.enableHarkVolumeChangeEvent(false);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
StreamManager.prototype.once = function (type, handler) {
|
|
_super.prototype.onceAux.call(this, type, "Event '" + type + "' triggered once by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler);
|
|
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 (this.stream.hasAudio) {
|
|
if (type === 'publisherStartSpeaking') {
|
|
this.stream.enableOnceHarkSpeakingEvent();
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
this.stream.enableOnceHarkStoppedSpeakingEvent();
|
|
}
|
|
if (type === 'streamAudioVolumeChange') {
|
|
this.stream.enableOnceHarkVolumeChangeEvent(false);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
StreamManager.prototype.off = function (type, handler) {
|
|
_super.prototype.off.call(this, type, handler);
|
|
if (type === 'publisherStartSpeaking') {
|
|
var remainingStartSpeakingEventListeners = this.ee.getListeners(type).length + this.stream.session.ee.getListeners(type).length;
|
|
if (remainingStartSpeakingEventListeners === 0) {
|
|
this.stream.disableHarkSpeakingEvent(false);
|
|
}
|
|
}
|
|
if (type === 'publisherStopSpeaking') {
|
|
var remainingStopSpeakingEventListeners = this.ee.getListeners(type).length + this.stream.session.ee.getListeners(type).length;
|
|
if (remainingStopSpeakingEventListeners === 0) {
|
|
this.stream.disableHarkStoppedSpeakingEvent(false);
|
|
}
|
|
}
|
|
if (type === 'streamAudioVolumeChange') {
|
|
var remainingVolumeEventListeners = this.ee.getListeners(type).length;
|
|
if (remainingVolumeEventListeners === 0) {
|
|
this.stream.disableHarkVolumeChangeEvent(false);
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
StreamManager.prototype.addVideoElement = function (video) {
|
|
this.initializeVideoProperties(video);
|
|
if (!this.remote && 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
|
|
});
|
|
logger.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 = this.createVideo();
|
|
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.updatePublisherSpeakingEventsOptions = function (publisherSpeakingEventsOptions) {
|
|
var currentHarkOptions = !!this.stream.harkOptions ? this.stream.harkOptions : (this.stream.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {});
|
|
var newInterval = (typeof publisherSpeakingEventsOptions.interval === 'number') ?
|
|
publisherSpeakingEventsOptions.interval : ((typeof currentHarkOptions.interval === 'number') ? currentHarkOptions.interval : 100);
|
|
var newThreshold = (typeof publisherSpeakingEventsOptions.threshold === 'number') ?
|
|
publisherSpeakingEventsOptions.threshold : ((typeof currentHarkOptions.threshold === 'number') ? currentHarkOptions.threshold : -50);
|
|
this.stream.harkOptions = {
|
|
interval: newInterval,
|
|
threshold: newThreshold
|
|
};
|
|
if (!!this.stream.speechEvent) {
|
|
this.stream.speechEvent.setInterval(newInterval);
|
|
this.stream.speechEvent.setThreshold(newThreshold);
|
|
}
|
|
};
|
|
StreamManager.prototype.initializeVideoProperties = function (video) {
|
|
if (!(!this.remote && this.stream.displayMyRemote())) {
|
|
if (video.srcObject !== this.stream.getMediaStream()) {
|
|
video.srcObject = this.stream.getMediaStream();
|
|
}
|
|
}
|
|
video.autoplay = true;
|
|
video.controls = false;
|
|
if (platform.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) {
|
|
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) {
|
|
if (!!streamManagerVideo.video && !!streamManagerVideo.video.removeEventListener) {
|
|
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')]);
|
|
}
|
|
_this.removeSrcObject(streamManagerVideo);
|
|
_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;
|
|
logger.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.activateStreamPlayingEventExceptionTimeout();
|
|
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.createVideo = function () {
|
|
return document.createElement('video');
|
|
};
|
|
StreamManager.prototype.removeSrcObject = function (streamManagerVideo) {
|
|
streamManagerVideo.video.srcObject = null;
|
|
this.deactivateStreamPlayingEventExceptionTimeout();
|
|
};
|
|
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';
|
|
};
|
|
StreamManager.prototype.activateStreamPlayingEventExceptionTimeout = function () {
|
|
var _this = this;
|
|
if (!this.remote) {
|
|
return;
|
|
}
|
|
if (this.streamPlayingEventExceptionTimeout != null) {
|
|
return;
|
|
}
|
|
var msTimeout = this.stream.session.openvidu.advancedConfiguration.noStreamPlayingEventExceptionTimeout || 4000;
|
|
this.streamPlayingEventExceptionTimeout = setTimeout(function () {
|
|
var msg = 'StreamManager of Stream ' + _this.stream.streamId + ' (' + (_this.remote ? 'Subscriber' : 'Publisher') + ') did not trigger "streamPlaying" event in ' + msTimeout + ' ms';
|
|
logger.warn(msg);
|
|
_this.stream.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.stream.session, ExceptionEvent_1.ExceptionEventName.NO_STREAM_PLAYING_EVENT, _this, msg)]);
|
|
delete _this.streamPlayingEventExceptionTimeout;
|
|
}, msTimeout);
|
|
};
|
|
StreamManager.prototype.deactivateStreamPlayingEventExceptionTimeout = function () {
|
|
clearTimeout(this.streamPlayingEventExceptionTimeout);
|
|
delete this.streamPlayingEventExceptionTimeout;
|
|
};
|
|
return StreamManager;
|
|
}(EventDispatcher_1.EventDispatcher));
|
|
exports.StreamManager = StreamManager;
|
|
|
|
},{"../OpenViduInternal/Enums/VideoInsertMode":41,"../OpenViduInternal/Events/ExceptionEvent":45,"../OpenViduInternal/Events/StreamManagerEvent":53,"../OpenViduInternal/Events/VideoElementEvent":55,"../OpenViduInternal/Logger/OpenViduLogger":66,"../OpenViduInternal/Utils/Platform":70,"./EventDispatcher":30}],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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.Subscriber = void 0;
|
|
var StreamManager_1 = require("./StreamManager");
|
|
var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
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;
|
|
});
|
|
this.stream.audioActive = value;
|
|
logger.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;
|
|
});
|
|
this.stream.videoActive = value;
|
|
logger.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream');
|
|
return this;
|
|
};
|
|
return Subscriber;
|
|
}(StreamManager_1.StreamManager));
|
|
exports.Subscriber = Subscriber;
|
|
|
|
},{"../OpenViduInternal/Logger/OpenViduLogger":66,"./StreamManager":37}],39:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.LocalRecorderState = void 0;
|
|
var LocalRecorderState;
|
|
(function (LocalRecorderState) {
|
|
LocalRecorderState["READY"] = "READY";
|
|
LocalRecorderState["RECORDING"] = "RECORDING";
|
|
LocalRecorderState["PAUSED"] = "PAUSED";
|
|
LocalRecorderState["FINISHED"] = "FINISHED";
|
|
})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {}));
|
|
|
|
},{}],40:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OpenViduError = exports.OpenViduErrorName = void 0;
|
|
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["INPUT_AUDIO_DEVICE_GENERIC_ERROR"] = "INPUT_AUDIO_DEVICE_GENERIC_ERROR";
|
|
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;
|
|
|
|
},{}],41:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.VideoInsertMode = void 0;
|
|
var VideoInsertMode;
|
|
(function (VideoInsertMode) {
|
|
VideoInsertMode["AFTER"] = "AFTER";
|
|
VideoInsertMode["APPEND"] = "APPEND";
|
|
VideoInsertMode["BEFORE"] = "BEFORE";
|
|
VideoInsertMode["PREPEND"] = "PREPEND";
|
|
VideoInsertMode["REPLACE"] = "REPLACE";
|
|
})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {}));
|
|
|
|
},{}],42:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.ConnectionEvent = void 0;
|
|
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":44}],43:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.ConnectionPropertyChangedEvent = void 0;
|
|
var Event_1 = require("./Event");
|
|
var ConnectionPropertyChangedEvent = (function (_super) {
|
|
__extends(ConnectionPropertyChangedEvent, _super);
|
|
function ConnectionPropertyChangedEvent(target, connection, changedProperty, newValue, oldValue) {
|
|
var _this = _super.call(this, false, target, 'connectionPropertyChanged') || this;
|
|
_this.connection = connection;
|
|
_this.changedProperty = changedProperty;
|
|
_this.newValue = newValue;
|
|
_this.oldValue = oldValue;
|
|
return _this;
|
|
}
|
|
ConnectionPropertyChangedEvent.prototype.callDefaultBehavior = function () { };
|
|
return ConnectionPropertyChangedEvent;
|
|
}(Event_1.Event));
|
|
exports.ConnectionPropertyChangedEvent = ConnectionPropertyChangedEvent;
|
|
|
|
},{"./Event":44}],44:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Event = void 0;
|
|
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;
|
|
|
|
},{}],45:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.ExceptionEvent = exports.ExceptionEventName = void 0;
|
|
var Event_1 = require("./Event");
|
|
var ExceptionEventName;
|
|
(function (ExceptionEventName) {
|
|
ExceptionEventName["ICE_CANDIDATE_ERROR"] = "ICE_CANDIDATE_ERROR";
|
|
ExceptionEventName["ICE_CONNECTION_FAILED"] = "ICE_CONNECTION_FAILED";
|
|
ExceptionEventName["ICE_CONNECTION_DISCONNECTED"] = "ICE_CONNECTION_DISCONNECTED";
|
|
ExceptionEventName["NO_STREAM_PLAYING_EVENT"] = "NO_STREAM_PLAYING_EVENT";
|
|
})(ExceptionEventName = exports.ExceptionEventName || (exports.ExceptionEventName = {}));
|
|
var ExceptionEvent = (function (_super) {
|
|
__extends(ExceptionEvent, _super);
|
|
function ExceptionEvent(session, name, origin, message, data) {
|
|
var _this = _super.call(this, false, session, 'exception') || this;
|
|
_this.name = name;
|
|
_this.origin = origin;
|
|
_this.message = message;
|
|
_this.data = data;
|
|
return _this;
|
|
}
|
|
ExceptionEvent.prototype.callDefaultBehavior = function () { };
|
|
return ExceptionEvent;
|
|
}(Event_1.Event));
|
|
exports.ExceptionEvent = ExceptionEvent;
|
|
|
|
},{"./Event":44}],46:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.FilterEvent = void 0;
|
|
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":44}],47:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.NetworkQualityLevelChangedEvent = void 0;
|
|
var Event_1 = require("./Event");
|
|
var NetworkQualityLevelChangedEvent = (function (_super) {
|
|
__extends(NetworkQualityLevelChangedEvent, _super);
|
|
function NetworkQualityLevelChangedEvent(target, newValue, oldValue, connection) {
|
|
var _this = _super.call(this, false, target, 'networkQualityLevelChanged') || this;
|
|
_this.newValue = newValue;
|
|
_this.oldValue = oldValue;
|
|
_this.connection = connection;
|
|
return _this;
|
|
}
|
|
NetworkQualityLevelChangedEvent.prototype.callDefaultBehavior = function () { };
|
|
return NetworkQualityLevelChangedEvent;
|
|
}(Event_1.Event));
|
|
exports.NetworkQualityLevelChangedEvent = NetworkQualityLevelChangedEvent;
|
|
|
|
},{"./Event":44}],48:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.PublisherSpeakingEvent = void 0;
|
|
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":44}],49:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.RecordingEvent = void 0;
|
|
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":44}],50:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.SessionDisconnectedEvent = void 0;
|
|
var Event_1 = require("./Event");
|
|
var OpenViduLogger_1 = require("../Logger/OpenViduLogger");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
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 () {
|
|
logger.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
|
|
var session = this.target;
|
|
session.remoteConnections.forEach(function (remoteConnection) {
|
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
var connectionId = remoteConnection.connectionId;
|
|
if (!!((_a = session.remoteConnections.get(connectionId)) === null || _a === void 0 ? void 0 : _a.stream)) {
|
|
(_b = session.remoteConnections.get(connectionId)) === null || _b === void 0 ? void 0 : _b.stream.disposeWebRtcPeer();
|
|
(_c = session.remoteConnections.get(connectionId)) === null || _c === void 0 ? void 0 : _c.stream.disposeMediaStream();
|
|
if ((_d = session.remoteConnections.get(connectionId)) === null || _d === void 0 ? void 0 : _d.stream.streamManager) {
|
|
(_e = session.remoteConnections.get(connectionId)) === null || _e === void 0 ? void 0 : _e.stream.streamManager.removeAllVideos();
|
|
}
|
|
var streamId = (_g = (_f = session.remoteConnections.get(connectionId)) === null || _f === void 0 ? void 0 : _f.stream) === null || _g === void 0 ? void 0 : _g.streamId;
|
|
if (!!streamId) {
|
|
session.remoteStreamsCreated.delete(streamId);
|
|
}
|
|
(_h = session.remoteConnections.get(connectionId)) === null || _h === void 0 ? void 0 : _h.dispose();
|
|
}
|
|
session.remoteConnections.delete(connectionId);
|
|
});
|
|
};
|
|
return SessionDisconnectedEvent;
|
|
}(Event_1.Event));
|
|
exports.SessionDisconnectedEvent = SessionDisconnectedEvent;
|
|
|
|
},{"../Logger/OpenViduLogger":66,"./Event":44}],51:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.SignalEvent = void 0;
|
|
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, 'signal') || this;
|
|
if (!!type) {
|
|
_this.type = 'signal:' + type;
|
|
}
|
|
_this.data = data;
|
|
_this.from = from;
|
|
return _this;
|
|
}
|
|
SignalEvent.prototype.callDefaultBehavior = function () { };
|
|
return SignalEvent;
|
|
}(Event_1.Event));
|
|
exports.SignalEvent = SignalEvent;
|
|
|
|
},{"./Event":44}],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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.StreamEvent = void 0;
|
|
var Event_1 = require("./Event");
|
|
var Publisher_1 = require("../../OpenVidu/Publisher");
|
|
var Session_1 = require("../../OpenVidu/Session");
|
|
var OpenViduLogger_1 = require("../Logger/OpenViduLogger");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
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) {
|
|
logger.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'");
|
|
this.stream.disposeWebRtcPeer();
|
|
}
|
|
else if (this.target instanceof Publisher_1.Publisher) {
|
|
logger.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();
|
|
this.stream.session.remoteStreamsCreated.delete(this.stream.streamId);
|
|
var remoteConnection = this.stream.session.remoteConnections.get(this.stream.connection.connectionId);
|
|
if (!!remoteConnection && !!remoteConnection.remoteOptions) {
|
|
var streamOptionsServer = remoteConnection.remoteOptions.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":34,"../../OpenVidu/Session":35,"../Logger/OpenViduLogger":66,"./Event":44}],53:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.StreamManagerEvent = void 0;
|
|
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":44}],54:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.StreamPropertyChangedEvent = void 0;
|
|
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":44}],55:[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 (Object.prototype.hasOwnProperty.call(b, 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 });
|
|
exports.VideoElementEvent = void 0;
|
|
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":44}],56:[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;
|
|
|
|
},{}],57:[function(require,module,exports){
|
|
var JsonRpcClient = require('./jsonrpcclient');
|
|
exports.JsonRpcClient = JsonRpcClient;
|
|
|
|
},{"./jsonrpcclient":58}],58:[function(require,module,exports){
|
|
var RpcBuilder = require('../');
|
|
var WebSocketWithReconnection = require('./transports/webSocketWithReconnection');
|
|
var OpenViduLogger = require('../../../Logger/OpenViduLogger').OpenViduLogger;
|
|
Date.now = Date.now || function () {
|
|
return +new Date;
|
|
};
|
|
var PING_INTERVAL = 5000;
|
|
var RECONNECTING = 'RECONNECTING';
|
|
var CONNECTED = 'CONNECTED';
|
|
var DISCONNECTED = 'DISCONNECTED';
|
|
var Logger = OpenViduLogger.getInstance();
|
|
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) {
|
|
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;
|
|
ws.close(code, reason);
|
|
};
|
|
this.forceClose = function (millis) {
|
|
ws.forceClose(millis);
|
|
};
|
|
this.reconnect = function () {
|
|
ws.reconnectWs();
|
|
};
|
|
this.resetPing = function () {
|
|
enabledPings = true;
|
|
pingNextNum = 0;
|
|
usePing();
|
|
};
|
|
this.getReadyState = function () {
|
|
return ws.getReadyState();
|
|
};
|
|
}
|
|
module.exports = JsonRpcClient;
|
|
|
|
},{"../":61,"../../../Logger/OpenViduLogger":66,"./transports/webSocketWithReconnection":60}],59:[function(require,module,exports){
|
|
var WebSocketWithReconnection = require('./webSocketWithReconnection');
|
|
exports.WebSocketWithReconnection = WebSocketWithReconnection;
|
|
|
|
},{"./webSocketWithReconnection":60}],60:[function(require,module,exports){
|
|
"use strict";
|
|
var OpenViduLogger = require('../../../../Logger/OpenViduLogger').OpenViduLogger;
|
|
var Logger = OpenViduLogger.getInstance();
|
|
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 reconnecting = false;
|
|
var ws = new WebSocket(wsUri);
|
|
ws.onopen = function () {
|
|
Logger.debug("WebSocket connected to " + 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);
|
|
}
|
|
};
|
|
var reconnectionOnClose = function () {
|
|
if (ws.readyState === CLOSED) {
|
|
if (closing) {
|
|
Logger.debug("Connection closed by user");
|
|
}
|
|
else {
|
|
if (config.ismasternodecrashed()) {
|
|
Logger.error("Master Node has crashed. Stopping reconnection process");
|
|
}
|
|
else {
|
|
Logger.debug("Connection closed unexpectedly. Reconnecting...");
|
|
reconnect(MAX_RETRIES, 1);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Logger.debug("Close callback from previous websocket. Ignoring it");
|
|
}
|
|
};
|
|
ws.onclose = reconnectionOnClose;
|
|
function reconnect(maxRetries, numRetries) {
|
|
Logger.debug("reconnect (attempt #" + numRetries + ", max=" + maxRetries + ")");
|
|
if (numRetries === 1) {
|
|
if (reconnecting) {
|
|
Logger.warn("Trying to reconnect when already reconnecting... Ignoring this reconnection.");
|
|
return;
|
|
}
|
|
else {
|
|
reconnecting = true;
|
|
}
|
|
if (config.onreconnecting) {
|
|
config.onreconnecting();
|
|
}
|
|
}
|
|
reconnectAux(maxRetries, numRetries);
|
|
}
|
|
function reconnectAux(maxRetries, numRetries) {
|
|
Logger.debug("Reconnection attempt #" + numRetries);
|
|
ws.close();
|
|
ws = new WebSocket(wsUri);
|
|
ws.onopen = function () {
|
|
Logger.debug("Reconnected to " + wsUri + " after " + numRetries + " attempts...");
|
|
reconnecting = false;
|
|
registerMessageHandler();
|
|
if (config.onreconnected()) {
|
|
config.onreconnected();
|
|
}
|
|
ws.onclose = reconnectionOnClose;
|
|
};
|
|
ws.onerror = function (error) {
|
|
Logger.warn("Reconnection error: ", error);
|
|
if (numRetries === maxRetries) {
|
|
if (config.ondisconnect) {
|
|
config.ondisconnect();
|
|
}
|
|
}
|
|
else {
|
|
setTimeout(function () {
|
|
reconnect(maxRetries, numRetries + 1);
|
|
}, RETRY_TIME_MS);
|
|
}
|
|
};
|
|
}
|
|
this.close = function () {
|
|
closing = true;
|
|
ws.close();
|
|
};
|
|
this.reconnectWs = function () {
|
|
Logger.debug("reconnectWs");
|
|
reconnect(MAX_RETRIES, 1);
|
|
};
|
|
this.send = function (message) {
|
|
ws.send(message);
|
|
};
|
|
this.addEventListener = function (type, callback) {
|
|
registerMessageHandler = function () {
|
|
ws.addEventListener(type, callback);
|
|
};
|
|
registerMessageHandler();
|
|
};
|
|
this.getReadyState = function () {
|
|
return ws.readyState;
|
|
};
|
|
}
|
|
module.exports = WebSocketWithReconnection;
|
|
|
|
},{"../../../../Logger/OpenViduLogger":66}],61:[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":56,"./clients":57,"./clients/transports":59,"./packers":64,"events":1,"inherits":6}],62:[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;
|
|
|
|
},{}],63:[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;
|
|
|
|
},{}],64:[function(require,module,exports){
|
|
var JsonRPC = require('./JsonRPC');
|
|
var XmlRPC = require('./XmlRPC');
|
|
exports.JsonRPC = JsonRPC;
|
|
exports.XmlRPC = XmlRPC;
|
|
|
|
},{"./JsonRPC":62,"./XmlRPC":63}],65:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ConsoleLogger = void 0;
|
|
var ConsoleLogger = (function () {
|
|
function ConsoleLogger(console) {
|
|
this.logger = console;
|
|
this.log = window.console.log,
|
|
this.info = window.console.info,
|
|
this.debug = window.console.debug,
|
|
this.warn = window.console.warn,
|
|
this.error = window.console.error;
|
|
}
|
|
return ConsoleLogger;
|
|
}());
|
|
exports.ConsoleLogger = ConsoleLogger;
|
|
|
|
},{}],66:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OpenViduLogger = void 0;
|
|
var jsnlog_1 = require("jsnlog");
|
|
var ConsoleLogger_1 = require("./ConsoleLogger");
|
|
var OpenViduLoggerConfiguration_1 = require("./OpenViduLoggerConfiguration");
|
|
var OpenViduLogger = (function () {
|
|
function OpenViduLogger() {
|
|
this.JSNLOG_URL = "/openvidu/elk/openvidu-browser-logs";
|
|
this.MAX_JSNLOG_BATCH_LOG_MESSAGES = 100;
|
|
this.MAX_MSECONDS_BATCH_MESSAGES = 5000;
|
|
this.MAX_LENGTH_STRING_JSON = 1000;
|
|
this.defaultConsoleLogger = new ConsoleLogger_1.ConsoleLogger(window.console);
|
|
this.isProdMode = false;
|
|
this.isJSNLogSetup = false;
|
|
}
|
|
OpenViduLogger.configureJSNLog = function (openVidu, token) {
|
|
var _this = this;
|
|
try {
|
|
if ((window['LOG_JSNLOG_RESULTS']) ||
|
|
(this.instance && openVidu.isPro
|
|
&& this.instance.isOpenViduBrowserLogsDebugActive(openVidu)
|
|
&& this.instance.canConfigureJSNLog(openVidu, this.instance))) {
|
|
if (openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug_app) {
|
|
this.instance.replaceWindowConsole();
|
|
}
|
|
this.instance.isJSNLogSetup = false;
|
|
this.instance.info("Configuring JSNLogs.");
|
|
var finalUserId_1 = openVidu.finalUserId;
|
|
var sessionId_1 = openVidu.session.sessionId;
|
|
var beforeSendCallback = function (xhr) {
|
|
var parentReadyStateFunction = xhr.onreadystatechange;
|
|
xhr.onreadystatechange = function () {
|
|
if (_this.isInvalidResponse(xhr)) {
|
|
Object.defineProperty(xhr, "readyState", { value: 4 });
|
|
Object.defineProperty(xhr, "status", { value: 200 });
|
|
_this.instance.disableLogger();
|
|
}
|
|
parentReadyStateFunction();
|
|
};
|
|
xhr.setRequestHeader('Authorization', "Basic " + btoa(finalUserId_1 + "%/%" + sessionId_1 + ":" + token));
|
|
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
xhr.setRequestHeader('OV-Final-User-Id', finalUserId_1);
|
|
xhr.setRequestHeader('OV-Session-Id', sessionId_1);
|
|
xhr.setRequestHeader('OV-Token', token);
|
|
};
|
|
this.instance.currentAppender = jsnlog_1.JL.createAjaxAppender("appender-" + finalUserId_1 + "-" + sessionId_1);
|
|
this.instance.currentAppender.setOptions({
|
|
beforeSend: beforeSendCallback,
|
|
maxBatchSize: 1000,
|
|
batchSize: this.instance.MAX_JSNLOG_BATCH_LOG_MESSAGES,
|
|
batchTimeout: this.instance.MAX_MSECONDS_BATCH_MESSAGES
|
|
});
|
|
var logSerializer = function (obj) {
|
|
var getCircularReplacer = function () {
|
|
var seen = new WeakSet();
|
|
return function (key, value) {
|
|
if (typeof value === "object" && value != null) {
|
|
if (seen.has(value) || (HTMLElement && value instanceof HTMLElement)) {
|
|
return;
|
|
}
|
|
seen.add(value);
|
|
}
|
|
return value;
|
|
};
|
|
};
|
|
var stringifyJson = JSON.stringify(obj, getCircularReplacer());
|
|
if (stringifyJson.length > _this.instance.MAX_LENGTH_STRING_JSON) {
|
|
stringifyJson = stringifyJson.substring(0, _this.instance.MAX_LENGTH_STRING_JSON) + "...";
|
|
}
|
|
if (window['LOG_JSNLOG_RESULTS']) {
|
|
console.log(stringifyJson);
|
|
}
|
|
return stringifyJson;
|
|
};
|
|
jsnlog_1.JL.setOptions({
|
|
defaultAjaxUrl: openVidu.httpUri + this.instance.JSNLOG_URL,
|
|
serialize: logSerializer,
|
|
enabled: true
|
|
});
|
|
jsnlog_1.JL().setOptions({
|
|
appenders: [this.instance.currentAppender]
|
|
});
|
|
this.instance.isJSNLogSetup = true;
|
|
this.instance.loggingSessionId = sessionId_1;
|
|
this.instance.info("JSNLog configured.");
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.error("Error configuring JSNLog: ");
|
|
console.error(e);
|
|
this.instance.disableLogger();
|
|
}
|
|
};
|
|
OpenViduLogger.getInstance = function () {
|
|
if (!OpenViduLogger.instance) {
|
|
OpenViduLogger.instance = new OpenViduLogger();
|
|
}
|
|
return OpenViduLogger.instance;
|
|
};
|
|
OpenViduLogger.isInvalidResponse = function (xhr) {
|
|
return xhr.status == 401 || xhr.status == 403 || xhr.status == 404 || xhr.status == 0;
|
|
};
|
|
OpenViduLogger.prototype.canConfigureJSNLog = function (openVidu, logger) {
|
|
return openVidu.session.sessionId != logger.loggingSessionId;
|
|
};
|
|
OpenViduLogger.prototype.isOpenViduBrowserLogsDebugActive = function (openVidu) {
|
|
return openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug ||
|
|
openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug_app;
|
|
};
|
|
OpenViduLogger.prototype.getConsoleWithJSNLog = function () {
|
|
return function (openViduLogger) {
|
|
return {
|
|
log: function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
openViduLogger.defaultConsoleLogger.log.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
jsnlog_1.JL().info(arguments);
|
|
}
|
|
},
|
|
info: function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
openViduLogger.defaultConsoleLogger.info.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
jsnlog_1.JL().info(arguments);
|
|
}
|
|
},
|
|
debug: function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
openViduLogger.defaultConsoleLogger.debug.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
},
|
|
warn: function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
openViduLogger.defaultConsoleLogger.warn.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
jsnlog_1.JL().warn(arguments);
|
|
}
|
|
},
|
|
error: function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
openViduLogger.defaultConsoleLogger.error.apply(openViduLogger.defaultConsoleLogger.logger, arguments);
|
|
if (openViduLogger.isJSNLogSetup) {
|
|
jsnlog_1.JL().error(arguments);
|
|
}
|
|
}
|
|
};
|
|
}(this);
|
|
};
|
|
OpenViduLogger.prototype.replaceWindowConsole = function () {
|
|
window.console = this.defaultConsoleLogger.logger;
|
|
window.console.log = this.getConsoleWithJSNLog().log;
|
|
window.console.info = this.getConsoleWithJSNLog().info;
|
|
window.console.debug = this.getConsoleWithJSNLog().debug;
|
|
window.console.warn = this.getConsoleWithJSNLog().warn;
|
|
window.console.error = this.getConsoleWithJSNLog().error;
|
|
};
|
|
OpenViduLogger.prototype.disableLogger = function () {
|
|
jsnlog_1.JL.setOptions({ enabled: false });
|
|
this.isJSNLogSetup = false;
|
|
this.loggingSessionId = undefined;
|
|
this.currentAppender = undefined;
|
|
window.console = this.defaultConsoleLogger.logger;
|
|
window.console.log = this.defaultConsoleLogger.log;
|
|
window.console.info = this.defaultConsoleLogger.info;
|
|
window.console.debug = this.defaultConsoleLogger.debug;
|
|
window.console.warn = this.defaultConsoleLogger.warn;
|
|
window.console.error = this.defaultConsoleLogger.error;
|
|
};
|
|
OpenViduLogger.prototype.log = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
if (!this.isProdMode) {
|
|
this.defaultConsoleLogger.log.apply(this.defaultConsoleLogger.logger, arguments);
|
|
}
|
|
if (this.isJSNLogSetup) {
|
|
jsnlog_1.JL().info(arguments);
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.debug = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
if (!this.isProdMode) {
|
|
this.defaultConsoleLogger.debug.apply(this.defaultConsoleLogger.logger, arguments);
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.info = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
if (!this.isProdMode) {
|
|
this.defaultConsoleLogger.info.apply(this.defaultConsoleLogger.logger, arguments);
|
|
}
|
|
if (this.isJSNLogSetup) {
|
|
jsnlog_1.JL().info(arguments);
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.warn = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
if (!this.isProdMode) {
|
|
this.defaultConsoleLogger.warn.apply(this.defaultConsoleLogger.logger, arguments);
|
|
}
|
|
if (this.isJSNLogSetup) {
|
|
jsnlog_1.JL().warn(arguments);
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.error = function () {
|
|
var args = [];
|
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
args[_i] = arguments[_i];
|
|
}
|
|
this.defaultConsoleLogger.error.apply(this.defaultConsoleLogger.logger, arguments);
|
|
if (this.isJSNLogSetup) {
|
|
jsnlog_1.JL().error(arguments);
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.flush = function () {
|
|
if (this.isJSNLogSetup && this.currentAppender != null) {
|
|
this.currentAppender.sendBatch();
|
|
}
|
|
};
|
|
OpenViduLogger.prototype.enableProdMode = function () {
|
|
this.isProdMode = true;
|
|
};
|
|
return OpenViduLogger;
|
|
}());
|
|
exports.OpenViduLogger = OpenViduLogger;
|
|
|
|
},{"./ConsoleLogger":65,"./OpenViduLoggerConfiguration":67,"jsnlog":7}],67:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.OpenViduLoggerConfiguration = void 0;
|
|
var OpenViduLoggerConfiguration;
|
|
(function (OpenViduLoggerConfiguration) {
|
|
OpenViduLoggerConfiguration["disabled"] = "disabled";
|
|
OpenViduLoggerConfiguration["debug"] = "debug";
|
|
OpenViduLoggerConfiguration["debug_app"] = "debug_app";
|
|
})(OpenViduLoggerConfiguration = exports.OpenViduLoggerConfiguration || (exports.OpenViduLoggerConfiguration = {}));
|
|
|
|
},{}],68:[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 = window.getScreenId;
|
|
|
|
},{}],69:[function(require,module,exports){
|
|
var chromeMediaSource = 'screen';
|
|
var sourceId;
|
|
var screenCallback;
|
|
if (typeof window !== 'undefined' && typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined') {
|
|
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;
|
|
|
|
},{}],70:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.PlatformUtils = void 0;
|
|
var platform = require("platform");
|
|
var PlatformUtils = (function () {
|
|
function PlatformUtils() {
|
|
}
|
|
PlatformUtils.getInstance = function () {
|
|
if (!this.instance) {
|
|
this.instance = new PlatformUtils();
|
|
}
|
|
return PlatformUtils.instance;
|
|
};
|
|
PlatformUtils.prototype.isChromeBrowser = function () {
|
|
return platform.name === "Chrome";
|
|
};
|
|
PlatformUtils.prototype.isSafariBrowser = function () {
|
|
return platform.name === "Safari";
|
|
};
|
|
PlatformUtils.prototype.isChromeMobileBrowser = function () {
|
|
return platform.name === "Chrome Mobile";
|
|
};
|
|
PlatformUtils.prototype.isFirefoxBrowser = function () {
|
|
return platform.name === "Firefox";
|
|
};
|
|
PlatformUtils.prototype.isFirefoxMobileBrowser = function () {
|
|
return platform.name === "Firefox Mobile" || platform.name === "Firefox for iOS";
|
|
};
|
|
PlatformUtils.prototype.isOperaBrowser = function () {
|
|
return platform.name === "Opera";
|
|
};
|
|
PlatformUtils.prototype.isOperaMobileBrowser = function () {
|
|
return platform.name === "Opera Mobile";
|
|
};
|
|
PlatformUtils.prototype.isEdgeBrowser = function () {
|
|
var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1;
|
|
return platform.name === "Microsoft Edge" && version >= 80;
|
|
};
|
|
PlatformUtils.prototype.isEdgeMobileBrowser = function () {
|
|
var _a, _b;
|
|
var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1;
|
|
return platform.name === "Microsoft Edge" && (((_a = platform.os) === null || _a === void 0 ? void 0 : _a.family) === 'Android' || ((_b = platform.os) === null || _b === void 0 ? void 0 : _b.family) === 'iOS') && version > 45;
|
|
};
|
|
PlatformUtils.prototype.isAndroidBrowser = function () {
|
|
return platform.name === "Android Browser";
|
|
};
|
|
PlatformUtils.prototype.isElectron = function () {
|
|
return platform.name === "Electron";
|
|
};
|
|
PlatformUtils.prototype.isSamsungBrowser = function () {
|
|
return (platform.name === "Samsung Internet Mobile" ||
|
|
platform.name === "Samsung Internet");
|
|
};
|
|
PlatformUtils.prototype.isIPhoneOrIPad = function () {
|
|
var userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
|
var isTouchable = "ontouchend" in document;
|
|
var isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable;
|
|
var isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) &&
|
|
/\b(\w*Mobile\w*)\b/.test(userAgent) &&
|
|
isTouchable;
|
|
return isIPad || isIPhone;
|
|
};
|
|
PlatformUtils.prototype.isIOSWithSafari = function () {
|
|
var userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
|
|
return this.isIPhoneOrIPad() && (/\b(\w*Apple\w*)\b/.test(navigator.vendor) &&
|
|
/\b(\w*Safari\w*)\b/.test(userAgent) &&
|
|
!/\b(\w*CriOS\w*)\b/.test(userAgent) &&
|
|
!/\b(\w*FxiOS\w*)\b/.test(userAgent));
|
|
};
|
|
PlatformUtils.prototype.isIonicIos = function () {
|
|
return this.isIPhoneOrIPad() && platform.ua.indexOf("Safari") === -1;
|
|
};
|
|
PlatformUtils.prototype.isIonicAndroid = function () {
|
|
return (platform.os.family === "Android" && platform.name == "Android Browser");
|
|
};
|
|
PlatformUtils.prototype.isMobileDevice = function () {
|
|
return platform.os.family === "iOS" || platform.os.family === "Android";
|
|
};
|
|
PlatformUtils.prototype.isReactNative = function () {
|
|
return false;
|
|
};
|
|
PlatformUtils.prototype.isChromium = function () {
|
|
return this.isChromeBrowser() || this.isChromeMobileBrowser() ||
|
|
this.isOperaBrowser() || this.isOperaMobileBrowser() ||
|
|
this.isEdgeBrowser() || this.isEdgeMobileBrowser() ||
|
|
this.isSamsungBrowser() ||
|
|
this.isIonicAndroid() || this.isIonicIos() ||
|
|
this.isElectron();
|
|
};
|
|
PlatformUtils.prototype.canScreenShare = function () {
|
|
var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1;
|
|
if (this.isMobileDevice()) {
|
|
return false;
|
|
}
|
|
return (this.isChromeBrowser() ||
|
|
this.isFirefoxBrowser() ||
|
|
this.isOperaBrowser() ||
|
|
this.isElectron() ||
|
|
this.isEdgeBrowser() ||
|
|
(this.isSafariBrowser() && version >= 13));
|
|
};
|
|
PlatformUtils.prototype.getName = function () {
|
|
return platform.name || "";
|
|
};
|
|
PlatformUtils.prototype.getVersion = function () {
|
|
return platform.version || "";
|
|
};
|
|
PlatformUtils.prototype.getFamily = function () {
|
|
return platform.os.family || "";
|
|
};
|
|
PlatformUtils.prototype.getDescription = function () {
|
|
return platform.description || "";
|
|
};
|
|
return PlatformUtils;
|
|
}());
|
|
exports.PlatformUtils = PlatformUtils;
|
|
|
|
},{"platform":9}],71:[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 (Object.prototype.hasOwnProperty.call(b, 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 __());
|
|
};
|
|
})();
|
|
var __assign = (this && this.__assign) || function () {
|
|
__assign = Object.assign || function(t) {
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
s = arguments[i];
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
t[p] = s[p];
|
|
}
|
|
return t;
|
|
};
|
|
return __assign.apply(this, arguments);
|
|
};
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.WebRtcPeerSendrecv = exports.WebRtcPeerSendonly = exports.WebRtcPeerRecvonly = exports.WebRtcPeer = void 0;
|
|
var freeice = require("freeice");
|
|
var uuid_1 = require("uuid");
|
|
var ExceptionEvent_1 = require("../Events/ExceptionEvent");
|
|
var OpenViduLogger_1 = require("../Logger/OpenViduLogger");
|
|
var Platform_1 = require("../Utils/Platform");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
var simulcastVideoEncodings = [
|
|
{
|
|
rid: "r0",
|
|
scaleResolutionDownBy: 4,
|
|
},
|
|
{
|
|
rid: "r1",
|
|
scaleResolutionDownBy: 2,
|
|
},
|
|
{
|
|
rid: "r2",
|
|
scaleResolutionDownBy: 1,
|
|
},
|
|
];
|
|
var WebRtcPeer = (function () {
|
|
function WebRtcPeer(configuration) {
|
|
var _this = this;
|
|
this.remoteCandidatesQueue = [];
|
|
this.localCandidatesQueue = [];
|
|
this.iceCandidateList = [];
|
|
this.candidategatheringdone = false;
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
this.configuration = __assign(__assign({}, configuration), { iceServers: !!configuration.iceServers &&
|
|
configuration.iceServers.length > 0
|
|
? configuration.iceServers
|
|
: freeice(), mediaStream: configuration.mediaStream !== undefined
|
|
? configuration.mediaStream
|
|
: null, mode: !!configuration.mode ? configuration.mode : "sendrecv", id: !!configuration.id ? configuration.id : this.generateUniqueId() });
|
|
this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers });
|
|
this.pc.addEventListener('icecandidate', function (event) {
|
|
if (event.candidate != null) {
|
|
var candidate = event.candidate;
|
|
_this.configuration.onIceCandidate(candidate);
|
|
if (candidate.candidate !== '') {
|
|
_this.localCandidatesQueue.push({ candidate: candidate.candidate });
|
|
}
|
|
}
|
|
});
|
|
this.pc.addEventListener('signalingstatechange', function () {
|
|
if (_this.pc.signalingState === 'stable') {
|
|
while (_this.iceCandidateList.length > 0) {
|
|
var candidate = _this.iceCandidateList.shift();
|
|
_this.pc.addIceCandidate(candidate);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
WebRtcPeer.prototype.getId = function () {
|
|
return this.configuration.id;
|
|
};
|
|
WebRtcPeer.prototype.dispose = function () {
|
|
logger.debug('Disposing WebRtcPeer');
|
|
if (this.pc) {
|
|
if (this.pc.signalingState === 'closed') {
|
|
return;
|
|
}
|
|
this.pc.close();
|
|
this.remoteCandidatesQueue = [];
|
|
this.localCandidatesQueue = [];
|
|
}
|
|
};
|
|
WebRtcPeer.prototype.createOffer = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
var _i, _a, track, tcInit, tc, sendParams, _b, _c, kind, hasAudio, hasVideo, options;
|
|
return __generator(this, function (_d) {
|
|
switch (_d.label) {
|
|
case 0:
|
|
if (!("addTransceiver" in this.pc)) return [3, 7];
|
|
logger.debug("[createOffer] Method RTCPeerConnection.addTransceiver() is available; using it");
|
|
if (!(this.configuration.mode !== "recvonly")) return [3, 5];
|
|
if (!this.configuration.mediaStream) {
|
|
reject(new Error(this.configuration.mode + " direction requested, but no stream was configured to be sent"));
|
|
return [2];
|
|
}
|
|
_i = 0, _a = this.configuration.mediaStream.getTracks();
|
|
_d.label = 1;
|
|
case 1:
|
|
if (!(_i < _a.length)) return [3, 4];
|
|
track = _a[_i];
|
|
tcInit = {
|
|
direction: this.configuration.mode,
|
|
streams: [this.configuration.mediaStream],
|
|
};
|
|
if (this.configuration.simulcast && track.kind === "video") {
|
|
tcInit.sendEncodings = simulcastVideoEncodings;
|
|
}
|
|
tc = this.pc.addTransceiver(track, tcInit);
|
|
if (!(this.configuration.simulcast && track.kind === "video")) return [3, 3];
|
|
sendParams = tc.sender.getParameters();
|
|
if (!(!("encodings" in sendParams) ||
|
|
sendParams.encodings.length !== tcInit.sendEncodings.length)) return [3, 3];
|
|
sendParams.encodings = tcInit.sendEncodings;
|
|
return [4, tc.sender.setParameters(sendParams)];
|
|
case 2:
|
|
_d.sent();
|
|
_d.label = 3;
|
|
case 3:
|
|
_i++;
|
|
return [3, 1];
|
|
case 4: return [3, 6];
|
|
case 5:
|
|
for (_b = 0, _c = ["audio", "video"]; _b < _c.length; _b++) {
|
|
kind = _c[_b];
|
|
if (!this.configuration.mediaConstraints[kind]) {
|
|
continue;
|
|
}
|
|
this.configuration.mediaStream = new MediaStream();
|
|
this.pc.addTransceiver(kind, {
|
|
direction: this.configuration.mode,
|
|
streams: [this.configuration.mediaStream],
|
|
});
|
|
}
|
|
_d.label = 6;
|
|
case 6:
|
|
this.pc
|
|
.createOffer()
|
|
.then(function (sdpOffer) { return resolve(sdpOffer); })
|
|
.catch(function (error) { return reject(error); });
|
|
return [3, 8];
|
|
case 7:
|
|
logger.error("[createOffer] Method RTCPeerConnection.addTransceiver() is NOT available; using LEGACY offerToReceive{Audio,Video}");
|
|
if (!!this.configuration.mediaStream) {
|
|
this.deprecatedPeerConnectionTrackApi();
|
|
}
|
|
hasAudio = this.configuration.mediaConstraints.audio;
|
|
hasVideo = this.configuration.mediaConstraints.video;
|
|
options = {
|
|
offerToReceiveAudio: this.configuration.mode !== "sendonly" && hasAudio,
|
|
offerToReceiveVideo: this.configuration.mode !== "sendonly" && hasVideo,
|
|
};
|
|
logger.debug("RTCPeerConnection.createOffer() options:", JSON.stringify(options));
|
|
this.pc
|
|
.createOffer(options)
|
|
.then(function (sdpOffer) { return resolve(sdpOffer); })
|
|
.catch(function (error) { return reject(error); });
|
|
_d.label = 8;
|
|
case 8: return [2];
|
|
}
|
|
});
|
|
}); });
|
|
};
|
|
WebRtcPeer.prototype.deprecatedPeerConnectionTrackApi = function () {
|
|
for (var _i = 0, _a = this.configuration.mediaStream.getTracks(); _i < _a.length; _i++) {
|
|
var track = _a[_i];
|
|
this.pc.addTrack(track, this.configuration.mediaStream);
|
|
}
|
|
};
|
|
WebRtcPeer.prototype.createAnswer = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
if ("getTransceivers" in _this.pc) {
|
|
logger.debug("[createAnswer] Method RTCPeerConnection.getTransceivers() is available; using it");
|
|
var _loop_1 = function (kind) {
|
|
if (!_this.configuration.mediaConstraints[kind]) {
|
|
return "continue";
|
|
}
|
|
var tc = _this.pc
|
|
.getTransceivers()
|
|
.find(function (tc) { return tc.receiver.track.kind === kind; });
|
|
if (tc) {
|
|
tc.direction = _this.configuration.mode;
|
|
}
|
|
else {
|
|
reject(new Error(kind + " requested, but no transceiver was created from remote description"));
|
|
}
|
|
};
|
|
for (var _i = 0, _a = ["audio", "video"]; _i < _a.length; _i++) {
|
|
var kind = _a[_i];
|
|
_loop_1(kind);
|
|
}
|
|
_this.pc
|
|
.createAnswer()
|
|
.then(function (sdpAnswer) { return resolve(sdpAnswer); })
|
|
.catch(function (error) { return reject(error); });
|
|
}
|
|
else {
|
|
var offerAudio = void 0, 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: offerAudio,
|
|
offerToReceiveVideo: offerVideo
|
|
};
|
|
_this.pc.createAnswer(constraints).then(function (sdpAnswer) {
|
|
resolve(sdpAnswer);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.processLocalOffer = function (offer) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
_this.pc.setLocalDescription(offer)
|
|
.then(function () {
|
|
var localDescription = _this.pc.localDescription;
|
|
if (!!localDescription) {
|
|
logger.debug('Local description set', localDescription.sdp);
|
|
resolve();
|
|
}
|
|
else {
|
|
reject('Local description is not defined');
|
|
}
|
|
})
|
|
.catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.processRemoteOffer = function (sdpOffer) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var offer = {
|
|
type: 'offer',
|
|
sdp: sdpOffer
|
|
};
|
|
logger.debug('SDP offer received, setting remote description', offer);
|
|
if (_this.pc.signalingState === 'closed') {
|
|
reject('RTCPeerConnection is closed when trying to set remote description');
|
|
}
|
|
_this.setRemoteDescription(offer)
|
|
.then(function () {
|
|
resolve();
|
|
})
|
|
.catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.processLocalAnswer = function (answer) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
logger.debug('SDP answer created, setting local description');
|
|
if (_this.pc.signalingState === 'closed') {
|
|
reject('RTCPeerConnection is closed when trying to set local description');
|
|
}
|
|
_this.pc.setLocalDescription(answer)
|
|
.then(function () { return resolve(); })
|
|
.catch(function (error) { return reject(error); });
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.processRemoteAnswer = function (sdpAnswer) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
var answer = {
|
|
type: 'answer',
|
|
sdp: sdpAnswer
|
|
};
|
|
logger.debug('SDP answer received, setting remote description');
|
|
if (_this.pc.signalingState === 'closed') {
|
|
reject('RTCPeerConnection is closed when trying to set remote description');
|
|
}
|
|
_this.setRemoteDescription(answer)
|
|
.then(function () { return resolve(); })
|
|
.catch(function (error) { return reject(error); });
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.setRemoteDescription = function (sdp) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
return __generator(this, function (_a) {
|
|
return [2, this.pc.setRemoteDescription(sdp)];
|
|
});
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) {
|
|
logger.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();
|
|
}
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.addIceConnectionStateChangeListener = function (otherId) {
|
|
var _this = this;
|
|
this.pc.addEventListener('iceconnectionstatechange', function () {
|
|
var iceConnectionState = _this.pc.iceConnectionState;
|
|
switch (iceConnectionState) {
|
|
case 'disconnected':
|
|
var msg1 = 'IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "disconnected". Possible network disconnection';
|
|
logger.warn(msg1);
|
|
_this.configuration.onIceConnectionStateException(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED, msg1);
|
|
break;
|
|
case 'failed':
|
|
var msg2 = 'IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') to "failed"';
|
|
logger.error(msg2);
|
|
_this.configuration.onIceConnectionStateException(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED, msg2);
|
|
break;
|
|
case 'closed':
|
|
logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "closed"');
|
|
break;
|
|
case 'new':
|
|
logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "new"');
|
|
break;
|
|
case 'checking':
|
|
logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "checking"');
|
|
break;
|
|
case 'connected':
|
|
logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "connected"');
|
|
break;
|
|
case 'completed':
|
|
logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "completed"');
|
|
break;
|
|
}
|
|
});
|
|
};
|
|
WebRtcPeer.prototype.generateUniqueId = function () {
|
|
return uuid_1.v4();
|
|
};
|
|
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;
|
|
|
|
},{"../Events/ExceptionEvent":45,"../Logger/OpenViduLogger":66,"../Utils/Platform":70,"freeice":2,"uuid":10}],72:[function(require,module,exports){
|
|
"use strict";
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (_) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.WebRtcStats = void 0;
|
|
var OpenViduLogger_1 = require("../Logger/OpenViduLogger");
|
|
var Platform_1 = require("../Utils/Platform");
|
|
var logger = OpenViduLogger_1.OpenViduLogger.getInstance();
|
|
var platform;
|
|
;
|
|
var WebRtcStats = (function () {
|
|
function WebRtcStats(stream) {
|
|
this.stream = stream;
|
|
this.STATS_ITEM_NAME = 'webrtc-stats-config';
|
|
this.webRtcStatsEnabled = false;
|
|
this.statsInterval = 1;
|
|
platform = Platform_1.PlatformUtils.getInstance();
|
|
}
|
|
WebRtcStats.prototype.isEnabled = function () {
|
|
return this.webRtcStatsEnabled;
|
|
};
|
|
WebRtcStats.prototype.initWebRtcStats = function () {
|
|
var _this = this;
|
|
var webrtcObj = localStorage.getItem(this.STATS_ITEM_NAME);
|
|
if (!!webrtcObj) {
|
|
this.webRtcStatsEnabled = true;
|
|
var webrtcStatsConfig = JSON.parse(webrtcObj);
|
|
logger.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
|
|
logger.warn('localStorage item: ' + JSON.stringify(webrtcStatsConfig));
|
|
this.POST_URL = webrtcStatsConfig.httpEndpoint;
|
|
this.statsInterval = webrtcStatsConfig.interval;
|
|
this.webRtcStatsIntervalId = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0: return [4, this.sendStatsToHttpEndpoint()];
|
|
case 1:
|
|
_a.sent();
|
|
return [2];
|
|
}
|
|
});
|
|
}); }, this.statsInterval * 1000);
|
|
}
|
|
else {
|
|
logger.debug('WebRtc stats not enabled');
|
|
}
|
|
};
|
|
WebRtcStats.prototype.getSelectedIceCandidateInfo = function () {
|
|
var _this = this;
|
|
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
var statsReport, transportStat, candidatePairs, localCandidates, remoteCandidates, selectedCandidatePair, selectedCandidatePairId, length_1, iterator, i, candidatePair, localCandidateId, remoteCandidateId, finalLocalCandidate, candList, cand, _i, cand_1, c, finalRemoteCandidate, candList, cand, _a, cand_2, c;
|
|
return __generator(this, function (_b) {
|
|
switch (_b.label) {
|
|
case 0: return [4, this.stream.getRTCPeerConnection().getStats()];
|
|
case 1:
|
|
statsReport = _b.sent();
|
|
candidatePairs = new Map();
|
|
localCandidates = new Map();
|
|
remoteCandidates = new Map();
|
|
statsReport.forEach(function (stat) {
|
|
if (stat.type === 'transport' && (platform.isChromium() || platform.isSafariBrowser() || platform.isReactNative())) {
|
|
transportStat = stat;
|
|
}
|
|
switch (stat.type) {
|
|
case 'candidate-pair':
|
|
candidatePairs.set(stat.id, stat);
|
|
break;
|
|
case 'local-candidate':
|
|
localCandidates.set(stat.id, stat);
|
|
break;
|
|
case 'remote-candidate':
|
|
remoteCandidates.set(stat.id, stat);
|
|
break;
|
|
}
|
|
});
|
|
if (transportStat != null) {
|
|
selectedCandidatePairId = transportStat.selectedCandidatePairId;
|
|
selectedCandidatePair = candidatePairs.get(selectedCandidatePairId);
|
|
}
|
|
else {
|
|
length_1 = candidatePairs.size;
|
|
iterator = candidatePairs.values();
|
|
for (i = 0; i < length_1; i++) {
|
|
candidatePair = iterator.next().value;
|
|
if (candidatePair['selected']) {
|
|
selectedCandidatePair = candidatePair;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
localCandidateId = selectedCandidatePair.localCandidateId;
|
|
remoteCandidateId = selectedCandidatePair.remoteCandidateId;
|
|
finalLocalCandidate = localCandidates.get(localCandidateId);
|
|
if (!!finalLocalCandidate) {
|
|
candList = this.stream.getLocalIceCandidateList();
|
|
cand = candList.filter(function (c) {
|
|
return (!!c.candidate &&
|
|
(c.candidate.indexOf(finalLocalCandidate.ip) >= 0 || c.candidate.indexOf(finalLocalCandidate.address) >= 0) &&
|
|
c.candidate.indexOf(finalLocalCandidate.port) >= 0);
|
|
});
|
|
finalLocalCandidate.raw = [];
|
|
for (_i = 0, cand_1 = cand; _i < cand_1.length; _i++) {
|
|
c = cand_1[_i];
|
|
finalLocalCandidate.raw.push(c.candidate);
|
|
}
|
|
}
|
|
else {
|
|
finalLocalCandidate = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used';
|
|
}
|
|
finalRemoteCandidate = remoteCandidates.get(remoteCandidateId);
|
|
if (!!finalRemoteCandidate) {
|
|
candList = this.stream.getRemoteIceCandidateList();
|
|
cand = candList.filter(function (c) {
|
|
return (!!c.candidate &&
|
|
(c.candidate.indexOf(finalRemoteCandidate.ip) >= 0 || c.candidate.indexOf(finalRemoteCandidate.address) >= 0) &&
|
|
c.candidate.indexOf(finalRemoteCandidate.port) >= 0);
|
|
});
|
|
finalRemoteCandidate.raw = [];
|
|
for (_a = 0, cand_2 = cand; _a < cand_2.length; _a++) {
|
|
c = cand_2[_a];
|
|
finalRemoteCandidate.raw.push(c.candidate);
|
|
}
|
|
}
|
|
else {
|
|
finalRemoteCandidate = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used';
|
|
}
|
|
resolve({
|
|
localCandidate: finalLocalCandidate,
|
|
remoteCandidate: finalRemoteCandidate
|
|
});
|
|
return [2];
|
|
}
|
|
});
|
|
}); });
|
|
};
|
|
WebRtcStats.prototype.stopWebRtcStats = function () {
|
|
if (this.webRtcStatsEnabled) {
|
|
clearInterval(this.webRtcStatsIntervalId);
|
|
logger.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId);
|
|
}
|
|
};
|
|
WebRtcStats.prototype.sendStats = function (url, response) {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var configuration, error_1;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
_a.trys.push([0, 2, , 3]);
|
|
configuration = {
|
|
headers: {
|
|
'Content-type': 'application/json'
|
|
},
|
|
body: JSON.stringify(response),
|
|
method: 'POST',
|
|
};
|
|
return [4, fetch(url, configuration)];
|
|
case 1:
|
|
_a.sent();
|
|
return [3, 3];
|
|
case 2:
|
|
error_1 = _a.sent();
|
|
logger.error("sendStats error: " + JSON.stringify(error_1));
|
|
return [3, 3];
|
|
case 3: return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
WebRtcStats.prototype.sendStatsToHttpEndpoint = function () {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var webrtcStats, response, error_2;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
_a.trys.push([0, 3, , 4]);
|
|
return [4, this.getCommonStats()];
|
|
case 1:
|
|
webrtcStats = _a.sent();
|
|
response = this.generateJSONStatsResponse(webrtcStats);
|
|
return [4, this.sendStats(this.POST_URL, response)];
|
|
case 2:
|
|
_a.sent();
|
|
return [3, 4];
|
|
case 3:
|
|
error_2 = _a.sent();
|
|
logger.log(error_2);
|
|
return [3, 4];
|
|
case 4: return [2];
|
|
}
|
|
});
|
|
});
|
|
};
|
|
WebRtcStats.prototype.getCommonStats = function () {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var _this = this;
|
|
return __generator(this, function (_a) {
|
|
return [2, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
var statsReport, response, videoTrackStats, candidatePairStats;
|
|
var _this = this;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0: return [4, this.stream.getRTCPeerConnection().getStats()];
|
|
case 1:
|
|
statsReport = _a.sent();
|
|
response = this.getWebRtcStatsResponseOutline();
|
|
videoTrackStats = ['framesReceived', 'framesDropped', 'framesSent', 'frameHeight', 'frameWidth'];
|
|
candidatePairStats = ['availableOutgoingBitrate', 'currentRoundTripTime'];
|
|
statsReport.forEach(function (stat) {
|
|
var mediaType = stat.mediaType != null ? stat.mediaType : stat.kind;
|
|
var addStat = function (direction, key) {
|
|
if (stat[key] != null && response[direction] != null) {
|
|
if (!mediaType && (videoTrackStats.indexOf(key) > -1)) {
|
|
mediaType = 'video';
|
|
}
|
|
if (direction != null && mediaType != null && key != null && response[direction][mediaType] != null) {
|
|
response[direction][mediaType][key] = Number(stat[key]);
|
|
}
|
|
else if (direction != null && key != null && candidatePairStats.includes(key)) {
|
|
response[direction][key] = Number(stat[key]);
|
|
}
|
|
}
|
|
};
|
|
switch (stat.type) {
|
|
case "outbound-rtp":
|
|
addStat('outbound', 'bytesSent');
|
|
addStat('outbound', 'packetsSent');
|
|
addStat('outbound', 'framesEncoded');
|
|
addStat('outbound', 'nackCount');
|
|
addStat('outbound', 'firCount');
|
|
addStat('outbound', 'pliCount');
|
|
addStat('outbound', 'qpSum');
|
|
break;
|
|
case "inbound-rtp":
|
|
addStat('inbound', 'bytesReceived');
|
|
addStat('inbound', 'packetsReceived');
|
|
addStat('inbound', 'packetsLost');
|
|
addStat('inbound', 'jitter');
|
|
addStat('inbound', 'framesDecoded');
|
|
addStat('inbound', 'nackCount');
|
|
addStat('inbound', 'firCount');
|
|
addStat('inbound', 'pliCount');
|
|
break;
|
|
case 'track':
|
|
addStat('inbound', 'jitterBufferDelay');
|
|
addStat('inbound', 'framesReceived');
|
|
addStat('outbound', 'framesDropped');
|
|
addStat('outbound', 'framesSent');
|
|
addStat(_this.stream.isLocal() ? 'outbound' : 'inbound', 'frameHeight');
|
|
addStat(_this.stream.isLocal() ? 'outbound' : 'inbound', 'frameWidth');
|
|
break;
|
|
case 'candidate-pair':
|
|
addStat('candidatepair', 'currentRoundTripTime');
|
|
addStat('candidatepair', 'availableOutgoingBitrate');
|
|
break;
|
|
}
|
|
});
|
|
if (!(response === null || response === void 0 ? void 0 : response.candidatepair) || Object.keys(response.candidatepair).length === 0) {
|
|
delete response.candidatepair;
|
|
}
|
|
return [2, resolve(response)];
|
|
}
|
|
});
|
|
}); })];
|
|
});
|
|
});
|
|
};
|
|
WebRtcStats.prototype.generateJSONStatsResponse = function (stats) {
|
|
return {
|
|
'@timestamp': new Date().toISOString(),
|
|
participant_id: this.stream.connection.data,
|
|
session_id: this.stream.session.sessionId,
|
|
platform: platform.getName(),
|
|
platform_description: platform.getDescription(),
|
|
stream: 'webRTC',
|
|
webrtc_stats: stats
|
|
};
|
|
};
|
|
WebRtcStats.prototype.getWebRtcStatsResponseOutline = function () {
|
|
if (this.stream.isLocal()) {
|
|
return {
|
|
outbound: {
|
|
audio: {},
|
|
video: {}
|
|
},
|
|
candidatepair: {}
|
|
};
|
|
}
|
|
else {
|
|
return {
|
|
inbound: {
|
|
audio: {},
|
|
video: {}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
return WebRtcStats;
|
|
}());
|
|
exports.WebRtcStats = WebRtcStats;
|
|
|
|
},{"../Logger/OpenViduLogger":66,"../Utils/Platform":70}]},{},[28])
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2pzbmxvZy9qc25sb2cuanMiLCIuLi9ub2RlX21vZHVsZXMvbm9ybWFsaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3BsYXRmb3JtL3BsYXRmb3JtLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvbWQ1LWJyb3dzZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L25pbC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvcGFyc2UuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3JlZ2V4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9ybmctYnJvd3Nlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3Qvc2hhMS1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9zdHJpbmdpZnkuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3YxLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92My5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvdjM1LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvdjUuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3ZhbGlkYXRlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92ZXJzaW9uLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3dpbGRlbWl0dGVyL3dpbGRlbWl0dGVyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3dvbGZ5ODctZXZlbnRlbWl0dGVyL0V2ZW50RW1pdHRlci5qcyIsIi4uL3BhY2thZ2UuanNvbiIsIk1haW4udHMiLCJPcGVuVmlkdS9Db25uZWN0aW9uLnRzIiwiT3BlblZpZHUvRXZlbnREaXNwYXRjaGVyLnRzIiwiT3BlblZpZHUvRmlsdGVyLnRzIiwiT3BlblZpZHUvTG9jYWxSZWNvcmRlci50cyIsIk9wZW5WaWR1L09wZW5WaWR1LnRzIiwiT3BlblZpZHUvUHVibGlzaGVyLnRzIiwiT3BlblZpZHUvU2Vzc2lvbi50cyIsIk9wZW5WaWR1L1N0cmVhbS50cyIsIk9wZW5WaWR1L1N0cmVhbU1hbmFnZXIudHMiLCJPcGVuVmlkdS9TdWJzY3JpYmVyLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUudHMiLCJPcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3IudHMiLCJPcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZS50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXhjZXB0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9GaWx0ZXJFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL05ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9NYXBwZXIuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL2pzb25ycGNjbGllbnQuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy90cmFuc3BvcnRzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy93ZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL3BhY2tlcnMvSnNvblJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL1htbFJQQy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL2luZGV4LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvQ29uc29sZUxvZ2dlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmctQXV0by5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9VdGlscy9QbGF0Zm9ybS50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3AvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzV1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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SUFFTCxrQkFBQztBQUFELENBbFdBLEFBa1dDLElBQUE7QUFsV1ksa0NBQVciLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUiA9IHR5cGVvZiBSZWZsZWN0ID09PSAnb2JqZWN0JyA/IFJlZmxlY3QgOiBudWxsXG52YXIgUmVmbGVjdEFwcGx5ID0gUiAmJiB0eXBlb2YgUi5hcHBseSA9PT0gJ2Z1bmN0aW9uJ1xuICA/IFIuYXBwbHlcbiAgOiBmdW5jdGlvbiBSZWZsZWN0QXBwbHkodGFyZ2V0LCByZWNlaXZlciwgYXJncykge1xuICAgIHJldHVybiBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHkuY2FsbCh0YXJnZXQsIHJlY2VpdmVyLCBhcmdzKTtcbiAgfVxuXG52YXIgUmVmbGVjdE93bktleXNcbmlmIChSICYmIHR5cGVvZiBSLm93bktleXMgPT09ICdmdW5jdGlvbicpIHtcbiAgUmVmbGVjdE93bktleXMgPSBSLm93bktleXNcbn0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykge1xuICBSZWZsZWN0T3duS2V5cyA9IGZ1bmN0aW9uIFJlZmxlY3RPd25LZXlzKHRhcmdldCkge1xuICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0YXJnZXQpXG4gICAgICAuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModGFyZ2V0KSk7XG4gIH07XG59IGVsc2Uge1xuICBSZWZsZWN0T3duS2V5cyA9IGZ1bmN0aW9uIFJlZmxlY3RPd25LZXlzKHRhcmdldCkge1xuICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0YXJnZXQpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBQcm9jZXNzRW1pdFdhcm5pbmcod2FybmluZykge1xuICBpZiAoY29uc29sZSAmJiBjb25zb2xlLndhcm4pIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcbn1cblxudmFyIE51bWJlcklzTmFOID0gTnVtYmVyLmlzTmFOIHx8IGZ1bmN0aW9uIE51bWJlcklzTmFOKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSAhPT0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgRXZlbnRFbWl0dGVyLmluaXQuY2FsbCh0aGlzKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xubW9kdWxlLmV4cG9ydHMub25jZSA9IG9uY2U7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzQ291bnQgPSAwO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG5mdW5jdGlvbiBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBGdW5jdGlvbi4gUmVjZWl2ZWQgdHlwZSAnICsgdHlwZW9mIGxpc3RlbmVyKTtcbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICBpZiAodHlwZW9mIGFyZyAhPT0gJ251bWJlcicgfHwgYXJnIDwgMCB8fCBOdW1iZXJJc05hTihhcmcpKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIG9mIFwiZGVmYXVsdE1heExpc3RlbmVyc1wiIGlzIG91dCBvZiByYW5nZS4gSXQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBudW1iZXIuIFJlY2VpdmVkICcgKyBhcmcgKyAnLicpO1xuICAgIH1cbiAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICB9XG59KTtcblxuRXZlbnRFbWl0dGVyLmluaXQgPSBmdW5jdGlvbigpIHtcblxuICBpZiAodGhpcy5fZXZlbnRzID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMuX2V2ZW50cyA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpLl9ldmVudHMpIHtcbiAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59O1xuXG4vLyBPYnZpb3VzbHkgbm90IGFsbCBFbWl0dGVycyBzaG91bGQgYmUgbGltaXRlZCB0byAxMC4gVGhpcyBmdW5jdGlvbiBhbGxvd3Ncbi8vIHRoYXQgdG8gYmUgaW5jcmVhc2VkLiBTZXQgdG8gemVybyBmb3IgdW5saW1pdGVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBzZXRNYXhMaXN0ZW5lcnMobikge1xuICBpZiAodHlwZW9mIG4gIT09ICdudW1iZXInIHx8IG4gPCAwIHx8IE51bWJlcklzTmFOKG4pKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBvZiBcIm5cIiBpcyBvdXQgb2YgcmFuZ2UuIEl0IG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyLiBSZWNlaXZlZCAnICsgbiArICcuJyk7XG4gIH1cbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiBfZ2V0TWF4TGlzdGVuZXJzKHRoYXQpIHtcbiAgaWYgKHRoYXQuX21heExpc3RlbmVycyA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgcmV0dXJuIHRoYXQuX21heExpc3RlbmVycztcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5nZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRNYXhMaXN0ZW5lcnMoKSB7XG4gIHJldHVybiBfZ2V0TWF4TGlzdGVuZXJzKHRoaXMpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gZW1pdCh0eXBlKSB7XG4gIHZhciBhcmdzID0gW107XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgaWYgKGV2ZW50cyAhPT0gdW5kZWZpbmVkKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT09IHVuZGVmaW5lZCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgdmFyIGVyO1xuICAgIGlmIChhcmdzLmxlbmd0aCA+IDApXG4gICAgICBlciA9IGFyZ3NbMF07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIC8vIE5vdGU6IFRoZSBjb21tZW50cyBvbiB0aGUgYHRocm93YCBsaW5lcyBhcmUgaW50ZW50aW9uYWwsIHRoZXkgc2hvd1xuICAgICAgLy8gdXAgaW4gTm9kZSdzIG91dHB1dCBpZiB0aGlzIHJlc3VsdHMgaW4gYW4gdW5oYW5kbGVkIGV4Y2VwdGlvbi5cbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH1cbiAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgdmFyIGVyciA9IG5ldyBFcnJvcignVW5oYW5kbGVkIGVycm9yLicgKyAoZXIgPyAnICgnICsgZXIubWVzc2FnZSArICcpJyA6ICcnKSk7XG4gICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICB0aHJvdyBlcnI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gIH1cblxuICB2YXIgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoaGFuZGxlciA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBmYWxzZTtcblxuICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICBSZWZsZWN0QXBwbHkoaGFuZGxlciwgdGhpcywgYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIFJlZmxlY3RBcHBseShsaXN0ZW5lcnNbaV0sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0YXJnZXQuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKGV4aXN0aW5nID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBPcHRpbWl6ZSB0aGUgY2FzZSBvZiBvbmUgbGlzdGVuZXIuIERvbid0IG5lZWQgdGhlIGV4dHJhIGFycmF5IG9iamVjdC5cbiAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICAgICsrdGFyZ2V0Ll9ldmVudHNDb3VudDtcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIGV4aXN0aW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID1cbiAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgfSBlbHNlIGlmIChwcmVwZW5kKSB7XG4gICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBtID0gX2dldE1heExpc3RlbmVycyh0YXJnZXQpO1xuICAgIGlmIChtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtICYmICFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAvLyBObyBlcnJvciBjb2RlIGZvciB0aGlzIHNpbmNlIGl0IGlzIGEgV2FybmluZ1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtc3ludGF4XG4gICAgICB2YXIgdyA9IG5ldyBFcnJvcignUG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSBsZWFrIGRldGVjdGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyAnICsgU3RyaW5nKHR5cGUpICsgJyBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdhZGRlZC4gVXNlIGVtaXR0ZXIuc2V0TWF4TGlzdGVuZXJzKCkgdG8gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdCcpO1xuICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICB3LmVtaXR0ZXIgPSB0YXJnZXQ7XG4gICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgIFByb2Nlc3NFbWl0V2FybmluZyh3KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZExpc3RlbmVyID1cbiAgICBmdW5jdGlvbiBwcmVwZW5kTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIHRydWUpO1xuICAgIH07XG5cbmZ1bmN0aW9uIG9uY2VXcmFwcGVyKCkge1xuICBpZiAoIXRoaXMuZmlyZWQpIHtcbiAgICB0aGlzLnRhcmdldC5yZW1vdmVMaXN0ZW5lcih0aGlzLnR5cGUsIHRoaXMud3JhcEZuKTtcbiAgICB0aGlzLmZpcmVkID0gdHJ1ZTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmFwcGx5KHRoaXMudGFyZ2V0LCBhcmd1bWVudHMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IG9uY2VXcmFwcGVyLmJpbmQoc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcik7XG4gICAgICB0aGlzLnByZXBlbmRMaXN0ZW5lcih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbi8vIEVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZiBhbmQgb25seSBpZiB0aGUgbGlzdGVuZXIgd2FzIHJlbW92ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID1cbiAgICBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGxpc3QsIGV2ZW50cywgcG9zaXRpb24sIGksIG9yaWdpbmFsTGlzdGVuZXI7XG5cbiAgICAgIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBsaXN0ID0gZXZlbnRzW3R5cGVdO1xuICAgICAgaWYgKGxpc3QgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMSlcbiAgICAgICAgICBldmVudHNbdHlwZV0gPSBsaXN0WzBdO1xuXG4gICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub2ZmID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmIChldmVudHMgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgbGlzdGVuZXJzID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gICAgICB9IGVsc2UgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmIChldmVudHMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gW107XG5cbiAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG4gIGlmIChldmxpc3RlbmVyID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/XG4gICAgdW53cmFwTGlzdGVuZXJzKGV2bGlzdGVuZXIpIDogYXJyYXlDbG9uZShldmxpc3RlbmVyLCBldmxpc3RlbmVyLmxlbmd0aCk7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24gbGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgdHJ1ZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJhd0xpc3RlbmVycyA9IGZ1bmN0aW9uIHJhd0xpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSkge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIubGlzdGVuZXJDb3VudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGxpc3RlbmVyQ291bnQuY2FsbChlbWl0dGVyLCB0eXBlKTtcbiAgfVxufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gbGlzdGVuZXJDb3VudDtcbmZ1bmN0aW9uIGxpc3RlbmVyQ291bnQodHlwZSkge1xuICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuXG4gIGlmIChldmVudHMgIT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdE93bktleXModGhpcy5fZXZlbnRzKSA6IFtdO1xufTtcblxuZnVuY3Rpb24gYXJyYXlDbG9uZShhcnIsIG4pIHtcbiAgdmFyIGNvcHkgPSBuZXcgQXJyYXkobik7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKVxuICAgIGNvcHlbaV0gPSBhcnJbaV07XG4gIHJldHVybiBjb3B5O1xufVxuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICg7IGluZGV4ICsgMSA8IGxpc3QubGVuZ3RoOyBpbmRleCsrKVxuICAgIGxpc3RbaW5kZXhdID0gbGlzdFtpbmRleCArIDFdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiB1bndyYXBMaXN0ZW5lcnMoYXJyKSB7XG4gIHZhciByZXQgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmV0Lmxlbmd0aDsgKytpKSB7XG4gICAgcmV0W2ldID0gYXJyW2ldLmxpc3RlbmVyIHx8IGFycltpXTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBvbmNlKGVtaXR0ZXIsIG5hbWUpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmdW5jdGlvbiBlcnJvckxpc3RlbmVyKGVycikge1xuICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihuYW1lLCByZXNvbHZlcik7XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNvbHZlcigpIHtcbiAgICAgIGlmICh0eXBlb2YgZW1pdHRlci5yZW1vdmVMaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIGVycm9yTGlzdGVuZXIpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShbXS5zbGljZS5jYWxsKGFyZ3VtZW50cykpO1xuICAgIH07XG5cbiAgICBldmVudFRhcmdldEFnbm9zdGljQWRkTGlzdGVuZXIoZW1pdHRlciwgbmFtZSwgcmVzb2x2ZXIsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICBpZiAobmFtZSAhPT0gJ2Vycm9yJykge1xuICAgICAgYWRkRXJyb3JIYW5kbGVySWZFdmVudEVtaXR0ZXIoZW1pdHRlciwgZXJyb3JMaXN0ZW5lciwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGFkZEVycm9ySGFuZGxlcklmRXZlbnRFbWl0dGVyKGVtaXR0ZXIsIGhhbmRsZXIsIGZsYWdzKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5vbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGV2ZW50VGFyZ2V0QWdub3N0aWNBZGRMaXN0ZW5lcihlbWl0dGVyLCAnZXJyb3InLCBoYW5kbGVyLCBmbGFncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXZlbnRUYXJnZXRBZ25vc3RpY0FkZExpc3RlbmVyKGVtaXR0ZXIsIG5hbWUsIGxpc3RlbmVyLCBmbGFncykge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIub24gPT09ICdmdW5jdGlvbicpIHtcbiAgICBpZiAoZmxhZ3Mub25jZSkge1xuICAgICAgZW1pdHRlci5vbmNlKG5hbWUsIGxpc3RlbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZW1pdHRlci5vbihuYW1lLCBsaXN0ZW5lcik7XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiBlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyBFdmVudFRhcmdldCBkb2VzIG5vdCBoYXZlIGBlcnJvcmAgZXZlbnQgc2VtYW50aWNzIGxpa2UgTm9kZVxuICAgIC8vIEV2ZW50RW1pdHRlcnMsIHdlIGRvIG5vdCBsaXN0ZW4gZm9yIGBlcnJvcmAgZXZlbnRzIGhlcmUuXG4gICAgZW1pdHRlci5hZGRFdmVudExpc3RlbmVyKG5hbWUsIGZ1bmN0aW9uIHdyYXBMaXN0ZW5lcihhcmcpIHtcbiAgICAgIC8vIElFIGRvZXMgbm90IGhhdmUgYnVpbHRpbiBgeyBvbmNlOiB0cnVlIH1gIHN1cHBvcnQgc28gd2VcbiAgICAgIC8vIGhhdmUgdG8gZG8gaXQgbWFudWFsbHkuXG4gICAgICBpZiAoZmxhZ3Mub25jZSkge1xuICAgICAgICBlbWl0dGVyLnJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSwgd3JhcExpc3RlbmVyKTtcbiAgICAgIH1cbiAgICAgIGxpc3RlbmVyKGFyZyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwiZW1pdHRlclwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBFdmVudEVtaXR0ZXIuIFJlY2VpdmVkIHR5cGUgJyArIHR5cGVvZiBlbWl0dGVyKTtcbiAgfVxufVxuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIG5vcm1hbGljZSA9IHJlcXVpcmUoJ25vcm1hbGljZScpO1xuXG4vKipcbiAgIyBmcmVlaWNlXG5cbiAgVGhlIGBmcmVlaWNlYCBtb2R1bGUgaXMgYSBzaW1wbGUgd2F5IG9mIGdldHRpbmcgcmFuZG9tIFNUVU4gb3IgVFVSTiBzZXJ2ZXJcbiAgZm9yIHlvdXIgV2ViUlRDIGFwcGxpY2F0aW9uLiAgVGhlIGxpc3Qgb2Ygc2VydmVycyAoanVzdCBTVFVOIGF0IHRoaXMgc3RhZ2UpXG4gIHdlcmUgc291cmNlZCBmcm9tIHRoaXMgW2dpc3RdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3p6aXVuaS8zNzQxOTMzKS5cblxuICAjIyBFeGFtcGxlIFVzZVxuXG4gIFRoZSBmb2xsb3dpbmcgZGVtb25zdHJhdGVzIGhvdyB5b3UgY2FuIHVzZSBgZnJlZWljZWAgd2l0aFxuICBbcnRjLXF1aWNrY29ubmVjdF0oaHR0cHM6Ly9naXRodWIuY29tL3J0Yy1pby9ydGMtcXVpY2tjb25uZWN0KTpcblxuICA8PDwgZXhhbXBsZXMvcXVpY2tjb25uZWN0LmpzXG5cbiAgQXMgdGhlIGBmcmVlaWNlYCBtb2R1bGUgZ2VuZXJhdGVzIGljZSBzZXJ2ZXJzIGluIGEgbGlzdCBjb21wbGlhbnQgd2l0aCB0aGVcbiAgV2ViUlRDIHNwZWMgeW91IHdpbGwgYmUgYWJsZSB0byB1c2UgaXQgd2l0aCByYXcgYFJUQ1BlZXJDb25uZWN0aW9uYFxuICBjb25zdHJ1Y3RvcnMgYW5kIG90aGVyIFdlYlJUQyBsaWJyYXJpZXMuXG5cbiAgIyMgSGV5LCBkb24ndCB1c2UgbXkgU1RVTi9UVVJOIHNlcnZlciFcblxuICBJZiBmb3Igc29tZSByZWFzb24geW91ciBmcmVlIFNUVU4gb3IgVFVSTiBzZXJ2ZXIgZW5kcyB1cCBpbiB0aGVcbiAgbGlzdCBvZiBzZXJ2ZXJzIChbc3R1bl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3N0dW4uanNvbikgb3JcbiAgW3R1cm5dKGh0dHBzOi8vZ2l0aHViLmNvbS9EYW1vbk9laGxtYW4vZnJlZWljZS9ibG9iL21hc3Rlci90dXJuLmpzb24pKVxuICB0aGF0IGlzIHVzZWQgaW4gdGhpcyBtb2R1bGUsIHlvdSBjYW4gZmVlbFxuICBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgb24gdGhpcyByZXBvc2l0b3J5IGFuZCB0aG9zZSBzZXJ2ZXJzIHdpbGwgYmUgcmVtb3ZlZFxuICB3aXRoaW4gMjQgaG91cnMgKG9yIHNvb25lcikuICBUaGlzIGlzIHRoZSBxdWlja2VzdCBhbmQgcHJvYmFibHkgdGhlIG1vc3RcbiAgcG9saXRlIHdheSB0byBoYXZlIHNvbWV0aGluZyByZW1vdmVkIChhbmQgcHJvdmlkZXMgdXMgc29tZSB2aXNpYmlsaXR5XG4gIGlmIHNvbWVvbmUgb3BlbnMgYSBwdWxsIHJlcXVlc3QgcmVxdWVzdGluZyB0aGF0IGEgc2VydmVyIGlzIGFkZGVkKS5cblxuICAjIyBQbGVhc2UgYWRkIG15IHNlcnZlciFcblxuICBJZiB5b3UgaGF2ZSBhIHNlcnZlciB0aGF0IHlvdSB3aXNoIHRvIGFkZCB0byB0aGUgbGlzdCwgdGhhdCdzIGF3ZXNvbWUhIEknbVxuICBzdXJlIEkgc3BlYWsgb24gYmVoYWxmIG9mIGEgd2hvbGUgcGlsZSBvZiBXZWJSVEMgZGV2ZWxvcGVycyB3aG8gc2F5IHRoYW5rcy5cbiAgVG8gZ2V0IGl0IGludG8gdGhlIGxpc3QsIGZlZWwgZnJlZSB0byBlaXRoZXIgb3BlbiBhIHB1bGwgcmVxdWVzdCBvciBpZiB5b3VcbiAgZmluZCB0aGF0IHByb2Nlc3MgYSBiaXQgZGF1bnRpbmcgdGhlbiBqdXN0IGNyZWF0ZSBhbiBpc3N1ZSByZXF1ZXN0aW5nXG4gIHRoZSBhZGRpdGlvbiBvZiB0aGUgc2VydmVyIChtYWtlIHN1cmUgeW91IHByb3ZpZGUgYWxsIHRoZSBkZXRhaWxzLCBhbmQgaWZcbiAgeW91IGhhdmUgYSBUZXJtcyBvZiBTZXJ2aWNlIHRoZW4gaW5jbHVkaW5nIHRoYXQgaW4gdGhlIFBSL2lzc3VlIHdvdWxkIGJlXG4gIGF3ZXNvbWUpLlxuXG4gICMjIEkga25vdyBvZiBhIGZyZWUgc2VydmVyLCBjYW4gSSBhZGQgaXQ/XG5cbiAgU3VyZSwgaWYgeW91IGRvIHlvdXIgaG9tZXdvcmsgYW5kIG1ha2Ugc3VyZSBpdCBpcyBvayB0byB1c2UgKEknbSBjdXJyZW50bHlcbiAgaW4gdGhlIHByb2Nlc3Mgb2YgcmV2aWV3aW5nIHRoZSB0ZXJtcyBvZiB0aG9zZSBTVFVOIHNlcnZlcnMgaW5jbHVkZWQgZnJvbVxuICB0aGUgb3JpZ2luYWwgbGlzdCkuICBJZiBpdCdzIG9rIHRvIGdvLCB0aGVuIHBsZWFzZSBzZWUgdGhlIHByZXZpb3VzIGVudHJ5XG4gIGZvciBob3cgdG8gYWRkIGl0LlxuXG4gICMjIEN1cnJlbnQgTGlzdCBvZiBTZXJ2ZXJzXG5cbiAgKiBjdXJyZW50IGFzIGF0IHRoZSB0aW1lIG9mIGxhc3QgYFJFQURNRS5tZGAgZmlsZSBnZW5lcmF0aW9uXG5cbiAgIyMjIFNUVU5cblxuICA8PDwgc3R1bi5qc29uXG5cbiAgIyMjIFRVUk5cblxuICA8PDwgdHVybi5qc29uXG5cbioqL1xuXG52YXIgZnJlZWljZSA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgLy8gaWYgYSBsaXN0IG9mIHNlcnZlcnMgaGFzIGJlZW4gcHJvdmlkZWQsIHRoZW4gdXNlIGl0IGluc3RlYWQgb2YgZGVmYXVsdHNcbiAgdmFyIHNlcnZlcnMgPSB7XG4gICAgc3R1bjogKG9wdHMgfHwge30pLnN0dW4gfHwgcmVxdWlyZSgnLi9zdHVuLmpzb24nKSxcbiAgICB0dXJuOiAob3B0cyB8fCB7fSkudHVybiB8fCByZXF1aXJlKCcuL3R1cm4uanNvbicpXG4gIH07XG5cbiAgdmFyIHN0dW5Db3VudCA9IChvcHRzIHx8IHt9KS5zdHVuQ291bnQgfHwgMjtcbiAgdmFyIHR1cm5Db3VudCA9IChvcHRzIHx8IHt9KS50dXJuQ291bnQgfHwgMDtcbiAgdmFyIHNlbGVjdGVkO1xuXG4gIGZ1bmN0aW9uIGdldFNlcnZlcnModHlwZSwgY291bnQpIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgdmFyIGlucHV0ID0gW10uY29uY2F0KHNlcnZlcnNbdHlwZV0pO1xuICAgIHZhciBpZHg7XG5cbiAgICB3aGlsZSAoaW5wdXQubGVuZ3RoICYmIG91dC5sZW5ndGggPCBjb3VudCkge1xuICAgICAgaWR4ID0gKE1hdGgucmFuZG9tKCkgKiBpbnB1dC5sZW5ndGgpIHwgMDtcbiAgICAgIG91dCA9IG91dC5jb25jYXQoaW5wdXQuc3BsaWNlKGlkeCwgMSkpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQubWFwKGZ1bmN0aW9uKHVybCkge1xuICAgICAgICAvL0lmIGl0J3MgYSBub3QgYSBzdHJpbmcsIGRvbid0IHRyeSB0byBcIm5vcm1hbGljZVwiIGl0IG90aGVyd2lzZSB1c2luZyB0eXBlOnVybCB3aWxsIHNjcmV3IGl0IHVwXG4gICAgICAgIGlmICgodHlwZW9mIHVybCAhPT0gJ3N0cmluZycpICYmICghICh1cmwgaW5zdGFuY2VvZiBTdHJpbmcpKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBub3JtYWxpY2UodHlwZSArICc6JyArIHVybCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFkZCBzdHVuIHNlcnZlcnNcbiAgc2VsZWN0ZWQgPSBbXS5jb25jYXQoZ2V0U2VydmVycygnc3R1bicsIHN0dW5Db3VudCkpO1xuXG4gIGlmICh0dXJuQ291bnQpIHtcbiAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmNvbmNhdChnZXRTZXJ2ZXJzKCd0dXJuJywgdHVybkNvdW50KSk7XG4gIH1cblxuICByZXR1cm4gc2VsZWN0ZWQ7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZyZWVpY2U7IiwibW9kdWxlLmV4cG9ydHM9W1xuICBcInN0dW4ubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjEubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjIubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjMubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bjQubC5nb29nbGUuY29tOjE5MzAyXCIsXG4gIFwic3R1bi5la2lnYS5uZXRcIixcbiAgXCJzdHVuLmlkZWFzaXAuY29tXCIsXG4gIFwic3R1bi5zY2hsdW5kLmRlXCIsXG4gIFwic3R1bi5zdHVucHJvdG9jb2wub3JnOjM0NzhcIixcbiAgXCJzdHVuLnZvaXBhcm91bmQuY29tXCIsXG4gIFwic3R1bi52b2lwYnVzdGVyLmNvbVwiLFxuICBcInN0dW4udm9pcHN0dW50LmNvbVwiLFxuICBcInN0dW4udm94Z3JhdGlhLm9yZ1wiXG5dXG4iLCJtb2R1bGUuZXhwb3J0cz1bXVxuIiwidmFyIFdpbGRFbWl0dGVyID0gcmVxdWlyZSgnd2lsZGVtaXR0ZXInKTtcblxuZnVuY3Rpb24gZ2V0TWF4Vm9sdW1lIChhbmFseXNlciwgZmZ0Qmlucykge1xuICB2YXIgbWF4Vm9sdW1lID0gLUluZmluaXR5O1xuICBhbmFseXNlci5nZXRGbG9hdEZyZXF1ZW5jeURhdGEoZmZ0Qmlucyk7XG5cbiAgZm9yKHZhciBpPTQsIGlpPWZmdEJpbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgIGlmIChmZnRCaW5zW2ldID4gbWF4Vm9sdW1lICYmIGZmdEJpbnNbaV0gPCAwKSB7XG4gICAgICBtYXhWb2x1bWUgPSBmZnRCaW5zW2ldO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbWF4Vm9sdW1lO1xufVxuXG5cbnZhciBhdWRpb0NvbnRleHRUeXBlO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gIGF1ZGlvQ29udGV4dFR5cGUgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG59XG4vLyB1c2UgYSBzaW5nbGUgYXVkaW8gY29udGV4dCBkdWUgdG8gaGFyZHdhcmUgbGltaXRzXG52YXIgYXVkaW9Db250ZXh0ID0gbnVsbDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyZWFtLCBvcHRpb25zKSB7XG4gIHZhciBoYXJrZXIgPSBuZXcgV2lsZEVtaXR0ZXIoKTtcblxuICAvLyBtYWtlIGl0IG5vdCBicmVhayBpbiBub24tc3VwcG9ydGVkIGJyb3dzZXJzXG4gIGlmICghYXVkaW9Db250ZXh0VHlwZSkgcmV0dXJuIGhhcmtlcjtcblxuICAvL0NvbmZpZ1xuICB2YXIgb3B0aW9ucyA9IG9wdGlvbnMgfHwge30sXG4gICAgICBzbW9vdGhpbmcgPSAob3B0aW9ucy5zbW9vdGhpbmcgfHwgMC4xKSxcbiAgICAgIGludGVydmFsID0gKG9wdGlvbnMuaW50ZXJ2YWwgfHwgNTApLFxuICAgICAgdGhyZXNob2xkID0gb3B0aW9ucy50aHJlc2hvbGQsXG4gICAgICBwbGF5ID0gb3B0aW9ucy5wbGF5LFxuICAgICAgaGlzdG9yeSA9IG9wdGlvbnMuaGlzdG9yeSB8fCAxMCxcbiAgICAgIHJ1bm5pbmcgPSB0cnVlO1xuXG4gIC8vIEVuc3VyZSB0aGF0IGp1c3QgYSBzaW5nbGUgQXVkaW9Db250ZXh0IGlzIGludGVybmFsbHkgY3JlYXRlZFxuICBhdWRpb0NvbnRleHQgPSBvcHRpb25zLmF1ZGlvQ29udGV4dCB8fCBhdWRpb0NvbnRleHQgfHwgbmV3IGF1ZGlvQ29udGV4dFR5cGUoKTtcblxuICB2YXIgc291cmNlTm9kZSwgZmZ0QmlucywgYW5hbHlzZXI7XG5cbiAgYW5hbHlzZXIgPSBhdWRpb0NvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgYW5hbHlzZXIuZmZ0U2l6ZSA9IDUxMjtcbiAgYW5hbHlzZXIuc21vb3RoaW5nVGltZUNvbnN0YW50ID0gc21vb3RoaW5nO1xuICBmZnRCaW5zID0gbmV3IEZsb2F0MzJBcnJheShhbmFseXNlci5mcmVxdWVuY3lCaW5Db3VudCk7XG5cbiAgaWYgKHN0cmVhbS5qcXVlcnkpIHN0cmVhbSA9IHN0cmVhbVswXTtcbiAgaWYgKHN0cmVhbSBpbnN0YW5jZW9mIEhUTUxBdWRpb0VsZW1lbnQgfHwgc3RyZWFtIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkge1xuICAgIC8vQXVkaW8gVGFnXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYUVsZW1lbnRTb3VyY2Uoc3RyZWFtKTtcbiAgICBpZiAodHlwZW9mIHBsYXkgPT09ICd1bmRlZmluZWQnKSBwbGF5ID0gdHJ1ZTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9IGVsc2Uge1xuICAgIC8vV2ViUlRDIFN0cmVhbVxuICAgIHNvdXJjZU5vZGUgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAgICB0aHJlc2hvbGQgPSB0aHJlc2hvbGQgfHwgLTUwO1xuICB9XG5cbiAgc291cmNlTm9kZS5jb25uZWN0KGFuYWx5c2VyKTtcbiAgaWYgKHBsYXkpIGFuYWx5c2VyLmNvbm5lY3QoYXVkaW9Db250ZXh0LmRlc3RpbmF0aW9uKTtcblxuICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcblxuICBoYXJrZXIuc3VzcGVuZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhdWRpb0NvbnRleHQuc3VzcGVuZCgpO1xuICB9XG4gIGhhcmtlci5yZXN1bWUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnJlc3VtZSgpO1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShoYXJrZXIsICdzdGF0ZScsIHsgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXVkaW9Db250ZXh0LnN0YXRlO1xuICB9fSk7XG4gIGF1ZGlvQ29udGV4dC5vbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgaGFya2VyLmVtaXQoJ3N0YXRlX2NoYW5nZScsIGF1ZGlvQ29udGV4dC5zdGF0ZSk7XG4gIH1cblxuICBoYXJrZXIuc2V0VGhyZXNob2xkID0gZnVuY3Rpb24odCkge1xuICAgIHRocmVzaG9sZCA9IHQ7XG4gIH07XG5cbiAgaGFya2VyLnNldEludGVydmFsID0gZnVuY3Rpb24oaSkge1xuICAgIGludGVydmFsID0gaTtcbiAgfTtcblxuICBoYXJrZXIuc3RvcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIC0xMDAsIHRocmVzaG9sZCk7XG4gICAgaWYgKGhhcmtlci5zcGVha2luZykge1xuICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICBoYXJrZXIuZW1pdCgnc3RvcHBlZF9zcGVha2luZycpO1xuICAgIH1cbiAgICBhbmFseXNlci5kaXNjb25uZWN0KCk7XG4gICAgc291cmNlTm9kZS5kaXNjb25uZWN0KCk7XG4gIH07XG4gIGhhcmtlci5zcGVha2luZ0hpc3RvcnkgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBoaXN0b3J5OyBpKyspIHtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwKTtcbiAgfVxuXG4gIC8vIFBvbGwgdGhlIGFuYWx5c2VyIG5vZGUgdG8gZGV0ZXJtaW5lIGlmIHNwZWFraW5nXG4gIC8vIGFuZCBlbWl0IGV2ZW50cyBpZiBjaGFuZ2VkXG4gIHZhciBsb29wZXIgPSBmdW5jdGlvbigpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuXG4gICAgICAvL2NoZWNrIGlmIHN0b3AgaGFzIGJlZW4gY2FsbGVkXG4gICAgICBpZighcnVubmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50Vm9sdW1lID0gZ2V0TWF4Vm9sdW1lKGFuYWx5c2VyLCBmZnRCaW5zKTtcblxuICAgICAgaGFya2VyLmVtaXQoJ3ZvbHVtZV9jaGFuZ2UnLCBjdXJyZW50Vm9sdW1lLCB0aHJlc2hvbGQpO1xuXG4gICAgICB2YXIgaGlzdG9yeSA9IDA7XG4gICAgICBpZiAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCAmJiAhaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIC8vIHRyaWdnZXIgcXVpY2tseSwgc2hvcnQgaGlzdG9yeVxuICAgICAgICBmb3IgKHZhciBpID0gaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGggLSAzOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA+PSAyKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gdHJ1ZTtcbiAgICAgICAgICBoYXJrZXIuZW1pdCgnc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Vm9sdW1lIDwgdGhyZXNob2xkICYmIGhhcmtlci5zcGVha2luZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhhcmtlci5zcGVha2luZ0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBoaXN0b3J5ICs9IGhhcmtlci5zcGVha2luZ0hpc3RvcnlbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhpc3RvcnkgPT0gMCkge1xuICAgICAgICAgIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3Rvcnkuc2hpZnQoKTtcbiAgICAgIGhhcmtlci5zcGVha2luZ0hpc3RvcnkucHVzaCgwICsgKGN1cnJlbnRWb2x1bWUgPiB0aHJlc2hvbGQpKTtcblxuICAgICAgbG9vcGVyKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9O1xuICBsb29wZXIoKTtcblxuICByZXR1cm4gaGFya2VyO1xufVxuIiwiaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgaWYgKHN1cGVyQ3Rvcikge1xuICAgICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuICB9O1xufSBlbHNlIHtcbiAgLy8gb2xkIHNjaG9vbCBzaGltIGZvciBvbGQgYnJvd3NlcnNcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBpZiAoc3VwZXJDdG9yKSB7XG4gICAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKClcbiAgICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICAgIH1cbiAgfVxufVxuIiwiLyogXHJcbiAqIEpTTkxvZyAyLjMwLjBcclxuICogT3BlbiBzb3VyY2UgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKiBDb3B5cmlnaHQgMjAxMi0yMDE3IE1hdHRpanMgUGVyZGVjayBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKi9cclxudmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xyXG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xyXG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgfTtcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xyXG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG4gICAgfTtcclxufSkoKTtcclxuZnVuY3Rpb24gSkwobG9nZ2VyTmFtZSkge1xyXG4gICAgLy8gSWYgbmFtZSBpcyBlbXB0eSwgcmV0dXJuIHRoZSByb290IGxvZ2dlclxyXG4gICAgaWYgKCFsb2dnZXJOYW1lKSB7XHJcbiAgICAgICAgcmV0dXJuIEpMLl9fO1xyXG4gICAgfVxyXG4gICAgLy8gSW1wbGVtZW50cyBBcnJheS5yZWR1Y2UuIEpTTkxvZyBzdXBwb3J0cyBJRTgrIGFuZCByZWR1Y2UgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGF0IGJyb3dzZXIuXHJcbiAgICAvLyBTYW1lIGludGVyZmFjZSBhcyB0aGUgc3RhbmRhcmQgcmVkdWNlLCBleGNlcHQgdGhhdCBcclxuICAgIGlmICghQXJyYXkucHJvdG90eXBlLnJlZHVjZSkge1xyXG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5yZWR1Y2UgPSBmdW5jdGlvbiAoY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSkge1xyXG4gICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IGluaXRpYWxWYWx1ZTtcclxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlID0gY2FsbGJhY2socHJldmlvdXNWYWx1ZSwgdGhpc1tpXSwgaSwgdGhpcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuICAgIHZhciBhY2N1bXVsYXRlZExvZ2dlck5hbWUgPSAnJztcclxuICAgIHZhciBsb2dnZXIgPSAoJy4nICsgbG9nZ2VyTmFtZSkuc3BsaXQoJy4nKS5yZWR1Y2UoZnVuY3Rpb24gKHByZXYsIGN1cnIsIGlkeCwgYXJyKSB7XHJcbiAgICAgICAgLy8gaWYgbG9nZ2VybmFtZSBpcyBhLmIuYywgdGhhbiBjdXJyZW50TG9nZ2VyIHdpbGwgYmUgc2V0IHRvIHRoZSBsb2dnZXJzXHJcbiAgICAgICAgLy8gcm9vdCAgIChwcmV2OiBKTCwgY3VycjogJycpXHJcbiAgICAgICAgLy8gYSAgICAgIChwcmV2OiBKTC5fXywgY3VycjogJ2EnKVxyXG4gICAgICAgIC8vIGEuYiAgICAocHJldjogSkwuX18uX19hLCBjdXJyOiAnYicpXHJcbiAgICAgICAgLy8gYS5iLmMgIChwcmV2OiBKTC5fXy5fX2EuX19hLmIsIGN1cnI6ICdjJylcclxuICAgICAgICAvLyBOb3RlIHRoYXQgd2hlbiBhIG5ldyBsb2dnZXIgbmFtZSBpcyBlbmNvdW50ZXJlZCAoc3VjaCBhcyAnYS5iLmMnKSxcclxuICAgICAgICAvLyBhIG5ldyBsb2dnZXIgb2JqZWN0IGlzIGNyZWF0ZWQgYW5kIGFkZGVkIGFzIGEgcHJvcGVydHkgdG8gdGhlIHBhcmVudCAoJ2EuYicpLlxyXG4gICAgICAgIC8vIFRoZSByb290IGxvZ2dlciBpcyBhZGRlZCBhcyBhIHByb3BlcnR5IG9mIHRoZSBKTCBvYmplY3QgaXRzZWxmLlxyXG4gICAgICAgIC8vIEl0IGlzIGVzc2VudGlhbCB0aGF0IHRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSBjb250YWluaW5nIHRoZSBjaGlsZCBsb2dnZXJcclxuICAgICAgICAvLyBjb250YWlucyB0aGUgZnVsbCAncGF0aCcgbmFtZSBvZiB0aGUgY2hpbGQgbG9nZ2VyICgnYS5iLmMnKSBpbnN0ZWFkIG9mXHJcbiAgICAgICAgLy8ganVzdCB0aGUgYml0IGFmdGVyIHRoZSBsYXN0IHBlcmlvZCAoJ2MnKS5cclxuICAgICAgICAvLyBUaGlzIGlzIGJlY2F1c2UgdGhlIHBhcmVudCBpbmhlcml0cyBwcm9wZXJ0aWVzIGZyb20gaXRzIGFuY2VzdG9ycy5cclxuICAgICAgICAvLyBTbyBpZiB0aGUgcm9vdCBoYXMgYSBjaGlsZCBsb2dnZXIgJ2MnIChzdG9yZWQgaW4gYSBwcm9wZXJ0eSAnYycgb2YgdGhlIHJvb3QgbG9nZ2VyKSxcclxuICAgICAgICAvLyB0aGVuIGxvZ2dlciAnYS5iJyBoYXMgdGhhdCBzYW1lIHByb3BlcnR5ICdjJyB0aHJvdWdoIGluaGVyaXRhbmNlLlxyXG4gICAgICAgIC8vIFRoZSBuYW1lcyBvZiB0aGUgbG9nZ2VyIHByb3BlcnRpZXMgc3RhcnQgd2l0aCBfXywgc28gdGhlIHJvb3QgbG9nZ2VyIFxyXG4gICAgICAgIC8vICh3aGljaCBoYXMgbmFtZSAnJyksIGhhcyBhIG5pY2UgcHJvcGVydHkgbmFtZSAnX18nLiAgICAgICAgICAgICAgXHJcbiAgICAgICAgLy8gYWNjdW11bGF0ZWRMb2dnZXJOYW1lIGV2YWx1YXRlcyBmYWxzZSAoJycgaXMgZmFsc3kpIGluIGZpcnN0IGl0ZXJhdGlvbiB3aGVuIHByZXYgaXMgdGhlIHJvb3QgbG9nZ2VyLlxyXG4gICAgICAgIC8vIGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSB3aWxsIGJlIHRoZSBsb2dnZXIgbmFtZSBjb3JyZXNwb25kaW5nIHdpdGggdGhlIGxvZ2dlciBpbiBjdXJyZW50TG9nZ2VyLlxyXG4gICAgICAgIC8vIEtlZXAgaW4gbWluZCB0aGF0IHRoZSBjdXJyZW50TG9nZ2VyIG1heSBub3QgYmUgZGVmaW5lZCB5ZXQsIHNvIGNhbid0IGdldCB0aGUgbmFtZSBmcm9tXHJcbiAgICAgICAgLy8gdGhlIGN1cnJlbnRMb2dnZXIgb2JqZWN0IGl0c2VsZi4gXHJcbiAgICAgICAgaWYgKGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSkge1xyXG4gICAgICAgICAgICBhY2N1bXVsYXRlZExvZ2dlck5hbWUgKz0gJy4nICsgY3VycjtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSA9IGN1cnI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBjdXJyZW50TG9nZ2VyID0gcHJldlsnX18nICsgYWNjdW11bGF0ZWRMb2dnZXJOYW1lXTtcclxuICAgICAgICAvLyBJZiB0aGUgY3VycmVudExvZ2dlciAob3IgdGhlIGFjdHVhbCBsb2dnZXIgYmVpbmcgc291Z2h0KSBkb2VzIG5vdCB5ZXQgZXhpc3QsIFxyXG4gICAgICAgIC8vIGNyZWF0ZSBpdCBub3cuXHJcbiAgICAgICAgaWYgKGN1cnJlbnRMb2dnZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAvLyBTZXQgdGhlIHByb3RvdHlwZSBvZiB0aGUgTG9nZ2VyIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIHRoZSBwYXJlbnQgb2YgdGhlIGxvZ2dlclxyXG4gICAgICAgICAgICAvLyB0byBiZSBjcmVhdGVkLiBUaGlzIHdheSwgX19wcm90byBvZiB0aGUgbmV3IGxvZ2dlciBvYmplY3Qgd2lsbCBwb2ludCBhdCB0aGUgcGFyZW50LlxyXG4gICAgICAgICAgICAvLyBXaGVuIGxvZ2dlci5sZXZlbCBpcyBldmFsdWF0ZWQgYW5kIGlzIG5vdCBwcmVzZW50LCB0aGUgSmF2YVNjcmlwdCBydW50aW1lIHdpbGwgXHJcbiAgICAgICAgICAgIC8vIHdhbGsgZG93biB0aGUgcHJvdG90eXBlIGNoYWluIHRvIGZpbmQgdGhlIGZpcnN0IGFuY2VzdG9yIHdpdGggYSBsZXZlbCBwcm9wZXJ0eS5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHByZXYgYXQgdGhpcyBwb2ludCByZWZlcnMgdG8gdGhlIHBhcmVudCBsb2dnZXIuXHJcbiAgICAgICAgICAgIEpMLkxvZ2dlci5wcm90b3R5cGUgPSBwcmV2O1xyXG4gICAgICAgICAgICBjdXJyZW50TG9nZ2VyID0gbmV3IEpMLkxvZ2dlcihhY2N1bXVsYXRlZExvZ2dlck5hbWUpO1xyXG4gICAgICAgICAgICBwcmV2WydfXycgKyBhY2N1bXVsYXRlZExvZ2dlck5hbWVdID0gY3VycmVudExvZ2dlcjtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRMb2dnZXI7XHJcbiAgICB9LCBKTC5fXyk7XHJcbiAgICByZXR1cm4gbG9nZ2VyO1xyXG59XHJcbihmdW5jdGlvbiAoSkwpIHtcclxuICAgIC8vIEluaXRpYWxpc2UgcmVxdWVzdElkIHRvIGVtcHR5IHN0cmluZy4gSWYgeW91IGRvbid0IGRvIHRoaXMgYW5kIHRoZSB1c2VyXHJcbiAgICAvLyBkb2VzIG5vdCBzZXQgaXQgdmlhIHNldE9wdGlvbnMsIHRoZW4gdGhlIEpTTkxvZy1SZXF1ZXN0SWQgaGVhZGVyIHdpbGxcclxuICAgIC8vIGhhdmUgdmFsdWUgXCJ1bmRlZmluZWRcIiwgd2hpY2ggZG9lc24ndCBsb29rIGdvb2QgaW4gYSBsb2cuXHJcbiAgICAvL1xyXG4gICAgLy8gTm90ZSB0aGF0IHlvdSBhbHdheXMgd2FudCB0byBzZW5kIGEgcmVxdWVzdElkIGFzIHBhcnQgb2YgbG9nIHJlcXVlc3RzLFxyXG4gICAgLy8gb3RoZXJ3aXNlIHRoZSBzZXJ2ZXIgc2lkZSBjb21wb25lbnQgZG9lc24ndCBrbm93IHRoaXMgaXMgYSBsb2cgcmVxdWVzdFxyXG4gICAgLy8gYW5kIG1heSBjcmVhdGUgYSBuZXcgcmVxdWVzdCBpZCBmb3IgdGhlIGxvZyByZXF1ZXN0LCBjYXVzaW5nIGNvbmZ1c2lvblxyXG4gICAgLy8gaW4gdGhlIGxvZy5cclxuICAgIEpMLnJlcXVlc3RJZCA9ICcnO1xyXG4gICAgLy8gTnVtYmVyIHVuaXF1ZWx5IGlkZW50aWZ5aW5nIGV2ZXJ5IGxvZyBlbnRyeSB3aXRoaW4gdGhlIHJlcXVlc3QuXHJcbiAgICBKTC5lbnRyeUlkID0gMDtcclxuICAgIC8vIEFsbG93IHByb3BlcnR5IGluamVjdGlvbiBvZiB0aGVzZSBjbGFzc2VzLCB0byBlbmFibGUgdW5pdCB0ZXN0aW5nXHJcbiAgICBKTC5fY3JlYXRlWE1MSHR0cFJlcXVlc3QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBuZXcgWE1MSHR0cFJlcXVlc3QoKTsgfTtcclxuICAgIEpMLl9nZXRUaW1lID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gKG5ldyBEYXRlKS5nZXRUaW1lKCk7IH07XHJcbiAgICBKTC5fY29uc29sZSA9IGNvbnNvbGU7XHJcbiAgICAvLyAtLS0tLSBwcml2YXRlIHZhcmlhYmxlc1xyXG4gICAgSkwuX2FwcGVuZGVyTmFtZXMgPSBbXTtcclxuICAgIC8qKlxyXG4gICAgQ29waWVzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5IGZyb20gb25lIG9iamVjdCB0byB0aGUgb3RoZXIuXHJcbiAgICBUaGlzIGlzIHVzZWQgdG8gY29weSBwcm9wZXJ0eSB2YWx1ZXMgYXMgcGFydCBvZiBzZXRPcHRpb24gZm9yIGxvZ2dlcnMgYW5kIGFwcGVuZGVycy5cclxuXHJcbiAgICBCZWNhdXNlIGxvZ2dlcnMgaW5oZXJpdCBwcm9wZXJ0eSB2YWx1ZXMgZnJvbSB0aGVpciBwYXJlbnRzLCBpdCBpcyBpbXBvcnRhbnQgbmV2ZXIgdG9cclxuICAgIGNyZWF0ZSBhIHByb3BlcnR5IG9uIGEgbG9nZ2VyIGlmIHRoZSBpbnRlbnQgaXMgdG8gaW5oZXJpdCBmcm9tIHRoZSBwYXJlbnQuXHJcblxyXG4gICAgQ29weWluZyBydWxlczpcclxuICAgIDEpIGlmIHRoZSBmcm9tIHByb3BlcnR5IGlzIHVuZGVmaW5lZCAoZm9yIGV4YW1wbGUsIG5vdCBtZW50aW9uZWQgaW4gYSBKU09OIG9iamVjdCksIHRoZVxyXG4gICAgICAgdG8gcHJvcGVydHkgaXMgbm90IGFmZmVjdGVkIGF0IGFsbC5cclxuICAgIDIpIGlmIHRoZSBmcm9tIHByb3BlcnR5IGlzIG51bGwsIHRoZSB0byBwcm9wZXJ0eSBpcyBkZWxldGVkIChzbyB0aGUgbG9nZ2VyIHdpbGwgaW5oZXJpdCBmcm9tXHJcbiAgICAgICBpdHMgcGFyZW50KS5cclxuICAgIDMpIE90aGVyd2lzZSwgdGhlIGZyb20gcHJvcGVydHkgaXMgY29waWVkIHRvIHRoZSB0byBwcm9wZXJ0eS5cclxuICAgICovXHJcbiAgICBmdW5jdGlvbiBjb3B5UHJvcGVydHkocHJvcGVydHlOYW1lLCBmcm9tLCB0bykge1xyXG4gICAgICAgIGlmIChmcm9tW3Byb3BlcnR5TmFtZV0gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChmcm9tW3Byb3BlcnR5TmFtZV0gPT09IG51bGwpIHtcclxuICAgICAgICAgICAgZGVsZXRlIHRvW3Byb3BlcnR5TmFtZV07XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdG9bcHJvcGVydHlOYW1lXSA9IGZyb21bcHJvcGVydHlOYW1lXTtcclxuICAgIH1cclxuICAgIC8qKlxyXG4gICAgUmV0dXJucyB0cnVlIGlmIGEgbG9nIHNob3VsZCBnbyBhaGVhZC5cclxuICAgIERvZXMgbm90IGNoZWNrIGxldmVsLlxyXG5cclxuICAgIEBwYXJhbSBmaWx0ZXJzXHJcbiAgICAgICAgRmlsdGVycyB0aGF0IGRldGVybWluZSB3aGV0aGVyIGEgbG9nIGNhbiBnbyBhaGVhZC5cclxuICAgICovXHJcbiAgICBmdW5jdGlvbiBhbGxvdyhmaWx0ZXJzKSB7XHJcbiAgICAgICAgLy8gSWYgZW5hYmxlZCBpcyBub3QgbnVsbCBvciB1bmRlZmluZWQsIHRoZW4gaWYgaXQgaXMgZmFsc2UsIHRoZW4gcmV0dXJuIGZhbHNlXHJcbiAgICAgICAgLy8gTm90ZSB0aGF0IHVuZGVmaW5lZD09bnVsbCAoISlcclxuICAgICAgICBpZiAoIShKTC5lbmFibGVkID09IG51bGwpKSB7XHJcbiAgICAgICAgICAgIGlmICghSkwuZW5hYmxlZCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIElmIHRoZSByZWdleCBjb250YWlucyBhIGJ1ZywgdGhhdCB3aWxsIHRocm93IGFuIGV4Y2VwdGlvbi5cclxuICAgICAgICAvLyBJZ25vcmUgdGhpcywgYW5kIHBhc3MgdGhlIGxvZyBpdGVtIChiZXR0ZXIgdG9vIG11Y2ggdGhhbiB0b28gbGl0dGxlKS5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZmlsdGVycy51c2VyQWdlbnRSZWdleCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFuZXcgUmVnRXhwKGZpbHRlcnMudXNlckFnZW50UmVnZXgpLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmaWx0ZXJzLmlwUmVnZXggJiYgSkwuY2xpZW50SVApIHtcclxuICAgICAgICAgICAgICAgIGlmICghbmV3IFJlZ0V4cChmaWx0ZXJzLmlwUmVnZXgpLnRlc3QoSkwuY2xpZW50SVApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7IH1cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIC8qKlxyXG4gICAgUmV0dXJucyB0cnVlIGlmIGEgbG9nIHNob3VsZCBnbyBhaGVhZCwgYmFzZWQgb24gdGhlIG1lc3NhZ2UuXHJcblxyXG4gICAgQHBhcmFtIGZpbHRlcnNcclxuICAgICAgICBGaWx0ZXJzIHRoYXQgZGV0ZXJtaW5lIHdoZXRoZXIgYSBsb2cgY2FuIGdvIGFoZWFkLlxyXG5cclxuICAgIEBwYXJhbSBtZXNzYWdlXHJcbiAgICAgICAgTWVzc2FnZSB0byBiZSBsb2dnZWQuXHJcbiAgICAqL1xyXG4gICAgZnVuY3Rpb24gYWxsb3dNZXNzYWdlKGZpbHRlcnMsIG1lc3NhZ2UpIHtcclxuICAgICAgICAvLyBJZiB0aGUgcmVnZXggY29udGFpbnMgYSBidWcsIHRoYXQgd2lsbCB0aHJvdyBhbiBleGNlcHRpb24uXHJcbiAgICAgICAgLy8gSWdub3JlIHRoaXMsIGFuZCBwYXNzIHRoZSBsb2cgaXRlbSAoYmV0dGVyIHRvbyBtdWNoIHRoYW4gdG9vIGxpdHRsZSkuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGZpbHRlcnMuZGlzYWxsb3cpIHtcclxuICAgICAgICAgICAgICAgIGlmIChuZXcgUmVnRXhwKGZpbHRlcnMuZGlzYWxsb3cpLnRlc3QobWVzc2FnZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG4gICAgLy8gSWYgbG9nT2JqZWN0IGlzIGEgZnVuY3Rpb24sIHRoZSBmdW5jdGlvbiBpcyBldmFsdWF0ZWQgKHdpdGhvdXQgcGFyYW1ldGVycylcclxuICAgIC8vIGFuZCB0aGUgcmVzdWx0IHJldHVybmVkLlxyXG4gICAgLy8gT3RoZXJ3aXNlLCBsb2dPYmplY3QgaXRzZWxmIGlzIHJldHVybmVkLlxyXG4gICAgZnVuY3Rpb24gc3RyaW5naWZ5TG9nT2JqZWN0RnVuY3Rpb24obG9nT2JqZWN0KSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBsb2dPYmplY3QgPT0gXCJmdW5jdGlvblwiKSB7XHJcbiAgICAgICAgICAgIGlmIChsb2dPYmplY3QgaW5zdGFuY2VvZiBSZWdFeHApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2dPYmplY3QudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2dPYmplY3QoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbG9nT2JqZWN0O1xyXG4gICAgfVxyXG4gICAgdmFyIFN0cmluZ2lmaWVkTG9nT2JqZWN0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIC8vICogbXNnIC0gXHJcbiAgICAgICAgLy8gICAgICBpZiB0aGUgbG9nT2JqZWN0IGlzIGEgc2NhbGFyIChhZnRlciBwb3NzaWJsZSBmdW5jdGlvbiBldmFsdWF0aW9uKSwgdGhpcyBpcyBzZXQgdG9cclxuICAgICAgICAvLyAgICAgIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHNjYWxhci4gT3RoZXJ3aXNlIGl0IGlzIGxlZnQgdW5kZWZpbmVkLlxyXG4gICAgICAgIC8vICogbWV0YSAtXHJcbiAgICAgICAgLy8gICAgICBpZiB0aGUgbG9nT2JqZWN0IGlzIGFuIG9iamVjdCAoYWZ0ZXIgcG9zc2libGUgZnVuY3Rpb24gZXZhbHVhdGlvbiksIHRoaXMgaXMgc2V0IHRvXHJcbiAgICAgICAgLy8gICAgICB0aGF0IG9iamVjdC4gT3RoZXJ3aXNlIGl0IGlzIGxlZnQgdW5kZWZpbmVkLlxyXG4gICAgICAgIC8vICogZmluYWxTdHJpbmcgLVxyXG4gICAgICAgIC8vICAgICAgVGhpcyBpcyBzZXQgdG8gdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBsb2dPYmplY3QgKGFmdGVyIHBvc3NpYmxlIGZ1bmN0aW9uIGV2YWx1YXRpb24pLFxyXG4gICAgICAgIC8vICAgICAgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIGl0IGlzIGFuIHNjYWxhciBvciBhbiBvYmplY3QuIEFuIG9iamVjdCBpcyBzdHJpbmdpZmllZCB0byBhIEpTT04gc3RyaW5nLlxyXG4gICAgICAgIC8vICAgICAgTm90ZSB0aGF0IHlvdSBjYW4ndCBjYWxsIHRoaXMgZmllbGQgXCJmaW5hbFwiLCBiZWNhdXNlIGFzIHNvbWUgcG9pbnQgdGhpcyB3YXMgYSByZXNlcnZlZFxyXG4gICAgICAgIC8vICAgICAgSmF2YVNjcmlwdCBrZXl3b3JkIGFuZCB1c2luZyBmaW5hbCB0cmlwcyB1cCBzb21lIG1pbmlmaWVycy5cclxuICAgICAgICBmdW5jdGlvbiBTdHJpbmdpZmllZExvZ09iamVjdChtc2csIG1ldGEsIGZpbmFsU3RyaW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMubXNnID0gbXNnO1xyXG4gICAgICAgICAgICB0aGlzLm1ldGEgPSBtZXRhO1xyXG4gICAgICAgICAgICB0aGlzLmZpbmFsU3RyaW5nID0gZmluYWxTdHJpbmc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBTdHJpbmdpZmllZExvZ09iamVjdDtcclxuICAgIH0oKSk7XHJcbiAgICAvLyBUYWtlcyBhIGxvZ09iamVjdCwgd2hpY2ggY2FuIGJlIFxyXG4gICAgLy8gKiBhIHNjYWxhclxyXG4gICAgLy8gKiBhbiBvYmplY3RcclxuICAgIC8vICogYSBwYXJhbWV0ZXJsZXNzIGZ1bmN0aW9uLCB3aGljaCByZXR1cm5zIHRoZSBzY2FsYXIgb3Igb2JqZWN0IHRvIGxvZy5cclxuICAgIC8vIFJldHVybnMgYSBzdHJpbmdpZmllZExvZ09iamVjdFxyXG4gICAgZnVuY3Rpb24gc3RyaW5naWZ5TG9nT2JqZWN0KGxvZ09iamVjdCkge1xyXG4gICAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIHdvcmtzIGlmIGxvZ09iamVjdCBpcyBudWxsLlxyXG4gICAgICAgIC8vIHR5cGVvZiBudWxsIGlzIG9iamVjdC5cclxuICAgICAgICAvLyBKU09OLnN0cmluZ2lmeShudWxsKSByZXR1cm5zIFwibnVsbFwiLlxyXG4gICAgICAgIHZhciBhY3R1YWxMb2dPYmplY3QgPSBzdHJpbmdpZnlMb2dPYmplY3RGdW5jdGlvbihsb2dPYmplY3QpO1xyXG4gICAgICAgIHZhciBmaW5hbFN0cmluZztcclxuICAgICAgICAvLyBOb3RlIHRoYXQgdHlwZW9mIGFjdHVhbExvZ09iamVjdCBzaG91bGQgbm90IGJlIFwiZnVuY3Rpb25cIiwgYmVjYXVzZSB0aGF0IGhhcyBcclxuICAgICAgICAvLyBiZWVuIHJlc29sdmVkIHdpdGggc3RyaW5naWZ5TG9nT2JqZWN0RnVuY3Rpb24uXHJcbiAgICAgICAgc3dpdGNoICh0eXBlb2YgYWN0dWFsTG9nT2JqZWN0KSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJzdHJpbmdcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5naWZpZWRMb2dPYmplY3QoYWN0dWFsTG9nT2JqZWN0LCBudWxsLCBhY3R1YWxMb2dPYmplY3QpO1xyXG4gICAgICAgICAgICBjYXNlIFwibnVtYmVyXCI6XHJcbiAgICAgICAgICAgICAgICBmaW5hbFN0cmluZyA9IGFjdHVhbExvZ09iamVjdC50b1N0cmluZygpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChmaW5hbFN0cmluZywgbnVsbCwgZmluYWxTdHJpbmcpO1xyXG4gICAgICAgICAgICBjYXNlIFwiYm9vbGVhblwiOlxyXG4gICAgICAgICAgICAgICAgZmluYWxTdHJpbmcgPSBhY3R1YWxMb2dPYmplY3QudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5naWZpZWRMb2dPYmplY3QoZmluYWxTdHJpbmcsIG51bGwsIGZpbmFsU3RyaW5nKTtcclxuICAgICAgICAgICAgY2FzZSBcInVuZGVmaW5lZFwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChcInVuZGVmaW5lZFwiLCBudWxsLCBcInVuZGVmaW5lZFwiKTtcclxuICAgICAgICAgICAgY2FzZSBcIm9iamVjdFwiOlxyXG4gICAgICAgICAgICAgICAgaWYgKChhY3R1YWxMb2dPYmplY3QgaW5zdGFuY2VvZiBSZWdFeHApIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgKGFjdHVhbExvZ09iamVjdCBpbnN0YW5jZW9mIFN0cmluZykgfHxcclxuICAgICAgICAgICAgICAgICAgICAoYWN0dWFsTG9nT2JqZWN0IGluc3RhbmNlb2YgTnVtYmVyKSB8fFxyXG4gICAgICAgICAgICAgICAgICAgIChhY3R1YWxMb2dPYmplY3QgaW5zdGFuY2VvZiBCb29sZWFuKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbmFsU3RyaW5nID0gYWN0dWFsTG9nT2JqZWN0LnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChmaW5hbFN0cmluZywgbnVsbCwgZmluYWxTdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBKTC5zZXJpYWxpemUgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxTdHJpbmcgPSBKTC5zZXJpYWxpemUuY2FsbCh0aGlzLCBhY3R1YWxMb2dPYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShhY3R1YWxMb2dPYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIG1zZyBmaWVsZCB0byBcIlwiIGluc3RlYWQgb2YgbnVsbC4gU29tZSBXaW5zdG9uIHRyYW5zcG9ydHNcclxuICAgICAgICAgICAgICAgICAgICAvLyBhc3N1bWUgdGhhdCB0aGUgbXNnIGZpZWxkIGlzIG5vdCBudWxsLlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5naWZpZWRMb2dPYmplY3QoXCJcIiwgYWN0dWFsTG9nT2JqZWN0LCBmaW5hbFN0cmluZyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZ2lmaWVkTG9nT2JqZWN0KFwidW5rbm93blwiLCBudWxsLCBcInVua25vd25cIik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gc2V0T3B0aW9ucyhvcHRpb25zKSB7XHJcbiAgICAgICAgY29weVByb3BlcnR5KFwiZW5hYmxlZFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJtYXhNZXNzYWdlc1wiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJkZWZhdWx0QWpheFVybFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJjbGllbnRJUFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJyZXF1ZXN0SWRcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgY29weVByb3BlcnR5KFwiZGVmYXVsdEJlZm9yZVNlbmRcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgY29weVByb3BlcnR5KFwic2VyaWFsaXplXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfVxyXG4gICAgSkwuc2V0T3B0aW9ucyA9IHNldE9wdGlvbnM7XHJcbiAgICBmdW5jdGlvbiBnZXRBbGxMZXZlbCgpIHsgcmV0dXJuIC0yMTQ3NDgzNjQ4OyB9XHJcbiAgICBKTC5nZXRBbGxMZXZlbCA9IGdldEFsbExldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0VHJhY2VMZXZlbCgpIHsgcmV0dXJuIDEwMDA7IH1cclxuICAgIEpMLmdldFRyYWNlTGV2ZWwgPSBnZXRUcmFjZUxldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0RGVidWdMZXZlbCgpIHsgcmV0dXJuIDIwMDA7IH1cclxuICAgIEpMLmdldERlYnVnTGV2ZWwgPSBnZXREZWJ1Z0xldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0SW5mb0xldmVsKCkgeyByZXR1cm4gMzAwMDsgfVxyXG4gICAgSkwuZ2V0SW5mb0xldmVsID0gZ2V0SW5mb0xldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0V2FybkxldmVsKCkgeyByZXR1cm4gNDAwMDsgfVxyXG4gICAgSkwuZ2V0V2FybkxldmVsID0gZ2V0V2FybkxldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0RXJyb3JMZXZlbCgpIHsgcmV0dXJuIDUwMDA7IH1cclxuICAgIEpMLmdldEVycm9yTGV2ZWwgPSBnZXRFcnJvckxldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0RmF0YWxMZXZlbCgpIHsgcmV0dXJuIDYwMDA7IH1cclxuICAgIEpMLmdldEZhdGFsTGV2ZWwgPSBnZXRGYXRhbExldmVsO1xyXG4gICAgZnVuY3Rpb24gZ2V0T2ZmTGV2ZWwoKSB7IHJldHVybiAyMTQ3NDgzNjQ3OyB9XHJcbiAgICBKTC5nZXRPZmZMZXZlbCA9IGdldE9mZkxldmVsO1xyXG4gICAgZnVuY3Rpb24gbGV2ZWxUb1N0cmluZyhsZXZlbCkge1xyXG4gICAgICAgIGlmIChsZXZlbCA8PSAxMDAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBcInRyYWNlXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChsZXZlbCA8PSAyMDAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBcImRlYnVnXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChsZXZlbCA8PSAzMDAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBcImluZm9cIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGxldmVsIDw9IDQwMDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwid2FyblwiO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAobGV2ZWwgPD0gNTAwMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gXCJlcnJvclwiO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gXCJmYXRhbFwiO1xyXG4gICAgfVxyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICB2YXIgRXhjZXB0aW9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIC8vIGRhdGEgcmVwbGFjZXMgbWVzc2FnZS4gSXQgdGFrZXMgbm90IGp1c3Qgc3RyaW5ncywgYnV0IGFsc28gb2JqZWN0cyBhbmQgZnVuY3Rpb25zLCBqdXN0IGxpa2UgdGhlIGxvZyBmdW5jdGlvbi5cclxuICAgICAgICAvLyBpbnRlcm5hbGx5LCB0aGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIGlzIHN0b3JlZCBpbiB0aGUgbWVzc2FnZSBwcm9wZXJ0eSAoaW5oZXJpdGVkIGZyb20gRXJyb3IpXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBpbm5lcjogaW5uZXIgZXhjZXB0aW9uLiBDYW4gYmUgbnVsbCBvciB1bmRlZmluZWQuIFxyXG4gICAgICAgIGZ1bmN0aW9uIEV4Y2VwdGlvbihkYXRhLCBpbm5lcikge1xyXG4gICAgICAgICAgICB0aGlzLmlubmVyID0gaW5uZXI7XHJcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IFwiSkwuRXhjZXB0aW9uXCI7XHJcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9IHN0cmluZ2lmeUxvZ09iamVjdChkYXRhKS5maW5hbFN0cmluZztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIEV4Y2VwdGlvbjtcclxuICAgIH0oKSk7XHJcbiAgICBKTC5FeGNlcHRpb24gPSBFeGNlcHRpb247XHJcbiAgICAvLyBEZXJpdmUgRXhjZXB0aW9uIGZyb20gRXJyb3IgKGEgSG9zdCBvYmplY3QpLCBzbyBicm93c2Vyc1xyXG4gICAgLy8gYXJlIG1vcmUgbGlrZWx5IHRvIHByb2R1Y2UgYSBzdGFjayB0cmFjZSBmb3IgaXQgaW4gdGhlaXIgY29uc29sZS5cclxuICAgIC8vXHJcbiAgICAvLyBOb3RlIHRoYXQgaW5zdGFuY2VvZiBhZ2FpbnN0IGFuIG9iamVjdCBjcmVhdGVkIHdpdGggdGhpcyBjb25zdHJ1Y3RvclxyXG4gICAgLy8gd2lsbCByZXR1cm4gdHJ1ZSBpbiB0aGVzZSBjYXNlczpcclxuICAgIC8vIDxvYmplY3Q+IGluc3RhbmNlb2YgSkwuRXhjZXB0aW9uKTtcclxuICAgIC8vIDxvYmplY3Q+IGluc3RhbmNlb2YgRXJyb3IpO1xyXG4gICAgRXhjZXB0aW9uLnByb3RvdHlwZSA9IG5ldyBFcnJvcigpO1xyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICB2YXIgTG9nSXRlbSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBsOiBsZXZlbFxyXG4gICAgICAgIC8vIG06IG1lc3NhZ2VcclxuICAgICAgICAvLyBuOiBsb2dnZXIgbmFtZVxyXG4gICAgICAgIC8vIHQgKHRpbWVTdGFtcCkgaXMgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBzaW5jZSAxIEphbnVhcnkgMTk3MCAwMDowMDowMCBVVENcclxuICAgICAgICAvLyB1OiBudW1iZXIgdW5pcXVlbHkgaWRlbnRpZnlpbmcgdGhpcyBlbnRyeSBmb3IgdGhpcyByZXF1ZXN0LlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gS2VlcGluZyB0aGUgcHJvcGVydHkgbmFtZXMgcmVhbGx5IHNob3J0LCBiZWNhdXNlIHRoZXkgd2lsbCBiZSBzZW50IGluIHRoZVxyXG4gICAgICAgIC8vIEpTT04gcGF5bG9hZCB0byB0aGUgc2VydmVyLlxyXG4gICAgICAgIGZ1bmN0aW9uIExvZ0l0ZW0obCwgbSwgbiwgdCwgdSkge1xyXG4gICAgICAgICAgICB0aGlzLmwgPSBsO1xyXG4gICAgICAgICAgICB0aGlzLm0gPSBtO1xyXG4gICAgICAgICAgICB0aGlzLm4gPSBuO1xyXG4gICAgICAgICAgICB0aGlzLnQgPSB0O1xyXG4gICAgICAgICAgICB0aGlzLnUgPSB1O1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gTG9nSXRlbTtcclxuICAgIH0oKSk7XHJcbiAgICBKTC5Mb2dJdGVtID0gTG9nSXRlbTtcclxuICAgIGZ1bmN0aW9uIG5ld0xvZ0l0ZW0obGV2ZWxOYnIsIG1lc3NhZ2UsIGxvZ2dlck5hbWUpIHtcclxuICAgICAgICBKTC5lbnRyeUlkKys7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBMb2dJdGVtKGxldmVsTmJyLCBtZXNzYWdlLCBsb2dnZXJOYW1lLCBKTC5fZ2V0VGltZSgpLCBKTC5lbnRyeUlkKTtcclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIGNsZWFyVGltZXIodGltZXIpIHtcclxuICAgICAgICBpZiAodGltZXIuaWQpIHtcclxuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyLmlkKTtcclxuICAgICAgICAgICAgdGltZXIuaWQgPSBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIHNldFRpbWVyKHRpbWVyLCB0aW1lb3V0TXMsIGNhbGxiYWNrKSB7XHJcbiAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xyXG4gICAgICAgIGlmICghdGltZXIuaWQpIHtcclxuICAgICAgICAgICAgdGltZXIuaWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIC8vIHVzZSBjYWxsIHRvIGVuc3VyZSB0aGF0IHRoZSB0aGlzIGFzIHVzZWQgaW5zaWRlIHNlbmRCYXRjaCB3aGVuIGl0IHJ1bnMgaXMgdGhlXHJcbiAgICAgICAgICAgICAgICAvLyBzYW1lIHRoaXMgYXQgdGhpcyBwb2ludC5cclxuICAgICAgICAgICAgICAgIGNhbGxiYWNrLmNhbGwodGhhdCk7XHJcbiAgICAgICAgICAgIH0sIHRpbWVvdXRNcyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgdmFyIEFwcGVuZGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIC8vIHNlbmRMb2dJdGVtcyB0YWtlcyBhbiBhcnJheSBvZiBsb2cgaXRlbXMuIEl0IHdpbGwgYmUgY2FsbGVkIHdoZW5cclxuICAgICAgICAvLyB0aGUgYXBwZW5kZXIgaGFzIGl0ZW1zIHRvIHByb2Nlc3MgKHN1Y2ggYXMsIHNlbmQgdG8gdGhlIHNlcnZlcikuXHJcbiAgICAgICAgLy8gc2VuZExvZ0l0ZW1zIHdpbGwgY2FsbCBzdWNjZXNzQ2FsbGJhY2sgYWZ0ZXIgdGhlIGl0ZW1zIGhhdmUgYmVlbiBzdWNjZXNzZnVsbHkgc2VudC5cclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIE5vdGUgdGhhdCBhZnRlciBzZW5kTG9nSXRlbXMgcmV0dXJucywgdGhlIGFwcGVuZGVyIG1heSB0cnVuY2F0ZVxyXG4gICAgICAgIC8vIHRoZSBMb2dJdGVtIGFycmF5LCBzbyB0aGUgZnVuY3Rpb24gaGFzIHRvIGNvcHkgdGhlIGNvbnRlbnQgb2YgdGhlIGFycmF5XHJcbiAgICAgICAgLy8gaW4gc29tZSBmYXNoaW9uIChlZy4gc2VyaWFsaXplKSBiZWZvcmUgcmV0dXJuaW5nLlxyXG4gICAgICAgIGZ1bmN0aW9uIEFwcGVuZGVyKGFwcGVuZGVyTmFtZSwgc2VuZExvZ0l0ZW1zKSB7XHJcbiAgICAgICAgICAgIHRoaXMuYXBwZW5kZXJOYW1lID0gYXBwZW5kZXJOYW1lO1xyXG4gICAgICAgICAgICB0aGlzLnNlbmRMb2dJdGVtcyA9IHNlbmRMb2dJdGVtcztcclxuICAgICAgICAgICAgdGhpcy5sZXZlbCA9IEpMLmdldFRyYWNlTGV2ZWwoKTtcclxuICAgICAgICAgICAgLy8gc2V0IHRvIHN1cGVyIGhpZ2ggbGV2ZWwsIHNvIGlmIHVzZXIgaW5jcmVhc2VzIGxldmVsLCBsZXZlbCBpcyB1bmxpa2VseSB0byBnZXQgXHJcbiAgICAgICAgICAgIC8vIGFib3ZlIHNlbmRXaXRoQnVmZmVyTGV2ZWxcclxuICAgICAgICAgICAgdGhpcy5zZW5kV2l0aEJ1ZmZlckxldmVsID0gMjE0NzQ4MzY0NztcclxuICAgICAgICAgICAgdGhpcy5zdG9yZUluQnVmZmVyTGV2ZWwgPSAtMjE0NzQ4MzY0ODtcclxuICAgICAgICAgICAgdGhpcy5idWZmZXJTaXplID0gMDsgLy8gYnVmZmVyaW5nIHN3aXRjaCBvZmYgYnkgZGVmYXVsdFxyXG4gICAgICAgICAgICB0aGlzLmJhdGNoU2l6ZSA9IDE7XHJcbiAgICAgICAgICAgIHRoaXMubWF4QmF0Y2hTaXplID0gMjA7XHJcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hUaW1lb3V0ID0gMjE0NzQ4MzY0NztcclxuICAgICAgICAgICAgdGhpcy5zZW5kVGltZW91dCA9IDUwMDA7XHJcbiAgICAgICAgICAgIC8vIEhvbGRzIGFsbCBsb2cgaXRlbXMgd2l0aCBsZXZlbHMgaGlnaGVyIHRoYW4gc3RvcmVJbkJ1ZmZlckxldmVsIFxyXG4gICAgICAgICAgICAvLyBidXQgbG93ZXIgdGhhbiBsZXZlbC4gVGhlc2UgaXRlbXMgbWF5IG5ldmVyIGJlIHNlbnQuXHJcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gW107XHJcbiAgICAgICAgICAgIC8vIEhvbGRzIGFsbCBpdGVtcyB0aGF0IHdlIGRvIHdhbnQgdG8gc2VuZCwgdW50aWwgd2UgaGF2ZSBhIGZ1bGxcclxuICAgICAgICAgICAgLy8gYmF0Y2ggKGFzIGRldGVybWluZWQgYnkgYmF0Y2hTaXplKS5cclxuICAgICAgICAgICAgdGhpcy5iYXRjaEJ1ZmZlciA9IFtdO1xyXG4gICAgICAgICAgICAvLyBIb2xkcyB0aGUgaWQgb2YgdGhlIHRpbWVyIGltcGxlbWVudGluZyB0aGUgYmF0Y2ggdGltZW91dC5cclxuICAgICAgICAgICAgLy8gQ2FuIGJlIG51bGwuXHJcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYW4gb2JqZWN0LCBzbyBpdCBjYW4gYmUgcGFzc2VkIHRvIGEgbWV0aG9kIHRoYXQgdXBkYXRlZCB0aGUgdGltZXIgdmFyaWFibGUuXHJcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hUaW1lb3V0VGltZXIgPSB7IGlkOiBudWxsIH07XHJcbiAgICAgICAgICAgIC8vIEhvbGRzIHRoZSBpZCBvZiB0aGUgdGltZXIgaW1wbGVtZW50aW5nIHRoZSBzZW5kIHRpbWVvdXQuXHJcbiAgICAgICAgICAgIC8vIENhbiBiZSBudWxsLlxyXG4gICAgICAgICAgICB0aGlzLnNlbmRUaW1lb3V0VGltZXIgPSB7IGlkOiBudWxsIH07XHJcbiAgICAgICAgICAgIC8vIE51bWJlciBvZiBsb2cgaXRlbXMgdGhhdCBoYXMgYmVlbiBza2lwcGVkIGR1ZSB0byBiYXRjaCBidWZmZXIgYXQgbWF4IHNpemUsXHJcbiAgICAgICAgICAgIC8vIHNpbmNlIGFwcGVuZGVyIGNyZWF0aW9uIG9yIHNpbmNlIGNyZWF0aW9uIG9mIHRoZSBsYXN0IFwic2tpcHBlZFwiIHdhcm5pbmcgbG9nIGVudHJ5LlxyXG4gICAgICAgICAgICB0aGlzLm5ickxvZ0l0ZW1zU2tpcHBlZCA9IDA7XHJcbiAgICAgICAgICAgIC8vIFdpbGwgYmUgMCBpZiBubyBsb2cgcmVxdWVzdCBpcyBvdXRzdGFuZGluZyBhdCB0aGUgbW9tZW50LlxyXG4gICAgICAgICAgICAvLyBPdGhlcndpc2UgdGhlIG51bWJlciBvZiBsb2cgaXRlbXMgaW4gdGhlIG91dHN0YW5kaW5nIHJlcXVlc3QuXHJcbiAgICAgICAgICAgIHRoaXMubmJyTG9nSXRlbXNCZWluZ1NlbnQgPSAwO1xyXG4gICAgICAgICAgICB2YXIgZW1wdHlOYW1lRXJyb3JNZXNzYWdlID0gXCJUcnlpbmcgdG8gY3JlYXRlIGFuIGFwcGVuZGVyIHdpdGhvdXQgYSBuYW1lIG9yIHdpdGggYW4gZW1wdHkgbmFtZVwiO1xyXG4gICAgICAgICAgICAvLyBUaGlzIGV2YWx1YXRlcyB0byB0cnVlIGlmIGFwcGVuZGVyTmFtZSBpcyBlaXRoZXIgbnVsbCBvciB1bmRlZmluZWQhXHJcbiAgICAgICAgICAgIC8vIERvIG5vdCBjaGVjayBoZXJlIGlmIHRoZSBuYW1lIGlzIFwiXCIsIGJlY2F1c2UgdGhhdCB3b3VsZCBzdG9wIHlvdSBjcmVhdGluZyB0aGUgXHJcbiAgICAgICAgICAgIC8vIGRlZmF1bHQgYXBwZW5kZXIuXHJcbiAgICAgICAgICAgIGlmIChhcHBlbmRlck5hbWUgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBlbXB0eU5hbWVFcnJvck1lc3NhZ2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKEpMLl9hcHBlbmRlck5hbWVzLmluZGV4T2YoYXBwZW5kZXJOYW1lKSAhPSAtMSkge1xyXG4gICAgICAgICAgICAgICAgLy8gSWYgdXNlciBwYXNzZWQgaW4gXCJcIiwgdGhhdCB3aWxsIG5vdyBoYXZlIGJlZW4gcGlja2VkIHVwIGFzIGEgZHVwbGljYXRlXHJcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIGRlZmF1bHQgYXBwZW5kZXIgYWxzbyB1c2VzIFwiXCIuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWFwcGVuZGVyTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVtcHR5TmFtZUVycm9yTWVzc2FnZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRocm93IFwiTXVsdGlwbGUgYXBwZW5kZXJzIHVzZSB0aGUgc2FtZSBuYW1lIFwiICsgYXBwZW5kZXJOYW1lO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIEpMLl9hcHBlbmRlck5hbWVzLnB1c2goYXBwZW5kZXJOYW1lKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLmFkZExvZ0l0ZW1zVG9CdWZmZXIgPSBmdW5jdGlvbiAobG9nSXRlbXMpIHtcclxuICAgICAgICAgICAgLy8gSWYgdGhlIGJhdGNoIGJ1ZmZlciBoYXMgcmVhY2hlZCBpdHMgbWF4aW11bSBsaW1pdCwgXHJcbiAgICAgICAgICAgIC8vIHNraXAgdGhlIGxvZyBpdGVtIGFuZCBpbmNyZWFzZSB0aGUgXCJza2lwcGVkIGl0ZW1zXCIgY291bnRlci5cclxuICAgICAgICAgICAgaWYgKHRoaXMuYmF0Y2hCdWZmZXIubGVuZ3RoID49IHRoaXMubWF4QmF0Y2hTaXplKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5ickxvZ0l0ZW1zU2tpcHBlZCArPSBsb2dJdGVtcy5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gSWYgbWF4TWVzc2FnZXMgaXMgbm90IG51bGwgb3IgdW5kZWZpbmVkLCB0aGVuIGRlY3JlYXNlIGl0IGJ5IHRoZSBiYXRjaCBzaXplLlxyXG4gICAgICAgICAgICAvLyBUaGlzIGNhbiByZXN1bHQgaW4gYSBuZWdhdGl2ZSBtYXhNZXNzYWdlcy5cclxuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHVuZGVmaW5lZD09bnVsbCAoISlcclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHdlIG1heSBiZSBzZW5kaW5nIG1vcmUgbWVzc2FnZXMgdGhhbiB0aGUgbWF4TWVzc2FnZXMgbGltaXQgYWxsb3dzLFxyXG4gICAgICAgICAgICAvLyBpZiB3ZSBzdG9yZWQgdHJhY2UgbWVzc2FnZXMuIFJhdGlvbmFsZSBpcyB0aGUgYnVmZmVyIGZvciB0cmFjZSBtZXNzYWdlcyBpcyBsaW1pdGVkLFxyXG4gICAgICAgICAgICAvLyBhbmQgaWYgd2UgY3V0IG9mZiBhdCBleGFjdGx5IG1heE1lc3NhZ2VzLCB3ZSdkIGFsc28gbG9vc2UgdGhlIGhpZ2ggc2V2ZXJpdHkgbWVzc2FnZVxyXG4gICAgICAgICAgICAvLyB0aGF0IGNhdXNlZCB0aGUgdHJhY2UgbWVzc2FnZXMgdG8gYmUgc2VudCAodW5sZXNzIHdlIGNhdGVyIGZvciB0aGlzIHNwZWNpZmljYWxseSwgd2hpY2hcclxuICAgICAgICAgICAgLy8gaXMgbW9yZSBjb21wbGV4aXR5KS5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIG11bHRpcGxlIGFwcGVuZGVycyBzZW5kaW5nIHRoZSBzYW1lIG1lc3NhZ2UsIG1heE1lc3NhZ2Ugd2lsbCBiZSBkZWNyZWFzZWRcclxuICAgICAgICAgICAgLy8gYnkgZWFjaCBhcHBlbmRlciBmb3IgdGhlIHNhbWUgbWVzc2FnZS4gVGhpcyBpczpcclxuICAgICAgICAgICAgLy8gMSkgb25seSBhcHBlbmRlcnMga25vdyB3aGV0aGVyIGEgbWVzc2FnZSB3aWxsIGFjdHVhbGx5IGJlIHNlbnQgKGJhc2VkIG9uIHN0b3JlSW5CdWZmZXJMZXZlbCksXHJcbiAgICAgICAgICAgIC8vICAgIHNvIHRoZSBsb2dnZXJzIGNvdWxkbid0IGRvIHRoaXMgdXBkYXRlO1xyXG4gICAgICAgICAgICAvLyAyKSBpZiB5b3UgaGF2ZSBtdWx0aXBsZSBhcHBlbmRlcnMgaGl0dGluZyB0aGUgc2FtZSBzZXJ2ZXIsIHRoaXMgbWF5IGJlIHdoYXQgeW91IHdhbnQuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIEluIG1vc3QgY2FzZXMgdGhlcmUgaXMgb25seSAxIGFwcGVuZGVyLCBzbyB0aGlzIHRoZW4gZG9lc24ndCBtYXR0ZXIuXHJcbiAgICAgICAgICAgIGlmICghKEpMLm1heE1lc3NhZ2VzID09IG51bGwpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoSkwubWF4TWVzc2FnZXMgPCAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgSkwubWF4TWVzc2FnZXMgLT0gbG9nSXRlbXMubGVuZ3RoO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hCdWZmZXIgPSB0aGlzLmJhdGNoQnVmZmVyLmNvbmNhdChsb2dJdGVtcyk7XHJcbiAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIGJ1ZmZlciwgc2V0IHRoZSB0aW1lclxyXG4gICAgICAgICAgICAvLyB0byBlbnN1cmUgaXQgd2lsbCBiZSBzZW50IHdpdGhpbiB0aGUgdGltZW91dCBwZXJpb2QuXHJcbiAgICAgICAgICAgIC8vIElmIGl0IGlzIG5vdCB0aGUgZmlyc3QgaXRlbSwgbGVhdmUgdGhlIHRpbWVyIGFsb25lIHNvIHRvIG5vdCB0byBcclxuICAgICAgICAgICAgLy8gaW5jcmVhc2UgdGhlIHRpbWVvdXQgZm9yIHRoZSBmaXJzdCBpdGVtLlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBUbyBkZXRlcm1pbmUgaWYgdGhpcyBpcyB0aGUgZmlyc3QgaXRlbSwgbG9vayBhdCB0aGUgdGltZXIgdmFyaWFibGUuXHJcbiAgICAgICAgICAgIC8vIERvIG5vdCBsb29rIGF0IHRoZSBidWZmZXIgbGVuZ3RoLCBiZWNhdXNlIHdlIGFsc28gcHV0IGl0ZW1zIGluIHRoZSBidWZmZXJcclxuICAgICAgICAgICAgLy8gdmlhIGEgY29uY2F0IChieXBhc3NpbmcgdGhpcyBmdW5jdGlvbikuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIFRoZSBzZXRUaW1lciBtZXRob2Qgb25seSBzZXRzIHRoZSB0aW1lciBpZiBpdCBpcyBub3QgYWxyZWFkeSBydW5uaW5nLlxyXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcbiAgICAgICAgICAgIHNldFRpbWVyKHRoaXMuYmF0Y2hUaW1lb3V0VGltZXIsIHRoaXMuYmF0Y2hUaW1lb3V0LCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB0aGF0LnNlbmRCYXRjaC5jYWxsKHRoYXQpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIDtcclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUuYmF0Y2hCdWZmZXJIYXNPdmVyZHVlTWVzc2FnZXMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VBZ2VNcyA9IEpMLl9nZXRUaW1lKCkgLSB0aGlzLmJhdGNoQnVmZmVyW2ldLnQ7XHJcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUFnZU1zID4gdGhpcy5iYXRjaFRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgbm8gbW9yZSBtZXNzYWdlIHdpbGwgZXZlciBiZSBhZGRlZCB0byB0aGUgYmF0Y2ggYnVmZmVyLFxyXG4gICAgICAgIC8vIGJ1dCB0aGUgYmF0Y2ggYnVmZmVyIGhhcyBtZXNzYWdlcyBub3cgLSBzbyBpZiB0aGVyZSBhcmUgbm90IGVub3VnaCB0byBtYWtlIHVwIGEgYmF0Y2gsXHJcbiAgICAgICAgLy8gYW5kIHRoZXJlIGlzIG5vIGJhdGNoIHRpbWVvdXQsIHRoZW4gdGhleSB3aWxsIG5ldmVyIGJlIHNlbnQuIFRoaXMgaXMgZXNwZWNpYWxseSBpbXBvcnRhbnQgaWYgXHJcbiAgICAgICAgLy8gbWF4TWVzc2FnZXMgd2FzIHJlYWNoZWQgd2hpbGUganNubG9nLmpzIHdhcyByZXRyeWluZyBzZW5kaW5nIG1lc3NhZ2VzIHRvIHRoZSBzZXJ2ZXIuXHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLmJhdGNoQnVmZmVySGFzU3RyYW5kZWRNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gKCEoSkwubWF4TWVzc2FnZXMgPT0gbnVsbCkpICYmIChKTC5tYXhNZXNzYWdlcyA8IDEpICYmICh0aGlzLmJhdGNoQnVmZmVyLmxlbmd0aCA+IDApO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLnNlbmRCYXRjaElmQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmICgodGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGggPj0gdGhpcy5iYXRjaFNpemUpIHx8XHJcbiAgICAgICAgICAgICAgICB0aGlzLmJhdGNoQnVmZmVySGFzT3ZlcmR1ZU1lc3NhZ2VzKCkgfHxcclxuICAgICAgICAgICAgICAgIHRoaXMuYmF0Y2hCdWZmZXJIYXNTdHJhbmRlZE1lc3NhZ2UoKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kQmF0Y2goKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLm9uU2VuZGluZ0VuZGVkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVyKHRoaXMuc2VuZFRpbWVvdXRUaW1lcik7XHJcbiAgICAgICAgICAgIHRoaXMubmJyTG9nSXRlbXNCZWluZ1NlbnQgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLnNlbmRCYXRjaElmQ29tcGxldGUoKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIEFwcGVuZGVyLnByb3RvdHlwZS5zZXRPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwibGV2ZWxcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImlwUmVnZXhcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcInVzZXJBZ2VudFJlZ2V4XCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJkaXNhbGxvd1wiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwic2VuZFdpdGhCdWZmZXJMZXZlbFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwic3RvcmVJbkJ1ZmZlckxldmVsXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJidWZmZXJTaXplXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJiYXRjaFNpemVcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcIm1heEJhdGNoU2l6ZVwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiYmF0Y2hUaW1lb3V0XCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJzZW5kVGltZW91dFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuYnVmZmVyU2l6ZSA8IHRoaXMuYnVmZmVyLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5idWZmZXIubGVuZ3RoID0gdGhpcy5idWZmZXJTaXplO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0aGlzLm1heEJhdGNoU2l6ZSA8IHRoaXMuYmF0Y2hTaXplKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSkwuRXhjZXB0aW9uKHtcclxuICAgICAgICAgICAgICAgICAgICBcIm1lc3NhZ2VcIjogXCJtYXhCYXRjaFNpemUgY2Fubm90IGJlIHNtYWxsZXIgdGhhbiBiYXRjaFNpemVcIixcclxuICAgICAgICAgICAgICAgICAgICBcIm1heEJhdGNoU2l6ZVwiOiB0aGlzLm1heEJhdGNoU2l6ZSxcclxuICAgICAgICAgICAgICAgICAgICBcImJhdGNoU2l6ZVwiOiB0aGlzLmJhdGNoU2l6ZVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvKipcclxuICAgICAgICBDYWxsZWQgYnkgYSBsb2dnZXIgdG8gbG9nIGEgbG9nIGl0ZW0uXHJcbiAgICAgICAgSWYgaW4gcmVzcG9uc2UgdG8gdGhpcyBjYWxsIG9uZSBvciBtb3JlIGxvZyBpdGVtcyBuZWVkIHRvIGJlIHByb2Nlc3NlZFxyXG4gICAgICAgIChlZy4sIHNlbnQgdG8gdGhlIHNlcnZlciksIHRoaXMgbWV0aG9kIGNhbGxzIHRoaXMuc2VuZExvZ0l0ZW1zXHJcbiAgICAgICAgd2l0aCBhbiBhcnJheSB3aXRoIGFsbCBpdGVtcyB0byBiZSBwcm9jZXNzZWQuXHJcblxyXG4gICAgICAgIE5vdGUgdGhhdCB0aGUgbmFtZSBhbmQgcGFyYW1ldGVycyBvZiB0aGlzIGZ1bmN0aW9uIG11c3QgbWF0Y2ggdGhvc2Ugb2YgdGhlIGxvZyBmdW5jdGlvbiBvZlxyXG4gICAgICAgIGEgV2luc3RvbiB0cmFuc3BvcnQgb2JqZWN0LCBzbyB0aGF0IHVzZXJzIGNhbiB1c2UgdGhlc2UgdHJhbnNwb3J0cyBhcyBhcHBlbmRlcnMuXHJcbiAgICAgICAgVGhhdCBpcyB3aHkgdGhlcmUgYXJlIG1hbnkgcGFyYW1ldGVycyB0aGF0IGFyZSBub3QgYWN0dWFsbHkgdXNlZCBieSB0aGlzIGZ1bmN0aW9uLlxyXG5cclxuICAgICAgICBsZXZlbCAtIHN0cmluZyB3aXRoIHRoZSBsZXZlbCAoXCJ0cmFjZVwiLCBcImRlYnVnXCIsIGV0Yy4pIE9ubHkgdXNlZCBieSBXaW5zdG9uIHRyYW5zcG9ydHMuXHJcbiAgICAgICAgbXNnIC0gaHVtYW4gcmVhZGFibGUgbWVzc2FnZS4gVW5kZWZpbmVkIGlmIHRoZSBsb2cgaXRlbSBpcyBhbiBvYmplY3QuIE9ubHkgdXNlZCBieSBXaW5zdG9uIHRyYW5zcG9ydHMuXHJcbiAgICAgICAgbWV0YSAtIGxvZyBvYmplY3QuIEFsd2F5cyBkZWZpbmVkLCBiZWNhdXNlIGF0IGxlYXN0IGl0IGNvbnRhaW5zIHRoZSBsb2dnZXIgbmFtZS4gT25seSB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBjYWxsYmFjayAtIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhlIGxvZyBpdGVtIGhhcyBiZWVuIGxvZ2dlZC4gT25seSB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBsZXZlbE5iciAtIGxldmVsIGFzIGEgbnVtYmVyLiBOb3QgdXNlZCBieSBXaW5zdG9uIHRyYW5zcG9ydHMuXHJcbiAgICAgICAgbWVzc2FnZSAtIGxvZyBpdGVtLiBJZiB0aGUgdXNlciBsb2dnZWQgYW4gb2JqZWN0LCB0aGlzIGlzIHRoZSBKU09OIHN0cmluZy4gIE5vdCB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBsb2dnZXJOYW1lOiBuYW1lIG9mIHRoZSBsb2dnZXIuICBOb3QgdXNlZCBieSBXaW5zdG9uIHRyYW5zcG9ydHMuXHJcbiAgICAgICAgKi9cclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUubG9nID0gZnVuY3Rpb24gKGxldmVsLCBtc2csIG1ldGEsIGNhbGxiYWNrLCBsZXZlbE5iciwgbWVzc2FnZSwgbG9nZ2VyTmFtZSkge1xyXG4gICAgICAgICAgICB2YXIgbG9nSXRlbTtcclxuICAgICAgICAgICAgaWYgKCFhbGxvdyh0aGlzKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghYWxsb3dNZXNzYWdlKHRoaXMsIG1lc3NhZ2UpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGxldmVsTmJyIDwgdGhpcy5zdG9yZUluQnVmZmVyTGV2ZWwpIHtcclxuICAgICAgICAgICAgICAgIC8vIElnbm9yZSB0aGUgbG9nIGl0ZW0gY29tcGxldGVseVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGxvZ0l0ZW0gPSBuZXdMb2dJdGVtKGxldmVsTmJyLCBtZXNzYWdlLCBsb2dnZXJOYW1lKTtcclxuICAgICAgICAgICAgaWYgKGxldmVsTmJyIDwgdGhpcy5sZXZlbCkge1xyXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgaW4gdGhlIGhvbGQgYnVmZmVyLiBEbyBub3Qgc2VuZC5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJ1ZmZlclNpemUgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIucHVzaChsb2dJdGVtKTtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBleGNlZWRlZCBtYXggYnVmZmVyIHNpemUsIHJlbW92ZSBvbGRlc3QgaXRlbVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmJ1ZmZlci5sZW5ndGggPiB0aGlzLmJ1ZmZlclNpemUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIuc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gV2FudCB0byBzZW5kIHRoZSBpdGVtXHJcbiAgICAgICAgICAgIHRoaXMuYWRkTG9nSXRlbXNUb0J1ZmZlcihbbG9nSXRlbV0pO1xyXG4gICAgICAgICAgICBpZiAobGV2ZWxOYnIgPj0gdGhpcy5zZW5kV2l0aEJ1ZmZlckxldmVsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBXYW50IHRvIHNlbmQgdGhlIGNvbnRlbnRzIG9mIHRoZSBidWZmZXIuXHJcbiAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgLy8gU2VuZCB0aGUgYnVmZmVyIEFGVEVSIHNlbmRpbmcgdGhlIGhpZ2ggcHJpb3JpdHkgaXRlbS5cclxuICAgICAgICAgICAgICAgIC8vIElmIHlvdSB3ZXJlIHRvIHNlbmQgdGhlIGhpZ2ggcHJpb3JpdHkgaXRlbSBhZnRlciB0aGUgYnVmZmVyLFxyXG4gICAgICAgICAgICAgICAgLy8gaWYgd2UncmUgY2xvc2UgdG8gbWF4TWVzc2FnZXMgb3IgbWF4QmF0Y2hTaXplLFxyXG4gICAgICAgICAgICAgICAgLy8gdGhlbiB0aGUgdHJhY2UgbWVzc2FnZXMgaW4gdGhlIGJ1ZmZlciBjb3VsZCBjcm93ZCBvdXQgdGhlIGFjdHVhbCBoaWdoIHByaW9yaXR5IGl0ZW0uXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5idWZmZXIubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRMb2dJdGVtc1RvQnVmZmVyKHRoaXMuYnVmZmVyKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5sZW5ndGggPSAwO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuc2VuZEJhdGNoSWZDb21wbGV0ZSgpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgO1xyXG4gICAgICAgIC8vIFByb2Nlc3NlcyB0aGUgYmF0Y2ggYnVmZmVyXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBNYWtlIHRoaXMgcHVibGljLCBzbyBpdCBjYW4gYmUgY2FsbGVkIGZyb20gb3V0c2lkZSB0aGUgbGlicmFyeSxcclxuICAgICAgICAvLyB3aGVuIHRoZSBwYWdlIGlzIHVubG9hZGVkLlxyXG4gICAgICAgIEFwcGVuZGVyLnByb3RvdHlwZS5zZW5kQmF0Y2ggPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIC8vIERvIG5vdCBjbGVhciB0aGUgYmF0Y2ggdGltZXIgaWYgeW91IGRvbid0IGdvIGFoZWFkIGhlcmUgYmVjYXVzZVxyXG4gICAgICAgICAgICAvLyBhIHNlbmQgaXMgYWxyZWFkeSBpbiBwcm9ncmVzcy4gT3RoZXJ3aXNlIHRoZSBtZXNzYWdlcyB0aGF0IHdlcmUgc3RvcHBlZCBmcm9tIGdvaW5nIG91dFxyXG4gICAgICAgICAgICAvLyBtYXkgZ2V0IGlnbm9yZWQgYmVjYXVzZSB0aGUgYmF0Y2ggdGltZXIgbmV2ZXIgd2VudCBvZmYuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm5ickxvZ0l0ZW1zQmVpbmdTZW50ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNsZWFyVGltZXIodGhpcy5iYXRjaFRpbWVvdXRUaW1lcik7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmJhdGNoQnVmZmVyLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gRGVjaWRlZCBhdCB0aGlzIHBvaW50IHRvIHNlbmQgY29udGVudHMgb2YgdGhlIGJ1ZmZlclxyXG4gICAgICAgICAgICB0aGlzLm5ickxvZ0l0ZW1zQmVpbmdTZW50ID0gdGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGg7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcclxuICAgICAgICAgICAgc2V0VGltZXIodGhpcy5zZW5kVGltZW91dFRpbWVyLCB0aGlzLnNlbmRUaW1lb3V0LCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB0aGF0Lm9uU2VuZGluZ0VuZGVkLmNhbGwodGhhdCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB0aGlzLnNlbmRMb2dJdGVtcyh0aGlzLmJhdGNoQnVmZmVyLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBMb2cgZW50cmllcyBoYXZlIGJlZW4gc3VjY2Vzc2Z1bGx5IHNlbnQgdG8gc2VydmVyXHJcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGZpcnN0IChuYnJMb2dJdGVtc0JlaW5nU2VudCkgaXRlbXMgaW4gdGhlIGJhdGNoIGJ1ZmZlciwgYmVjYXVzZSB0aGV5IGFyZSB0aGUgb25lc1xyXG4gICAgICAgICAgICAgICAgLy8gdGhhdCB3ZXJlIHNlbnQuXHJcbiAgICAgICAgICAgICAgICB0aGF0LmJhdGNoQnVmZmVyLnNwbGljZSgwLCB0aGF0Lm5ickxvZ0l0ZW1zQmVpbmdTZW50KTtcclxuICAgICAgICAgICAgICAgIC8vIElmIGl0ZW1zIGhhZCB0byBiZSBza2lwcGVkLCBhZGQgYSBXQVJOIG1lc3NhZ2VcclxuICAgICAgICAgICAgICAgIGlmICh0aGF0Lm5ickxvZ0l0ZW1zU2tpcHBlZCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0LmJhdGNoQnVmZmVyLnB1c2gobmV3TG9nSXRlbShnZXRXYXJuTGV2ZWwoKSwgXCJMb3N0IFwiICsgdGhhdC5uYnJMb2dJdGVtc1NraXBwZWQgKyBcIiBtZXNzYWdlcy4gRWl0aGVyIGNvbm5lY3Rpb24gd2l0aCB0aGUgc2VydmVyIHdhcyBkb3duIG9yIGxvZ2dpbmcgd2FzIGRpc2FibGVkIHZpYSB0aGUgZW5hYmxlZCBvcHRpb24uIFJlZHVjZSBsb3N0IG1lc3NhZ2VzIGJ5IGluY3JlYXNpbmcgdGhlIGFqYXhBcHBlbmRlciBvcHRpb24gbWF4QmF0Y2hTaXplLlwiLCB0aGF0LmFwcGVuZGVyTmFtZSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQubmJyTG9nSXRlbXNTa2lwcGVkID0gMDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRoYXQub25TZW5kaW5nRW5kZWQuY2FsbCh0aGF0KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICByZXR1cm4gQXBwZW5kZXI7XHJcbiAgICB9KCkpO1xyXG4gICAgSkwuQXBwZW5kZXIgPSBBcHBlbmRlcjtcclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgdmFyIEFqYXhBcHBlbmRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcclxuICAgICAgICBfX2V4dGVuZHMoQWpheEFwcGVuZGVyLCBfc3VwZXIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIEFqYXhBcHBlbmRlcihhcHBlbmRlck5hbWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIGFwcGVuZGVyTmFtZSwgQWpheEFwcGVuZGVyLnByb3RvdHlwZS5zZW5kTG9nSXRlbXNBamF4KSB8fCB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgICAgICBBamF4QXBwZW5kZXIucHJvdG90eXBlLnNldE9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJ1cmxcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImJlZm9yZVNlbmRcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIF9zdXBlci5wcm90b3R5cGUuc2V0T3B0aW9ucy5jYWxsKHRoaXMsIG9wdGlvbnMpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9O1xyXG4gICAgICAgIEFqYXhBcHBlbmRlci5wcm90b3R5cGUuc2VuZExvZ0l0ZW1zQWpheCA9IGZ1bmN0aW9uIChsb2dJdGVtcywgc3VjY2Vzc0NhbGxiYWNrKSB7XHJcbiAgICAgICAgICAgIC8vIEpTT04uc3RyaW5naWZ5IGlzIG9ubHkgc3VwcG9ydGVkIG9uIElFOCtcclxuICAgICAgICAgICAgLy8gVXNlIHRyeS1jYXRjaCBpbiBjYXNlIHdlIGdldCBhbiBleGNlcHRpb24gaGVyZS5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gVGhlIFwiclwiIGZpZWxkIGlzIG5vdyBvYnNvbGV0ZS4gV2hlbiB3cml0aW5nIGEgc2VydmVyIHNpZGUgY29tcG9uZW50LCBcclxuICAgICAgICAgICAgLy8gcmVhZCB0aGUgSFRUUCBoZWFkZXIgXCJKU05Mb2ctUmVxdWVzdElkXCJcclxuICAgICAgICAgICAgLy8gdG8gZ2V0IHRoZSByZXF1ZXN0IGlkLlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBUaGUgLk5ldCBzZXJ2ZXIgc2lkZSBjb21wb25lbnRcclxuICAgICAgICAgICAgLy8gbm93IHVzZXMgdGhlIEpTTkxvZy1SZXF1ZXN0SWQgSFRUUCBIZWFkZXIsIGJlY2F1c2UgdGhpcyBhbGxvd3MgaXQgdG9cclxuICAgICAgICAgICAgLy8gZGV0ZWN0IHdoZXRoZXIgdGhlIGluY29taW5nIHJlcXVlc3QgaGFzIGEgcmVxdWVzdCBpZC5cclxuICAgICAgICAgICAgLy8gSWYgdGhlIHJlcXVlc3QgaWQgd2VyZSBpbiB0aGUganNvbiBwYXlsb2FkLCBpdCB3b3VsZCBoYXZlIHRvIHJlYWQgdGhlIGpzb25cclxuICAgICAgICAgICAgLy8gZnJvbSB0aGUgc3RyZWFtLCBpbnRlcmZlcmluZyB3aXRoIG5vcm1hbCBub24tbG9nZ2luZyByZXF1ZXN0cy5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gVG8gc2VlIHdoYXQgY2hhcmFjdGVycyB5b3UgY2FuIHVzZSBpbiB0aGUgSFRUUCBoZWFkZXIsIHZpc2l0OlxyXG4gICAgICAgICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NjEzODEvY3VzdG9tLWh0dHAtaGVhZGVycy1uYW1pbmctY29udmVudGlvbnMvMzU2MTM5OSMzNTYxMzk5XHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIEl0IG5lZWRzIHRoaXMgYWJpbGl0eSwgc28gdXNlcnMgb2YgTkxvZyBjYW4gc2V0IGEgcmVxdWVzdElkIHZhcmlhYmxlIGluIE5Mb2dcclxuICAgICAgICAgICAgLy8gYmVmb3JlIHRoZSBzZXJ2ZXIgc2lkZSBjb21wb25lbnQgdHJpZXMgdG8gbG9nIHRoZSBjbGllbnQgc2lkZSBsb2cgbWVzc2FnZVxyXG4gICAgICAgICAgICAvLyB0aHJvdWdoIGFuIE5Mb2cgbG9nZ2VyLlxyXG4gICAgICAgICAgICAvLyBVbmxpa2UgTG9nNE5ldCwgTkxvZyBkb2Vzbid0IGFsbG93IHlvdSB0byByZWdpc3RlciBhbiBvYmplY3Qgd2hvc2UgVG9TdHJpbmcoKVxyXG4gICAgICAgICAgICAvLyBpcyBvbmx5IGNhbGxlZCB3aGVuIGl0IHRyaWVzIHRvIGxvZyBzb21ldGhpbmcsIHNvIHRoZSByZXF1ZXN0SWQgaGFzIHRvIGJlIFxyXG4gICAgICAgICAgICAvLyBkZXRlcm1pbmVkIHJpZ2h0IGF0IHRoZSBzdGFydCBvZiByZXF1ZXN0IHByb2Nlc3NpbmcuXHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEbyBub3Qgc2VuZCBsb2dzLCBpZiBKTC5lbmFibGVkIGlzIHNldCB0byBmYWxzZS5cclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyBEbyBub3QgY2FsbCBzdWNjZXNzQ2FsbGJhY2sgaGVyZS4gQWZ0ZXIgZWFjaCB0aW1lb3V0LCBqc25sb2cgd2lsbCByZXRyeSBzZW5kaW5nIHRoZSBtZXNzYWdlLlxyXG4gICAgICAgICAgICAgICAgLy8gSWYganNubG9nIGdldHMgcmUtZW5hYmxlZCwgaXQgd2lsbCB0aGVuIGxvZyB0aGUgbnVtYmVyIG9mIG1lc3NhZ2VzIGxvZ2dlZC5cclxuICAgICAgICAgICAgICAgIC8vIElmIGl0IGRvZXNuJ3QgZ2V0IHJlLWVuYWJsZWQsIGFtb3VudCBvZiBjcHUgY3ljbGVzIHdhc3RlZCBpcyBtaW5pbWFsLlxyXG4gICAgICAgICAgICAgICAgaWYgKCFhbGxvdyh0aGlzKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIElmIGEgcmVxdWVzdCBpcyBpbiBwcm9ncmVzcywgYWJvcnQgaXQuXHJcbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UsIGl0IG1heSBjYWxsIHRoZSBzdWNjZXNzIGNhbGxiYWNrLCB3aGljaCB3aWxsIGJlIHZlcnkgY29uZnVzaW5nLlxyXG4gICAgICAgICAgICAgICAgLy8gSXQgbWF5IGFsc28gc3RvcCB0aGUgaW5mbGlnaHQgcmVxdWVzdCBmcm9tIHJlc3VsdGluZyBpbiBhIGxvZyBhdCB0aGUgc2VydmVyLlxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMueGhyICYmICh0aGlzLnhoci5yZWFkeVN0YXRlICE9IDApICYmICh0aGlzLnhoci5yZWFkeVN0YXRlICE9IDQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy54aHIuYWJvcnQoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIEJlY2F1c2UgYSByZWFjdC1uYXRpdmUgWE1MSHR0cFJlcXVlc3QgY2Fubm90IGJlIHJldXNlZCBpdCBuZWVkcyB0byBiZSByZWNyZWF0ZWQgd2l0aCBlYWNoIHJlcXVlc3RcclxuICAgICAgICAgICAgICAgIHRoaXMueGhyID0gSkwuX2NyZWF0ZVhNTEh0dHBSZXF1ZXN0KCk7XHJcbiAgICAgICAgICAgICAgICAvLyBPbmx5IGRldGVybWluZSB0aGUgdXJsIHJpZ2h0IGJlZm9yZSB5b3Ugc2VuZCBhIGxvZyByZXF1ZXN0LlxyXG4gICAgICAgICAgICAgICAgLy8gRG8gbm90IHNldCB0aGUgdXJsIHdoZW4gY29uc3RydWN0aW5nIHRoZSBhcHBlbmRlci5cclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGJlY2F1c2UgdGhlIHNlcnZlciBzaWRlIGNvbXBvbmVudCBzZXRzIGRlZmF1bHRBamF4VXJsXHJcbiAgICAgICAgICAgICAgICAvLyBpbiBhIGNhbGwgdG8gc2V0T3B0aW9ucywgQUZURVIgdGhlIEpMIG9iamVjdCBhbmQgdGhlIGRlZmF1bHQgYXBwZW5kZXJcclxuICAgICAgICAgICAgICAgIC8vIGhhdmUgYmVlbiBjcmVhdGVkLiBcclxuICAgICAgICAgICAgICAgIHZhciBhamF4VXJsID0gXCIvanNubG9nLmxvZ2dlclwiO1xyXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBldmFsdWF0ZXMgdG8gdHJ1ZSBpZiBkZWZhdWx0QWpheFVybCBpcyBudWxsIG9yIHVuZGVmaW5lZFxyXG4gICAgICAgICAgICAgICAgaWYgKCEoSkwuZGVmYXVsdEFqYXhVcmwgPT0gbnVsbCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBhamF4VXJsID0gSkwuZGVmYXVsdEFqYXhVcmw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51cmwpIHtcclxuICAgICAgICAgICAgICAgICAgICBhamF4VXJsID0gdGhpcy51cmw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLnhoci5vcGVuKCdQT1NUJywgYWpheFVybCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnhoci5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy54aHIuc2V0UmVxdWVzdEhlYWRlcignSlNOTG9nLVJlcXVlc3RJZCcsIEpMLnJlcXVlc3RJZCk7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT24gbW9zdCBicm93c2VycywgaWYgdGhlIHJlcXVlc3QgZmFpbHMgKGVnLiBpbnRlcm5ldCBpcyBnb25lKSxcclxuICAgICAgICAgICAgICAgICAgICAvLyBpdCB3aWxsIHNldCB4aHIucmVhZHlTdGF0ZSA9PSA0IGFuZCB4aHIuc3RhdHVzICE9IDIwMCAoMCBpZiByZXF1ZXN0IGNvdWxkIG5vdCBiZSBzZW50KSBpbW1lZGlhdGVseS5cclxuICAgICAgICAgICAgICAgICAgICAvLyBIb3dldmVyLCBFZGdlIGFuZCBJRSB3aWxsIG5vdCBjaGFuZ2UgdGhlIHJlYWR5U3RhdGUgYXQgYWxsIGlmIHRoZSBpbnRlcm5ldCBnb2VzIGF3YXkgd2hpbGUgd2FpdGluZ1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGZvciBhIHJlc3BvbnNlLlxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFNvbWUgc2VydmVycyB3aWxsIHJldHVybiBhIDIwNCAoc3VjY2Vzcywgbm8gY29udGVudCkgd2hlbiB0aGUgSlNOTG9nIGVuZHBvaW50XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gcmV0dXJucyB0aGUgZW1wdHkgcmVzcG9uc2UuIFNvIGNoZWNrIG9uIGFueSBjb2RlIGluIHRoZSAyLi4gcmFuZ2UsIG5vdCBqdXN0IDIwMC5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoKHRoYXQueGhyLnJlYWR5U3RhdGUgPT0gNCkgJiYgKHRoYXQueGhyLnN0YXR1cyA+PSAyMDAgJiYgdGhhdC54aHIuc3RhdHVzIDwgMzAwKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgdmFyIGpzb24gPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcjogSkwucmVxdWVzdElkLFxyXG4gICAgICAgICAgICAgICAgICAgIGxnOiBsb2dJdGVtc1xyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIC8vIGNhbGwgYmVmb3JlU2VuZCBjYWxsYmFja1xyXG4gICAgICAgICAgICAgICAgLy8gZmlyc3QgdHJ5IHRoZSBjYWxsYmFjayBvbiB0aGUgYXBwZW5kZXJcclxuICAgICAgICAgICAgICAgIC8vIHRoZW4gdGhlIGdsb2JhbCBkZWZhdWx0QmVmb3JlU2VuZCBjYWxsYmFja1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmJlZm9yZVNlbmQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZm9yZVNlbmQuY2FsbCh0aGlzLCB0aGlzLnhociwganNvbik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgSkwuZGVmYXVsdEJlZm9yZVNlbmQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICBKTC5kZWZhdWx0QmVmb3JlU2VuZC5jYWxsKHRoaXMsIHRoaXMueGhyLCBqc29uKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHZhciBmaW5hbG1zZyA9IEpTT04uc3RyaW5naWZ5KGpzb24pO1xyXG4gICAgICAgICAgICAgICAgdGhpcy54aHIuc2VuZChmaW5hbG1zZyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmV0dXJuIEFqYXhBcHBlbmRlcjtcclxuICAgIH0oQXBwZW5kZXIpKTtcclxuICAgIEpMLkFqYXhBcHBlbmRlciA9IEFqYXhBcHBlbmRlcjtcclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgdmFyIENvbnNvbGVBcHBlbmRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcclxuICAgICAgICBfX2V4dGVuZHMoQ29uc29sZUFwcGVuZGVyLCBfc3VwZXIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIENvbnNvbGVBcHBlbmRlcihhcHBlbmRlck5hbWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIGFwcGVuZGVyTmFtZSwgQ29uc29sZUFwcGVuZGVyLnByb3RvdHlwZS5zZW5kTG9nSXRlbXNDb25zb2xlKSB8fCB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgICAgICBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLmNsb2cgPSBmdW5jdGlvbiAobG9nRW50cnkpIHtcclxuICAgICAgICAgICAgSkwuX2NvbnNvbGUubG9nKGxvZ0VudHJ5KTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIENvbnNvbGVBcHBlbmRlci5wcm90b3R5cGUuY2Vycm9yID0gZnVuY3Rpb24gKGxvZ0VudHJ5KSB7XHJcbiAgICAgICAgICAgIGlmIChKTC5fY29uc29sZS5lcnJvcikge1xyXG4gICAgICAgICAgICAgICAgSkwuX2NvbnNvbGUuZXJyb3IobG9nRW50cnkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9nKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgQ29uc29sZUFwcGVuZGVyLnByb3RvdHlwZS5jd2FybiA9IGZ1bmN0aW9uIChsb2dFbnRyeSkge1xyXG4gICAgICAgICAgICBpZiAoSkwuX2NvbnNvbGUud2Fybikge1xyXG4gICAgICAgICAgICAgICAgSkwuX2NvbnNvbGUud2Fybihsb2dFbnRyeSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNsb2cobG9nRW50cnkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLmNpbmZvID0gZnVuY3Rpb24gKGxvZ0VudHJ5KSB7XHJcbiAgICAgICAgICAgIGlmIChKTC5fY29uc29sZS5pbmZvKSB7XHJcbiAgICAgICAgICAgICAgICBKTC5fY29uc29sZS5pbmZvKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2xvZyhsb2dFbnRyeSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICAgIC8vIElFMTEgaGFzIGEgY29uc29sZS5kZWJ1ZyBmdW5jdGlvbi4gQnV0IGl0cyBjb25zb2xlIGRvZXNuJ3QgaGF2ZSBcclxuICAgICAgICAvLyB0aGUgb3B0aW9uIHRvIHNob3cvaGlkZSBkZWJ1ZyBtZXNzYWdlcyAodGhlIHNhbWUgd2F5IENocm9tZSBhbmQgRkYgZG8pLFxyXG4gICAgICAgIC8vIGV2ZW4gdGhvdWdoIGl0IGRvZXMgaGF2ZSBzdWNoIGJ1dHRvbnMgZm9yIEVycm9yLCBXYXJuLCBJbmZvLlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gRm9yIG5vdywgdGhpcyBtZWFucyB0aGF0IGRlYnVnIG1lc3NhZ2VzIGNhbiBub3QgYmUgaGlkZGVuIG9uIElFLlxyXG4gICAgICAgIC8vIExpdmUgd2l0aCB0aGlzLCBzZWVpbmcgdGhhdCBpdCB3b3JrcyBmaW5lIG9uIEZGIGFuZCBDaHJvbWUsIHdoaWNoXHJcbiAgICAgICAgLy8gd2lsbCBiZSBtdWNoIG1vcmUgcG9wdWxhciB3aXRoIGRldmVsb3BlcnMuXHJcbiAgICAgICAgQ29uc29sZUFwcGVuZGVyLnByb3RvdHlwZS5jZGVidWcgPSBmdW5jdGlvbiAobG9nRW50cnkpIHtcclxuICAgICAgICAgICAgaWYgKEpMLl9jb25zb2xlLmRlYnVnKSB7XHJcbiAgICAgICAgICAgICAgICBKTC5fY29uc29sZS5kZWJ1Zyhsb2dFbnRyeSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNpbmZvKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgQ29uc29sZUFwcGVuZGVyLnByb3RvdHlwZS5zZW5kTG9nSXRlbXNDb25zb2xlID0gZnVuY3Rpb24gKGxvZ0l0ZW1zLCBzdWNjZXNzQ2FsbGJhY2spIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBzZW5kIGxvZ3MsIGlmIEpMLmVuYWJsZWQgaXMgc2V0IHRvIGZhbHNlXHJcbiAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgLy8gRG8gbm90IGNhbGwgc3VjY2Vzc0NhbGxiYWNrIGhlcmUuIEFmdGVyIGVhY2ggdGltZW91dCwganNubG9nIHdpbGwgcmV0cnkgc2VuZGluZyB0aGUgbWVzc2FnZS5cclxuICAgICAgICAgICAgICAgIC8vIElmIGpzbmxvZyBnZXRzIHJlLWVuYWJsZWQsIGl0IHdpbGwgdGhlbiBsb2cgdGhlIG51bWJlciBvZiBtZXNzYWdlcyBsb2dnZWQuXHJcbiAgICAgICAgICAgICAgICAvLyBJZiBpdCBkb2Vzbid0IGdldCByZS1lbmFibGVkLCBhbW91bnQgb2YgY3B1IGN5Y2xlcyB3YXN0ZWQgaXMgbWluaW1hbC5cclxuICAgICAgICAgICAgICAgIGlmICghYWxsb3codGhpcykpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoIUpMLl9jb25zb2xlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdmFyIGk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbG9nSXRlbXMubGVuZ3RoOyArK2kpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbGkgPSBsb2dJdGVtc1tpXTtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbXNnID0gbGkubiArIFwiOiBcIiArIGxpLm07XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSBsb2cgdGhlIHRpbWVzdGFtcCBpZiB3ZSdyZSBvbiB0aGUgc2VydmVyXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gKHdpbmRvdyBpcyB1bmRlZmluZWQpLiBPbiB0aGUgYnJvd3NlciwgdGhlIHVzZXJcclxuICAgICAgICAgICAgICAgICAgICAvLyBzZWVzIHRoZSBsb2cgZW50cnkgcHJvYmFibHkgaW1tZWRpYXRlbHksIHNvIGluIHRoYXQgY2FzZVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSB0aW1lc3RhbXAgaXMgY2x1dHRlci5cclxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbXNnID0gbmV3IERhdGUobGkudCkgKyBcIiB8IFwiICsgbXNnO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAobGkubCA8PSBKTC5nZXREZWJ1Z0xldmVsKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jZGVidWcobXNnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobGkubCA8PSBKTC5nZXRJbmZvTGV2ZWwoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNpbmZvKG1zZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGxpLmwgPD0gSkwuZ2V0V2FybkxldmVsKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jd2Fybihtc2cpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jZXJyb3IobXNnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJldHVybiBDb25zb2xlQXBwZW5kZXI7XHJcbiAgICB9KEFwcGVuZGVyKSk7XHJcbiAgICBKTC5Db25zb2xlQXBwZW5kZXIgPSBDb25zb2xlQXBwZW5kZXI7XHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgdmFyIExvZ2dlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBmdW5jdGlvbiBMb2dnZXIobG9nZ2VyTmFtZSkge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ2dlck5hbWUgPSBsb2dnZXJOYW1lO1xyXG4gICAgICAgICAgICAvLyBDcmVhdGUgc2VlblJleGVzLCBvdGhlcndpc2UgdGhpcyBsb2dnZXIgd2lsbCB1c2UgdGhlIHNlZW5SZXhlc1xyXG4gICAgICAgICAgICAvLyBvZiBpdHMgcGFyZW50IHZpYSB0aGUgcHJvdG90eXBlIGNoYWluLlxyXG4gICAgICAgICAgICB0aGlzLnNlZW5SZWdleGVzID0gW107XHJcbiAgICAgICAgfVxyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuc2V0T3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImxldmVsXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJ1c2VyQWdlbnRSZWdleFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiZGlzYWxsb3dcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImlwUmVnZXhcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImFwcGVuZGVyc1wiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwib25jZU9ubHlcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIC8vIFJlc2V0IHNlZW5SZWdleGVzLCBpbiBjYXNlIG9uY2VPbmx5IGhhcyBiZWVuIGNoYW5nZWQuXHJcbiAgICAgICAgICAgIHRoaXMuc2VlblJlZ2V4ZXMgPSBbXTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvLyBUdXJucyBhbiBleGNlcHRpb24gaW50byBhbiBvYmplY3QgdGhhdCBjYW4gYmUgc2VudCB0byB0aGUgc2VydmVyLlxyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuYnVpbGRFeGNlcHRpb25PYmplY3QgPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICB2YXIgZXhjT2JqZWN0ID0ge307XHJcbiAgICAgICAgICAgIGlmIChlLnN0YWNrKSB7XHJcbiAgICAgICAgICAgICAgICBleGNPYmplY3Quc3RhY2sgPSBlLnN0YWNrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZXhjT2JqZWN0LmUgPSBlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChlLm1lc3NhZ2UpIHtcclxuICAgICAgICAgICAgICAgIGV4Y09iamVjdC5tZXNzYWdlID0gZS5tZXNzYWdlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChlLm5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGV4Y09iamVjdC5uYW1lID0gZS5uYW1lO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChlLmRhdGEpIHtcclxuICAgICAgICAgICAgICAgIGV4Y09iamVjdC5kYXRhID0gZS5kYXRhO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChlLmlubmVyKSB7XHJcbiAgICAgICAgICAgICAgICBleGNPYmplY3QuaW5uZXIgPSB0aGlzLmJ1aWxkRXhjZXB0aW9uT2JqZWN0KGUuaW5uZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBleGNPYmplY3Q7XHJcbiAgICAgICAgfTtcclxuICAgICAgICAvLyBMb2dzIGEgbG9nIGl0ZW0uXHJcbiAgICAgICAgLy8gUGFyYW1ldGVyIGUgY29udGFpbnMgYW4gZXhjZXB0aW9uIChvciBudWxsIG9yIHVuZGVmaW5lZCkuXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBSZWFzb24gdGhhdCBwcm9jZXNzaW5nIGV4Y2VwdGlvbnMgaXMgZG9uZSBhdCB0aGlzIGxvdyBsZXZlbCBpcyB0aGF0XHJcbiAgICAgICAgLy8gMSkgbm8gbmVlZCB0byBzcGVuZCB0aGUgY3B1IGN5Y2xlcyBpZiB0aGUgbG9nZ2VyIGlzIHN3aXRjaGVkIG9mZlxyXG4gICAgICAgIC8vIDIpIGZhdGFsRXhjZXB0aW9uIHRha2VzIGJvdGggYSBsb2dPYmplY3QgYW5kIGFuIGV4Y2VwdGlvbiwgYW5kIHRoZSBsb2dPYmplY3RcclxuICAgICAgICAvLyAgICBtYXkgYmUgYSBmdW5jdGlvbiB0aGF0IHNob3VsZCBvbmx5IGJlIGV4ZWN1dGVkIGlmIHRoZSBsb2dnZXIgaXMgc3dpdGNoZWQgb24uXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBJZiBhbiBleGNlcHRpb24gaXMgcGFzc2VkIGluLCB0aGUgY29udGVudHMgb2YgbG9nT2JqZWN0IGlzIGF0dGFjaGVkIHRvIHRoZSBleGNlcHRpb25cclxuICAgICAgICAvLyBvYmplY3QgaW4gYSBuZXcgcHJvcGVydHkgbG9nRGF0YS5cclxuICAgICAgICAvLyBUaGUgcmVzdWx0aW5nIGV4Y2VwdGlvbiBvYmplY3QgaXMgdGhhbiB3b3JrZWQgaW50byBhIG1lc3NhZ2UgdG8gdGhlIHNlcnZlci5cclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIG5vIGV4Y2VwdGlvbiwgbG9nT2JqZWN0IGl0c2VsZiBpcyB3b3JrZWQgaW50byB0aGUgbWVzc2FnZSB0byB0aGUgc2VydmVyLlxyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUubG9nID0gZnVuY3Rpb24gKGxldmVsLCBsb2dPYmplY3QsIGUpIHtcclxuICAgICAgICAgICAgdmFyIGkgPSAwO1xyXG4gICAgICAgICAgICB2YXIgY29tcG9zaXRlTWVzc2FnZTtcclxuICAgICAgICAgICAgdmFyIGV4Y09iamVjdDtcclxuICAgICAgICAgICAgLy8gSWYgd2UgY2FuJ3QgZmluZCBhbnkgYXBwZW5kZXJzLCBkbyBub3RoaW5nXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5hcHBlbmRlcnMpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICgoKGxldmVsID49IHRoaXMubGV2ZWwpKSAmJiBhbGxvdyh0aGlzKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBleGNPYmplY3QgPSB0aGlzLmJ1aWxkRXhjZXB0aW9uT2JqZWN0KGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGV4Y09iamVjdC5sb2dEYXRhID0gc3RyaW5naWZ5TG9nT2JqZWN0RnVuY3Rpb24obG9nT2JqZWN0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGV4Y09iamVjdCA9IGxvZ09iamVjdDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGNvbXBvc2l0ZU1lc3NhZ2UgPSBzdHJpbmdpZnlMb2dPYmplY3QoZXhjT2JqZWN0KTtcclxuICAgICAgICAgICAgICAgIGlmIChhbGxvd01lc3NhZ2UodGhpcywgY29tcG9zaXRlTWVzc2FnZS5maW5hbFN0cmluZykpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBTZWUgd2hldGhlciBtZXNzYWdlIGlzIGEgZHVwbGljYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMub25jZU9ubHkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaSA9IHRoaXMub25jZU9ubHkubGVuZ3RoIC0gMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5ldyBSZWdFeHAodGhpcy5vbmNlT25seVtpXSkudGVzdChjb21wb3NpdGVNZXNzYWdlLmZpbmFsU3RyaW5nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlZW5SZWdleGVzW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlZW5SZWdleGVzW2ldID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIG1lc3NhZ2UgdG8gYWxsIGFwcGVuZGVyc1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB0aGVzZSBhcHBlbmRlcnMgY291bGQgYmUgV2luc3RvbiB0cmFuc3BvcnRzXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2ZsYXRpcm9uL3dpbnN0b25cclxuICAgICAgICAgICAgICAgICAgICBjb21wb3NpdGVNZXNzYWdlLm1ldGEgPSBjb21wb3NpdGVNZXNzYWdlLm1ldGEgfHwge307XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZSB0aGF0IGlmIHRoZSB1c2VyIGlzIGxvZ2dpbmcgYW4gb2JqZWN0LCBjb21wb3NpdGVNZXNzYWdlLm1ldGEgd2lsbCBob2xkIGEgcmVmZXJlbmNlIHRvIHRoYXQgb2JqZWN0LlxyXG4gICAgICAgICAgICAgICAgICAgIC8vIERvIG5vdCBhZGQgZmllbGRzIHRvIGNvbXBvc2l0ZU1lc3NhZ2UubWV0YSwgb3RoZXJ3aXNlIHRoZSB1c2VyJ3Mgb2JqZWN0IHdpbGwgZ2V0IHRoYXQgZmllbGQgb3V0IG9mIHRoZSBibHVlLlxyXG4gICAgICAgICAgICAgICAgICAgIGkgPSB0aGlzLmFwcGVuZGVycy5sZW5ndGggLSAxO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChpID49IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hcHBlbmRlcnNbaV0ubG9nKGxldmVsVG9TdHJpbmcobGV2ZWwpLCBjb21wb3NpdGVNZXNzYWdlLm1zZywgY29tcG9zaXRlTWVzc2FnZS5tZXRhLCBmdW5jdGlvbiAoKSB7IH0sIGxldmVsLCBjb21wb3NpdGVNZXNzYWdlLmZpbmFsU3RyaW5nLCB0aGlzLmxvZ2dlck5hbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpLS07XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS50cmFjZSA9IGZ1bmN0aW9uIChsb2dPYmplY3QpIHsgcmV0dXJuIHRoaXMubG9nKGdldFRyYWNlTGV2ZWwoKSwgbG9nT2JqZWN0KTsgfTtcclxuICAgICAgICBMb2dnZXIucHJvdG90eXBlLmRlYnVnID0gZnVuY3Rpb24gKGxvZ09iamVjdCkgeyByZXR1cm4gdGhpcy5sb2coZ2V0RGVidWdMZXZlbCgpLCBsb2dPYmplY3QpOyB9O1xyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuaW5mbyA9IGZ1bmN0aW9uIChsb2dPYmplY3QpIHsgcmV0dXJuIHRoaXMubG9nKGdldEluZm9MZXZlbCgpLCBsb2dPYmplY3QpOyB9O1xyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUud2FybiA9IGZ1bmN0aW9uIChsb2dPYmplY3QpIHsgcmV0dXJuIHRoaXMubG9nKGdldFdhcm5MZXZlbCgpLCBsb2dPYmplY3QpOyB9O1xyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuZXJyb3IgPSBmdW5jdGlvbiAobG9nT2JqZWN0KSB7IHJldHVybiB0aGlzLmxvZyhnZXRFcnJvckxldmVsKCksIGxvZ09iamVjdCk7IH07XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5mYXRhbCA9IGZ1bmN0aW9uIChsb2dPYmplY3QpIHsgcmV0dXJuIHRoaXMubG9nKGdldEZhdGFsTGV2ZWwoKSwgbG9nT2JqZWN0KTsgfTtcclxuICAgICAgICBMb2dnZXIucHJvdG90eXBlLmZhdGFsRXhjZXB0aW9uID0gZnVuY3Rpb24gKGxvZ09iamVjdCwgZSkgeyByZXR1cm4gdGhpcy5sb2coZ2V0RmF0YWxMZXZlbCgpLCBsb2dPYmplY3QsIGUpOyB9O1xyXG4gICAgICAgIHJldHVybiBMb2dnZXI7XHJcbiAgICB9KCkpO1xyXG4gICAgSkwuTG9nZ2VyID0gTG9nZ2VyO1xyXG4gICAgZnVuY3Rpb24gY3JlYXRlQWpheEFwcGVuZGVyKGFwcGVuZGVyTmFtZSkge1xyXG4gICAgICAgIHJldHVybiBuZXcgQWpheEFwcGVuZGVyKGFwcGVuZGVyTmFtZSk7XHJcbiAgICB9XHJcbiAgICBKTC5jcmVhdGVBamF4QXBwZW5kZXIgPSBjcmVhdGVBamF4QXBwZW5kZXI7XHJcbiAgICBmdW5jdGlvbiBjcmVhdGVDb25zb2xlQXBwZW5kZXIoYXBwZW5kZXJOYW1lKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDb25zb2xlQXBwZW5kZXIoYXBwZW5kZXJOYW1lKTtcclxuICAgIH1cclxuICAgIEpMLmNyZWF0ZUNvbnNvbGVBcHBlbmRlciA9IGNyZWF0ZUNvbnNvbGVBcHBlbmRlcjtcclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAvLyBJbiB0aGUgYnJvd3NlciwgdGhlIGRlZmF1bHQgYXBwZW5kZXIgaXMgdGhlIEFqYXhBcHBlbmRlci5cclxuICAgIC8vIFVuZGVyIG5vZGVqcyAod2hlcmUgdGhlcmUgaXMgbm8gXCJ3aW5kb3dcIiksIHVzZSB0aGUgQ29uc29sZUFwcGVuZGVyIGluc3RlYWQuXHJcbiAgICAvLyBcclxuICAgIC8vIERvIE5PVCBjcmVhdGUgYW4gQWpheEFwcGVuZGVyIG9iamVjdCBpZiB5b3UgYXJlIG5vdCBvbiBhIGJyb3dzZXIgKHRoYXQgaXMsIHdpbmRvdyBpcyBub3QgZGVmaW5lZCkuXHJcbiAgICAvLyBUaGF0IHdvdWxkIHRyeSB0byBjcmVhdGUgYW4gWG1sSHR0cFJlcXVlc3Qgb2JqZWN0LCB3aGljaCB3aWxsIGNyYXNoIG91dHNpZGUgYSBicm93c2VyLlxyXG4gICAgdmFyIGRlZmF1bHRBcHBlbmRlcjtcclxuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgIGRlZmF1bHRBcHBlbmRlciA9IG5ldyBBamF4QXBwZW5kZXIoXCJcIik7XHJcbiAgICB9XHJcbiAgICBlbHNlIHtcclxuICAgICAgICBkZWZhdWx0QXBwZW5kZXIgPSBuZXcgQ29uc29sZUFwcGVuZGVyKFwiXCIpO1xyXG4gICAgfVxyXG4gICAgLy8gQ3JlYXRlIHJvb3QgbG9nZ2VyXHJcbiAgICAvL1xyXG4gICAgLy8gTm90ZSB0aGF0IHRoaXMgaXMgdGhlIHBhcmVudCBvZiBhbGwgb3RoZXIgbG9nZ2Vycy5cclxuICAgIC8vIExvZ2dlciBcInhcIiB3aWxsIGJlIHN0b3JlZCBhdFxyXG4gICAgLy8gSkwuX18ueFxyXG4gICAgLy8gTG9nZ2VyIFwieC55XCIgYXRcclxuICAgIC8vIEpMLl9fLngueVxyXG4gICAgSkwuX18gPSBuZXcgSkwuTG9nZ2VyKFwiXCIpO1xyXG4gICAgSkwuX18uc2V0T3B0aW9ucyh7XHJcbiAgICAgICAgbGV2ZWw6IEpMLmdldERlYnVnTGV2ZWwoKSxcclxuICAgICAgICBhcHBlbmRlcnM6IFtkZWZhdWx0QXBwZW5kZXJdXHJcbiAgICB9KTtcclxufSkoSkwgfHwgKEpMID0ge30pKTtcclxuaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgLy8gQWxsb3dzIFN5c3RlbUpzIHRvIGltcG9ydCBqc25sb2cuanMuIFNlZVxyXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21wZXJkZWNrL2pzbmxvZy5qcy9pc3N1ZXMvNTZcclxuICAgIGV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XHJcbiAgICBleHBvcnRzLkpMID0gSkw7XHJcbn1cclxuLy8gU3VwcG9ydCBBTUQgbW9kdWxlIGZvcm1hdFxyXG52YXIgZGVmaW5lO1xyXG5pZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcclxuICAgIGRlZmluZSgnanNubG9nJywgW10sIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gSkw7XHJcbiAgICB9KTtcclxufVxyXG4vLyBJZiB0aGUgX19qc25sb2dfY29uZmlndXJlIGdsb2JhbCBmdW5jdGlvbiBoYXMgYmVlblxyXG4vLyBjcmVhdGVkLCBjYWxsIGl0IG5vdy4gVGhpcyBhbGxvd3MgeW91IHRvIGNyZWF0ZSBhIGdsb2JhbCBmdW5jdGlvblxyXG4vLyBzZXR0aW5nIGxvZ2dlciBvcHRpb25zIGV0Yy4gaW5saW5lIGluIHRoZSBwYWdlIGJlZm9yZSBqc25sb2cuanNcclxuLy8gaGFzIGJlZW4gbG9hZGVkLlxyXG5pZiAodHlwZW9mIF9fanNubG9nX2NvbmZpZ3VyZSA9PSAnZnVuY3Rpb24nKSB7XHJcbiAgICBfX2pzbmxvZ19jb25maWd1cmUoSkwpO1xyXG59XHJcbi8vIENyZWF0ZSBvbmVycm9yIGhhbmRsZXIgdG8gbG9nIHVuY2F1Z2h0IGV4Y2VwdGlvbnMgdG8gdGhlIHNlcnZlciBzaWRlIGxvZywgYnV0IG9ubHkgaWYgdGhlcmUgXHJcbi8vIGlzIG5vIHN1Y2ggaGFuZGxlciBhbHJlYWR5LlxyXG4vLyBNdXN0IHVzZSBcInR5cGVvZiB3aW5kb3dcIiBoZXJlLCBiZWNhdXNlIGluIE5vZGVKcywgd2luZG93IGlzIG5vdCBkZWZpbmVkIGF0IGFsbCwgc28gY2Fubm90IHJlZmVyIHRvIHdpbmRvdyBpbiBhbnkgd2F5LlxyXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgIXdpbmRvdy5vbmVycm9yKSB7XHJcbiAgICB3aW5kb3cub25lcnJvciA9IGZ1bmN0aW9uIChlcnJvck1zZywgdXJsLCBsaW5lTnVtYmVyLCBjb2x1bW4sIGVycm9yT2JqKSB7XHJcbiAgICAgICAgLy8gU2VuZCBvYmplY3Qgd2l0aCBhbGwgZGF0YSB0byBzZXJ2ZXIgc2lkZSBsb2csIHVzaW5nIHNldmVyaXR5IGZhdGFsLCBcclxuICAgICAgICAvLyBmcm9tIGxvZ2dlciBcIm9uZXJyb3JMb2dnZXJcIlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gVXNlIGVycm9yTXNnLm1lc3NhZ2UgaWYgYXZhaWxhYmxlLCBzbyBBbmd1bGFyIDQgdGVtcGxhdGUgZXJyb3JzIHdpbGwgYmUgbG9nZ2VkLlxyXG4gICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbXBlcmRlY2svanNubG9nLmpzL3B1bGwvNjhcclxuICAgICAgICBKTChcIm9uZXJyb3JMb2dnZXJcIikuZmF0YWxFeGNlcHRpb24oe1xyXG4gICAgICAgICAgICBcIm1zZ1wiOiBcIlVuY2F1Z2h0IEV4Y2VwdGlvblwiLFxyXG4gICAgICAgICAgICBcImVycm9yTXNnXCI6IGVycm9yTXNnID8gKGVycm9yTXNnLm1lc3NhZ2UgfHwgZXJyb3JNc2cpIDogJycsXHJcbiAgICAgICAgICAgIFwidXJsXCI6IHVybCxcclxuICAgICAgICAgICAgXCJsaW5lIG51bWJlclwiOiBsaW5lTnVtYmVyLCBcImNvbHVtblwiOiBjb2x1bW5cclxuICAgICAgICB9LCBlcnJvck9iaik7XHJcbiAgICAgICAgLy8gVGVsbCBicm93c2VyIHRvIHJ1biBpdHMgb3duIGVycm9yIGhhbmRsZXIgYXMgd2VsbCAgIFxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH07XHJcbn1cclxuLy8gRGVhbCB3aXRoIHVuaGFuZGxlZCBleGNlcHRpb25zIHRocm93biBpbiBwcm9taXNlc1xyXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgIXdpbmRvdy5vbnVuaGFuZGxlZHJlamVjdGlvbikge1xyXG4gICAgd2luZG93Lm9udW5oYW5kbGVkcmVqZWN0aW9uID0gZnVuY3Rpb24gKGV2ZW50KSB7XHJcbiAgICAgICAgLy8gU2VuZCBvYmplY3Qgd2l0aCBhbGwgZGF0YSB0byBzZXJ2ZXIgc2lkZSBsb2csIHVzaW5nIHNldmVyaXR5IGZhdGFsLCBcclxuICAgICAgICAvLyBmcm9tIGxvZ2dlciBcIm9uZXJyb3JMb2dnZXJcIi5cclxuICAgICAgICAvLyBOZWVkIHRvIGNoZWNrIGJvdGggZXZlbnQucmVhc29uLm1lc3NhZ2UgYW5kIGV2ZW50Lm1lc3NhZ2UsXHJcbiAgICAgICAgLy8gYmVjYXVzZSBTeXN0ZW1KcyB3cmFwcyBleGNlcHRpb25zIGFuZCB0aHJvd3MgYSBuZXcgb2JqZWN0IHdoaWNoIGRvZXNuJ3QgaGF2ZSBhIHJlYXNvbiBwcm9wZXJ0eS5cclxuICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3N5c3RlbWpzL3N5c3RlbWpzL2lzc3Vlcy8xMzA5XHJcbiAgICAgICAgSkwoXCJvbmVycm9yTG9nZ2VyXCIpLmZhdGFsRXhjZXB0aW9uKHtcclxuICAgICAgICAgICAgXCJtc2dcIjogXCJ1bmhhbmRsZWRyZWplY3Rpb25cIixcclxuICAgICAgICAgICAgXCJlcnJvck1zZ1wiOiBldmVudC5yZWFzb24gPyBldmVudC5yZWFzb24ubWVzc2FnZSA6IGV2ZW50Lm1lc3NhZ2UgfHwgbnVsbFxyXG4gICAgICAgIH0sIGV2ZW50LnJlYXNvbik7XHJcbiAgICB9O1xyXG59XHJcbiIsIi8qKlxuICAjIG5vcm1hbGljZVxuXG4gIE5vcm1hbGl6ZSBhbiBpY2Ugc2VydmVyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IChvciBwbGFpbiBvbGQgc3RyaW5nKSBpbnRvIGEgZm9ybWF0XG4gIHRoYXQgaXMgdXNhYmxlIGluIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFdlYlJUQy4gIFByaW1hcmlseSB0aGlzIG1vZHVsZSBpcyBkZXNpZ25lZFxuICB0byBoZWxwIHdpdGggdGhlIHRyYW5zaXRpb24gb2YgdGhlIGB1cmxgIGF0dHJpYnV0ZSBvZiB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG9cbiAgdGhlIGB1cmxzYCBhdHRyaWJ1dGUuXG5cbiAgIyMgRXhhbXBsZSBVc2FnZVxuXG4gIDw8PCBleGFtcGxlcy9zaW1wbGUuanNcblxuKiovXG5cbnZhciBwcm90b2NvbHMgPSBbXG4gICdzdHVuOicsXG4gICd0dXJuOidcbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgdmFyIHVybCA9IChpbnB1dCB8fCB7fSkudXJsIHx8IGlucHV0O1xuICB2YXIgcHJvdG9jb2w7XG4gIHZhciBwYXJ0cztcbiAgdmFyIG91dHB1dCA9IHt9O1xuXG4gIC8vIGlmIHdlIGRvbid0IGhhdmUgYSBzdHJpbmcgdXJsLCB0aGVuIGFsbG93IHRoZSBpbnB1dCB0byBwYXNzdGhyb3VnaFxuICBpZiAodHlwZW9mIHVybCAhPSAnc3RyaW5nJyAmJiAoISAodXJsIGluc3RhbmNlb2YgU3RyaW5nKSkpIHtcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyB0cmltIHRoZSB1cmwgc3RyaW5nLCBhbmQgY29udmVydCB0byBhbiBhcnJheVxuICB1cmwgPSB1cmwudHJpbSgpO1xuXG4gIC8vIGlmIHRoZSBwcm90b2NvbCBpcyBub3Qga25vd24sIHRoZW4gcGFzc3Rocm91Z2hcbiAgcHJvdG9jb2wgPSBwcm90b2NvbHNbcHJvdG9jb2xzLmluZGV4T2YodXJsLnNsaWNlKDAsIDUpKV07XG4gIGlmICghIHByb3RvY29sKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gbm93IGxldCdzIGF0dGFjayB0aGUgcmVtYWluaW5nIHVybCBwYXJ0c1xuICB1cmwgPSB1cmwuc2xpY2UoNSk7XG4gIHBhcnRzID0gdXJsLnNwbGl0KCdAJyk7XG5cbiAgb3V0cHV0LnVzZXJuYW1lID0gaW5wdXQudXNlcm5hbWU7XG4gIG91dHB1dC5jcmVkZW50aWFsID0gaW5wdXQuY3JlZGVudGlhbDtcbiAgLy8gaWYgd2UgaGF2ZSBhbiBhdXRoZW50aWNhdGlvbiBwYXJ0LCB0aGVuIHNldCB0aGUgY3JlZGVudGlhbHNcbiAgaWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICB1cmwgPSBwYXJ0c1sxXTtcbiAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCc6Jyk7XG5cbiAgICAvLyBhZGQgdGhlIG91dHB1dCBjcmVkZW50aWFsIGFuZCB1c2VybmFtZVxuICAgIG91dHB1dC51c2VybmFtZSA9IHBhcnRzWzBdO1xuICAgIG91dHB1dC5jcmVkZW50aWFsID0gKGlucHV0IHx8IHt9KS5jcmVkZW50aWFsIHx8IHBhcnRzWzFdIHx8ICcnO1xuICB9XG5cbiAgb3V0cHV0LnVybCA9IHByb3RvY29sICsgdXJsO1xuICBvdXRwdXQudXJscyA9IFsgb3V0cHV0LnVybCBdO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuIiwiLyohXG4gKiBQbGF0Zm9ybS5qcyB2MS4zLjZcbiAqIENvcHlyaWdodCAyMDE0LTIwMjAgQmVuamFtaW4gVGFuXG4gKiBDb3B5cmlnaHQgMjAxMS0yMDEzIEpvaG4tRGF2aWQgRGFsdG9uXG4gKiBBdmFpbGFibGUgdW5kZXIgTUlUIGxpY2Vuc2VcbiAqL1xuOyhmdW5jdGlvbigpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVybWluZSBpZiB2YWx1ZXMgYXJlIG9mIHRoZSBsYW5ndWFnZSB0eXBlIGBPYmplY3RgLiAqL1xuICB2YXIgb2JqZWN0VHlwZXMgPSB7XG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZVxuICB9O1xuXG4gIC8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgcm9vdCA9IChvYmplY3RUeXBlc1t0eXBlb2Ygd2luZG93XSAmJiB3aW5kb3cpIHx8IHRoaXM7XG5cbiAgLyoqIEJhY2t1cCBwb3NzaWJsZSBnbG9iYWwgb2JqZWN0LiAqL1xuICB2YXIgb2xkUm9vdCA9IHJvb3Q7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHM7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xuICB2YXIgZnJlZU1vZHVsZSA9IG9iamVjdFR5cGVzW3R5cGVvZiBtb2R1bGVdICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgLiAqL1xuICB2YXIgZnJlZUdsb2JhbCA9IGZyZWVFeHBvcnRzICYmIGZyZWVNb2R1bGUgJiYgdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWw7XG4gIGlmIChmcmVlR2xvYmFsICYmIChmcmVlR2xvYmFsLmdsb2JhbCA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLndpbmRvdyA9PT0gZnJlZUdsb2JhbCB8fCBmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBhcyB0aGUgbWF4aW11bSBsZW5ndGggb2YgYW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAqIFNlZSB0aGUgW0VTNiBzcGVjXShodHRwOi8vcGVvcGxlLm1vemlsbGEub3JnL35qb3JlbmRvcmZmL2VzNi1kcmFmdC5odG1sI3NlYy10b2xlbmd0aClcbiAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIHZhciBtYXhTYWZlSW50ZWdlciA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG5cbiAgLyoqIFJlZ3VsYXIgZXhwcmVzc2lvbiB0byBkZXRlY3QgT3BlcmEuICovXG4gIHZhciByZU9wZXJhID0gL1xcYk9wZXJhLztcblxuICAvKiogUG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHRoaXNCaW5kaW5nID0gdGhpcztcblxuICAvKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xuICB2YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gIC8qKiBVc2VkIHRvIGNoZWNrIGZvciBvd24gcHJvcGVydGllcyBvZiBhbiBvYmplY3QuICovXG4gIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIHZhbHVlcy4gKi9cbiAgdmFyIHRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLyoqXG4gICAqIENhcGl0YWxpemVzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY2FwaXRhbGl6ZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNhcGl0YWxpemVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gU3RyaW5nKHN0cmluZyk7XG4gICAgcmV0dXJuIHN0cmluZy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0cmluZy5zbGljZSgxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHV0aWxpdHkgZnVuY3Rpb24gdG8gY2xlYW4gdXAgdGhlIE9TIG5hbWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcyBUaGUgT1MgbmFtZSB0byBjbGVhbiB1cC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXR0ZXJuXSBBIGBSZWdFeHBgIHBhdHRlcm4gbWF0Y2hpbmcgdGhlIE9TIG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbGFiZWxdIEEgbGFiZWwgZm9yIHRoZSBPUy5cbiAgICovXG4gIGZ1bmN0aW9uIGNsZWFudXBPUyhvcywgcGF0dGVybiwgbGFiZWwpIHtcbiAgICAvLyBQbGF0Zm9ybSB0b2tlbnMgYXJlIGRlZmluZWQgYXQ6XG4gICAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgLy8gaHR0cDovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAwODExMjIwNTM5NTAvaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L21zNTM3NTAzKFZTLjg1KS5hc3B4XG4gICAgdmFyIGRhdGEgPSB7XG4gICAgICAnMTAuMCc6ICcxMCcsXG4gICAgICAnNi40JzogICcxMCBUZWNobmljYWwgUHJldmlldycsXG4gICAgICAnNi4zJzogICc4LjEnLFxuICAgICAgJzYuMic6ICAnOCcsXG4gICAgICAnNi4xJzogICdTZXJ2ZXIgMjAwOCBSMiAvIDcnLFxuICAgICAgJzYuMCc6ICAnU2VydmVyIDIwMDggLyBWaXN0YScsXG4gICAgICAnNS4yJzogICdTZXJ2ZXIgMjAwMyAvIFhQIDY0LWJpdCcsXG4gICAgICAnNS4xJzogICdYUCcsXG4gICAgICAnNS4wMSc6ICcyMDAwIFNQMScsXG4gICAgICAnNS4wJzogICcyMDAwJyxcbiAgICAgICc0LjAnOiAgJ05UJyxcbiAgICAgICc0LjkwJzogJ01FJ1xuICAgIH07XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgdmVyc2lvbiBmcm9tIHBsYXRmb3JtIHRva2Vucy5cbiAgICBpZiAocGF0dGVybiAmJiBsYWJlbCAmJiAvXldpbi9pLnRlc3Qob3MpICYmICEvXldpbmRvd3MgUGhvbmUgL2kudGVzdChvcykgJiZcbiAgICAgICAgKGRhdGEgPSBkYXRhWy9bXFxkLl0rJC8uZXhlYyhvcyldKSkge1xuICAgICAgb3MgPSAnV2luZG93cyAnICsgZGF0YTtcbiAgICB9XG4gICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgb3MgPSBTdHJpbmcob3MpO1xuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwpIHtcbiAgICAgIG9zID0gb3MucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgbGFiZWwpO1xuICAgIH1cblxuICAgIG9zID0gZm9ybWF0KFxuICAgICAgb3MucmVwbGFjZSgvIGNlJC9pLCAnIENFJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYmhwdy9pLCAnd2ViJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hY2ludG9zaFxcYi8sICdNYWMgT1MnKVxuICAgICAgICAucmVwbGFjZSgvX1Bvd2VyUENcXGIvaSwgJyBPUycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoT1MgWCkgW14gXFxkXSsvaSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYk1hYyAoT1MgWClcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFwvKFxcZCkvLCAnICQxJylcbiAgICAgICAgLnJlcGxhY2UoL18vZywgJy4nKVxuICAgICAgICAucmVwbGFjZSgvKD86IEJlUEN8WyAuXSpmY1sgXFxkLl0rKSQvaSwgJycpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJ4ODZcXC42NFxcYi9naSwgJ3g4Nl82NCcpXG4gICAgICAgIC5yZXBsYWNlKC9cXGIoV2luZG93cyBQaG9uZSkgT1NcXGIvLCAnJDEnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKENocm9tZSBPUyBcXHcrKSBbXFxkLl0rXFxiLywgJyQxJylcbiAgICAgICAgLnNwbGl0KCcgb24gJylbMF1cbiAgICApO1xuXG4gICAgcmV0dXJuIG9zO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGl0ZXJhdGlvbiB1dGlsaXR5IGZvciBhcnJheXMgYW5kIG9iamVjdHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIGVhY2gob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBvYmplY3QgPyBvYmplY3QubGVuZ3RoIDogMDtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+IC0xICYmIGxlbmd0aCA8PSBtYXhTYWZlSW50ZWdlcikge1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2luZGV4XSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvck93bihvYmplY3QsIGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpbSBhbmQgY29uZGl0aW9uYWxseSBjYXBpdGFsaXplIHN0cmluZyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBmb3JtYXQuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gZm9ybWF0KHN0cmluZykge1xuICAgIHN0cmluZyA9IHRyaW0oc3RyaW5nKTtcbiAgICByZXR1cm4gL14oPzp3ZWJPU3xpKD86T1N8UCkpLy50ZXN0KHN0cmluZylcbiAgICAgID8gc3RyaW5nXG4gICAgICA6IGNhcGl0YWxpemUoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlcyBvdmVyIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLCBleGVjdXRpbmcgdGhlIGBjYWxsYmFja2AgZm9yIGVhY2guXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiBleGVjdXRlZCBwZXIgb3duIHByb3BlcnR5LlxuICAgKi9cbiAgZnVuY3Rpb24gZm9yT3duKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgICAgY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW50ZXJuYWwgYFtbQ2xhc3NdXWAgb2YgYSB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBgW1tDbGFzc11dYC5cbiAgICovXG4gIGZ1bmN0aW9uIGdldENsYXNzT2YodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbFxuICAgICAgPyBjYXBpdGFsaXplKHZhbHVlKVxuICAgICAgOiB0b1N0cmluZy5jYWxsKHZhbHVlKS5zbGljZSg4LCAtMSk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCBvYmplY3RzIGNhbiByZXR1cm4gdHlwZSB2YWx1ZXMgdGhhdCBhcmUgZGlmZmVyZW50IGZyb20gdGhlaXIgYWN0dWFsXG4gICAqIGRhdGEgdHlwZS4gVGhlIG9iamVjdHMgd2UgYXJlIGNvbmNlcm5lZCB3aXRoIHVzdWFsbHkgcmV0dXJuIG5vbi1wcmltaXRpdmVcbiAgICogdHlwZXMgb2YgXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiLCBvciBcInVua25vd25cIi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSBvYmplY3QgVGhlIG93bmVyIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBhIG5vbi1wcmltaXRpdmUsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGlzSG9zdFR5cGUob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHZhciB0eXBlID0gb2JqZWN0ICE9IG51bGwgPyB0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSA6ICdudW1iZXInO1xuICAgIHJldHVybiAhL14oPzpib29sZWFufG51bWJlcnxzdHJpbmd8dW5kZWZpbmVkKSQvLnRlc3QodHlwZSkgJiZcbiAgICAgICh0eXBlID09ICdvYmplY3QnID8gISFvYmplY3RbcHJvcGVydHldIDogdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgYSBzdHJpbmcgZm9yIHVzZSBpbiBhIGBSZWdFeHBgIGJ5IG1ha2luZyBoeXBoZW5zIGFuZCBzcGFjZXMgb3B0aW9uYWwuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBxdWFsaWZ5LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgcXVhbGlmaWVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIHF1YWxpZnkoc3RyaW5nKSB7XG4gICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UoLyhbIC1dKSg/ISQpL2csICckMT8nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGJhcmUtYm9uZXMgYEFycmF5I3JlZHVjZWAgbGlrZSB1dGlsaXR5IGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHsqfSBUaGUgYWNjdW11bGF0ZWQgcmVzdWx0LlxuICAgKi9cbiAgZnVuY3Rpb24gcmVkdWNlKGFycmF5LCBjYWxsYmFjaykge1xuICAgIHZhciBhY2N1bXVsYXRvciA9IG51bGw7XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGFycmF5KTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gYSBzdHJpbmcuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byB0cmltLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgdHJpbW1lZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiB0cmltKHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC9eICt8ICskL2csICcnKTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHBsYXRmb3JtIG9iamVjdC5cbiAgICpcbiAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gW3VhPW5hdmlnYXRvci51c2VyQWdlbnRdIFRoZSB1c2VyIGFnZW50IHN0cmluZyBvclxuICAgKiAgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IEEgcGxhdGZvcm0gb2JqZWN0LlxuICAgKi9cbiAgZnVuY3Rpb24gcGFyc2UodWEpIHtcblxuICAgIC8qKiBUaGUgZW52aXJvbm1lbnQgY29udGV4dCBvYmplY3QuICovXG4gICAgdmFyIGNvbnRleHQgPSByb290O1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGEgY3VzdG9tIGNvbnRleHQgaXMgcHJvdmlkZWQuICovXG4gICAgdmFyIGlzQ3VzdG9tQ29udGV4dCA9IHVhICYmIHR5cGVvZiB1YSA9PSAnb2JqZWN0JyAmJiBnZXRDbGFzc09mKHVhKSAhPSAnU3RyaW5nJztcblxuICAgIC8vIEp1Z2dsZSBhcmd1bWVudHMuXG4gICAgaWYgKGlzQ3VzdG9tQ29udGV4dCkge1xuICAgICAgY29udGV4dCA9IHVhO1xuICAgICAgdWEgPSBudWxsO1xuICAgIH1cblxuICAgIC8qKiBCcm93c2VyIG5hdmlnYXRvciBvYmplY3QuICovXG4gICAgdmFyIG5hdiA9IGNvbnRleHQubmF2aWdhdG9yIHx8IHt9O1xuXG4gICAgLyoqIEJyb3dzZXIgdXNlciBhZ2VudCBzdHJpbmcuICovXG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdi51c2VyQWdlbnQgfHwgJyc7XG5cbiAgICB1YSB8fCAodWEgPSB1c2VyQWdlbnQpO1xuXG4gICAgLyoqIFVzZWQgdG8gZmxhZyB3aGVuIGB0aGlzQmluZGluZ2AgaXMgdGhlIFtNb2R1bGVTY29wZV0uICovXG4gICAgdmFyIGlzTW9kdWxlU2NvcGUgPSBpc0N1c3RvbUNvbnRleHQgfHwgdGhpc0JpbmRpbmcgPT0gb2xkUm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBpZiBicm93c2VyIGlzIGxpa2UgQ2hyb21lLiAqL1xuICAgIHZhciBsaWtlQ2hyb21lID0gaXNDdXN0b21Db250ZXh0XG4gICAgICA/ICEhbmF2Lmxpa2VDaHJvbWVcbiAgICAgIDogL1xcYkNocm9tZVxcYi8udGVzdCh1YSkgJiYgIS9pbnRlcm5hbHxcXG4vaS50ZXN0KHRvU3RyaW5nLnRvU3RyaW5nKCkpO1xuXG4gICAgLyoqIEludGVybmFsIGBbW0NsYXNzXV1gIHZhbHVlIHNob3J0Y3V0cy4gKi9cbiAgICB2YXIgb2JqZWN0Q2xhc3MgPSAnT2JqZWN0JyxcbiAgICAgICAgYWlyUnVudGltZUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnU2NyaXB0QnJpZGdpbmdQcm94eU9iamVjdCcsXG4gICAgICAgIGVudmlyb0NsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnRW52aXJvbm1lbnQnLFxuICAgICAgICBqYXZhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIGNvbnRleHQuamF2YSkgPyAnSmF2YVBhY2thZ2UnIDogZ2V0Q2xhc3NPZihjb250ZXh0LmphdmEpLFxuICAgICAgICBwaGFudG9tQ2xhc3MgPSBpc0N1c3RvbUNvbnRleHQgPyBvYmplY3RDbGFzcyA6ICdSdW50aW1lT2JqZWN0JztcblxuICAgIC8qKiBEZXRlY3QgSmF2YSBlbnZpcm9ubWVudHMuICovXG4gICAgdmFyIGphdmEgPSAvXFxiSmF2YS8udGVzdChqYXZhQ2xhc3MpICYmIGNvbnRleHQuamF2YTtcblxuICAgIC8qKiBEZXRlY3QgUmhpbm8uICovXG4gICAgdmFyIHJoaW5vID0gamF2YSAmJiBnZXRDbGFzc09mKGNvbnRleHQuZW52aXJvbm1lbnQpID09IGVudmlyb0NsYXNzO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBhbHBoYS4gKi9cbiAgICB2YXIgYWxwaGEgPSBqYXZhID8gJ2EnIDogJ1xcdTAzYjEnO1xuXG4gICAgLyoqIEEgY2hhcmFjdGVyIHRvIHJlcHJlc2VudCBiZXRhLiAqL1xuICAgIHZhciBiZXRhID0gamF2YSA/ICdiJyA6ICdcXHUwM2IyJztcblxuICAgIC8qKiBCcm93c2VyIGRvY3VtZW50IG9iamVjdC4gKi9cbiAgICB2YXIgZG9jID0gY29udGV4dC5kb2N1bWVudCB8fCB7fTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBPcGVyYSBicm93c2VyIChQcmVzdG8tYmFzZWQpLlxuICAgICAqIGh0dHA6Ly93d3cuaG93dG9jcmVhdGUuY28udWsvb3BlcmFTdHVmZi9vcGVyYU9iamVjdC5odG1sXG4gICAgICogaHR0cDovL2Rldi5vcGVyYS5jb20vYXJ0aWNsZXMvdmlldy9vcGVyYS1taW5pLXdlYi1jb250ZW50LWF1dGhvcmluZy1ndWlkZWxpbmVzLyNvcGVyYW1pbmlcbiAgICAgKi9cbiAgICB2YXIgb3BlcmEgPSBjb250ZXh0Lm9wZXJhbWluaSB8fCBjb250ZXh0Lm9wZXJhO1xuXG4gICAgLyoqIE9wZXJhIGBbW0NsYXNzXV1gLiAqL1xuICAgIHZhciBvcGVyYUNsYXNzID0gcmVPcGVyYS50ZXN0KG9wZXJhQ2xhc3MgPSAoaXNDdXN0b21Db250ZXh0ICYmIG9wZXJhKSA/IG9wZXJhWydbW0NsYXNzXV0nXSA6IGdldENsYXNzT2Yob3BlcmEpKVxuICAgICAgPyBvcGVyYUNsYXNzXG4gICAgICA6IChvcGVyYSA9IG51bGwpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqIFRlbXBvcmFyeSB2YXJpYWJsZSB1c2VkIG92ZXIgdGhlIHNjcmlwdCdzIGxpZmV0aW1lLiAqL1xuICAgIHZhciBkYXRhO1xuXG4gICAgLyoqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlLiAqL1xuICAgIHZhciBhcmNoID0gdWE7XG5cbiAgICAvKiogUGxhdGZvcm0gZGVzY3JpcHRpb24gYXJyYXkuICovXG4gICAgdmFyIGRlc2NyaXB0aW9uID0gW107XG5cbiAgICAvKiogUGxhdGZvcm0gYWxwaGEvYmV0YSBpbmRpY2F0b3IuICovXG4gICAgdmFyIHByZXJlbGVhc2UgPSBudWxsO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSB0aGF0IGVudmlyb25tZW50IGZlYXR1cmVzIHNob3VsZCBiZSB1c2VkIHRvIHJlc29sdmUgdGhlIHBsYXRmb3JtLiAqL1xuICAgIHZhciB1c2VGZWF0dXJlcyA9IHVhID09IHVzZXJBZ2VudDtcblxuICAgIC8qKiBUaGUgYnJvd3Nlci9lbnZpcm9ubWVudCB2ZXJzaW9uLiAqL1xuICAgIHZhciB2ZXJzaW9uID0gdXNlRmVhdHVyZXMgJiYgb3BlcmEgJiYgdHlwZW9mIG9wZXJhLnZlcnNpb24gPT0gJ2Z1bmN0aW9uJyAmJiBvcGVyYS52ZXJzaW9uKCk7XG5cbiAgICAvKiogQSBmbGFnIHRvIGluZGljYXRlIGlmIHRoZSBPUyBlbmRzIHdpdGggXCIvIFZlcnNpb25cIiAqL1xuICAgIHZhciBpc1NwZWNpYWxDYXNlZE9TO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBsYXlvdXQgZW5naW5lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbGF5b3V0ID0gZ2V0TGF5b3V0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0VkZ2VIVE1MJywgJ3BhdHRlcm4nOiAnRWRnZScgfSxcbiAgICAgICdUcmlkZW50JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1dlYktpdCcsICdwYXR0ZXJuJzogJ0FwcGxlV2ViS2l0JyB9LFxuICAgICAgJ2lDYWInLFxuICAgICAgJ1ByZXN0bycsXG4gICAgICAnTmV0RnJvbnQnLFxuICAgICAgJ1Rhc21hbicsXG4gICAgICAnS0hUTUwnLFxuICAgICAgJ0dlY2tvJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBicm93c2VyIG5hbWVzIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBuYW1lID0gZ2V0TmFtZShbXG4gICAgICAnQWRvYmUgQUlSJyxcbiAgICAgICdBcm9yYScsXG4gICAgICAnQXZhbnQgQnJvd3NlcicsXG4gICAgICAnQnJlYWNoJyxcbiAgICAgICdDYW1pbm8nLFxuICAgICAgJ0VsZWN0cm9uJyxcbiAgICAgICdFcGlwaGFueScsXG4gICAgICAnRmVubmVjJyxcbiAgICAgICdGbG9jaycsXG4gICAgICAnR2FsZW9uJyxcbiAgICAgICdHcmVlbkJyb3dzZXInLFxuICAgICAgJ2lDYWInLFxuICAgICAgJ0ljZXdlYXNlbCcsXG4gICAgICAnSy1NZWxlb24nLFxuICAgICAgJ0tvbnF1ZXJvcicsXG4gICAgICAnTHVuYXNjYXBlJyxcbiAgICAgICdNYXh0aG9uJyxcbiAgICAgIHsgJ2xhYmVsJzogJ01pY3Jvc29mdCBFZGdlJywgJ3BhdHRlcm4nOiAnKD86RWRnZXxFZGd8RWRnQXxFZGdpT1MpJyB9LFxuICAgICAgJ01pZG9yaScsXG4gICAgICAnTm9vayBCcm93c2VyJyxcbiAgICAgICdQYWxlTW9vbicsXG4gICAgICAnUGhhbnRvbUpTJyxcbiAgICAgICdSYXZlbicsXG4gICAgICAnUmVrb25xJyxcbiAgICAgICdSb2NrTWVsdCcsXG4gICAgICB7ICdsYWJlbCc6ICdTYW1zdW5nIEludGVybmV0JywgJ3BhdHRlcm4nOiAnU2Ftc3VuZ0Jyb3dzZXInIH0sXG4gICAgICAnU2VhTW9ua2V5JyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NpbGsnLCAncGF0dGVybic6ICcoPzpDbG91ZDl8U2lsay1BY2NlbGVyYXRlZCknIH0sXG4gICAgICAnU2xlaXBuaXInLFxuICAgICAgJ1NsaW1Ccm93c2VyJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1NSV2FyZSBJcm9uJywgJ3BhdHRlcm4nOiAnSXJvbicgfSxcbiAgICAgICdTdW5yaXNlJyxcbiAgICAgICdTd2lmdGZveCcsXG4gICAgICAnVml2YWxkaScsXG4gICAgICAnV2F0ZXJmb3gnLFxuICAgICAgJ1dlYlBvc2l0aXZlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ1lhbmRleCBCcm93c2VyJywgJ3BhdHRlcm4nOiAnWWFCcm93c2VyJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnVUMgQnJvd3NlcicsICdwYXR0ZXJuJzogJ1VDQnJvd3NlcicgfSxcbiAgICAgICdPcGVyYSBNaW5pJyxcbiAgICAgIHsgJ2xhYmVsJzogJ09wZXJhIE1pbmknLCAncGF0dGVybic6ICdPUGlPUycgfSxcbiAgICAgICdPcGVyYScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYScsICdwYXR0ZXJuJzogJ09QUicgfSxcbiAgICAgICdDaHJvbWl1bScsXG4gICAgICAnQ2hyb21lJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZScsICdwYXR0ZXJuJzogJyg/OkhlYWRsZXNzQ2hyb21lKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBNb2JpbGUnLCAncGF0dGVybic6ICcoPzpDcmlPU3xDck1vKScgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0ZpcmVmb3gnLCAncGF0dGVybic6ICcoPzpGaXJlZm94fE1pbmVmaWVsZCknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94IGZvciBpT1MnLCAncGF0dGVybic6ICdGeGlPUycgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0lFJywgJ3BhdHRlcm4nOiAnSUVNb2JpbGUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ01TSUUnIH0sXG4gICAgICAnU2FmYXJpJ1xuICAgIF0pO1xuXG4gICAgLyogRGV0ZWN0YWJsZSBwcm9kdWN0cyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgcHJvZHVjdCA9IGdldFByb2R1Y3QoW1xuICAgICAgeyAnbGFiZWwnOiAnQmxhY2tCZXJyeScsICdwYXR0ZXJuJzogJ0JCMTAnIH0sXG4gICAgICAnQmxhY2tCZXJyeScsXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUycsICdwYXR0ZXJuJzogJ0dULUk5MDAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMyJywgJ3BhdHRlcm4nOiAnR1QtSTkxMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzMnLCAncGF0dGVybic6ICdHVC1JOTMwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNCcsICdwYXR0ZXJuJzogJ0dULUk5NTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM1JywgJ3BhdHRlcm4nOiAnU00tRzkwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNicsICdwYXR0ZXJuJzogJ1NNLUc5MjAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYgRWRnZScsICdwYXR0ZXJuJzogJ1NNLUc5MjUnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzcnLCAncGF0dGVybic6ICdTTS1HOTMwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTM1JyB9LFxuICAgICAgJ0dvb2dsZSBUVicsXG4gICAgICAnTHVtaWEnLFxuICAgICAgJ2lQYWQnLFxuICAgICAgJ2lQb2QnLFxuICAgICAgJ2lQaG9uZScsXG4gICAgICAnS2luZGxlJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0tpbmRsZSBGaXJlJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ05leHVzJyxcbiAgICAgICdOb29rJyxcbiAgICAgICdQbGF5Qm9vaycsXG4gICAgICAnUGxheVN0YXRpb24gVml0YScsXG4gICAgICAnUGxheVN0YXRpb24nLFxuICAgICAgJ1RvdWNoUGFkJyxcbiAgICAgICdUcmFuc2Zvcm1lcicsXG4gICAgICB7ICdsYWJlbCc6ICdXaWkgVScsICdwYXR0ZXJuJzogJ1dpaVUnIH0sXG4gICAgICAnV2lpJyxcbiAgICAgICdYYm94IE9uZScsXG4gICAgICB7ICdsYWJlbCc6ICdYYm94IDM2MCcsICdwYXR0ZXJuJzogJ1hib3gnIH0sXG4gICAgICAnWG9vbSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgbWFudWZhY3R1cmVycy4gKi9cbiAgICB2YXIgbWFudWZhY3R1cmVyID0gZ2V0TWFudWZhY3R1cmVyKHtcbiAgICAgICdBcHBsZSc6IHsgJ2lQYWQnOiAxLCAnaVBob25lJzogMSwgJ2lQb2QnOiAxIH0sXG4gICAgICAnQWxjYXRlbCc6IHt9LFxuICAgICAgJ0FyY2hvcyc6IHt9LFxuICAgICAgJ0FtYXpvbic6IHsgJ0tpbmRsZSc6IDEsICdLaW5kbGUgRmlyZSc6IDEgfSxcbiAgICAgICdBc3VzJzogeyAnVHJhbnNmb3JtZXInOiAxIH0sXG4gICAgICAnQmFybmVzICYgTm9ibGUnOiB7ICdOb29rJzogMSB9LFxuICAgICAgJ0JsYWNrQmVycnknOiB7ICdQbGF5Qm9vayc6IDEgfSxcbiAgICAgICdHb29nbGUnOiB7ICdHb29nbGUgVFYnOiAxLCAnTmV4dXMnOiAxIH0sXG4gICAgICAnSFAnOiB7ICdUb3VjaFBhZCc6IDEgfSxcbiAgICAgICdIVEMnOiB7fSxcbiAgICAgICdIdWF3ZWknOiB7fSxcbiAgICAgICdMZW5vdm8nOiB7fSxcbiAgICAgICdMRyc6IHt9LFxuICAgICAgJ01pY3Jvc29mdCc6IHsgJ1hib3gnOiAxLCAnWGJveCBPbmUnOiAxIH0sXG4gICAgICAnTW90b3JvbGEnOiB7ICdYb29tJzogMSB9LFxuICAgICAgJ05pbnRlbmRvJzogeyAnV2lpIFUnOiAxLCAgJ1dpaSc6IDEgfSxcbiAgICAgICdOb2tpYSc6IHsgJ0x1bWlhJzogMSB9LFxuICAgICAgJ09wcG8nOiB7fSxcbiAgICAgICdTYW1zdW5nJzogeyAnR2FsYXh5IFMnOiAxLCAnR2FsYXh5IFMyJzogMSwgJ0dhbGF4eSBTMyc6IDEsICdHYWxheHkgUzQnOiAxIH0sXG4gICAgICAnU29ueSc6IHsgJ1BsYXlTdGF0aW9uJzogMSwgJ1BsYXlTdGF0aW9uIFZpdGEnOiAxIH0sXG4gICAgICAnWGlhb21pJzogeyAnTWknOiAxLCAnUmVkbWknOiAxIH1cbiAgICB9KTtcblxuICAgIC8qIERldGVjdGFibGUgb3BlcmF0aW5nIHN5c3RlbXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIG9zID0gZ2V0T1MoW1xuICAgICAgJ1dpbmRvd3MgUGhvbmUnLFxuICAgICAgJ0thaU9TJyxcbiAgICAgICdBbmRyb2lkJyxcbiAgICAgICdDZW50T1MnLFxuICAgICAgeyAnbGFiZWwnOiAnQ2hyb21lIE9TJywgJ3BhdHRlcm4nOiAnQ3JPUycgfSxcbiAgICAgICdEZWJpYW4nLFxuICAgICAgeyAnbGFiZWwnOiAnRHJhZ29uRmx5IEJTRCcsICdwYXR0ZXJuJzogJ0RyYWdvbkZseScgfSxcbiAgICAgICdGZWRvcmEnLFxuICAgICAgJ0ZyZWVCU0QnLFxuICAgICAgJ0dlbnRvbycsXG4gICAgICAnSGFpa3UnLFxuICAgICAgJ0t1YnVudHUnLFxuICAgICAgJ0xpbnV4IE1pbnQnLFxuICAgICAgJ09wZW5CU0QnLFxuICAgICAgJ1JlZCBIYXQnLFxuICAgICAgJ1N1U0UnLFxuICAgICAgJ1VidW50dScsXG4gICAgICAnWHVidW50dScsXG4gICAgICAnQ3lnd2luJyxcbiAgICAgICdTeW1iaWFuIE9TJyxcbiAgICAgICdocHdPUycsXG4gICAgICAnd2ViT1MgJyxcbiAgICAgICd3ZWJPUycsXG4gICAgICAnVGFibGV0IE9TJyxcbiAgICAgICdUaXplbicsXG4gICAgICAnTGludXgnLFxuICAgICAgJ01hYyBPUyBYJyxcbiAgICAgICdNYWNpbnRvc2gnLFxuICAgICAgJ01hYycsXG4gICAgICAnV2luZG93cyA5ODsnLFxuICAgICAgJ1dpbmRvd3MgJ1xuICAgIF0pO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIGxheW91dCBlbmdpbmUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbGF5b3V0IGVuZ2luZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMYXlvdXQoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIG1hbnVmYWN0dXJlciBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gb2JqZWN0IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgbWFudWZhY3R1cmVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hbnVmYWN0dXJlcihndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgICAvLyBMb29rdXAgdGhlIG1hbnVmYWN0dXJlciBieSBwcm9kdWN0IG9yIHNjYW4gdGhlIFVBIGZvciB0aGUgbWFudWZhY3R1cmVyLlxuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChcbiAgICAgICAgICB2YWx1ZVtwcm9kdWN0XSB8fFxuICAgICAgICAgIHZhbHVlWy9eW2Etel0rKD86ICtbYS16XStcXGIpKi9pLmV4ZWMocHJvZHVjdCldIHx8XG4gICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBxdWFsaWZ5KGtleSkgKyAnKD86XFxcXGJ8XFxcXHcqXFxcXGQpJywgJ2knKS5leGVjKHVhKVxuICAgICAgICApICYmIGtleTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBicm93c2VyIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgYnJvd3NlciBuYW1lLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE5hbWUoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQgfHwgUmVnRXhwKCdcXFxcYicgKyAoXG4gICAgICAgICAgZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKVxuICAgICAgICApICsgJ1xcXFxiJywgJ2knKS5leGVjKHVhKSAmJiAoZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIE9TIG5hbWUgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgT1MgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRPUyhndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyg/Oi9bXFxcXGQuXSt8WyBcXFxcdy5dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gY2xlYW51cE9TKHJlc3VsdCwgcGF0dGVybiwgZ3Vlc3MubGFiZWwgfHwgZ3Vlc3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgcHJvZHVjdCBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIHByb2R1Y3QgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRQcm9kdWN0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICB2YXIgcGF0dGVybiA9IGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcyk7XG4gICAgICAgIGlmICghcmVzdWx0ICYmIChyZXN1bHQgPVxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcZCtbLlxcXFx3X10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnICpcXFxcdystW1xcXFx3XSonLCAnaScpLmV4ZWModWEpIHx8XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzo7ICooPzpbYS16XStbXy1dKT9bYS16XStcXFxcZCt8W14gKCk7LV0qKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAvLyBTcGxpdCBieSBmb3J3YXJkIHNsYXNoIGFuZCBhcHBlbmQgcHJvZHVjdCB2ZXJzaW9uIGlmIG5lZWRlZC5cbiAgICAgICAgICBpZiAoKHJlc3VsdCA9IFN0cmluZygoZ3Vlc3MubGFiZWwgJiYgIVJlZ0V4cChwYXR0ZXJuLCAnaScpLnRlc3QoZ3Vlc3MubGFiZWwpKSA/IGd1ZXNzLmxhYmVsIDogcmVzdWx0KS5zcGxpdCgnLycpKVsxXSAmJiAhL1tcXGQuXSsvLnRlc3QocmVzdWx0WzBdKSkge1xuICAgICAgICAgICAgcmVzdWx0WzBdICs9ICcgJyArIHJlc3VsdFsxXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ29ycmVjdCBjaGFyYWN0ZXIgY2FzZSBhbmQgY2xlYW51cCBzdHJpbmcuXG4gICAgICAgICAgZ3Vlc3MgPSBndWVzcy5sYWJlbCB8fCBndWVzcztcbiAgICAgICAgICByZXN1bHQgPSBmb3JtYXQocmVzdWx0WzBdXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAocGF0dGVybiwgJ2knKSwgZ3Vlc3MpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJzsgKig/OicgKyBndWVzcyArICdbXy1dKT8nLCAnaScpLCAnICcpXG4gICAgICAgICAgICAucmVwbGFjZShSZWdFeHAoJygnICsgZ3Vlc3MgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCAnJDEgJDInKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2ZXJzaW9uIHVzaW5nIGFuIGFycmF5IG9mIFVBIHBhdHRlcm5zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXR0ZXJucyBBbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCB2ZXJzaW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZlcnNpb24ocGF0dGVybnMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UocGF0dGVybnMsIGZ1bmN0aW9uKHJlc3VsdCwgcGF0dGVybikge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IChSZWdFeHAocGF0dGVybiArXG4gICAgICAgICAgJyg/Oi1bXFxcXGQuXSsvfCg/OiBmb3IgW1xcXFx3LV0rKT9bIC8tXSkoW1xcXFxkLl0rW14gKCk7L18tXSopJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fCBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIHdoZW4gdGhlIHBsYXRmb3JtIG9iamVjdCBpcyBjb2VyY2VkIHRvIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG5hbWUgdG9TdHJpbmdcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIGBwbGF0Zm9ybS5kZXNjcmlwdGlvbmAgaWYgYXZhaWxhYmxlLCBlbHNlIGFuIGVtcHR5IHN0cmluZy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZ1BsYXRmb3JtKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRpb24gfHwgJyc7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQ29udmVydCBsYXlvdXQgdG8gYW4gYXJyYXkgc28gd2UgY2FuIGFkZCBleHRyYSBkZXRhaWxzLlxuICAgIGxheW91dCAmJiAobGF5b3V0ID0gW2xheW91dF0pO1xuXG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgcHJvZHVjdHMuXG4gICAgLy8gQnJvd3NlcnMgb24gQW5kcm9pZCBkZXZpY2VzIHR5cGljYWxseSBwcm92aWRlIHRoZWlyIHByb2R1Y3QgSURTIGFmdGVyIFwiQW5kcm9pZDtcIlxuICAgIC8vIHVwIHRvIFwiQnVpbGRcIiBvciBcIikgQXBwbGVXZWJLaXRcIi5cbiAgICAvLyBFeGFtcGxlOlxuICAgIC8vIFwiTW96aWxsYS81LjAgKExpbnV4OyBBbmRyb2lkIDguMS4wOyBNb3RvIEcgKDUpIFBsdXMpIEFwcGxlV2ViS2l0LzUzNy4zNlxuICAgIC8vIChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzcwLjAuMzUzOC44MCBNb2JpbGUgU2FmYXJpLzUzNy4zNlwiXG4gICAgaWYgKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSAmJiAhcHJvZHVjdCAmJlxuICAgICAgICAoZGF0YSA9IC9cXGJBbmRyb2lkW147XSo7KC4qPykoPzpCdWlsZHxcXCkgQXBwbGVXZWJLaXQpXFxiL2kuZXhlYyh1YSkpKSB7XG4gICAgICBwcm9kdWN0ID0gdHJpbShkYXRhWzFdKVxuICAgICAgICAvLyBSZXBsYWNlIGFueSBsYW5ndWFnZSBjb2RlcyAoZWcuIFwiZW4tVVNcIikuXG4gICAgICAgIC5yZXBsYWNlKC9eW2Etel17Mn0tW2Etel17Mn07XFxzKi9pLCAnJylcbiAgICAgICAgfHwgbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHByb2R1Y3QgbmFtZXMgdGhhdCBjb250YWluIHRoZWlyIG1hbnVmYWN0dXJlcidzIG5hbWUuXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiAhcHJvZHVjdCkge1xuICAgICAgcHJvZHVjdCA9IGdldFByb2R1Y3QoW21hbnVmYWN0dXJlcl0pO1xuICAgIH0gZWxzZSBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBwcm9kdWN0XG4gICAgICAgIC5yZXBsYWNlKFJlZ0V4cCgnXignICsgcXVhbGlmeShtYW51ZmFjdHVyZXIpICsgJylbLV8uXFxcXHNdJywgJ2knKSwgbWFudWZhY3R1cmVyICsgJyAnKVxuICAgICAgICAucmVwbGFjZShSZWdFeHAoJ14oJyArIHF1YWxpZnkobWFudWZhY3R1cmVyKSArICcpWy1fLl0/KFxcXFx3KScsICdpJyksIG1hbnVmYWN0dXJlciArICcgJDInKTtcbiAgICB9XG4gICAgLy8gQ2xlYW4gdXAgR29vZ2xlIFRWLlxuICAgIGlmICgoZGF0YSA9IC9cXGJHb29nbGUgVFZcXGIvLmV4ZWMocHJvZHVjdCkpKSB7XG4gICAgICBwcm9kdWN0ID0gZGF0YVswXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHNpbXVsYXRvcnMuXG4gICAgaWYgKC9cXGJTaW11bGF0b3JcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgcHJvZHVjdCA9IChwcm9kdWN0ID8gcHJvZHVjdCArICcgJyA6ICcnKSArICdTaW11bGF0b3InO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgT3BlcmEgTWluaSA4KyBydW5uaW5nIGluIFR1cmJvL1VuY29tcHJlc3NlZCBtb2RlIG9uIGlPUy5cbiAgICBpZiAobmFtZSA9PSAnT3BlcmEgTWluaScgJiYgL1xcYk9QaU9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgncnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgTW9iaWxlIDExLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgL1xcYmxpa2UgaVBob25lIE9TXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGF0YSA9IHBhcnNlKHVhLnJlcGxhY2UoL2xpa2UgaVBob25lIE9TLywgJycpKTtcbiAgICAgIG1hbnVmYWN0dXJlciA9IGRhdGEubWFudWZhY3R1cmVyO1xuICAgICAgcHJvZHVjdCA9IGRhdGEucHJvZHVjdDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGlPUy5cbiAgICBlbHNlIGlmICgvXmlQLy50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBuYW1lIHx8IChuYW1lID0gJ1NhZmFyaScpO1xuICAgICAgb3MgPSAnaU9TJyArICgoZGF0YSA9IC8gT1MgKFtcXGRfXSspL2kuZXhlYyh1YSkpXG4gICAgICAgID8gJyAnICsgZGF0YVsxXS5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgOiAnJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBLdWJ1bnR1LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0tvbnF1ZXJvcicgJiYgL15MaW51eFxcYi9pLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9ICdLdWJ1bnR1JztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEFuZHJvaWQgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAoKG1hbnVmYWN0dXJlciAmJiBtYW51ZmFjdHVyZXIgIT0gJ0dvb2dsZScgJiZcbiAgICAgICAgKCgvQ2hyb21lLy50ZXN0KG5hbWUpICYmICEvXFxiTW9iaWxlIFNhZmFyaVxcYi9pLnRlc3QodWEpKSB8fCAvXFxiVml0YVxcYi8udGVzdChwcm9kdWN0KSkpIHx8XG4gICAgICAgICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgL15DaHJvbWUvLnRlc3QobmFtZSkgJiYgL1xcYlZlcnNpb25cXC8vaS50ZXN0KHVhKSkpIHtcbiAgICAgIG5hbWUgPSAnQW5kcm9pZCBCcm93c2VyJztcbiAgICAgIG9zID0gL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpID8gb3MgOiAnQW5kcm9pZCc7XG4gICAgfVxuICAgIC8vIERldGVjdCBTaWxrIGRlc2t0b3AvYWNjZWxlcmF0ZWQgbW9kZXMuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2lsaycpIHtcbiAgICAgIGlmICghL1xcYk1vYmkvaS50ZXN0KHVhKSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkJztcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB9XG4gICAgICBpZiAoL0FjY2VsZXJhdGVkICo9ICp0cnVlL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnYWNjZWxlcmF0ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IFVDIEJyb3dzZXIgc3BlZWQgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdVQyBCcm93c2VyJyAmJiAvXFxiVUNXRUJcXGIvLnRlc3QodWEpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdzcGVlZCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBQYWxlTW9vbiBpZGVudGlmeWluZyBhcyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1BhbGVNb29uJyAmJiAoZGF0YSA9IC9cXGJGaXJlZm94XFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzIEZpcmVmb3ggJyArIGRhdGFbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBPUyBhbmQgcHJvZHVjdHMgcnVubmluZyBGaXJlZm94LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIChkYXRhID0gL1xcYihNb2JpbGV8VGFibGV0fFRWKVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgb3MgfHwgKG9zID0gJ0ZpcmVmb3ggT1MnKTtcbiAgICAgIHByb2R1Y3QgfHwgKHByb2R1Y3QgPSBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGZhbHNlIHBvc2l0aXZlcyBmb3IgRmlyZWZveC9TYWZhcmkuXG4gICAgZWxzZSBpZiAoIW5hbWUgfHwgKGRhdGEgPSAhL1xcYk1pbmVmaWVsZFxcYi9pLnRlc3QodWEpICYmIC9cXGIoPzpGaXJlZm94fFNhZmFyaSlcXGIvLmV4ZWMobmFtZSkpKSB7XG4gICAgICAvLyBFc2NhcGUgdGhlIGAvYCBmb3IgRmlyZWZveCAxLlxuICAgICAgaWYgKG5hbWUgJiYgIXByb2R1Y3QgJiYgL1tcXC8sXXxeW14oXSs/XFwpLy50ZXN0KHVhLnNsaWNlKHVhLmluZGV4T2YoZGF0YSArICcvJykgKyA4KSkpIHtcbiAgICAgICAgLy8gQ2xlYXIgbmFtZSBvZiBmYWxzZSBwb3NpdGl2ZXMuXG4gICAgICAgIG5hbWUgPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gUmVhc3NpZ24gYSBnZW5lcmljIG5hbWUuXG4gICAgICBpZiAoKGRhdGEgPSBwcm9kdWN0IHx8IG1hbnVmYWN0dXJlciB8fCBvcykgJiZcbiAgICAgICAgICAocHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgL1xcYig/OkFuZHJvaWR8U3ltYmlhbiBPU3xUYWJsZXQgT1N8d2ViT1MpXFxiLy50ZXN0KG9zKSkpIHtcbiAgICAgICAgbmFtZSA9IC9bYS16XSsoPzogSGF0KT8vaS5leGVjKC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogZGF0YSkgKyAnIEJyb3dzZXInO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgQ2hyb21lIHZlcnNpb24gdG8gZGVzY3JpcHRpb24gZm9yIEVsZWN0cm9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0VsZWN0cm9uJyAmJiAoZGF0YSA9ICgvXFxiQ2hyb21lXFwvKFtcXGQuXSspXFxiLy5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyBkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IG5vbi1PcGVyYSAoUHJlc3RvLWJhc2VkKSB2ZXJzaW9ucyAob3JkZXIgaXMgaW1wb3J0YW50KS5cbiAgICBpZiAoIXZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSBnZXRWZXJzaW9uKFtcbiAgICAgICAgJyg/OkNsb3VkOXxDcmlPU3xDck1vfEVkZ2V8RWRnfEVkZ0F8RWRnaU9TfEZ4aU9TfEhlYWRsZXNzQ2hyb21lfElFTW9iaWxlfElyb258T3BlcmEgP01pbml8T1BpT1N8T1BSfFJhdmVufFNhbXN1bmdCcm93c2VyfFNpbGsoPyEvW1xcXFxkLl0rJCl8VUNCcm93c2VyfFlhQnJvd3NlciknLFxuICAgICAgICAnVmVyc2lvbicsXG4gICAgICAgIHF1YWxpZnkobmFtZSksXG4gICAgICAgICcoPzpGaXJlZm94fE1pbmVmaWVsZHxOZXRGcm9udCknXG4gICAgICBdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IHN0dWJib3JuIGxheW91dCBlbmdpbmVzLlxuICAgIGlmICgoZGF0YSA9XG4gICAgICAgICAgbGF5b3V0ID09ICdpQ2FiJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID4gMyAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgIC9cXGJPcGVyYVxcYi8udGVzdChuYW1lKSAmJiAoL1xcYk9QUlxcYi8udGVzdCh1YSkgPyAnQmxpbmsnIDogJ1ByZXN0bycpIHx8XG4gICAgICAgICAgL1xcYig/Ok1pZG9yaXxOb29rfFNhZmFyaSlcXGIvaS50ZXN0KHVhKSAmJiAhL14oPzpUcmlkZW50fEVkZ2VIVE1MKSQvLnRlc3QobGF5b3V0KSAmJiAnV2ViS2l0JyB8fFxuICAgICAgICAgICFsYXlvdXQgJiYgL1xcYk1TSUVcXGIvaS50ZXN0KHVhKSAmJiAob3MgPT0gJ01hYyBPUycgPyAnVGFzbWFuJyA6ICdUcmlkZW50JykgfHxcbiAgICAgICAgICBsYXlvdXQgPT0gJ1dlYktpdCcgJiYgL1xcYlBsYXlTdGF0aW9uXFxiKD8hIFZpdGFcXGIpL2kudGVzdChuYW1lKSAmJiAnTmV0RnJvbnQnXG4gICAgICAgICkpIHtcbiAgICAgIGxheW91dCA9IFtkYXRhXTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdpbmRvd3MgUGhvbmUgNyBkZXNrdG9wIG1vZGUuXG4gICAgaWYgKG5hbWUgPT0gJ0lFJyAmJiAoZGF0YSA9ICgvOyAqKD86WEJMV1B8WnVuZVdQKShcXGQrKS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lICcgKyAoL1xcKyQvLnRlc3QoZGF0YSkgPyBkYXRhIDogZGF0YSArICcueCcpO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDgueCBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAoL1xcYldQRGVza3RvcFxcYi9pLnRlc3QodWEpKSB7XG4gICAgICBuYW1lID0gJ0lFIE1vYmlsZSc7XG4gICAgICBvcyA9ICdXaW5kb3dzIFBob25lIDgueCc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIHZlcnNpb24gfHwgKHZlcnNpb24gPSAoL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkgfHwgMClbMV0pO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgSUUgMTEgaWRlbnRpZnlpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgZWxzZSBpZiAobmFtZSAhPSAnSUUnICYmIGxheW91dCA9PSAnVHJpZGVudCcgJiYgKGRhdGEgPSAvXFxicnY6KFtcXGQuXSspLy5leGVjKHVhKSkpIHtcbiAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ2lkZW50aWZ5aW5nIGFzICcgKyBuYW1lICsgKHZlcnNpb24gPyAnICcgKyB2ZXJzaW9uIDogJycpKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgdmVyc2lvbiA9IGRhdGFbMV07XG4gICAgfVxuICAgIC8vIExldmVyYWdlIGVudmlyb25tZW50IGZlYXR1cmVzLlxuICAgIGlmICh1c2VGZWF0dXJlcykge1xuICAgICAgLy8gRGV0ZWN0IHNlcnZlci1zaWRlIGVudmlyb25tZW50cy5cbiAgICAgIC8vIFJoaW5vIGhhcyBhIGdsb2JhbCBmdW5jdGlvbiB3aGlsZSBvdGhlcnMgaGF2ZSBhIGdsb2JhbCBvYmplY3QuXG4gICAgICBpZiAoaXNIb3N0VHlwZShjb250ZXh0LCAnZ2xvYmFsJykpIHtcbiAgICAgICAgaWYgKGphdmEpIHtcbiAgICAgICAgICBkYXRhID0gamF2YS5sYW5nLlN5c3RlbTtcbiAgICAgICAgICBhcmNoID0gZGF0YS5nZXRQcm9wZXJ0eSgnb3MuYXJjaCcpO1xuICAgICAgICAgIG9zID0gb3MgfHwgZGF0YS5nZXRQcm9wZXJ0eSgnb3MubmFtZScpICsgJyAnICsgZGF0YS5nZXRQcm9wZXJ0eSgnb3MudmVyc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaGlubykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gY29udGV4dC5yZXF1aXJlKCdyaW5nby9lbmdpbmUnKS52ZXJzaW9uLmpvaW4oJy4nKTtcbiAgICAgICAgICAgIG5hbWUgPSAnUmluZ29KUyc7XG4gICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBpZiAoKGRhdGEgPSBjb250ZXh0LnN5c3RlbSkgJiYgZGF0YS5nbG9iYWwuc3lzdGVtID09IGNvbnRleHQuc3lzdGVtKSB7XG4gICAgICAgICAgICAgIG5hbWUgPSAnTmFyd2hhbCc7XG4gICAgICAgICAgICAgIG9zIHx8IChvcyA9IGRhdGFbMF0ub3MgfHwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdSaGlubyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgIHR5cGVvZiBjb250ZXh0LnByb2Nlc3MgPT0gJ29iamVjdCcgJiYgIWNvbnRleHQucHJvY2Vzcy5icm93c2VyICYmXG4gICAgICAgICAgKGRhdGEgPSBjb250ZXh0LnByb2Nlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucyA9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLmVsZWN0cm9uID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ05vZGUgJyArIGRhdGEudmVyc2lvbnMubm9kZSk7XG4gICAgICAgICAgICAgIG5hbWUgPSAnRWxlY3Ryb24nO1xuICAgICAgICAgICAgICB2ZXJzaW9uID0gZGF0YS52ZXJzaW9ucy5lbGVjdHJvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMubncgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnQ2hyb21pdW0gJyArIHZlcnNpb24sICdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ05XLmpzJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMubnc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgbmFtZSA9ICdOb2RlLmpzJztcbiAgICAgICAgICAgIGFyY2ggPSBkYXRhLmFyY2g7XG4gICAgICAgICAgICBvcyA9IGRhdGEucGxhdGZvcm07XG4gICAgICAgICAgICB2ZXJzaW9uID0gL1tcXGQuXSsvLmV4ZWMoZGF0YS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHZlcnNpb24gPSB2ZXJzaW9uID8gdmVyc2lvblswXSA6IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgQWRvYmUgQUlSLlxuICAgICAgZWxzZSBpZiAoZ2V0Q2xhc3NPZigoZGF0YSA9IGNvbnRleHQucnVudGltZSkpID09IGFpclJ1bnRpbWVDbGFzcykge1xuICAgICAgICBuYW1lID0gJ0Fkb2JlIEFJUic7XG4gICAgICAgIG9zID0gZGF0YS5mbGFzaC5zeXN0ZW0uQ2FwYWJpbGl0aWVzLm9zO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IFBoYW50b21KUy5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnBoYW50b20pKSA9PSBwaGFudG9tQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdQaGFudG9tSlMnO1xuICAgICAgICB2ZXJzaW9uID0gKGRhdGEgPSBkYXRhLnZlcnNpb24gfHwgbnVsbCkgJiYgKGRhdGEubWFqb3IgKyAnLicgKyBkYXRhLm1pbm9yICsgJy4nICsgZGF0YS5wYXRjaCk7XG4gICAgICB9XG4gICAgICAvLyBEZXRlY3QgSUUgY29tcGF0aWJpbGl0eSBtb2Rlcy5cbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBkb2MuZG9jdW1lbnRNb2RlID09ICdudW1iZXInICYmIChkYXRhID0gL1xcYlRyaWRlbnRcXC8oXFxkKykvaS5leGVjKHVhKSkpIHtcbiAgICAgICAgLy8gV2UncmUgaW4gY29tcGF0aWJpbGl0eSBtb2RlIHdoZW4gdGhlIFRyaWRlbnQgdmVyc2lvbiArIDQgZG9lc24ndFxuICAgICAgICAvLyBlcXVhbCB0aGUgZG9jdW1lbnQgbW9kZS5cbiAgICAgICAgdmVyc2lvbiA9IFt2ZXJzaW9uLCBkb2MuZG9jdW1lbnRNb2RlXTtcbiAgICAgICAgaWYgKChkYXRhID0gK2RhdGFbMV0gKyA0KSAhPSB2ZXJzaW9uWzFdKSB7XG4gICAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnSUUgJyArIHZlcnNpb25bMV0gKyAnIG1vZGUnKTtcbiAgICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICcnKTtcbiAgICAgICAgICB2ZXJzaW9uWzFdID0gZGF0YTtcbiAgICAgICAgfVxuICAgICAgICB2ZXJzaW9uID0gbmFtZSA9PSAnSUUnID8gU3RyaW5nKHZlcnNpb25bMV0udG9GaXhlZCgxKSkgOiB2ZXJzaW9uWzBdO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIDExIG1hc2tpbmcgYXMgb3RoZXIgYnJvd3NlcnMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAvXig/OkNocm9tZXxGaXJlZm94KVxcYi8udGVzdChuYW1lKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdtYXNraW5nIGFzICcgKyBuYW1lICsgJyAnICsgdmVyc2lvbik7XG4gICAgICAgIG5hbWUgPSAnSUUnO1xuICAgICAgICB2ZXJzaW9uID0gJzExLjAnO1xuICAgICAgICBsYXlvdXQgPSBbJ1RyaWRlbnQnXTtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zICYmIGZvcm1hdChvcyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcmVyZWxlYXNlIHBoYXNlcy5cbiAgICBpZiAodmVyc2lvbiAmJiAoZGF0YSA9XG4gICAgICAgICAgLyg/OlthYl18ZHB8cHJlfFthYl1cXGQrcHJlKSg/OlxcZCtcXCs/KT8kL2kuZXhlYyh2ZXJzaW9uKSB8fFxuICAgICAgICAgIC8oPzphbHBoYXxiZXRhKSg/OiA/XFxkKT8vaS5leGVjKHVhICsgJzsnICsgKHVzZUZlYXR1cmVzICYmIG5hdi5hcHBNaW5vclZlcnNpb24pKSB8fFxuICAgICAgICAgIC9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAnYSdcbiAgICAgICAgKSkge1xuICAgICAgcHJlcmVsZWFzZSA9IC9iL2kudGVzdChkYXRhKSA/ICdiZXRhJyA6ICdhbHBoYSc7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKFJlZ0V4cChkYXRhICsgJ1xcXFwrPyQnKSwgJycpICtcbiAgICAgICAgKHByZXJlbGVhc2UgPT0gJ2JldGEnID8gYmV0YSA6IGFscGhhKSArICgvXFxkK1xcKz8vLmV4ZWMoZGF0YSkgfHwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgRmlyZWZveCBNb2JpbGUuXG4gICAgaWYgKG5hbWUgPT0gJ0Zlbm5lYycgfHwgbmFtZSA9PSAnRmlyZWZveCcgJiYgL1xcYig/OkFuZHJvaWR8RmlyZWZveCBPU3xLYWlPUylcXGIvLnRlc3Qob3MpKSB7XG4gICAgICBuYW1lID0gJ0ZpcmVmb3ggTW9iaWxlJztcbiAgICB9XG4gICAgLy8gT2JzY3VyZSBNYXh0aG9uJ3MgdW5yZWxpYWJsZSB2ZXJzaW9uLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ01heHRob24nICYmIHZlcnNpb24pIHtcbiAgICAgIHZlcnNpb24gPSB2ZXJzaW9uLnJlcGxhY2UoL1xcLltcXGQuXSsvLCAnLngnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFhib3ggMzYwIGFuZCBYYm94IE9uZS5cbiAgICBlbHNlIGlmICgvXFxiWGJveFxcYi9pLnRlc3QocHJvZHVjdCkpIHtcbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcpIHtcbiAgICAgICAgb3MgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHByb2R1Y3QgPT0gJ1hib3ggMzYwJyAmJiAvXFxiSUVNb2JpbGVcXGIvLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ21vYmlsZSBtb2RlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFkZCBtb2JpbGUgcG9zdGZpeC5cbiAgICBlbHNlIGlmICgoL14oPzpDaHJvbWV8SUV8T3BlcmEpJC8udGVzdChuYW1lKSB8fCBuYW1lICYmICFwcm9kdWN0ICYmICEvQnJvd3NlcnxNb2JpLy50ZXN0KG5hbWUpKSAmJlxuICAgICAgICAob3MgPT0gJ1dpbmRvd3MgQ0UnIHx8IC9Nb2JpL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lICs9ICcgTW9iaWxlJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIHBsYXRmb3JtIHByZXZpZXcuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnSUUnICYmIHVzZUZlYXR1cmVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoY29udGV4dC5leHRlcm5hbCA9PT0gbnVsbCkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ3BsYXRmb3JtIHByZXZpZXcnKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2VtYmVkZGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBCbGFja0JlcnJ5IE9TIHZlcnNpb24uXG4gICAgLy8gaHR0cDovL2RvY3MuYmxhY2tiZXJyeS5jb20vZW4vZGV2ZWxvcGVycy9kZWxpdmVyYWJsZXMvMTgxNjkvSFRUUF9oZWFkZXJzX3NlbnRfYnlfQkJfQnJvd3Nlcl8xMjM0OTExXzExLmpzcFxuICAgIGVsc2UgaWYgKCgvXFxiQmxhY2tCZXJyeVxcYi8udGVzdChwcm9kdWN0KSB8fCAvXFxiQkIxMFxcYi8udGVzdCh1YSkpICYmIChkYXRhID1cbiAgICAgICAgICAoUmVnRXhwKHByb2R1Y3QucmVwbGFjZSgvICsvZywgJyAqJykgKyAnLyhbLlxcXFxkXSspJywgJ2knKS5leGVjKHVhKSB8fCAwKVsxXSB8fFxuICAgICAgICAgIHZlcnNpb25cbiAgICAgICAgKSkge1xuICAgICAgZGF0YSA9IFtkYXRhLCAvQkIxMC8udGVzdCh1YSldO1xuICAgICAgb3MgPSAoZGF0YVsxXSA/IChwcm9kdWN0ID0gbnVsbCwgbWFudWZhY3R1cmVyID0gJ0JsYWNrQmVycnknKSA6ICdEZXZpY2UgU29mdHdhcmUnKSArICcgJyArIGRhdGFbMF07XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGlkZW50aWZ5aW5nL21hc2tpbmcgaXRzZWxmIGFzIGFub3RoZXIgYnJvd3Nlci5cbiAgICAvLyBodHRwOi8vd3d3Lm9wZXJhLmNvbS9zdXBwb3J0L2tiL3ZpZXcvODQzL1xuICAgIGVsc2UgaWYgKHRoaXMgIT0gZm9yT3duICYmIHByb2R1Y3QgIT0gJ1dpaScgJiYgKFxuICAgICAgICAgICh1c2VGZWF0dXJlcyAmJiBvcGVyYSkgfHxcbiAgICAgICAgICAoL09wZXJhLy50ZXN0KG5hbWUpICYmIC9cXGIoPzpNU0lFfEZpcmVmb3gpXFxiL2kudGVzdCh1YSkpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGJPUyBYICg/OlxcZCtcXC4pezIsfS8udGVzdChvcykpIHx8XG4gICAgICAgICAgKG5hbWUgPT0gJ0lFJyAmJiAoXG4gICAgICAgICAgICAob3MgJiYgIS9eV2luLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gNS41KSB8fFxuICAgICAgICAgICAgL1xcYldpbmRvd3MgWFBcXGIvLnRlc3Qob3MpICYmIHZlcnNpb24gPiA4IHx8XG4gICAgICAgICAgICB2ZXJzaW9uID09IDggJiYgIS9cXGJUcmlkZW50XFxiLy50ZXN0KHVhKVxuICAgICAgICAgICkpXG4gICAgICAgICkgJiYgIXJlT3BlcmEudGVzdCgoZGF0YSA9IHBhcnNlLmNhbGwoZm9yT3duLCB1YS5yZXBsYWNlKHJlT3BlcmEsICcnKSArICc7JykpKSAmJiBkYXRhLm5hbWUpIHtcbiAgICAgIC8vIFdoZW4gXCJpZGVudGlmeWluZ1wiLCB0aGUgVUEgY29udGFpbnMgYm90aCBPcGVyYSBhbmQgdGhlIG90aGVyIGJyb3dzZXIncyBuYW1lLlxuICAgICAgZGF0YSA9ICdpbmcgYXMgJyArIGRhdGEubmFtZSArICgoZGF0YSA9IGRhdGEudmVyc2lvbikgPyAnICcgKyBkYXRhIDogJycpO1xuICAgICAgaWYgKHJlT3BlcmEudGVzdChuYW1lKSkge1xuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpICYmIG9zID09ICdNYWMgT1MnKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEgPSAnaWRlbnRpZnknICsgZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gXCJtYXNraW5nXCIsIHRoZSBVQSBjb250YWlucyBvbmx5IHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGVsc2Uge1xuICAgICAgICBkYXRhID0gJ21hc2snICsgZGF0YTtcbiAgICAgICAgaWYgKG9wZXJhQ2xhc3MpIHtcbiAgICAgICAgICBuYW1lID0gZm9ybWF0KG9wZXJhQ2xhc3MucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxICQyJykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWUgPSAnT3BlcmEnO1xuICAgICAgICB9XG4gICAgICAgIGlmICgvXFxiSUVcXGIvLnRlc3QoZGF0YSkpIHtcbiAgICAgICAgICBvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF1c2VGZWF0dXJlcykge1xuICAgICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsYXlvdXQgPSBbJ1ByZXN0byddO1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChkYXRhKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IFdlYktpdCBOaWdodGx5IGFuZCBhcHByb3hpbWF0ZSBDaHJvbWUvU2FmYXJpIHZlcnNpb25zLlxuICAgIGlmICgoZGF0YSA9ICgvXFxiQXBwbGVXZWJLaXRcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAvLyBDb3JyZWN0IGJ1aWxkIG51bWJlciBmb3IgbnVtZXJpYyBjb21wYXJpc29uLlxuICAgICAgLy8gKGUuZy4gXCI1MzIuNVwiIGJlY29tZXMgXCI1MzIuMDVcIilcbiAgICAgIGRhdGEgPSBbcGFyc2VGbG9hdChkYXRhLnJlcGxhY2UoL1xcLihcXGQpJC8sICcuMCQxJykpLCBkYXRhXTtcbiAgICAgIC8vIE5pZ2h0bHkgYnVpbGRzIGFyZSBwb3N0Zml4ZWQgd2l0aCBhIFwiK1wiLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgZGF0YVsxXS5zbGljZSgtMSkgPT0gJysnKSB7XG4gICAgICAgIG5hbWUgPSAnV2ViS2l0IE5pZ2h0bHknO1xuICAgICAgICBwcmVyZWxlYXNlID0gJ2FscGhhJztcbiAgICAgICAgdmVyc2lvbiA9IGRhdGFbMV0uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgaW5jb3JyZWN0IGJyb3dzZXIgdmVyc2lvbnMuXG4gICAgICBlbHNlIGlmICh2ZXJzaW9uID09IGRhdGFbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uID09IChkYXRhWzJdID0gKC9cXGJTYWZhcmlcXC8oW1xcZC5dK1xcKz8pL2kuZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICAgIHZlcnNpb24gPSBudWxsO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHRoZSBmdWxsIENocm9tZSB2ZXJzaW9uIHdoZW4gYXZhaWxhYmxlLlxuICAgICAgZGF0YVsxXSA9ICgvXFxiKD86SGVhZGxlc3MpP0Nocm9tZVxcLyhbXFxkLl0rKS9pLmV4ZWModWEpIHx8IDApWzFdO1xuICAgICAgLy8gRGV0ZWN0IEJsaW5rIGxheW91dCBlbmdpbmUuXG4gICAgICBpZiAoZGF0YVswXSA9PSA1MzcuMzYgJiYgZGF0YVsyXSA9PSA1MzcuMzYgJiYgcGFyc2VGbG9hdChkYXRhWzFdKSA+PSAyOCAmJiBsYXlvdXQgPT0gJ1dlYktpdCcpIHtcbiAgICAgICAgbGF5b3V0ID0gWydCbGluayddO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEphdmFTY3JpcHRDb3JlLlxuICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzY4NDc0L2hvdy1jYW4taS1kZXRlY3Qtd2hpY2gtamF2YXNjcmlwdC1lbmdpbmUtdjgtb3ItanNjLWlzLXVzZWQtYXQtcnVudGltZS1pbi1hbmRyb2lcbiAgICAgIGlmICghdXNlRmVhdHVyZXMgfHwgKCFsaWtlQ2hyb21lICYmICFkYXRhWzFdKSkge1xuICAgICAgICBsYXlvdXQgJiYgKGxheW91dFsxXSA9ICdsaWtlIFNhZmFyaScpO1xuICAgICAgICBkYXRhID0gKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNDAwID8gMSA6IGRhdGEgPCA1MDAgPyAyIDogZGF0YSA8IDUyNiA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQgPyAnNCsnIDogZGF0YSA8IDUzNSA/IDUgOiBkYXRhIDwgNTM3ID8gNiA6IGRhdGEgPCA1MzggPyA3IDogZGF0YSA8IDYwMSA/IDggOiBkYXRhIDwgNjAyID8gOSA6IGRhdGEgPCA2MDQgPyAxMCA6IGRhdGEgPCA2MDYgPyAxMSA6IGRhdGEgPCA2MDggPyAxMiA6ICcxMicpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBDaHJvbWUnKTtcbiAgICAgICAgZGF0YSA9IGRhdGFbMV0gfHwgKGRhdGEgPSBkYXRhWzBdLCBkYXRhIDwgNTMwID8gMSA6IGRhdGEgPCA1MzIgPyAyIDogZGF0YSA8IDUzMi4wNSA/IDMgOiBkYXRhIDwgNTMzID8gNCA6IGRhdGEgPCA1MzQuMDMgPyA1IDogZGF0YSA8IDUzNC4wNyA/IDYgOiBkYXRhIDwgNTM0LjEwID8gNyA6IGRhdGEgPCA1MzQuMTMgPyA4IDogZGF0YSA8IDUzNC4xNiA/IDkgOiBkYXRhIDwgNTM0LjI0ID8gMTAgOiBkYXRhIDwgNTM0LjMwID8gMTEgOiBkYXRhIDwgNTM1LjAxID8gMTIgOiBkYXRhIDwgNTM1LjAyID8gJzEzKycgOiBkYXRhIDwgNTM1LjA3ID8gMTUgOiBkYXRhIDwgNTM1LjExID8gMTYgOiBkYXRhIDwgNTM1LjE5ID8gMTcgOiBkYXRhIDwgNTM2LjA1ID8gMTggOiBkYXRhIDwgNTM2LjEwID8gMTkgOiBkYXRhIDwgNTM3LjAxID8gMjAgOiBkYXRhIDwgNTM3LjExID8gJzIxKycgOiBkYXRhIDwgNTM3LjEzID8gMjMgOiBkYXRhIDwgNTM3LjE4ID8gMjQgOiBkYXRhIDwgNTM3LjI0ID8gMjUgOiBkYXRhIDwgNTM3LjM2ID8gMjYgOiBsYXlvdXQgIT0gJ0JsaW5rJyA/ICcyNycgOiAnMjgnKTtcbiAgICAgIH1cbiAgICAgIC8vIEFkZCB0aGUgcG9zdGZpeCBvZiBcIi54XCIgb3IgXCIrXCIgZm9yIGFwcHJveGltYXRlIHZlcnNpb25zLlxuICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gKz0gJyAnICsgKGRhdGEgKz0gdHlwZW9mIGRhdGEgPT0gJ251bWJlcicgPyAnLngnIDogL1suK10vLnRlc3QoZGF0YSkgPyAnJyA6ICcrJykpO1xuICAgICAgLy8gT2JzY3VyZSB2ZXJzaW9uIGZvciBzb21lIFNhZmFyaSAxLTIgcmVsZWFzZXMuXG4gICAgICBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAoIXZlcnNpb24gfHwgcGFyc2VJbnQodmVyc2lvbikgPiA0NSkpIHtcbiAgICAgICAgdmVyc2lvbiA9IGRhdGE7XG4gICAgICB9IGVsc2UgaWYgKG5hbWUgPT0gJ0Nocm9tZScgJiYgL1xcYkhlYWRsZXNzQ2hyb21lL2kudGVzdCh1YSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnaGVhZGxlc3MnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIGRlc2t0b3AgbW9kZXMuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhJyAmJiAgKGRhdGEgPSAvXFxiemJvdnx6dmF2JC8uZXhlYyhvcykpKSB7XG4gICAgICBuYW1lICs9ICcgJztcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgaWYgKGRhdGEgPT0gJ3p2YXYnKSB7XG4gICAgICAgIG5hbWUgKz0gJ01pbmknO1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWUgKz0gJ01vYmlsZSc7XG4gICAgICB9XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhICsgJyQnKSwgJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgQ2hyb21lIGRlc2t0b3AgbW9kZS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdTYWZhcmknICYmIC9cXGJDaHJvbWVcXGIvLmV4ZWMobGF5b3V0ICYmIGxheW91dFsxXSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgbmFtZSA9ICdDaHJvbWUgTW9iaWxlJztcbiAgICAgIHZlcnNpb24gPSBudWxsO1xuXG4gICAgICBpZiAoL1xcYk9TIFhcXGIvLnRlc3Qob3MpKSB7XG4gICAgICAgIG1hbnVmYWN0dXJlciA9ICdBcHBsZSc7XG4gICAgICAgIG9zID0gJ2lPUyA0LjMrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gTmV3ZXIgdmVyc2lvbnMgb2YgU1JXYXJlIElyb24gdXNlcyB0aGUgQ2hyb21lIHRhZyB0byBpbmRpY2F0ZSBpdHMgdmVyc2lvbiBudW1iZXIuXG4gICAgZWxzZSBpZiAoL1xcYlNSV2FyZSBJcm9uXFxiLy50ZXN0KG5hbWUpICYmICF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbignQ2hyb21lJyk7XG4gICAgfVxuICAgIC8vIFN0cmlwIGluY29ycmVjdCBPUyB2ZXJzaW9ucy5cbiAgICBpZiAodmVyc2lvbiAmJiB2ZXJzaW9uLmluZGV4T2YoKGRhdGEgPSAvW1xcZC5dKyQvLmV4ZWMob3MpKSkgPT0gMCAmJlxuICAgICAgICB1YS5pbmRleE9mKCcvJyArIGRhdGEgKyAnLScpID4gLTEpIHtcbiAgICAgIG9zID0gdHJpbShvcy5yZXBsYWNlKGRhdGEsICcnKSk7XG4gICAgfVxuICAgIC8vIEVuc3VyZSBPUyBkb2VzIG5vdCBpbmNsdWRlIHRoZSBicm93c2VyIG5hbWUuXG4gICAgaWYgKG9zICYmIG9zLmluZGV4T2YobmFtZSkgIT0gLTEgJiYgIVJlZ0V4cChuYW1lICsgJyBPUycpLnRlc3Qob3MpKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKCcgKicgKyBxdWFsaWZ5KG5hbWUpICsgJyAqJyksICcnKTtcbiAgICB9XG4gICAgLy8gQWRkIGxheW91dCBlbmdpbmUuXG4gICAgaWYgKGxheW91dCAmJiAhL1xcYig/OkF2YW50fE5vb2spXFxiLy50ZXN0KG5hbWUpICYmIChcbiAgICAgICAgL0Jyb3dzZXJ8THVuYXNjYXBlfE1heHRob24vLnRlc3QobmFtZSkgfHxcbiAgICAgICAgbmFtZSAhPSAnU2FmYXJpJyAmJiAvXmlPUy8udGVzdChvcykgJiYgL1xcYlNhZmFyaVxcYi8udGVzdChsYXlvdXRbMV0pIHx8XG4gICAgICAgIC9eKD86QWRvYmV8QXJvcmF8QnJlYWNofE1pZG9yaXxPcGVyYXxQaGFudG9tfFJla29ucXxSb2NrfFNhbXN1bmcgSW50ZXJuZXR8U2xlaXBuaXJ8U1JXYXJlIElyb258Vml2YWxkaXxXZWIpLy50ZXN0KG5hbWUpICYmIGxheW91dFsxXSkpIHtcbiAgICAgIC8vIERvbid0IGFkZCBsYXlvdXQgZGV0YWlscyB0byBkZXNjcmlwdGlvbiBpZiB0aGV5IGFyZSBmYWxzZXkuXG4gICAgICAoZGF0YSA9IGxheW91dFtsYXlvdXQubGVuZ3RoIC0gMV0pICYmIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIENvbWJpbmUgY29udGV4dHVhbCBpbmZvcm1hdGlvbi5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9IFsnKCcgKyBkZXNjcmlwdGlvbi5qb2luKCc7ICcpICsgJyknXTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIG1hbnVmYWN0dXJlciB0byBkZXNjcmlwdGlvbi5cbiAgICBpZiAobWFudWZhY3R1cmVyICYmIHByb2R1Y3QgJiYgcHJvZHVjdC5pbmRleE9mKG1hbnVmYWN0dXJlcikgPCAwKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdvbiAnICsgbWFudWZhY3R1cmVyKTtcbiAgICB9XG4gICAgLy8gQXBwZW5kIHByb2R1Y3QgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKHByb2R1Y3QpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goKC9eb24gLy50ZXN0KGRlc2NyaXB0aW9uW2Rlc2NyaXB0aW9uLmxlbmd0aCAtIDFdKSA/ICcnIDogJ29uICcpICsgcHJvZHVjdCk7XG4gICAgfVxuICAgIC8vIFBhcnNlIHRoZSBPUyBpbnRvIGFuIG9iamVjdC5cbiAgICBpZiAob3MpIHtcbiAgICAgIGRhdGEgPSAvIChbXFxkLitdKykkLy5leGVjKG9zKTtcbiAgICAgIGlzU3BlY2lhbENhc2VkT1MgPSBkYXRhICYmIG9zLmNoYXJBdChvcy5sZW5ndGggLSBkYXRhWzBdLmxlbmd0aCAtIDEpID09ICcvJztcbiAgICAgIG9zID0ge1xuICAgICAgICAnYXJjaGl0ZWN0dXJlJzogMzIsXG4gICAgICAgICdmYW1pbHknOiAoZGF0YSAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyBvcy5yZXBsYWNlKGRhdGFbMF0sICcnKSA6IG9zLFxuICAgICAgICAndmVyc2lvbic6IGRhdGEgPyBkYXRhWzFdIDogbnVsbCxcbiAgICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIHZlcnNpb24gPSB0aGlzLnZlcnNpb247XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZmFtaWx5ICsgKCh2ZXJzaW9uICYmICFpc1NwZWNpYWxDYXNlZE9TKSA/ICcgJyArIHZlcnNpb24gOiAnJykgKyAodGhpcy5hcmNoaXRlY3R1cmUgPT0gNjQgPyAnIDY0LWJpdCcgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICAgIC8vIEFkZCBicm93c2VyL09TIGFyY2hpdGVjdHVyZS5cbiAgICBpZiAoKGRhdGEgPSAvXFxiKD86QU1EfElBfFdpbnxXT1d8eDg2X3x4KTY0XFxiL2kuZXhlYyhhcmNoKSkgJiYgIS9cXGJpNjg2XFxiL2kudGVzdChhcmNoKSkge1xuICAgICAgaWYgKG9zKSB7XG4gICAgICAgIG9zLmFyY2hpdGVjdHVyZSA9IDY0O1xuICAgICAgICBvcy5mYW1pbHkgPSBvcy5mYW1pbHkucmVwbGFjZShSZWdFeHAoJyAqJyArIGRhdGEpLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgICAgbmFtZSAmJiAoL1xcYldPVzY0XFxiL2kudGVzdCh1YSkgfHxcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgL1xcdyg/Ojg2fDMyKSQvLnRlc3QobmF2LmNwdUNsYXNzIHx8IG5hdi5wbGF0Zm9ybSkgJiYgIS9cXGJXaW42NDsgeDY0XFxiL2kudGVzdCh1YSkpKVxuICAgICAgKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJzMyLWJpdCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDaHJvbWUgMzkgYW5kIGFib3ZlIG9uIE9TIFggaXMgYWx3YXlzIDY0LWJpdC5cbiAgICBlbHNlIGlmIChcbiAgICAgICAgb3MgJiYgL15PUyBYLy50ZXN0KG9zLmZhbWlseSkgJiZcbiAgICAgICAgbmFtZSA9PSAnQ2hyb21lJyAmJiBwYXJzZUZsb2F0KHZlcnNpb24pID49IDM5XG4gICAgKSB7XG4gICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICB9XG5cbiAgICB1YSB8fCAodWEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAbmFtZSBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHZhciBwbGF0Zm9ybSA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIHBsYXRmb3JtIGRlc2NyaXB0aW9uLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgb2YgdGhlIGJyb3dzZXIncyBsYXlvdXQgZW5naW5lLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGxheW91dCBlbmdpbmVzIGluY2x1ZGU6XG4gICAgICogXCJCbGlua1wiLCBcIkVkZ2VIVE1MXCIsIFwiR2Vja29cIiwgXCJUcmlkZW50XCIgYW5kIFwiV2ViS2l0XCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubGF5b3V0ID0gbGF5b3V0ICYmIGxheW91dFswXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0J3MgbWFudWZhY3R1cmVyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgbWFudWZhY3R1cmVycyBpbmNsdWRlOlxuICAgICAqIFwiQXBwbGVcIiwgXCJBcmNob3NcIiwgXCJBbWF6b25cIiwgXCJBc3VzXCIsIFwiQmFybmVzICYgTm9ibGVcIiwgXCJCbGFja0JlcnJ5XCIsXG4gICAgICogXCJHb29nbGVcIiwgXCJIUFwiLCBcIkhUQ1wiLCBcIkxHXCIsIFwiTWljcm9zb2Z0XCIsIFwiTW90b3JvbGFcIiwgXCJOaW50ZW5kb1wiLFxuICAgICAqIFwiTm9raWFcIiwgXCJTYW1zdW5nXCIgYW5kIFwiU29ueVwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm1hbnVmYWN0dXJlciA9IG1hbnVmYWN0dXJlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyL2Vudmlyb25tZW50LlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIGJyb3dzZXIgbmFtZXMgaW5jbHVkZTpcbiAgICAgKiBcIkNocm9tZVwiLCBcIkVsZWN0cm9uXCIsIFwiRmlyZWZveFwiLCBcIkZpcmVmb3ggZm9yIGlPU1wiLCBcIklFXCIsXG4gICAgICogXCJNaWNyb3NvZnQgRWRnZVwiLCBcIlBoYW50b21KU1wiLCBcIlNhZmFyaVwiLCBcIlNlYU1vbmtleVwiLCBcIlNpbGtcIixcbiAgICAgKiBcIk9wZXJhIE1pbmlcIiBhbmQgXCJPcGVyYVwiXG4gICAgICpcbiAgICAgKiBNb2JpbGUgdmVyc2lvbnMgb2Ygc29tZSBicm93c2VycyBoYXZlIFwiTW9iaWxlXCIgYXBwZW5kZWQgdG8gdGhlaXIgbmFtZTpcbiAgICAgKiBlZy4gXCJDaHJvbWUgTW9iaWxlXCIsIFwiRmlyZWZveCBNb2JpbGVcIiwgXCJJRSBNb2JpbGVcIiBhbmQgXCJPcGVyYSBNb2JpbGVcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5uYW1lID0gbmFtZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhbHBoYS9iZXRhIHJlbGVhc2UgaW5kaWNhdG9yLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5wcmVyZWxlYXNlID0gcHJlcmVsZWFzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0IGhvc3RpbmcgdGhlIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBUaGUgbGlzdCBvZiBjb21tb24gcHJvZHVjdHMgaW5jbHVkZTpcbiAgICAgKlxuICAgICAqIFwiQmxhY2tCZXJyeVwiLCBcIkdhbGF4eSBTNFwiLCBcIkx1bWlhXCIsIFwiaVBhZFwiLCBcImlQb2RcIiwgXCJpUGhvbmVcIiwgXCJLaW5kbGVcIixcbiAgICAgKiBcIktpbmRsZSBGaXJlXCIsIFwiTmV4dXNcIiwgXCJOb29rXCIsIFwiUGxheUJvb2tcIiwgXCJUb3VjaFBhZFwiIGFuZCBcIlRyYW5zZm9ybWVyXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJvZHVjdCA9IHByb2R1Y3Q7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYnJvd3NlcidzIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS51YSA9IHVhO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udmVyc2lvbiA9IG5hbWUgJiYgdmVyc2lvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgT2JqZWN0XG4gICAgICovXG4gICAgcGxhdGZvcm0ub3MgPSBvcyB8fCB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIENQVSBhcmNoaXRlY3R1cmUgdGhlIE9TIGlzIGJ1aWx0IGZvci5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEB0eXBlIG51bWJlcnxudWxsXG4gICAgICAgKi9cbiAgICAgICdhcmNoaXRlY3R1cmUnOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBmYW1pbHkgb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIENvbW1vbiB2YWx1ZXMgaW5jbHVkZTpcbiAgICAgICAqIFwiV2luZG93c1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggUjIgLyA3XCIsIFwiV2luZG93cyBTZXJ2ZXIgMjAwOCAvIFZpc3RhXCIsXG4gICAgICAgKiBcIldpbmRvd3MgWFBcIiwgXCJPUyBYXCIsIFwiTGludXhcIiwgXCJVYnVudHVcIiwgXCJEZWJpYW5cIiwgXCJGZWRvcmFcIiwgXCJSZWQgSGF0XCIsXG4gICAgICAgKiBcIlN1U0VcIiwgXCJBbmRyb2lkXCIsIFwiaU9TXCIgYW5kIFwiV2luZG93cyBQaG9uZVwiXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAnZmFtaWx5JzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgT1MuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAgICovXG4gICAgICAndmVyc2lvbic6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogUmV0dXJucyB0aGUgT1Mgc3RyaW5nLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIE9TIHN0cmluZy5cbiAgICAgICAqL1xuICAgICAgJ3RvU3RyaW5nJzogZnVuY3Rpb24oKSB7IHJldHVybiAnbnVsbCc7IH1cbiAgICB9O1xuXG4gICAgcGxhdGZvcm0ucGFyc2UgPSBwYXJzZTtcbiAgICBwbGF0Zm9ybS50b1N0cmluZyA9IHRvU3RyaW5nUGxhdGZvcm07XG5cbiAgICBpZiAocGxhdGZvcm0udmVyc2lvbikge1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCh2ZXJzaW9uKTtcbiAgICB9XG4gICAgaWYgKHBsYXRmb3JtLm5hbWUpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQobmFtZSk7XG4gICAgfVxuICAgIGlmIChvcyAmJiBuYW1lICYmICEob3MgPT0gU3RyaW5nKG9zKS5zcGxpdCgnICcpWzBdICYmIChvcyA9PSBuYW1lLnNwbGl0KCcgJylbMF0gfHwgcHJvZHVjdCkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKHByb2R1Y3QgPyAnKCcgKyBvcyArICcpJyA6ICdvbiAnICsgb3MpO1xuICAgIH1cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoKSB7XG4gICAgICBwbGF0Zm9ybS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uLmpvaW4oJyAnKTtcbiAgICB9XG4gICAgcmV0dXJuIHBsYXRmb3JtO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IHBsYXRmb3JtLlxuICB2YXIgcGxhdGZvcm0gPSBwYXJzZSgpO1xuXG4gIC8vIFNvbWUgQU1EIGJ1aWxkIG9wdGltaXplcnMsIGxpa2Ugci5qcywgY2hlY2sgZm9yIGNvbmRpdGlvbiBwYXR0ZXJucyBsaWtlIHRoZSBmb2xsb3dpbmc6XG4gIGlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEV4cG9zZSBwbGF0Zm9ybSBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIHBsYXRmb3JtIGlzXG4gICAgLy8gbG9hZGVkIGJ5IGEgc2NyaXB0IHRhZyBpbiB0aGUgcHJlc2VuY2Ugb2YgYW4gQU1EIGxvYWRlci5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9lcnJvcnMuaHRtbCNtaXNtYXRjaCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHJvb3QucGxhdGZvcm0gPSBwbGF0Zm9ybTtcblxuICAgIC8vIERlZmluZSBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlIHNvIHBsYXRmb3JtIGNhbiBiZSBhbGlhc2VkIHRocm91Z2ggcGF0aCBtYXBwaW5nLlxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBhbiBgZXhwb3J0c2Agb2JqZWN0LlxuICBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZvck93bihwbGF0Zm9ybSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgZnJlZUV4cG9ydHNba2V5XSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInYxXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF92LmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidjNcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3YyLmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidjRcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3YzLmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidjVcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3Y0LmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiTklMXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9uaWwuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ2ZXJzaW9uXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF92ZXJzaW9uLmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidmFsaWRhdGVcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3ZhbGlkYXRlLmRlZmF1bHQ7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwic3RyaW5naWZ5XCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9zdHJpbmdpZnkuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJwYXJzZVwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcGFyc2UuZGVmYXVsdDtcbiAgfVxufSk7XG5cbnZhciBfdiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdjEuanNcIikpO1xuXG52YXIgX3YyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92My5qc1wiKSk7XG5cbnZhciBfdjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3Y0LmpzXCIpKTtcblxudmFyIF92NCA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdjUuanNcIikpO1xuXG52YXIgX25pbCA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vbmlsLmpzXCIpKTtcblxudmFyIF92ZXJzaW9uID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92ZXJzaW9uLmpzXCIpKTtcblxudmFyIF92YWxpZGF0ZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdmFsaWRhdGUuanNcIikpO1xuXG52YXIgX3N0cmluZ2lmeSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vc3RyaW5naWZ5LmpzXCIpKTtcblxudmFyIF9wYXJzZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vcGFyc2UuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfSIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuXG4vKlxuICogQnJvd3Nlci1jb21wYXRpYmxlIEphdmFTY3JpcHQgTUQ1XG4gKlxuICogTW9kaWZpY2F0aW9uIG9mIEphdmFTY3JpcHQgTUQ1XG4gKiBodHRwczovL2dpdGh1Yi5jb20vYmx1ZWltcC9KYXZhU2NyaXB0LU1ENVxuICpcbiAqIENvcHlyaWdodCAyMDExLCBTZWJhc3RpYW4gVHNjaGFuXG4gKiBodHRwczovL2JsdWVpbXAubmV0XG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlOlxuICogaHR0cHM6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVRcbiAqXG4gKiBCYXNlZCBvblxuICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBSU0EgRGF0YSBTZWN1cml0eSwgSW5jLiBNRDUgTWVzc2FnZVxuICogRGlnZXN0IEFsZ29yaXRobSwgYXMgZGVmaW5lZCBpbiBSRkMgMTMyMS5cbiAqIFZlcnNpb24gMi4yIENvcHlyaWdodCAoQykgUGF1bCBKb2huc3RvbiAxOTk5IC0gMjAwOVxuICogT3RoZXIgY29udHJpYnV0b3JzOiBHcmVnIEhvbHQsIEFuZHJldyBLZXBlcnQsIFlkbmFyLCBMb3N0aW5ldFxuICogRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIEJTRCBMaWNlbnNlXG4gKiBTZWUgaHR0cDovL3BhamhvbWUub3JnLnVrL2NyeXB0L21kNSBmb3IgbW9yZSBpbmZvLlxuICovXG5mdW5jdGlvbiBtZDUoYnl0ZXMpIHtcbiAgaWYgKHR5cGVvZiBieXRlcyA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBtc2cgPSB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoYnl0ZXMpKTsgLy8gVVRGOCBlc2NhcGVcblxuICAgIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobXNnLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1zZy5sZW5ndGg7ICsraSkge1xuICAgICAgYnl0ZXNbaV0gPSBtc2cuY2hhckNvZGVBdChpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWQ1VG9IZXhFbmNvZGVkQXJyYXkod29yZHNUb01kNShieXRlc1RvV29yZHMoYnl0ZXMpLCBieXRlcy5sZW5ndGggKiA4KSk7XG59XG4vKlxuICogQ29udmVydCBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzIHRvIGFuIGFycmF5IG9mIGJ5dGVzXG4gKi9cblxuXG5mdW5jdGlvbiBtZDVUb0hleEVuY29kZWRBcnJheShpbnB1dCkge1xuICBjb25zdCBvdXRwdXQgPSBbXTtcbiAgY29uc3QgbGVuZ3RoMzIgPSBpbnB1dC5sZW5ndGggKiAzMjtcbiAgY29uc3QgaGV4VGFiID0gJzAxMjM0NTY3ODlhYmNkZWYnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoMzI7IGkgKz0gOCkge1xuICAgIGNvbnN0IHggPSBpbnB1dFtpID4+IDVdID4+PiBpICUgMzIgJiAweGZmO1xuICAgIGNvbnN0IGhleCA9IHBhcnNlSW50KGhleFRhYi5jaGFyQXQoeCA+Pj4gNCAmIDB4MGYpICsgaGV4VGFiLmNoYXJBdCh4ICYgMHgwZiksIDE2KTtcbiAgICBvdXRwdXQucHVzaChoZXgpO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dDtcbn1cbi8qKlxuICogQ2FsY3VsYXRlIG91dHB1dCBsZW5ndGggd2l0aCBwYWRkaW5nIGFuZCBiaXQgbGVuZ3RoXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGg4KSB7XG4gIHJldHVybiAoaW5wdXRMZW5ndGg4ICsgNjQgPj4+IDkgPDwgNCkgKyAxNCArIDE7XG59XG4vKlxuICogQ2FsY3VsYXRlIHRoZSBNRDUgb2YgYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3JkcywgYW5kIGEgYml0IGxlbmd0aC5cbiAqL1xuXG5cbmZ1bmN0aW9uIHdvcmRzVG9NZDUoeCwgbGVuKSB7XG4gIC8qIGFwcGVuZCBwYWRkaW5nICovXG4gIHhbbGVuID4+IDVdIHw9IDB4ODAgPDwgbGVuICUgMzI7XG4gIHhbZ2V0T3V0cHV0TGVuZ3RoKGxlbikgLSAxXSA9IGxlbjtcbiAgbGV0IGEgPSAxNzMyNTg0MTkzO1xuICBsZXQgYiA9IC0yNzE3MzM4Nzk7XG4gIGxldCBjID0gLTE3MzI1ODQxOTQ7XG4gIGxldCBkID0gMjcxNzMzODc4O1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkgKz0gMTYpIHtcbiAgICBjb25zdCBvbGRhID0gYTtcbiAgICBjb25zdCBvbGRiID0gYjtcbiAgICBjb25zdCBvbGRjID0gYztcbiAgICBjb25zdCBvbGRkID0gZDtcbiAgICBhID0gbWQ1ZmYoYSwgYiwgYywgZCwgeFtpXSwgNywgLTY4MDg3NjkzNik7XG4gICAgZCA9IG1kNWZmKGQsIGEsIGIsIGMsIHhbaSArIDFdLCAxMiwgLTM4OTU2NDU4Nik7XG4gICAgYyA9IG1kNWZmKGMsIGQsIGEsIGIsIHhbaSArIDJdLCAxNywgNjA2MTA1ODE5KTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgM10sIDIyLCAtMTA0NDUyNTMzMCk7XG4gICAgYSA9IG1kNWZmKGEsIGIsIGMsIGQsIHhbaSArIDRdLCA3LCAtMTc2NDE4ODk3KTtcbiAgICBkID0gbWQ1ZmYoZCwgYSwgYiwgYywgeFtpICsgNV0sIDEyLCAxMjAwMDgwNDI2KTtcbiAgICBjID0gbWQ1ZmYoYywgZCwgYSwgYiwgeFtpICsgNl0sIDE3LCAtMTQ3MzIzMTM0MSk7XG4gICAgYiA9IG1kNWZmKGIsIGMsIGQsIGEsIHhbaSArIDddLCAyMiwgLTQ1NzA1OTgzKTtcbiAgICBhID0gbWQ1ZmYoYSwgYiwgYywgZCwgeFtpICsgOF0sIDcsIDE3NzAwMzU0MTYpO1xuICAgIGQgPSBtZDVmZihkLCBhLCBiLCBjLCB4W2kgKyA5XSwgMTIsIC0xOTU4NDE0NDE3KTtcbiAgICBjID0gbWQ1ZmYoYywgZCwgYSwgYiwgeFtpICsgMTBdLCAxNywgLTQyMDYzKTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgMTFdLCAyMiwgLTE5OTA0MDQxNjIpO1xuICAgIGEgPSBtZDVmZihhLCBiLCBjLCBkLCB4W2kgKyAxMl0sIDcsIDE4MDQ2MDM2ODIpO1xuICAgIGQgPSBtZDVmZihkLCBhLCBiLCBjLCB4W2kgKyAxM10sIDEyLCAtNDAzNDExMDEpO1xuICAgIGMgPSBtZDVmZihjLCBkLCBhLCBiLCB4W2kgKyAxNF0sIDE3LCAtMTUwMjAwMjI5MCk7XG4gICAgYiA9IG1kNWZmKGIsIGMsIGQsIGEsIHhbaSArIDE1XSwgMjIsIDEyMzY1MzUzMjkpO1xuICAgIGEgPSBtZDVnZyhhLCBiLCBjLCBkLCB4W2kgKyAxXSwgNSwgLTE2NTc5NjUxMCk7XG4gICAgZCA9IG1kNWdnKGQsIGEsIGIsIGMsIHhbaSArIDZdLCA5LCAtMTA2OTUwMTYzMik7XG4gICAgYyA9IG1kNWdnKGMsIGQsIGEsIGIsIHhbaSArIDExXSwgMTQsIDY0MzcxNzcxMyk7XG4gICAgYiA9IG1kNWdnKGIsIGMsIGQsIGEsIHhbaV0sIDIwLCAtMzczODk3MzAyKTtcbiAgICBhID0gbWQ1Z2coYSwgYiwgYywgZCwgeFtpICsgNV0sIDUsIC03MDE1NTg2OTEpO1xuICAgIGQgPSBtZDVnZyhkLCBhLCBiLCBjLCB4W2kgKyAxMF0sIDksIDM4MDE2MDgzKTtcbiAgICBjID0gbWQ1Z2coYywgZCwgYSwgYiwgeFtpICsgMTVdLCAxNCwgLTY2MDQ3ODMzNSk7XG4gICAgYiA9IG1kNWdnKGIsIGMsIGQsIGEsIHhbaSArIDRdLCAyMCwgLTQwNTUzNzg0OCk7XG4gICAgYSA9IG1kNWdnKGEsIGIsIGMsIGQsIHhbaSArIDldLCA1LCA1Njg0NDY0MzgpO1xuICAgIGQgPSBtZDVnZyhkLCBhLCBiLCBjLCB4W2kgKyAxNF0sIDksIC0xMDE5ODAzNjkwKTtcbiAgICBjID0gbWQ1Z2coYywgZCwgYSwgYiwgeFtpICsgM10sIDE0LCAtMTg3MzYzOTYxKTtcbiAgICBiID0gbWQ1Z2coYiwgYywgZCwgYSwgeFtpICsgOF0sIDIwLCAxMTYzNTMxNTAxKTtcbiAgICBhID0gbWQ1Z2coYSwgYiwgYywgZCwgeFtpICsgMTNdLCA1LCAtMTQ0NDY4MTQ2Nyk7XG4gICAgZCA9IG1kNWdnKGQsIGEsIGIsIGMsIHhbaSArIDJdLCA5LCAtNTE0MDM3ODQpO1xuICAgIGMgPSBtZDVnZyhjLCBkLCBhLCBiLCB4W2kgKyA3XSwgMTQsIDE3MzUzMjg0NzMpO1xuICAgIGIgPSBtZDVnZyhiLCBjLCBkLCBhLCB4W2kgKyAxMl0sIDIwLCAtMTkyNjYwNzczNCk7XG4gICAgYSA9IG1kNWhoKGEsIGIsIGMsIGQsIHhbaSArIDVdLCA0LCAtMzc4NTU4KTtcbiAgICBkID0gbWQ1aGgoZCwgYSwgYiwgYywgeFtpICsgOF0sIDExLCAtMjAyMjU3NDQ2Myk7XG4gICAgYyA9IG1kNWhoKGMsIGQsIGEsIGIsIHhbaSArIDExXSwgMTYsIDE4MzkwMzA1NjIpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyAxNF0sIDIzLCAtMzUzMDk1NTYpO1xuICAgIGEgPSBtZDVoaChhLCBiLCBjLCBkLCB4W2kgKyAxXSwgNCwgLTE1MzA5OTIwNjApO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2kgKyA0XSwgMTEsIDEyNzI4OTMzNTMpO1xuICAgIGMgPSBtZDVoaChjLCBkLCBhLCBiLCB4W2kgKyA3XSwgMTYsIC0xNTU0OTc2MzIpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyAxMF0sIDIzLCAtMTA5NDczMDY0MCk7XG4gICAgYSA9IG1kNWhoKGEsIGIsIGMsIGQsIHhbaSArIDEzXSwgNCwgNjgxMjc5MTc0KTtcbiAgICBkID0gbWQ1aGgoZCwgYSwgYiwgYywgeFtpXSwgMTEsIC0zNTg1MzcyMjIpO1xuICAgIGMgPSBtZDVoaChjLCBkLCBhLCBiLCB4W2kgKyAzXSwgMTYsIC03MjI1MjE5NzkpO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyA2XSwgMjMsIDc2MDI5MTg5KTtcbiAgICBhID0gbWQ1aGgoYSwgYiwgYywgZCwgeFtpICsgOV0sIDQsIC02NDAzNjQ0ODcpO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2kgKyAxMl0sIDExLCAtNDIxODE1ODM1KTtcbiAgICBjID0gbWQ1aGgoYywgZCwgYSwgYiwgeFtpICsgMTVdLCAxNiwgNTMwNzQyNTIwKTtcbiAgICBiID0gbWQ1aGgoYiwgYywgZCwgYSwgeFtpICsgMl0sIDIzLCAtOTk1MzM4NjUxKTtcbiAgICBhID0gbWQ1aWkoYSwgYiwgYywgZCwgeFtpXSwgNiwgLTE5ODYzMDg0NCk7XG4gICAgZCA9IG1kNWlpKGQsIGEsIGIsIGMsIHhbaSArIDddLCAxMCwgMTEyNjg5MTQxNSk7XG4gICAgYyA9IG1kNWlpKGMsIGQsIGEsIGIsIHhbaSArIDE0XSwgMTUsIC0xNDE2MzU0OTA1KTtcbiAgICBiID0gbWQ1aWkoYiwgYywgZCwgYSwgeFtpICsgNV0sIDIxLCAtNTc0MzQwNTUpO1xuICAgIGEgPSBtZDVpaShhLCBiLCBjLCBkLCB4W2kgKyAxMl0sIDYsIDE3MDA0ODU1NzEpO1xuICAgIGQgPSBtZDVpaShkLCBhLCBiLCBjLCB4W2kgKyAzXSwgMTAsIC0xODk0OTg2NjA2KTtcbiAgICBjID0gbWQ1aWkoYywgZCwgYSwgYiwgeFtpICsgMTBdLCAxNSwgLTEwNTE1MjMpO1xuICAgIGIgPSBtZDVpaShiLCBjLCBkLCBhLCB4W2kgKyAxXSwgMjEsIC0yMDU0OTIyNzk5KTtcbiAgICBhID0gbWQ1aWkoYSwgYiwgYywgZCwgeFtpICsgOF0sIDYsIDE4NzMzMTMzNTkpO1xuICAgIGQgPSBtZDVpaShkLCBhLCBiLCBjLCB4W2kgKyAxNV0sIDEwLCAtMzA2MTE3NDQpO1xuICAgIGMgPSBtZDVpaShjLCBkLCBhLCBiLCB4W2kgKyA2XSwgMTUsIC0xNTYwMTk4MzgwKTtcbiAgICBiID0gbWQ1aWkoYiwgYywgZCwgYSwgeFtpICsgMTNdLCAyMSwgMTMwOTE1MTY0OSk7XG4gICAgYSA9IG1kNWlpKGEsIGIsIGMsIGQsIHhbaSArIDRdLCA2LCAtMTQ1NTIzMDcwKTtcbiAgICBkID0gbWQ1aWkoZCwgYSwgYiwgYywgeFtpICsgMTFdLCAxMCwgLTExMjAyMTAzNzkpO1xuICAgIGMgPSBtZDVpaShjLCBkLCBhLCBiLCB4W2kgKyAyXSwgMTUsIDcxODc4NzI1OSk7XG4gICAgYiA9IG1kNWlpKGIsIGMsIGQsIGEsIHhbaSArIDldLCAyMSwgLTM0MzQ4NTU1MSk7XG4gICAgYSA9IHNhZmVBZGQoYSwgb2xkYSk7XG4gICAgYiA9IHNhZmVBZGQoYiwgb2xkYik7XG4gICAgYyA9IHNhZmVBZGQoYywgb2xkYyk7XG4gICAgZCA9IHNhZmVBZGQoZCwgb2xkZCk7XG4gIH1cblxuICByZXR1cm4gW2EsIGIsIGMsIGRdO1xufVxuLypcbiAqIENvbnZlcnQgYW4gYXJyYXkgYnl0ZXMgdG8gYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3Jkc1xuICogQ2hhcmFjdGVycyA+MjU1IGhhdmUgdGhlaXIgaGlnaC1ieXRlIHNpbGVudGx5IGlnbm9yZWQuXG4gKi9cblxuXG5mdW5jdGlvbiBieXRlc1RvV29yZHMoaW5wdXQpIHtcbiAgaWYgKGlucHV0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IGxlbmd0aDggPSBpbnB1dC5sZW5ndGggKiA4O1xuICBjb25zdCBvdXRwdXQgPSBuZXcgVWludDMyQXJyYXkoZ2V0T3V0cHV0TGVuZ3RoKGxlbmd0aDgpKTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDg7IGkgKz0gOCkge1xuICAgIG91dHB1dFtpID4+IDVdIHw9IChpbnB1dFtpIC8gOF0gJiAweGZmKSA8PCBpICUgMzI7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufVxuLypcbiAqIEFkZCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zIGludGVybmFsbHlcbiAqIHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gKi9cblxuXG5mdW5jdGlvbiBzYWZlQWRkKHgsIHkpIHtcbiAgY29uc3QgbHN3ID0gKHggJiAweGZmZmYpICsgKHkgJiAweGZmZmYpO1xuICBjb25zdCBtc3cgPSAoeCA+PiAxNikgKyAoeSA+PiAxNikgKyAobHN3ID4+IDE2KTtcbiAgcmV0dXJuIG1zdyA8PCAxNiB8IGxzdyAmIDB4ZmZmZjtcbn1cbi8qXG4gKiBCaXR3aXNlIHJvdGF0ZSBhIDMyLWJpdCBudW1iZXIgdG8gdGhlIGxlZnQuXG4gKi9cblxuXG5mdW5jdGlvbiBiaXRSb3RhdGVMZWZ0KG51bSwgY250KSB7XG4gIHJldHVybiBudW0gPDwgY250IHwgbnVtID4+PiAzMiAtIGNudDtcbn1cbi8qXG4gKiBUaGVzZSBmdW5jdGlvbnMgaW1wbGVtZW50IHRoZSBmb3VyIGJhc2ljIG9wZXJhdGlvbnMgdGhlIGFsZ29yaXRobSB1c2VzLlxuICovXG5cblxuZnVuY3Rpb24gbWQ1Y21uKHEsIGEsIGIsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIHNhZmVBZGQoYml0Um90YXRlTGVmdChzYWZlQWRkKHNhZmVBZGQoYSwgcSksIHNhZmVBZGQoeCwgdCkpLCBzKSwgYik7XG59XG5cbmZ1bmN0aW9uIG1kNWZmKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIG1kNWNtbihiICYgYyB8IH5iICYgZCwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIG1kNWdnKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIG1kNWNtbihiICYgZCB8IGMgJiB+ZCwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIG1kNWhoKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIG1kNWNtbihiIF4gYyBeIGQsIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBtZDVpaShhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBtZDVjbW4oYyBeIChiIHwgfmQpLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxudmFyIF9kZWZhdWx0ID0gbWQ1O1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG52YXIgX2RlZmF1bHQgPSAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwJztcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuXG52YXIgX3ZhbGlkYXRlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92YWxpZGF0ZS5qc1wiKSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIHBhcnNlKHV1aWQpIHtcbiAgaWYgKCEoMCwgX3ZhbGlkYXRlLmRlZmF1bHQpKHV1aWQpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKCdJbnZhbGlkIFVVSUQnKTtcbiAgfVxuXG4gIGxldCB2O1xuICBjb25zdCBhcnIgPSBuZXcgVWludDhBcnJheSgxNik7IC8vIFBhcnNlICMjIyMjIyMjLS4uLi4tLi4uLi0uLi4uLS4uLi4uLi4uLi4uLlxuXG4gIGFyclswXSA9ICh2ID0gcGFyc2VJbnQodXVpZC5zbGljZSgwLCA4KSwgMTYpKSA+Pj4gMjQ7XG4gIGFyclsxXSA9IHYgPj4+IDE2ICYgMHhmZjtcbiAgYXJyWzJdID0gdiA+Pj4gOCAmIDB4ZmY7XG4gIGFyclszXSA9IHYgJiAweGZmOyAvLyBQYXJzZSAuLi4uLi4uLi0jIyMjLS4uLi4tLi4uLi0uLi4uLi4uLi4uLi5cblxuICBhcnJbNF0gPSAodiA9IHBhcnNlSW50KHV1aWQuc2xpY2UoOSwgMTMpLCAxNikpID4+PiA4O1xuICBhcnJbNV0gPSB2ICYgMHhmZjsgLy8gUGFyc2UgLi4uLi4uLi4tLi4uLi0jIyMjLS4uLi4tLi4uLi4uLi4uLi4uXG5cbiAgYXJyWzZdID0gKHYgPSBwYXJzZUludCh1dWlkLnNsaWNlKDE0LCAxOCksIDE2KSkgPj4+IDg7XG4gIGFycls3XSA9IHYgJiAweGZmOyAvLyBQYXJzZSAuLi4uLi4uLi0uLi4uLS4uLi4tIyMjIy0uLi4uLi4uLi4uLi5cblxuICBhcnJbOF0gPSAodiA9IHBhcnNlSW50KHV1aWQuc2xpY2UoMTksIDIzKSwgMTYpKSA+Pj4gODtcbiAgYXJyWzldID0gdiAmIDB4ZmY7IC8vIFBhcnNlIC4uLi4uLi4uLS4uLi4tLi4uLi0uLi4uLSMjIyMjIyMjIyMjI1xuICAvLyAoVXNlIFwiL1wiIHRvIGF2b2lkIDMyLWJpdCB0cnVuY2F0aW9uIHdoZW4gYml0LXNoaWZ0aW5nIGhpZ2gtb3JkZXIgYnl0ZXMpXG5cbiAgYXJyWzEwXSA9ICh2ID0gcGFyc2VJbnQodXVpZC5zbGljZSgyNCwgMzYpLCAxNikpIC8gMHgxMDAwMDAwMDAwMCAmIDB4ZmY7XG4gIGFyclsxMV0gPSB2IC8gMHgxMDAwMDAwMDAgJiAweGZmO1xuICBhcnJbMTJdID0gdiA+Pj4gMjQgJiAweGZmO1xuICBhcnJbMTNdID0gdiA+Pj4gMTYgJiAweGZmO1xuICBhcnJbMTRdID0gdiA+Pj4gOCAmIDB4ZmY7XG4gIGFyclsxNV0gPSB2ICYgMHhmZjtcbiAgcmV0dXJuIGFycjtcbn1cblxudmFyIF9kZWZhdWx0ID0gcGFyc2U7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcbnZhciBfZGVmYXVsdCA9IC9eKD86WzAtOWEtZl17OH0tWzAtOWEtZl17NH0tWzEtNV1bMC05YS1mXXszfS1bODlhYl1bMC05YS1mXXszfS1bMC05YS1mXXsxMn18MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwKSQvaTtcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gcm5nO1xuLy8gVW5pcXVlIElEIGNyZWF0aW9uIHJlcXVpcmVzIGEgaGlnaCBxdWFsaXR5IHJhbmRvbSAjIGdlbmVyYXRvci4gSW4gdGhlIGJyb3dzZXIgd2UgdGhlcmVmb3JlXG4vLyByZXF1aXJlIHRoZSBjcnlwdG8gQVBJIGFuZCBkbyBub3Qgc3VwcG9ydCBidWlsdC1pbiBmYWxsYmFjayB0byBsb3dlciBxdWFsaXR5IHJhbmRvbSBudW1iZXJcbi8vIGdlbmVyYXRvcnMgKGxpa2UgTWF0aC5yYW5kb20oKSkuXG5sZXQgZ2V0UmFuZG9tVmFsdWVzO1xuY29uc3Qgcm5kczggPSBuZXcgVWludDhBcnJheSgxNik7XG5cbmZ1bmN0aW9uIHJuZygpIHtcbiAgLy8gbGF6eSBsb2FkIHNvIHRoYXQgZW52aXJvbm1lbnRzIHRoYXQgbmVlZCB0byBwb2x5ZmlsbCBoYXZlIGEgY2hhbmNlIHRvIGRvIHNvXG4gIGlmICghZ2V0UmFuZG9tVmFsdWVzKSB7XG4gICAgLy8gZ2V0UmFuZG9tVmFsdWVzIG5lZWRzIHRvIGJlIGludm9rZWQgaW4gYSBjb250ZXh0IHdoZXJlIFwidGhpc1wiIGlzIGEgQ3J5cHRvIGltcGxlbWVudGF0aW9uLiBBbHNvLFxuICAgIC8vIGZpbmQgdGhlIGNvbXBsZXRlIGltcGxlbWVudGF0aW9uIG9mIGNyeXB0byAobXNDcnlwdG8pIG9uIElFMTEuXG4gICAgZ2V0UmFuZG9tVmFsdWVzID0gdHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQoY3J5cHRvKSB8fCB0eXBlb2YgbXNDcnlwdG8gIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT09ICdmdW5jdGlvbicgJiYgbXNDcnlwdG8uZ2V0UmFuZG9tVmFsdWVzLmJpbmQobXNDcnlwdG8pO1xuXG4gICAgaWYgKCFnZXRSYW5kb21WYWx1ZXMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY3J5cHRvLmdldFJhbmRvbVZhbHVlcygpIG5vdCBzdXBwb3J0ZWQuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdXVpZGpzL3V1aWQjZ2V0cmFuZG9tdmFsdWVzLW5vdC1zdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZ2V0UmFuZG9tVmFsdWVzKHJuZHM4KTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxuLy8gQWRhcHRlZCBmcm9tIENocmlzIFZlbmVzcycgU0hBMSBjb2RlIGF0XG4vLyBodHRwOi8vd3d3Lm1vdmFibGUtdHlwZS5jby51ay9zY3JpcHRzL3NoYTEuaHRtbFxuZnVuY3Rpb24gZihzLCB4LCB5LCB6KSB7XG4gIHN3aXRjaCAocykge1xuICAgIGNhc2UgMDpcbiAgICAgIHJldHVybiB4ICYgeSBeIH54ICYgejtcblxuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiB4IF4geSBeIHo7XG5cbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4geCAmIHkgXiB4ICYgeiBeIHkgJiB6O1xuXG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuIHggXiB5IF4gejtcbiAgfVxufVxuXG5mdW5jdGlvbiBST1RMKHgsIG4pIHtcbiAgcmV0dXJuIHggPDwgbiB8IHggPj4+IDMyIC0gbjtcbn1cblxuZnVuY3Rpb24gc2hhMShieXRlcykge1xuICBjb25zdCBLID0gWzB4NWE4Mjc5OTksIDB4NmVkOWViYTEsIDB4OGYxYmJjZGMsIDB4Y2E2MmMxZDZdO1xuICBjb25zdCBIID0gWzB4Njc0NTIzMDEsIDB4ZWZjZGFiODksIDB4OThiYWRjZmUsIDB4MTAzMjU0NzYsIDB4YzNkMmUxZjBdO1xuXG4gIGlmICh0eXBlb2YgYnl0ZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc3QgbXNnID0gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KGJ5dGVzKSk7IC8vIFVURjggZXNjYXBlXG5cbiAgICBieXRlcyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtc2cubGVuZ3RoOyArK2kpIHtcbiAgICAgIGJ5dGVzLnB1c2gobXNnLmNoYXJDb2RlQXQoaSkpO1xuICAgIH1cbiAgfSBlbHNlIGlmICghQXJyYXkuaXNBcnJheShieXRlcykpIHtcbiAgICAvLyBDb252ZXJ0IEFycmF5LWxpa2UgdG8gQXJyYXlcbiAgICBieXRlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGJ5dGVzKTtcbiAgfVxuXG4gIGJ5dGVzLnB1c2goMHg4MCk7XG4gIGNvbnN0IGwgPSBieXRlcy5sZW5ndGggLyA0ICsgMjtcbiAgY29uc3QgTiA9IE1hdGguY2VpbChsIC8gMTYpO1xuICBjb25zdCBNID0gbmV3IEFycmF5KE4pO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgTjsgKytpKSB7XG4gICAgY29uc3QgYXJyID0gbmV3IFVpbnQzMkFycmF5KDE2KTtcblxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikge1xuICAgICAgYXJyW2pdID0gYnl0ZXNbaSAqIDY0ICsgaiAqIDRdIDw8IDI0IHwgYnl0ZXNbaSAqIDY0ICsgaiAqIDQgKyAxXSA8PCAxNiB8IGJ5dGVzW2kgKiA2NCArIGogKiA0ICsgMl0gPDwgOCB8IGJ5dGVzW2kgKiA2NCArIGogKiA0ICsgM107XG4gICAgfVxuXG4gICAgTVtpXSA9IGFycjtcbiAgfVxuXG4gIE1bTiAtIDFdWzE0XSA9IChieXRlcy5sZW5ndGggLSAxKSAqIDggLyBNYXRoLnBvdygyLCAzMik7XG4gIE1bTiAtIDFdWzE0XSA9IE1hdGguZmxvb3IoTVtOIC0gMV1bMTRdKTtcbiAgTVtOIC0gMV1bMTVdID0gKGJ5dGVzLmxlbmd0aCAtIDEpICogOCAmIDB4ZmZmZmZmZmY7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBOOyArK2kpIHtcbiAgICBjb25zdCBXID0gbmV3IFVpbnQzMkFycmF5KDgwKTtcblxuICAgIGZvciAobGV0IHQgPSAwOyB0IDwgMTY7ICsrdCkge1xuICAgICAgV1t0XSA9IE1baV1bdF07XG4gICAgfVxuXG4gICAgZm9yIChsZXQgdCA9IDE2OyB0IDwgODA7ICsrdCkge1xuICAgICAgV1t0XSA9IFJPVEwoV1t0IC0gM10gXiBXW3QgLSA4XSBeIFdbdCAtIDE0XSBeIFdbdCAtIDE2XSwgMSk7XG4gICAgfVxuXG4gICAgbGV0IGEgPSBIWzBdO1xuICAgIGxldCBiID0gSFsxXTtcbiAgICBsZXQgYyA9IEhbMl07XG4gICAgbGV0IGQgPSBIWzNdO1xuICAgIGxldCBlID0gSFs0XTtcblxuICAgIGZvciAobGV0IHQgPSAwOyB0IDwgODA7ICsrdCkge1xuICAgICAgY29uc3QgcyA9IE1hdGguZmxvb3IodCAvIDIwKTtcbiAgICAgIGNvbnN0IFQgPSBST1RMKGEsIDUpICsgZihzLCBiLCBjLCBkKSArIGUgKyBLW3NdICsgV1t0XSA+Pj4gMDtcbiAgICAgIGUgPSBkO1xuICAgICAgZCA9IGM7XG4gICAgICBjID0gUk9UTChiLCAzMCkgPj4+IDA7XG4gICAgICBiID0gYTtcbiAgICAgIGEgPSBUO1xuICAgIH1cblxuICAgIEhbMF0gPSBIWzBdICsgYSA+Pj4gMDtcbiAgICBIWzFdID0gSFsxXSArIGIgPj4+IDA7XG4gICAgSFsyXSA9IEhbMl0gKyBjID4+PiAwO1xuICAgIEhbM10gPSBIWzNdICsgZCA+Pj4gMDtcbiAgICBIWzRdID0gSFs0XSArIGUgPj4+IDA7XG4gIH1cblxuICByZXR1cm4gW0hbMF0gPj4gMjQgJiAweGZmLCBIWzBdID4+IDE2ICYgMHhmZiwgSFswXSA+PiA4ICYgMHhmZiwgSFswXSAmIDB4ZmYsIEhbMV0gPj4gMjQgJiAweGZmLCBIWzFdID4+IDE2ICYgMHhmZiwgSFsxXSA+PiA4ICYgMHhmZiwgSFsxXSAmIDB4ZmYsIEhbMl0gPj4gMjQgJiAweGZmLCBIWzJdID4+IDE2ICYgMHhmZiwgSFsyXSA+PiA4ICYgMHhmZiwgSFsyXSAmIDB4ZmYsIEhbM10gPj4gMjQgJiAweGZmLCBIWzNdID4+IDE2ICYgMHhmZiwgSFszXSA+PiA4ICYgMHhmZiwgSFszXSAmIDB4ZmYsIEhbNF0gPj4gMjQgJiAweGZmLCBIWzRdID4+IDE2ICYgMHhmZiwgSFs0XSA+PiA4ICYgMHhmZiwgSFs0XSAmIDB4ZmZdO1xufVxuXG52YXIgX2RlZmF1bHQgPSBzaGExO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfdmFsaWRhdGUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3ZhbGlkYXRlLmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuLyoqXG4gKiBDb252ZXJ0IGFycmF5IG9mIDE2IGJ5dGUgdmFsdWVzIHRvIFVVSUQgc3RyaW5nIGZvcm1hdCBvZiB0aGUgZm9ybTpcbiAqIFhYWFhYWFhYLVhYWFgtWFhYWC1YWFhYLVhYWFhYWFhYWFhYWFxuICovXG5jb25zdCBieXRlVG9IZXggPSBbXTtcblxuZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICBieXRlVG9IZXgucHVzaCgoaSArIDB4MTAwKS50b1N0cmluZygxNikuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gc3RyaW5naWZ5KGFyciwgb2Zmc2V0ID0gMCkge1xuICAvLyBOb3RlOiBCZSBjYXJlZnVsIGVkaXRpbmcgdGhpcyBjb2RlISAgSXQncyBiZWVuIHR1bmVkIGZvciBwZXJmb3JtYW5jZVxuICAvLyBhbmQgd29ya3MgaW4gd2F5cyB5b3UgbWF5IG5vdCBleHBlY3QuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vdXVpZGpzL3V1aWQvcHVsbC80MzRcbiAgY29uc3QgdXVpZCA9IChieXRlVG9IZXhbYXJyW29mZnNldCArIDBdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMV1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAyXV0gKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDNdXSArICctJyArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgNF1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyA1XV0gKyAnLScgKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDZdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgN11dICsgJy0nICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyA4XV0gKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDldXSArICctJyArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTBdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTFdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTJdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTNdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTRdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMTVdXSkudG9Mb3dlckNhc2UoKTsgLy8gQ29uc2lzdGVuY3kgY2hlY2sgZm9yIHZhbGlkIFVVSUQuICBJZiB0aGlzIHRocm93cywgaXQncyBsaWtlbHkgZHVlIHRvIG9uZVxuICAvLyBvZiB0aGUgZm9sbG93aW5nOlxuICAvLyAtIE9uZSBvciBtb3JlIGlucHV0IGFycmF5IHZhbHVlcyBkb24ndCBtYXAgdG8gYSBoZXggb2N0ZXQgKGxlYWRpbmcgdG9cbiAgLy8gXCJ1bmRlZmluZWRcIiBpbiB0aGUgdXVpZClcbiAgLy8gLSBJbnZhbGlkIGlucHV0IHZhbHVlcyBmb3IgdGhlIFJGQyBgdmVyc2lvbmAgb3IgYHZhcmlhbnRgIGZpZWxkc1xuXG4gIGlmICghKDAsIF92YWxpZGF0ZS5kZWZhdWx0KSh1dWlkKSkge1xuICAgIHRocm93IFR5cGVFcnJvcignU3RyaW5naWZpZWQgVVVJRCBpcyBpbnZhbGlkJyk7XG4gIH1cblxuICByZXR1cm4gdXVpZDtcbn1cblxudmFyIF9kZWZhdWx0ID0gc3RyaW5naWZ5O1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfcm5nID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9ybmcuanNcIikpO1xuXG52YXIgX3N0cmluZ2lmeSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vc3RyaW5naWZ5LmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuLy8gKipgdjEoKWAgLSBHZW5lcmF0ZSB0aW1lLWJhc2VkIFVVSUQqKlxuLy9cbi8vIEluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9MaW9zSy9VVUlELmpzXG4vLyBhbmQgaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L3V1aWQuaHRtbFxubGV0IF9ub2RlSWQ7XG5cbmxldCBfY2xvY2tzZXE7IC8vIFByZXZpb3VzIHV1aWQgY3JlYXRpb24gdGltZVxuXG5cbmxldCBfbGFzdE1TZWNzID0gMDtcbmxldCBfbGFzdE5TZWNzID0gMDsgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS91dWlkanMvdXVpZCBmb3IgQVBJIGRldGFpbHNcblxuZnVuY3Rpb24gdjEob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgbGV0IGkgPSBidWYgJiYgb2Zmc2V0IHx8IDA7XG4gIGNvbnN0IGIgPSBidWYgfHwgbmV3IEFycmF5KDE2KTtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIGxldCBub2RlID0gb3B0aW9ucy5ub2RlIHx8IF9ub2RlSWQ7XG4gIGxldCBjbG9ja3NlcSA9IG9wdGlvbnMuY2xvY2tzZXEgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xvY2tzZXEgOiBfY2xvY2tzZXE7IC8vIG5vZGUgYW5kIGNsb2Nrc2VxIG5lZWQgdG8gYmUgaW5pdGlhbGl6ZWQgdG8gcmFuZG9tIHZhbHVlcyBpZiB0aGV5J3JlIG5vdFxuICAvLyBzcGVjaWZpZWQuICBXZSBkbyB0aGlzIGxhemlseSB0byBtaW5pbWl6ZSBpc3N1ZXMgcmVsYXRlZCB0byBpbnN1ZmZpY2llbnRcbiAgLy8gc3lzdGVtIGVudHJvcHkuICBTZWUgIzE4OVxuXG4gIGlmIChub2RlID09IG51bGwgfHwgY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgIGNvbnN0IHNlZWRCeXRlcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBfcm5nLmRlZmF1bHQpKCk7XG5cbiAgICBpZiAobm9kZSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC41LCBjcmVhdGUgYW5kIDQ4LWJpdCBub2RlIGlkLCAoNDcgcmFuZG9tIGJpdHMgKyBtdWx0aWNhc3QgYml0ID0gMSlcbiAgICAgIG5vZGUgPSBfbm9kZUlkID0gW3NlZWRCeXRlc1swXSB8IDB4MDEsIHNlZWRCeXRlc1sxXSwgc2VlZEJ5dGVzWzJdLCBzZWVkQnl0ZXNbM10sIHNlZWRCeXRlc1s0XSwgc2VlZEJ5dGVzWzVdXTtcbiAgICB9XG5cbiAgICBpZiAoY2xvY2tzZXEgPT0gbnVsbCkge1xuICAgICAgLy8gUGVyIDQuMi4yLCByYW5kb21pemUgKDE0IGJpdCkgY2xvY2tzZXFcbiAgICAgIGNsb2Nrc2VxID0gX2Nsb2Nrc2VxID0gKHNlZWRCeXRlc1s2XSA8PCA4IHwgc2VlZEJ5dGVzWzddKSAmIDB4M2ZmZjtcbiAgICB9XG4gIH0gLy8gVVVJRCB0aW1lc3RhbXBzIGFyZSAxMDAgbmFuby1zZWNvbmQgdW5pdHMgc2luY2UgdGhlIEdyZWdvcmlhbiBlcG9jaCxcbiAgLy8gKDE1ODItMTAtMTUgMDA6MDApLiAgSlNOdW1iZXJzIGFyZW4ndCBwcmVjaXNlIGVub3VnaCBmb3IgdGhpcywgc29cbiAgLy8gdGltZSBpcyBoYW5kbGVkIGludGVybmFsbHkgYXMgJ21zZWNzJyAoaW50ZWdlciBtaWxsaXNlY29uZHMpIGFuZCAnbnNlY3MnXG4gIC8vICgxMDAtbmFub3NlY29uZHMgb2Zmc2V0IGZyb20gbXNlY3MpIHNpbmNlIHVuaXggZXBvY2gsIDE5NzAtMDEtMDEgMDA6MDAuXG5cblxuICBsZXQgbXNlY3MgPSBvcHRpb25zLm1zZWNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1zZWNzIDogRGF0ZS5ub3coKTsgLy8gUGVyIDQuMi4xLjIsIHVzZSBjb3VudCBvZiB1dWlkJ3MgZ2VuZXJhdGVkIGR1cmluZyB0aGUgY3VycmVudCBjbG9ja1xuICAvLyBjeWNsZSB0byBzaW11bGF0ZSBoaWdoZXIgcmVzb2x1dGlvbiBjbG9ja1xuXG4gIGxldCBuc2VjcyA9IG9wdGlvbnMubnNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubnNlY3MgOiBfbGFzdE5TZWNzICsgMTsgLy8gVGltZSBzaW5jZSBsYXN0IHV1aWQgY3JlYXRpb24gKGluIG1zZWNzKVxuXG4gIGNvbnN0IGR0ID0gbXNlY3MgLSBfbGFzdE1TZWNzICsgKG5zZWNzIC0gX2xhc3ROU2VjcykgLyAxMDAwMDsgLy8gUGVyIDQuMi4xLjIsIEJ1bXAgY2xvY2tzZXEgb24gY2xvY2sgcmVncmVzc2lvblxuXG4gIGlmIChkdCA8IDAgJiYgb3B0aW9ucy5jbG9ja3NlcSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgY2xvY2tzZXEgPSBjbG9ja3NlcSArIDEgJiAweDNmZmY7XG4gIH0gLy8gUmVzZXQgbnNlY3MgaWYgY2xvY2sgcmVncmVzc2VzIChuZXcgY2xvY2tzZXEpIG9yIHdlJ3ZlIG1vdmVkIG9udG8gYSBuZXdcbiAgLy8gdGltZSBpbnRlcnZhbFxuXG5cbiAgaWYgKChkdCA8IDAgfHwgbXNlY3MgPiBfbGFzdE1TZWNzKSAmJiBvcHRpb25zLm5zZWNzID09PSB1bmRlZmluZWQpIHtcbiAgICBuc2VjcyA9IDA7XG4gIH0gLy8gUGVyIDQuMi4xLjIgVGhyb3cgZXJyb3IgaWYgdG9vIG1hbnkgdXVpZHMgYXJlIHJlcXVlc3RlZFxuXG5cbiAgaWYgKG5zZWNzID49IDEwMDAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidXVpZC52MSgpOiBDYW4ndCBjcmVhdGUgbW9yZSB0aGFuIDEwTSB1dWlkcy9zZWNcIik7XG4gIH1cblxuICBfbGFzdE1TZWNzID0gbXNlY3M7XG4gIF9sYXN0TlNlY3MgPSBuc2VjcztcbiAgX2Nsb2Nrc2VxID0gY2xvY2tzZXE7IC8vIFBlciA0LjEuNCAtIENvbnZlcnQgZnJvbSB1bml4IGVwb2NoIHRvIEdyZWdvcmlhbiBlcG9jaFxuXG4gIG1zZWNzICs9IDEyMjE5MjkyODAwMDAwOyAvLyBgdGltZV9sb3dgXG5cbiAgY29uc3QgdGwgPSAoKG1zZWNzICYgMHhmZmZmZmZmKSAqIDEwMDAwICsgbnNlY3MpICUgMHgxMDAwMDAwMDA7XG4gIGJbaSsrXSA9IHRsID4+PiAyNCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiAxNiAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRsID4+PiA4ICYgMHhmZjtcbiAgYltpKytdID0gdGwgJiAweGZmOyAvLyBgdGltZV9taWRgXG5cbiAgY29uc3QgdG1oID0gbXNlY3MgLyAweDEwMDAwMDAwMCAqIDEwMDAwICYgMHhmZmZmZmZmO1xuICBiW2krK10gPSB0bWggPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bWggJiAweGZmOyAvLyBgdGltZV9oaWdoX2FuZF92ZXJzaW9uYFxuXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMjQgJiAweGYgfCAweDEwOyAvLyBpbmNsdWRlIHZlcnNpb25cblxuICBiW2krK10gPSB0bWggPj4+IDE2ICYgMHhmZjsgLy8gYGNsb2NrX3NlcV9oaV9hbmRfcmVzZXJ2ZWRgIChQZXIgNC4yLjIgLSBpbmNsdWRlIHZhcmlhbnQpXG5cbiAgYltpKytdID0gY2xvY2tzZXEgPj4+IDggfCAweDgwOyAvLyBgY2xvY2tfc2VxX2xvd2BcblxuICBiW2krK10gPSBjbG9ja3NlcSAmIDB4ZmY7IC8vIGBub2RlYFxuXG4gIGZvciAobGV0IG4gPSAwOyBuIDwgNjsgKytuKSB7XG4gICAgYltpICsgbl0gPSBub2RlW25dO1xuICB9XG5cbiAgcmV0dXJuIGJ1ZiB8fCAoMCwgX3N0cmluZ2lmeS5kZWZhdWx0KShiKTtcbn1cblxudmFyIF9kZWZhdWx0ID0gdjE7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF92ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92MzUuanNcIikpO1xuXG52YXIgX21kID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9tZDUuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5jb25zdCB2MyA9ICgwLCBfdi5kZWZhdWx0KSgndjMnLCAweDMwLCBfbWQuZGVmYXVsdCk7XG52YXIgX2RlZmF1bHQgPSB2MztcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7XG5leHBvcnRzLlVSTCA9IGV4cG9ydHMuRE5TID0gdm9pZCAwO1xuXG52YXIgX3N0cmluZ2lmeSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vc3RyaW5naWZ5LmpzXCIpKTtcblxudmFyIF9wYXJzZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vcGFyc2UuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBzdHJpbmdUb0J5dGVzKHN0cikge1xuICBzdHIgPSB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoc3RyKSk7IC8vIFVURjggZXNjYXBlXG5cbiAgY29uc3QgYnl0ZXMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIGJ5dGVzLnB1c2goc3RyLmNoYXJDb2RlQXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIGJ5dGVzO1xufVxuXG5jb25zdCBETlMgPSAnNmJhN2I4MTAtOWRhZC0xMWQxLTgwYjQtMDBjMDRmZDQzMGM4JztcbmV4cG9ydHMuRE5TID0gRE5TO1xuY29uc3QgVVJMID0gJzZiYTdiODExLTlkYWQtMTFkMS04MGI0LTAwYzA0ZmQ0MzBjOCc7XG5leHBvcnRzLlVSTCA9IFVSTDtcblxuZnVuY3Rpb24gX2RlZmF1bHQobmFtZSwgdmVyc2lvbiwgaGFzaGZ1bmMpIHtcbiAgZnVuY3Rpb24gZ2VuZXJhdGVVVUlEKHZhbHVlLCBuYW1lc3BhY2UsIGJ1Ziwgb2Zmc2V0KSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHZhbHVlID0gc3RyaW5nVG9CeXRlcyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBuYW1lc3BhY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBuYW1lc3BhY2UgPSAoMCwgX3BhcnNlLmRlZmF1bHQpKG5hbWVzcGFjZSk7XG4gICAgfVxuXG4gICAgaWYgKG5hbWVzcGFjZS5sZW5ndGggIT09IDE2KSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoJ05hbWVzcGFjZSBtdXN0IGJlIGFycmF5LWxpa2UgKDE2IGl0ZXJhYmxlIGludGVnZXIgdmFsdWVzLCAwLTI1NSknKTtcbiAgICB9IC8vIENvbXB1dGUgaGFzaCBvZiBuYW1lc3BhY2UgYW5kIHZhbHVlLCBQZXIgNC4zXG4gICAgLy8gRnV0dXJlOiBVc2Ugc3ByZWFkIHN5bnRheCB3aGVuIHN1cHBvcnRlZCBvbiBhbGwgcGxhdGZvcm1zLCBlLmcuIGBieXRlcyA9XG4gICAgLy8gaGFzaGZ1bmMoWy4uLm5hbWVzcGFjZSwgLi4uIHZhbHVlXSlgXG5cblxuICAgIGxldCBieXRlcyA9IG5ldyBVaW50OEFycmF5KDE2ICsgdmFsdWUubGVuZ3RoKTtcbiAgICBieXRlcy5zZXQobmFtZXNwYWNlKTtcbiAgICBieXRlcy5zZXQodmFsdWUsIG5hbWVzcGFjZS5sZW5ndGgpO1xuICAgIGJ5dGVzID0gaGFzaGZ1bmMoYnl0ZXMpO1xuICAgIGJ5dGVzWzZdID0gYnl0ZXNbNl0gJiAweDBmIHwgdmVyc2lvbjtcbiAgICBieXRlc1s4XSA9IGJ5dGVzWzhdICYgMHgzZiB8IDB4ODA7XG5cbiAgICBpZiAoYnVmKSB7XG4gICAgICBvZmZzZXQgPSBvZmZzZXQgfHwgMDtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxNjsgKytpKSB7XG4gICAgICAgIGJ1ZltvZmZzZXQgKyBpXSA9IGJ5dGVzW2ldO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYnVmO1xuICAgIH1cblxuICAgIHJldHVybiAoMCwgX3N0cmluZ2lmeS5kZWZhdWx0KShieXRlcyk7XG4gIH0gLy8gRnVuY3Rpb24jbmFtZSBpcyBub3Qgc2V0dGFibGUgb24gc29tZSBwbGF0Zm9ybXMgKCMyNzApXG5cblxuICB0cnkge1xuICAgIGdlbmVyYXRlVVVJRC5uYW1lID0gbmFtZTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVtcHR5XG4gIH0gY2F0Y2ggKGVycikge30gLy8gRm9yIENvbW1vbkpTIGRlZmF1bHQgZXhwb3J0IHN1cHBvcnRcblxuXG4gIGdlbmVyYXRlVVVJRC5ETlMgPSBETlM7XG4gIGdlbmVyYXRlVVVJRC5VUkwgPSBVUkw7XG4gIHJldHVybiBnZW5lcmF0ZVVVSUQ7XG59IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfcm5nID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9ybmcuanNcIikpO1xuXG52YXIgX3N0cmluZ2lmeSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vc3RyaW5naWZ5LmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gdjQob3B0aW9ucywgYnVmLCBvZmZzZXQpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgY29uc3Qgcm5kcyA9IG9wdGlvbnMucmFuZG9tIHx8IChvcHRpb25zLnJuZyB8fCBfcm5nLmRlZmF1bHQpKCk7IC8vIFBlciA0LjQsIHNldCBiaXRzIGZvciB2ZXJzaW9uIGFuZCBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGBcblxuXG4gIHJuZHNbNl0gPSBybmRzWzZdICYgMHgwZiB8IDB4NDA7XG4gIHJuZHNbOF0gPSBybmRzWzhdICYgMHgzZiB8IDB4ODA7IC8vIENvcHkgYnl0ZXMgdG8gYnVmZmVyLCBpZiBwcm92aWRlZFxuXG4gIGlmIChidWYpIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgfHwgMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTY7ICsraSkge1xuICAgICAgYnVmW29mZnNldCArIGldID0gcm5kc1tpXTtcbiAgICB9XG5cbiAgICByZXR1cm4gYnVmO1xuICB9XG5cbiAgcmV0dXJuICgwLCBfc3RyaW5naWZ5LmRlZmF1bHQpKHJuZHMpO1xufVxuXG52YXIgX2RlZmF1bHQgPSB2NDtcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuXG52YXIgX3YgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3YzNS5qc1wiKSk7XG5cbnZhciBfc2hhID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zaGExLmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuY29uc3QgdjUgPSAoMCwgX3YuZGVmYXVsdCkoJ3Y1JywgMHg1MCwgX3NoYS5kZWZhdWx0KTtcbnZhciBfZGVmYXVsdCA9IHY1O1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfcmVnZXggPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3JlZ2V4LmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gdmFsaWRhdGUodXVpZCkge1xuICByZXR1cm4gdHlwZW9mIHV1aWQgPT09ICdzdHJpbmcnICYmIF9yZWdleC5kZWZhdWx0LnRlc3QodXVpZCk7XG59XG5cbnZhciBfZGVmYXVsdCA9IHZhbGlkYXRlO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfdmFsaWRhdGUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3ZhbGlkYXRlLmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gdmVyc2lvbih1dWlkKSB7XG4gIGlmICghKDAsIF92YWxpZGF0ZS5kZWZhdWx0KSh1dWlkKSkge1xuICAgIHRocm93IFR5cGVFcnJvcignSW52YWxpZCBVVUlEJyk7XG4gIH1cblxuICByZXR1cm4gcGFyc2VJbnQodXVpZC5zdWJzdHIoMTQsIDEpLCAxNik7XG59XG5cbnZhciBfZGVmYXVsdCA9IHZlcnNpb247XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCIvKlxuV2lsZEVtaXR0ZXIuanMgaXMgYSBzbGltIGxpdHRsZSBldmVudCBlbWl0dGVyIGJ5IEBoZW5yaWtqb3JldGVnIGxhcmdlbHkgYmFzZWRcbm9uIEB2aXNpb25tZWRpYSdzIEVtaXR0ZXIgZnJvbSBVSSBLaXQuXG5cbldoeT8gSSB3YW50ZWQgaXQgc3RhbmRhbG9uZS5cblxuSSBhbHNvIHdhbnRlZCBzdXBwb3J0IGZvciB3aWxkY2FyZCBlbWl0dGVycyBsaWtlIHRoaXM6XG5cbmVtaXR0ZXIub24oJyonLCBmdW5jdGlvbiAoZXZlbnROYW1lLCBvdGhlciwgZXZlbnQsIHBheWxvYWRzKSB7XG5cbn0pO1xuXG5lbWl0dGVyLm9uKCdzb21lbmFtZXNwYWNlKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIHBheWxvYWRzKSB7XG5cbn0pO1xuXG5QbGVhc2Ugbm90ZSB0aGF0IGNhbGxiYWNrcyB0cmlnZ2VyZWQgYnkgd2lsZGNhcmQgcmVnaXN0ZXJlZCBldmVudHMgYWxzbyBnZXRcbnRoZSBldmVudCBuYW1lIGFzIHRoZSBmaXJzdCBhcmd1bWVudC5cbiovXG5cbm1vZHVsZS5leHBvcnRzID0gV2lsZEVtaXR0ZXI7XG5cbmZ1bmN0aW9uIFdpbGRFbWl0dGVyKCkgeyB9XG5cbldpbGRFbWl0dGVyLm1peGluID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XG4gICAgdmFyIHByb3RvdHlwZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZSB8fCBjb25zdHJ1Y3RvcjtcblxuICAgIHByb3RvdHlwZS5pc1dpbGRFbWl0dGVyPSB0cnVlO1xuXG4gICAgLy8gTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC4gU3RvcmUgYSBncm91cCBuYW1lIGlmIHByZXNlbnQuXG4gICAgcHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XG4gICAgICAgIHZhciBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XG4gICAgICAgIGZ1bmMuX2dyb3VwTmFtZSA9IGdyb3VwO1xuICAgICAgICAodGhpcy5jYWxsYmFja3NbZXZlbnRdID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdIHx8IFtdKS5wdXNoKGZ1bmMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLy8gQWRkcyBhbiBgZXZlbnRgIGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGEgc2luZ2xlXG4gICAgLy8gdGltZSB0aGVuIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZC5cbiAgICBwcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIChldmVudCwgZ3JvdXBOYW1lLCBmbikge1xuICAgICAgICB2YXIgc2VsZiA9IHRoaXMsXG4gICAgICAgICAgICBoYXNHcm91cCA9IChhcmd1bWVudHMubGVuZ3RoID09PSAzKSxcbiAgICAgICAgICAgIGdyb3VwID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBmdW5jID0gaGFzR3JvdXAgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV07XG4gICAgICAgIGZ1bmN0aW9uIG9uKCkge1xuICAgICAgICAgICAgc2VsZi5vZmYoZXZlbnQsIG9uKTtcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uKGV2ZW50LCBncm91cCwgb24pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLy8gVW5iaW5kcyBhbiBlbnRpcmUgZ3JvdXBcbiAgICBwcm90b3R5cGUucmVsZWFzZUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwTmFtZSkge1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xuICAgICAgICB2YXIgaXRlbSwgaSwgbGVuLCBoYW5kbGVycztcbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XG4gICAgICAgICAgICBoYW5kbGVycyA9IHRoaXMuY2FsbGJhY2tzW2l0ZW1dO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gaGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFuZGxlcnNbaV0uX2dyb3VwTmFtZSA9PT0gZ3JvdXBOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coJ3JlbW92aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdCBhbmQgc2hvcnRlbiB0aGUgYXJyYXkgd2UncmUgbG9vcGluZyB0aHJvdWdoXG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgaS0tO1xuICAgICAgICAgICAgICAgICAgICBsZW4tLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8vIFJlbW92ZSB0aGUgZ2l2ZW4gY2FsbGJhY2sgZm9yIGBldmVudGAgb3IgYWxsXG4gICAgLy8gcmVnaXN0ZXJlZCBjYWxsYmFja3MuXG4gICAgcHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudCwgZm4pIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzW2V2ZW50XSxcbiAgICAgICAgICAgIGk7XG5cbiAgICAgICAgaWYgKCFjYWxsYmFja3MpIHJldHVybiB0aGlzO1xuXG4gICAgICAgIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrc1tldmVudF07XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbW92ZSBzcGVjaWZpYyBoYW5kbGVyXG4gICAgICAgIGkgPSBjYWxsYmFja3MuaW5kZXhPZihmbik7XG4gICAgICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLy8vIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxuICAgIC8vIGFsc28gY2FsbHMgYW55IGAqYCBoYW5kbGVyc1xuICAgIHByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICAgICAgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxuICAgICAgICAgICAgc3BlY2lhbENhbGxiYWNrcyA9IHRoaXMuZ2V0V2lsZGNhcmRDYWxsYmFja3MoZXZlbnQpLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGxlbixcbiAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICBsaXN0ZW5lcnM7XG5cbiAgICAgICAgaWYgKGNhbGxiYWNrcykge1xuICAgICAgICAgICAgbGlzdGVuZXJzID0gY2FsbGJhY2tzLnNsaWNlKCk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNwZWNpYWxDYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGxlbiA9IHNwZWNpYWxDYWxsYmFja3MubGVuZ3RoO1xuICAgICAgICAgICAgbGlzdGVuZXJzID0gc3BlY2lhbENhbGxiYWNrcy5zbGljZSgpO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsaXN0ZW5lcnNbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBbZXZlbnRdLmNvbmNhdChhcmdzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLy8gSGVscGVyIGZvciBmb3IgZmluZGluZyBzcGVjaWFsIHdpbGRjYXJkIGV2ZW50IGhhbmRsZXJzIHRoYXQgbWF0Y2ggdGhlIGV2ZW50XG4gICAgcHJvdG90eXBlLmdldFdpbGRjYXJkQ2FsbGJhY2tzID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xuICAgICAgICB2YXIgaXRlbSxcbiAgICAgICAgICAgIHNwbGl0LFxuICAgICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgICAgZm9yIChpdGVtIGluIHRoaXMuY2FsbGJhY2tzKSB7XG4gICAgICAgICAgICBzcGxpdCA9IGl0ZW0uc3BsaXQoJyonKTtcbiAgICAgICAgICAgIGlmIChpdGVtID09PSAnKicgfHwgKHNwbGl0Lmxlbmd0aCA9PT0gMiAmJiBldmVudE5hbWUuc2xpY2UoMCwgc3BsaXRbMF0ubGVuZ3RoKSA9PT0gc3BsaXRbMF0pKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh0aGlzLmNhbGxiYWNrc1tpdGVtXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuXG59O1xuXG5XaWxkRW1pdHRlci5taXhpbihXaWxkRW1pdHRlcik7XG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NS4yLjkgLSBnaXQuaW8vZWVcbiAqIFVubGljZW5zZSAtIGh0dHA6Ly91bmxpY2Vuc2Uub3JnL1xuICogT2xpdmVyIENhbGR3ZWxsIC0gaHR0cHM6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgLyoqXG4gICAgICogQ2xhc3MgZm9yIG1hbmFnaW5nIGV2ZW50cy5cbiAgICAgKiBDYW4gYmUgZXh0ZW5kZWQgdG8gcHJvdmlkZSBldmVudCBmdW5jdGlvbmFsaXR5IGluIG90aGVyIGNsYXNzZXMuXG4gICAgICpcbiAgICAgKiBAY2xhc3MgRXZlbnRFbWl0dGVyIE1hbmFnZXMgZXZlbnQgcmVnaXN0ZXJpbmcgYW5kIGVtaXR0aW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHt9XG5cbiAgICAvLyBTaG9ydGN1dHMgdG8gaW1wcm92ZSBzcGVlZCBhbmQgc2l6ZVxuICAgIHZhciBwcm90byA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGU7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkTGlzdGVuZXIgKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgPT09ICdmdW5jdGlvbicgfHwgbGlzdGVuZXIgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lci5saXN0ZW5lcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogVGhlIGxpc3RlbmVyIHdpbGwgbm90IGJlIGFkZGVkIGlmIGl0IGlzIGEgZHVwbGljYXRlLlxuICAgICAqIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgaXQgaXMgY2FsbGVkLlxuICAgICAqIElmIHlvdSBwYXNzIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lIHRoZW4gdGhlIGxpc3RlbmVyIHdpbGwgYmUgYWRkZWQgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKCFpc1ZhbGlkTGlzdGVuZXIobGlzdGVuZXIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcklzV3JhcHBlZCA9IHR5cGVvZiBsaXN0ZW5lciA9PT0gJ29iamVjdCc7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkgJiYgaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0ucHVzaChsaXN0ZW5lcklzV3JhcHBlZCA/IGxpc3RlbmVyIDoge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICAgICAgICAgIG9uY2U6IGZhbHNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vbiA9IGFsaWFzKCdhZGRMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogU2VtaS1hbGlhcyBvZiBhZGRMaXN0ZW5lci4gSXQgd2lsbCBhZGQgYSBsaXN0ZW5lciB0aGF0IHdpbGwgYmVcbiAgICAgKiBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgaXRzIGZpcnN0IGV4ZWN1dGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGF0dGFjaCB0aGUgbGlzdGVuZXIgdG8uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyBlbWl0dGVkLiBJZiB0aGUgZnVuY3Rpb24gcmV0dXJucyB0cnVlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkIGFmdGVyIGNhbGxpbmcuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkT25jZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkT25jZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkTGlzdGVuZXIoZXZ0LCB7XG4gICAgICAgICAgICBsaXN0ZW5lcjogbGlzdGVuZXIsXG4gICAgICAgICAgICBvbmNlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRPbmNlTGlzdGVuZXIuXG4gICAgICovXG4gICAgcHJvdG8ub25jZSA9IGFsaWFzKCdhZGRPbmNlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYW4gZXZlbnQgbmFtZS4gVGhpcyBpcyByZXF1aXJlZCBpZiB5b3Ugd2FudCB0byB1c2UgYSByZWdleCB0byBhZGQgYSBsaXN0ZW5lciB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gSWYgeW91IGRvbid0IGRvIHRoaXMgdGhlbiBob3cgZG8geW91IGV4cGVjdCBpdCB0byBrbm93IHdoYXQgZXZlbnQgdG8gYWRkIHRvPyBTaG91bGQgaXQganVzdCBhZGQgdG8gZXZlcnkgcG9zc2libGUgbWF0Y2ggZm9yIGEgcmVnZXg/IE5vLiBUaGF0IGlzIHNjYXJ5IGFuZCBiYWQuXG4gICAgICogWW91IG5lZWQgdG8gdGVsbCBpdCB3aGF0IGV2ZW50IG5hbWVzIHNob3VsZCBiZSBtYXRjaGVkIGJ5IGEgcmVnZXguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGNyZWF0ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudCA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50KGV2dCkge1xuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlcyBkZWZpbmVFdmVudCB0byBkZWZpbmUgbXVsdGlwbGUgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmdbXX0gZXZ0cyBBbiBhcnJheSBvZiBldmVudCBuYW1lcyB0byBkZWZpbmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnRzID0gZnVuY3Rpb24gZGVmaW5lRXZlbnRzKGV2dHMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBldnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmluZUV2ZW50KGV2dHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbGlzdGVuZXIgZnVuY3Rpb24gZnJvbSB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdoZW4gcGFzc2VkIGEgcmVndWxhciBleHByZXNzaW9uIGFzIHRoZSBldmVudCBuYW1lLCBpdCB3aWxsIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXIgTWV0aG9kIHRvIHJlbW92ZSBmcm9tIHRoZSBldmVudC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2dCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGluZGV4O1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzW2tleV0uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlTGlzdGVuZXJcbiAgICAgKi9cbiAgICBwcm90by5vZmYgPSBhbGlhcygncmVtb3ZlTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy4gWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIGFkZGVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIGFkZCB0aGUgYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKiBZZWFoLCB0aGlzIGZ1bmN0aW9uIGRvZXMgcXVpdGUgYSBiaXQuIFRoYXQncyBwcm9iYWJseSBhIGJhZCB0aGluZy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdHxSZWdFeHB9IGV2dCBBbiBldmVudCBuYW1lIGlmIHlvdSB3aWxsIHBhc3MgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIG5leHQuIEFuIG9iamVjdCBpZiB5b3Ugd2lzaCB0byBhZGQgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gYWRkLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVycyA9IGZ1bmN0aW9uIGFkZExpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKGZhbHNlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGlzdGVuZXJzIGluIGJ1bGsgdXNpbmcgdGhlIG1hbmlwdWxhdGVMaXN0ZW5lcnMgbWV0aG9kLlxuICAgICAqIElmIHlvdSBwYXNzIGFuIG9iamVjdCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0odHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzIHx8IHt9KSk7XG4iLCJtb2R1bGUuZXhwb3J0cz17XG4gICAgXCJhdXRob3JcIjogXCJPcGVuVmlkdVwiLFxuICAgIFwiZGVwZW5kZW5jaWVzXCI6IHtcbiAgICAgICAgXCJmcmVlaWNlXCI6IFwiMi4yLjJcIixcbiAgICAgICAgXCJoYXJrXCI6IFwiMS4yLjNcIixcbiAgICAgICAgXCJqc25sb2dcIjogXCIyLjMwLjBcIixcbiAgICAgICAgXCJwbGF0Zm9ybVwiOiBcIjEuMy42XCIsXG4gICAgICAgIFwidXVpZFwiOiBcIjguMy4yXCIsXG4gICAgICAgIFwid29sZnk4Ny1ldmVudGVtaXR0ZXJcIjogXCI1LjIuOVwiXG4gICAgfSxcbiAgICBcImRlc2NyaXB0aW9uXCI6IFwiT3BlblZpZHUgQnJvd3NlclwiLFxuICAgIFwiZGV2RGVwZW5kZW5jaWVzXCI6IHtcbiAgICAgICAgXCJAdHlwZXMvbm9kZVwiOiBcIjE1LjEyLjJcIixcbiAgICAgICAgXCJAdHlwZXMvcGxhdGZvcm1cIjogXCIxLjMuM1wiLFxuICAgICAgICBcImJyb3dzZXJpZnlcIjogXCIxNy4wLjBcIixcbiAgICAgICAgXCJncnVudFwiOiBcIjEuNC4xXCIsXG4gICAgICAgIFwiZ3J1bnQtY2xpXCI6IFwiMS40LjNcIixcbiAgICAgICAgXCJncnVudC1jb250cmliLWNvcHlcIjogXCIxLjAuMFwiLFxuICAgICAgICBcImdydW50LWNvbnRyaWItc2Fzc1wiOiBcIjIuMC4wXCIsXG4gICAgICAgIFwiZ3J1bnQtY29udHJpYi11Z2xpZnlcIjogXCI1LjAuMVwiLFxuICAgICAgICBcImdydW50LWNvbnRyaWItd2F0Y2hcIjogXCIxLjEuMFwiLFxuICAgICAgICBcImdydW50LXBvc3Rjc3NcIjogXCIwLjkuMFwiLFxuICAgICAgICBcImdydW50LXN0cmluZy1yZXBsYWNlXCI6IFwiMS4zLjFcIixcbiAgICAgICAgXCJncnVudC10c1wiOiBcIjYuMC4wLWJldGEuMjJcIixcbiAgICAgICAgXCJ0ZXJzZXJcIjogXCI1LjcuMFwiLFxuICAgICAgICBcInRzaWZ5XCI6IFwiNS4wLjRcIixcbiAgICAgICAgXCJ0c2xpbnRcIjogXCI2LjEuM1wiLFxuICAgICAgICBcInR5cGVkb2NcIjogXCIwLjE5LjJcIixcbiAgICAgICAgXCJ0eXBlc2NyaXB0XCI6IFwiNC4wLjdcIlxuICAgIH0sXG4gICAgXCJsaWNlbnNlXCI6IFwiQXBhY2hlLTIuMFwiLFxuICAgIFwibWFpblwiOiBcImxpYi9pbmRleC5qc1wiLFxuICAgIFwibmFtZVwiOiBcIm9wZW52aWR1LWJyb3dzZXJcIixcbiAgICBcInJlcG9zaXRvcnlcIjoge1xuICAgICAgICBcInR5cGVcIjogXCJnaXRcIixcbiAgICAgICAgXCJ1cmxcIjogXCJnaXQ6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1XCJcbiAgICB9LFxuICAgIFwic2NyaXB0c1wiOiB7XG4gICAgICAgIFwiYnJvd3NlcmlmeVwiOiBcIlZFUlNJT049JHtWRVJTSU9OOi1kZXZ9OyBta2RpciAtcCBzdGF0aWMvanMvICYmIGNkIHNyYyAmJiAuLi9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9iaW4vY21kLmpzIE1haW4udHMgLXAgWyB0c2lmeSBdIC0tZXhjbHVkZSBrdXJlbnRvLWJyb3dzZXItZXh0ZW5zaW9ucyAtLWRlYnVnIC1vIC4uL3N0YXRpYy9qcy9vcGVudmlkdS1icm93c2VyLSRWRVJTSU9OLmpzIC12XCIsXG4gICAgICAgIFwiYnJvd3NlcmlmeS1wcm9kXCI6IFwiVkVSU0lPTj0ke1ZFUlNJT046LWRldn07IG1rZGlyIC1wIHN0YXRpYy9qcy8gJiYgY2Qgc3JjICYmIC4uL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L2Jpbi9jbWQuanMgLS1kZWJ1ZyBNYWluLnRzIC1wIFsgdHNpZnkgXSAtLWV4Y2x1ZGUga3VyZW50by1icm93c2VyLWV4dGVuc2lvbnMgfCAuLi9ub2RlX21vZHVsZXMvdGVyc2VyL2Jpbi90ZXJzZXIgLS1zb3VyY2UtbWFwIGNvbnRlbnQ9aW5saW5lIC0tb3V0cHV0IC4uL3N0YXRpYy9qcy9vcGVudmlkdS1icm93c2VyLSRWRVJTSU9OLm1pbi5qc1wiLFxuICAgICAgICBcImJ1aWxkXCI6IFwiY2Qgc3JjL09wZW5WaWR1ICYmIC4vLi4vLi4vbm9kZV9tb2R1bGVzL3R5cGVzY3JpcHQvYmluL3RzYyAmJiBjZCAuLi8uLiAmJiAuL25vZGVfbW9kdWxlcy90eXBlc2NyaXB0L2Jpbi90c2MgLS1kZWNsYXJhdGlvbiBzcmMvaW5kZXgudHMgLS1vdXREaXIgLi9saWIgLS1zb3VyY2VNYXAgLS10YXJnZXQgZXM1IC0tbGliIGRvbSxlczUsZXMyMDE1LnByb21pc2Usc2NyaXB0aG9zdFwiLFxuICAgICAgICBcImRvY3NcIjogXCIuL2dlbmVyYXRlLWRvY3Muc2hcIlxuICAgIH0sXG4gICAgXCJ0eXBlc1wiOiBcImxpYi9pbmRleC5kLnRzXCIsXG4gICAgXCJ2ZXJzaW9uXCI6IFwiMi4xOS4wXCJcbn1cbiIsImltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSAnLi9PcGVuVmlkdS9PcGVuVmlkdSc7XG5pbXBvcnQgeyBKTCB9IGZyb20gJ2pzbmxvZyc7XG5cbmlmICh3aW5kb3cpIHtcbiAgICB3aW5kb3dbJ09wZW5WaWR1J10gPSBPcGVuVmlkdTtcbn1cblxuLy8gRGlzYWJsZSBqc25sb2cgd2hlbiBsaWJyYXJ5IGlzIGxvYWRlZFxuSkwuc2V0T3B0aW9ucyh7IGVuYWJsZWQ6IGZhbHNlIH0pXG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBMb2NhbENvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvTG9jYWxDb25uZWN0aW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBSZW1vdGVDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1JlbW90ZUNvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IEluYm91bmRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvSW5ib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgU3RyZWFtT3B0aW9uc1NlcnZlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL1N0cmVhbU9wdGlvbnNTZXJ2ZXInO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBFeGNlcHRpb25FdmVudCwgRXhjZXB0aW9uRXZlbnROYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXhjZXB0aW9uRXZlbnQnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSB1c2VyJ3MgY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbiAodGhlIGxvY2FsIG9uZSBhbmQgb3RoZXIgdXNlcidzIGNvbm5lY3Rpb25zKS5cbiAqIFRoZXJlZm9yZSBlYWNoIFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbV1dIG9iamVjdCBoYXMgYW4gYXR0cmlidXRlIG9mIHR5cGUgQ29ubmVjdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbiB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY29ubmVjdGlvblxuICAgICAqL1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgY29ubmVjdGlvbiB3YXMgY3JlYXRlZCBpbiBPcGVuVmlkdSBTZXJ2ZXIgKFVUQyBtaWxsaXNlY29uZHMpXG4gICAgICovXG4gICAgY3JlYXRpb25UaW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBEYXRhIGFzc29jaWF0ZWQgdG8gdGhpcyBjb25uZWN0aW9uIChhbmQgdGhlcmVmb3JlIHRvIGNlcnRhaW4gdXNlcikuIFRoaXMgaXMgYW4gaW1wb3J0YW50IGZpZWxkOlxuICAgICAqIGl0IGFsbG93cyB5b3UgdG8gYnJvYWRjYXN0IGFsbCB0aGUgaW5mb3JtYXRpb24geW91IHdhbnQgZm9yIGVhY2ggdXNlciAoYSB1c2VybmFtZSwgZm9yIGV4YW1wbGUpXG4gICAgICovXG4gICAgZGF0YTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogUm9sZSBvZiB0aGUgY29ubmVjdGlvbi5cbiAgICAgKiAtIGBTVUJTQ1JJQkVSYDogY2FuIHN1YnNjcmliZSB0byBwdWJsaXNoZWQgU3RyZWFtcyBvZiBvdGhlciB1c2VycyBieSBjYWxsaW5nIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqIC0gYFBVQkxJU0hFUmA6IFNVQlNDUklCRVIgcGVybWlzc2lvbnMgKyBjYW4gcHVibGlzaCB0aGVpciBvd24gU3RyZWFtcyBieSBjYWxsaW5nIFtbU2Vzc2lvbi5wdWJsaXNoXV1cbiAgICAgKiAtIGBNT0RFUkFUT1JgOiBTVUJTQ1JJQkVSICsgUFVCTElTSEVSIHBlcm1pc3Npb25zICsgY2FuIGZvcmNlIHRoZSB1bnB1Ymxpc2hpbmcgb3IgZGlzY29ubmVjdGlvbiBvdmVyIGEgdGhpcmQtcGFydHkgU3RyZWFtIG9yIENvbm5lY3Rpb24gYnkgY2FsbCBbW1Nlc3Npb24uZm9yY2VVbnB1Ymxpc2hdXSBhbmQgW1tTZXNzaW9uLmZvcmNlRGlzY29ubmVjdF1dXG4gICAgICpcbiAgICAgKiAqKk9ubHkgZGVmaW5lZCBmb3IgdGhlIGxvY2FsIGNvbm5lY3Rpb24uIEluIHJlbW90ZSBjb25uZWN0aW9ucyB3aWxsIGJlIGB1bmRlZmluZWRgKipcbiAgICAgKi9cbiAgICByb2xlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW1zIHB1Ymxpc2hlZCBieSB0aGlzIGNvbm5lY3Rpb24gd2lsbCBiZSByZWNvcmRlZCBvciBub3QuIFRoaXMgb25seSBhZmZlY3RzIFtJTkRJVklEVUFMIHJlY29yZGluZ10oL2VuL3N0YWJsZS9hZHZhbmNlZC1mZWF0dXJlcy9yZWNvcmRpbmcjc2VsZWN0aW5nLXN0cmVhbXMtdG8tYmUtcmVjb3JkZWQpIDxhIGhyZWY9XCJodHRwczovL2RvY3Mub3BlbnZpZHUuaW8vZW4vc3RhYmxlL29wZW52aWR1LXByby9cIiB0YXJnZXQ9XCJfYmxhbmtcIiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9jazsgYmFja2dyb3VuZC1jb2xvcjogcmdiKDAsIDEzNiwgMTcwKTsgY29sb3I6IHdoaXRlOyBmb250LXdlaWdodDogYm9sZDsgcGFkZGluZzogMHB4IDVweDsgbWFyZ2luLXJpZ2h0OiA1cHg7IGJvcmRlci1yYWRpdXM6IDNweDsgZm9udC1zaXplOiAxM3B4OyBsaW5lLWhlaWdodDoyMXB4OyBmb250LWZhbWlseTogTW9udHNlcnJhdCwgc2Fucy1zZXJpZlwiPlBSTzwvYT5cbiAgICAgKlxuICAgICAqICoqT25seSBkZWZpbmVkIGZvciB0aGUgbG9jYWwgY29ubmVjdGlvbi4gSW4gcmVtb3RlIGNvbm5lY3Rpb25zIHdpbGwgYmUgYHVuZGVmaW5lZGAqKlxuICAgICAqL1xuICAgIHJlY29yZDogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW0/OiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbG9jYWxPcHRpb25zOiBMb2NhbENvbm5lY3Rpb25PcHRpb25zIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZU9wdGlvbnM6IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3Bvc2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcnBjU2Vzc2lvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBzZXNzaW9uOiBTZXNzaW9uLCBjb25uZWN0aW9uT3B0aW9uczogTG9jYWxDb25uZWN0aW9uT3B0aW9ucyB8IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zKSB7XG4gICAgICAgIGxldCBtc2cgPSBcIidDb25uZWN0aW9uJyBjcmVhdGVkIFwiO1xuICAgICAgICBpZiAoISEoPExvY2FsQ29ubmVjdGlvbk9wdGlvbnM+Y29ubmVjdGlvbk9wdGlvbnMpLnJvbGUpIHtcbiAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gaXMgbG9jYWxcbiAgICAgICAgICAgIHRoaXMubG9jYWxPcHRpb25zID0gPExvY2FsQ29ubmVjdGlvbk9wdGlvbnM+Y29ubmVjdGlvbk9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9IHRoaXMubG9jYWxPcHRpb25zLmlkO1xuICAgICAgICAgICAgdGhpcy5jcmVhdGlvblRpbWUgPSB0aGlzLmxvY2FsT3B0aW9ucy5jcmVhdGVkQXQ7XG4gICAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLmxvY2FsT3B0aW9ucy5tZXRhZGF0YTtcbiAgICAgICAgICAgIHRoaXMucnBjU2Vzc2lvbklkID0gdGhpcy5sb2NhbE9wdGlvbnMuc2Vzc2lvbklkO1xuICAgICAgICAgICAgdGhpcy5yb2xlID0gdGhpcy5sb2NhbE9wdGlvbnMucm9sZTtcbiAgICAgICAgICAgIHRoaXMucmVjb3JkID0gdGhpcy5sb2NhbE9wdGlvbnMucmVjb3JkO1xuICAgICAgICAgICAgbXNnICs9ICcobG9jYWwpJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gaXMgcmVtb3RlXG4gICAgICAgICAgICB0aGlzLnJlbW90ZU9wdGlvbnMgPSA8UmVtb3RlQ29ubmVjdGlvbk9wdGlvbnM+Y29ubmVjdGlvbk9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9IHRoaXMucmVtb3RlT3B0aW9ucy5pZDtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gdGhpcy5yZW1vdGVPcHRpb25zLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgIGlmICh0aGlzLnJlbW90ZU9wdGlvbnMubWV0YWRhdGEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLnJlbW90ZU9wdGlvbnMubWV0YWRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5yZW1vdGVPcHRpb25zLnN0cmVhbXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRSZW1vdGVTdHJlYW1zKHRoaXMucmVtb3RlT3B0aW9ucy5zdHJlYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1zZyArPSBcIihyZW1vdGUpIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5yZW1vdGVPcHRpb25zLmlkICsgJ10nO1xuICAgICAgICB9XG4gICAgICAgIGxvZ2dlci5pbmZvKG1zZyk7XG4gICAgfVxuXG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpOiB2b2lkIHtcblxuICAgICAgICBsb2dnZXIuZGVidWcoKCEhdGhpcy5zdHJlYW0hLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCcgOiAnUmVtb3RlJykgKyAnY2FuZGlkYXRlIGZvcicgK1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQsIGNhbmRpZGF0ZSk7XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdvbkljZUNhbmRpZGF0ZScsIHtcbiAgICAgICAgICAgIGVuZHBvaW50TmFtZTogdGhpcy5jb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBjYW5kaWRhdGU6IGNhbmRpZGF0ZS5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNaWQ6IGNhbmRpZGF0ZS5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBjYW5kaWRhdGUuc2RwTUxpbmVJbmRleFxuICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIHNlbmRpbmcgSUNFIGNhbmRpZGF0ZTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnZXhjZXB0aW9uJywgW25ldyBFeGNlcHRpb25FdmVudCh0aGlzLnNlc3Npb24sIEV4Y2VwdGlvbkV2ZW50TmFtZS5JQ0VfQ0FORElEQVRFX0VSUk9SLCB0aGlzLnNlc3Npb24sIFwiVGhlcmUgd2FzIGFuIHVuZXhwZWN0ZWQgZXJyb3Igb24gdGhlIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgYW4gSUNFIGNhbmRpZGF0ZSBnZW5lcmF0ZWQgYW5kIHNlbnQgYnkgdGhlIGNsaWVudC1zaWRlXCIsIGVycm9yKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdFJlbW90ZVN0cmVhbXMob3B0aW9uczogU3RyZWFtT3B0aW9uc1NlcnZlcltdKTogdm9pZCB7XG5cbiAgICAgICAgLy8gVGhpcyBpcyByZWFkeSBmb3Igc3VwcG9ydGluZyBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uIG9iamVjdC4gUmlnaHQgbm93IHRoZSBsb29wIHdpbGwgYWx3YXlzIHJ1biBqdXN0IG9uY2VcbiAgICAgICAgLy8gdGhpcy5zdHJlYW0gc2hvdWxkIGFsc28gYmUgcmVwbGFjZWQgYnkgYSBjb2xsZWN0aW9uIG9mIHN0cmVhbXMgdG8gc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBDb25uZWN0aW9uXG4gICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRzID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnM6IEluYm91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgIGlkOiBvcHRzLmlkLFxuICAgICAgICAgICAgICAgIGNyZWF0ZWRBdDogb3B0cy5jcmVhdGVkQXQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbjogdGhpcyxcbiAgICAgICAgICAgICAgICBoYXNBdWRpbzogb3B0cy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICBoYXNWaWRlbzogb3B0cy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogb3B0cy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogb3B0cy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICB0eXBlT2ZWaWRlbzogb3B0cy50eXBlT2ZWaWRlbyxcbiAgICAgICAgICAgICAgICBmcmFtZVJhdGU6IG9wdHMuZnJhbWVSYXRlLFxuICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogISFvcHRzLnZpZGVvRGltZW5zaW9ucyA/IEpTT04ucGFyc2Uob3B0cy52aWRlb0RpbWVuc2lvbnMpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGZpbHRlcjogISFvcHRzLmZpbHRlciA/IG9wdHMuZmlsdGVyIDogdW5kZWZpbmVkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IFN0cmVhbSh0aGlzLnNlc3Npb24sIHN0cmVhbU9wdGlvbnMpO1xuXG4gICAgICAgICAgICB0aGlzLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgICAgICB9KTtcbiAgICAgICAgXG4gICAgICAgIGxvZ2dlci5pbmZvKFwiUmVtb3RlICdDb25uZWN0aW9uJyB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMuY29ubmVjdGlvbklkICsgJ10gaXMgbm93IGNvbmZpZ3VyZWQgZm9yIHJlY2VpdmluZyBTdHJlYW1zIHdpdGggb3B0aW9uczogJywgdGhpcy5zdHJlYW0hLmluYm91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkU3RyZWFtKHN0cmVhbTogU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHN0cmVhbS5jb25uZWN0aW9uID0gdGhpcztcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW92ZVN0cmVhbShzdHJlYW1JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0pIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgYXMgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBFdmVudERpc3BhdGNoZXIge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVzZXJIYW5kbGVyQXJyb3dIYW5kbGVyOiBXZWFrTWFwPChldmVudDogRXZlbnQpID0+IHZvaWQsIChldmVudDogRXZlbnQpID0+IHZvaWQ+ID0gbmV3IFdlYWtNYXAoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGZ1bmN0aW9uIGBoYW5kbGVyYCB0byBoYW5kbGUgZXZlbnQgYHR5cGVgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgRXZlbnREaXNwYXRjaGVyIG9iamVjdFxuICAgICAqL1xuICAgIGFic3RyYWN0IG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlcjtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgZnVuY3Rpb24gYGhhbmRsZXJgIHRvIGhhbmRsZSBldmVudCBgdHlwZWAganVzdCBvbmNlLiBUaGUgaGFuZGxlciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBmaXJzdCBleGVjdXRpb25cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBvYmplY3QgdGhhdCBkaXNwYXRjaGVkIHRoZSBldmVudFxuICAgICAqL1xuICAgIGFic3RyYWN0IG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGBoYW5kbGVyYCBmcm9tIGV2ZW50IGB0eXBlYC4gSWYgbm8gaGFuZGxlciBpcyBwcm92aWRlZCwgYWxsIGhhbmRsZXJzIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgb2ZmKHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTXVzdCByZW1vdmUgaW50ZXJuYWwgYXJyb3cgZnVuY3Rpb24gaGFuZGxlciBwYWlyZWQgd2l0aCB1c2VyIGhhbmRsZXJcbiAgICAgICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuZ2V0KGhhbmRsZXIpO1xuICAgICAgICAgICAgaWYgKCEhYXJyb3dIYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgYXJyb3dIYW5kbGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuZGVsZXRlKGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkF1eCh0eXBlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKG1lc3NhZ2UsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8obWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy51c2VySGFuZGxlckFycm93SGFuZGxlci5zZXQoaGFuZGxlciwgYXJyb3dIYW5kbGVyKTtcbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBhcnJvd0hhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25jZUF1eCh0eXBlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKG1lc3NhZ2UsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8obWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBoYW5kbGVyIGZyb20gbWFwIGFmdGVyIGZpcnN0IGFuZCBvbmx5IGV4ZWN1dGlvblxuICAgICAgICAgICAgdGhpcy51c2VySGFuZGxlckFycm93SGFuZGxlci5kZWxldGUoaGFuZGxlcik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuc2V0KGhhbmRsZXIsIGFycm93SGFuZGxlcik7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBhcnJvd0hhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgRmlsdGVyRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9GaWx0ZXJFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICogKipXQVJOSU5HKio6IGV4cGVyaW1lbnRhbCBvcHRpb24uIFRoaXMgaW50ZXJmYWNlIG1heSBjaGFuZ2UgaW4gdGhlIG5lYXIgZnV0dXJlXG4gKlxuICogVmlkZW8vYXVkaW8gZmlsdGVyIGFwcGxpZWQgdG8gYSBTdHJlYW0uIFNlZSBbW1N0cmVhbS5hcHBseUZpbHRlcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXIge1xuXG4gICAgLyoqXG4gICAgICogVHlwZSBvZiBmaWx0ZXIgYXBwbGllZC4gVGhpcyBpcyB0aGUgbmFtZSBvZiB0aGUgcmVtb3RlIGNsYXNzIGlkZW50aWZ5aW5nIHRoZSBmaWx0ZXIgdG8gYXBwbHkgaW4gS3VyZW50byBNZWRpYSBTZXJ2ZXIuXG4gICAgICogRm9yIGV4YW1wbGU6IGBcIkZhY2VPdmVybGF5RmlsdGVyXCJgLCBgXCJHU3RyZWFtZXJGaWx0ZXJcImAuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIGdldCB0aGlzIHByb3BlcnR5IGluIGAqLmttZC5qc29uYCBmaWxlcyBkZWZpbmluZyB0aGUgS3VyZW50byBmaWx0ZXJzLiBGb3IgZXhhbXBsZSwgZm9yIEdTdHJlYW1lckZpbHRlciB0aGF0J3NcbiAgICAgKiBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL0t1cmVudG8va21zLWZpbHRlcnMvYmxvYi81M2E0NTJmYWM3MWQ2MTc5NTk1MmUzZDIyMDIxNTZjNmIwMGY2ZDY1L3NyYy9zZXJ2ZXIvaW50ZXJmYWNlL2ZpbHRlcnMuR1N0cmVhbWVyRmlsdGVyLmttZC5qc29uI0w0KVxuICAgICAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFBhcmFtZXRlcnMgdXNlZCB0byBpbml0aWFsaXplIHRoZSBmaWx0ZXIuXG4gICAgICogVGhlc2UgY29ycmVzcG9uZCB0byB0aGUgY29uc3RydWN0b3IgcGFyYW1ldGVycyB1c2VkIGluIHRoZSBmaWx0ZXIgaW4gS3VyZW50byBNZWRpYSBTZXJ2ZXIgKGV4Y2VwdCBmb3IgYG1lZGlhUGlwZWxpbmVgIHBhcmFtZXRlciwgd2hpY2ggaXMgbmV2ZXIgbmVlZGVkKS5cbiAgICAgKlxuICAgICAqIEZvciBleGFtcGxlOiBmb3IgYGZpbHRlci50eXBlID0gXCJHU3RyZWFtZXJGaWx0ZXJcImAgY291bGQgYmUgYGZpbHRlci5vcHRpb25zID0ge1wiY29tbWFuZFwiOiBcInZpZGVvYmFsYW5jZSBzYXR1cmF0aW9uPTAuMFwifWBcbiAgICAgKlxuICAgICAqIFlvdSBjYW4gZ2V0IHRoaXMgcHJvcGVydHkgaW4gYCoua21kLmpzb25gIGZpbGVzIGRlZmluaW5nIHRoZSBLdXJlbnRvIGZpbHRlcnMuIEZvciBleGFtcGxlLCBmb3IgR1N0cmVhbWVyRmlsdGVyIHRoYXQnc1xuICAgICAqIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vS3VyZW50by9rbXMtZmlsdGVycy9ibG9iLzUzYTQ1MmZhYzcxZDYxNzk1OTUyZTNkMjIwMjE1NmM2YjAwZjZkNjUvc3JjL3NlcnZlci9pbnRlcmZhY2UvZmlsdGVycy5HU3RyZWFtZXJGaWx0ZXIua21kLmpzb24jTDEzLUwzMSlcbiAgICAgKi9cbiAgICBvcHRpb25zOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBWYWx1ZSBwYXNzZWQgdGhlIGxhc3QgdGltZSBbW0ZpbHRlci5leGVjTWV0aG9kXV0gd2FzIGNhbGxlZC4gSWYgYHVuZGVmaW5lZGAgdGhpcyBtZXRob2QgaGFzIG5vdCBiZWVuIGNhbGxlZCB5ZXQuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIHVzZSB0aGlzIHZhbHVlIHRvIGtub3cgdGhlIGN1cnJlbnQgc3RhdHVzIG9mIGFueSBhcHBsaWVkIGZpbHRlclxuICAgICAqL1xuICAgIGxhc3RFeGVjTWV0aG9kPzoge1xuICAgICAgICBtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBPYmplY3RcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhbmRsZXJzOiBNYXA8c3RyaW5nLCAoZXZlbnQ6IEZpbHRlckV2ZW50KSA9PiB2b2lkPiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcbiAgICBwcml2YXRlIGxvZ2dlcjogT3BlblZpZHVMb2dnZXI7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0eXBlOiBzdHJpbmcsIG9wdGlvbnM6IE9iamVjdCkge1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZXMgYSBmaWx0ZXIgbWV0aG9kLiBBdmFpbGFibGUgbWV0aG9kcyBhcmUgc3BlY2lmaWMgZm9yIGVhY2ggZmlsdGVyXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbWV0aG9kIE5hbWUgb2YgdGhlIG1ldGhvZFxuICAgICAqIEBwYXJhbSBwYXJhbXMgUGFyYW1ldGVycyBvZiB0aGUgbWV0aG9kXG4gICAgICovXG4gICAgZXhlY01ldGhvZChtZXRob2Q6IHN0cmluZywgcGFyYW1zOiBPYmplY3QpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdFeGVjdXRpbmcgZmlsdGVyIG1ldGhvZCB0byBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIGxldCBzdHJpbmdQYXJhbXM7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhcmFtcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBzdHJpbmdQYXJhbXMgPSBKU09OLnN0cmluZ2lmeShwYXJhbXMpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTXNnID0gXCIncGFyYW1zJyBwcm9wZXJ0eSBtdXN0IGJlIGEgSlNPTiBmb3JtYXR0ZWQgb2JqZWN0XCI7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvck1zZyk7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvck1zZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdHJpbmdQYXJhbXMgPSA8c3RyaW5nPnBhcmFtcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2V4ZWNGaWx0ZXJNZXRob2QnLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBtZXRob2QsIHBhcmFtczogc3RyaW5nUGFyYW1zIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgZXhlY3V0aW5nIGZpbHRlciBtZXRob2QgZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZXhlY3V0ZSBhIGZpbHRlciBtZXRob2RcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZpbHRlciBtZXRob2Qgc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkIG9uIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSAoPGFueT5PYmplY3QpLmFzc2lnbih7fSwgdGhpcy5zdHJlYW0uZmlsdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmZpbHRlciEubGFzdEV4ZWNNZXRob2QgPSB7IG1ldGhvZCwgcGFyYW1zOiBKU09OLnBhcnNlKHN0cmluZ1BhcmFtcykgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc3RyZWFtLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnZmlsdGVyJywgdGhpcy5zdHJlYW0uZmlsdGVyISwgb2xkVmFsdWUsICdleGVjRmlsdGVyTWV0aG9kJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIsIHRoaXMuc3RyZWFtLCAnZmlsdGVyJywgdGhpcy5zdHJlYW0uZmlsdGVyISwgb2xkVmFsdWUsICdleGVjRmlsdGVyTWV0aG9kJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIHRvIGNlcnRhaW4gZmlsdGVyIGV2ZW50LiBBdmFpbGFibGUgZXZlbnRzIGFyZSBzcGVjaWZpYyBmb3IgZWFjaCBmaWx0ZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSBldmVudFR5cGUgRXZlbnQgdG8gd2hpY2ggc3Vic2NyaWJlIHRvLlxuICAgICAqIEBwYXJhbSBoYW5kbGVyIEZ1bmN0aW9uIHRvIGV4ZWN1dGUgdXBvbiBldmVudCBkaXNwYXRjaGVkLiBJdCByZWNlaXZlcyBhcyBwYXJhbWV0ZXIgYSBbW0ZpbHRlckV2ZW50XV0gb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIGV2ZW50IGxpc3RlbmVyIHdhcyBzdWNjZXNzZnVsbHkgYXR0YWNoZWQgdG8gdGhlIGZpbHRlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgYWRkRXZlbnRMaXN0ZW5lcihldmVudFR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBGaWx0ZXJFdmVudCkgPT4gdm9pZCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0FkZGluZyBmaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICcgdG8gc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdhZGRGaWx0ZXJFdmVudExpc3RlbmVyJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiB0aGlzLnN0cmVhbS5zdHJlYW1JZCwgZXZlbnRUeXBlIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgYWRkaW5nIGZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJ2ZvciBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGFkZCBhIGZpbHRlciBldmVudCBsaXN0ZW5lclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZXJzLnNldChldmVudFR5cGUsIGhhbmRsZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJyBzdWNjZXNzZnVsbHkgYXBwbGllZCBvbiBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBjZXJ0YWluIGZpbHRlciBldmVudCBsaXN0ZW5lciBwcmV2aW91c2x5IHNldC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBldmVudFR5cGUgRXZlbnQgdG8gdW5zdWJzY3JpYmUgZnJvbS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgZXZlbnQgbGlzdGVuZXIgd2FzIHN1Y2Nlc3NmdWxseSByZW1vdmVkIGZyb20gdGhlIGZpbHRlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaW4gb3RoZXIgY2FzZVxuICAgICAqL1xuICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdSZW1vdmluZyBmaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICcgdG8gc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdyZW1vdmVGaWx0ZXJFdmVudExpc3RlbmVyJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiB0aGlzLnN0cmVhbS5zdHJlYW1JZCwgZXZlbnRUeXBlIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgcmVtb3ZpbmcgZmlsdGVyIGV2ZW50IGxpc3RlbmVyIHRvIGV2ZW50ICcgKyBldmVudFR5cGUgKyAnZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gYWRkIGEgZmlsdGVyIGV2ZW50IGxpc3RlbmVyXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlcnMuZGVsZXRlKGV2ZW50VHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRmlsdGVyIGV2ZW50IGxpc3RlbmVyIHRvIGV2ZW50ICcgKyBldmVudFR5cGUgKyAnIHN1Y2Nlc3NmdWxseSByZW1vdmVkIG9uIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsUmVjb3JkZXJTdGF0ZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvTG9jYWxSZWNvcmRlclN0YXRlJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlscyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0nO1xuXG5cbi8qKlxuICogQGhpZGRlblxuICovXG5kZWNsYXJlIHZhciBNZWRpYVJlY29yZGVyOiBhbnk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5sZXQgcGxhdGZvcm06IFBsYXRmb3JtVXRpbHM7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICpcbiAqID4gV0FSTklOR1M6XG4gKiAtIFBlcmZvcm1pbmcgYnJvd3NlciBsb2NhbCByZWNvcmRpbmcgb2YgKipyZW1vdGUgc3RyZWFtcyoqIG1heSBjYXVzZSBzb21lIHRyb3VibGVzLiBBIGxvbmcgd2FpdGluZyB0aW1lIG1heSBiZSByZXF1aXJlZCBhZnRlciBjYWxsaW5nIF9Mb2NhbFJlY29yZGVyLnN0b3AoKV8gaW4gdGhpcyBjYXNlXG4gKiAtIE9ubHkgQ2hyb21lIGFuZCBGaXJlZm94IHN1cHBvcnQgbG9jYWwgc3RyZWFtIHJlY29yZGluZ1xuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IGFueTtcbiAgICBwcml2YXRlIGNodW5rczogYW55W10gPSBbXTtcbiAgICBwcml2YXRlIGJsb2I/OiBCbG9iO1xuICAgIHByaXZhdGUgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlld1NyYzogc3RyaW5nO1xuICAgIHByaXZhdGUgdmlkZW9QcmV2aWV3OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbklkID0gKCEhdGhpcy5zdHJlYW0uY29ubmVjdGlvbikgPyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA6ICdkZWZhdWx0LWNvbm5lY3Rpb24nO1xuICAgICAgICB0aGlzLmlkID0gdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXycgKyB0aGlzLmNvbm5lY3Rpb25JZCArICdfbG9jYWxyZWNvcmQnO1xuICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQURZYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqXG4gICAgICogQHBhcmFtIG1pbWVUeXBlIFRoZSBbTWVkaWFSZWNvcmRlci5taW1lVHlwZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL01lZGlhUmVjb3JkZXIvbWltZVR5cGUpIHRvIGJlIHVzZWQgdG8gcmVjb3JkIHRoaXMgU3RyZWFtLlxuICAgICAqIE1ha2Ugc3VyZSB0aGUgcGxhdGZvcm0gc3VwcG9ydHMgaXQgb3IgdGhlIHByb21pc2Ugd2lsbCByZXR1cm4gYW4gZXJyb3IuIElmIHRoaXMgcGFyYW1ldGVyIGlzIG5vdCBwcm92aWRlZCwgdGhlIE1lZGlhUmVjb3JkZXIgd2lsbCB1c2UgdGhlIGRlZmF1bHQgY29kZWNzIGF2YWlsYWJsZSBpbiB0aGUgcGxhdGZvcm1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHN1Y2Nlc3NmdWxseSBzdGFydGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZWNvcmQobWltZVR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ01lZGlhUmVjb3JkZXIgbm90IHN1cHBvcnRlZCBvbiB5b3VyIGJyb3dzZXIuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgYnJvd3Nlci4gU2VlIGNvbXBhdGliaWxpdHkgaW4gaHR0cHM6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPU1lZGlhUmVjb3JkZXInKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVBRFkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5yZWNvcmQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUFEWVxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLmNsZWFuKClcXCcgb3IgaW5pdCBhIG5ldyBMb2NhbFJlY29yZGVyIGJlZm9yZScpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIlN0YXJ0aW5nIGxvY2FsIHJlY29yZGluZyBvZiBzdHJlYW0gJ1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyBcIicgb2YgY29ubmVjdGlvbiAnXCIgKyB0aGlzLmNvbm5lY3Rpb25JZCArIFwiJ1wiKTtcblxuICAgICAgICAgICAgICAgIGxldCBvcHRpb25zID0ge307XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFtaW1lVHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFNZWRpYVJlY29yZGVyLmlzVHlwZVN1cHBvcnRlZChtaW1lVHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdtaW1lVHlwZSBcIicgKyBtaW1lVHlwZSArICdcIiBpcyBub3Qgc3VwcG9ydGVkJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHsgbWltZVR5cGUgfTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ05vIG1pbWVUeXBlIHBhcmFtZXRlciBwcm92aWRlZC4gVXNpbmcgZGVmYXVsdCBjb2RlY3MnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdNZWRpYVJlY29yZGVyI2lzVHlwZVN1cHBvcnRlZCBpcyBub3Qgc3VwcG9ydGVkLiBVc2luZyBkZWZhdWx0IGNvZGVjcycpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCksIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdGFydCgxMCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdNZWRpYVJlY29yZGVyIGVycm9yOiAnLCBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnN0YXJ0ID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ01lZGlhUmVjb3JkZXIgc3RhcnRlZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMub25TdG9wRGVmYXVsdCgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucGF1c2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnTWVkaWFSZWNvcmRlciBwYXVzZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9ucmVzdW1lID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ01lZGlhUmVjb3JkZXIgcmVzdW1lZCAoc3RhdGU9JyArIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub253YXJuaW5nID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdNZWRpYVJlY29yZGVyIHdhcm5pbmc6ICcgKyBlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIHRoZSByZWNvcmRpbmcgb2YgdGhlIFN0cmVhbS4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYFJFQ09SRElOR2AuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFBBVVNFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyB3YXMgc3VjY2Vzc2Z1bGx5IHBhdXNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcGF1c2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUkVDT1JESU5HKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUEFVU0VEYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUkVDT1JESU5HYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcmVzdW1lZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVzdW1lKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlc3VtZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnBhdXNlKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByZXZpZXdzIHRoZSByZWNvcmRpbmcsIGFwcGVuZGluZyBhIG5ldyBIVE1MVmlkZW9FbGVtZW50IHRvIGVsZW1lbnQgd2l0aCBpZCBgcGFyZW50SWRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgcHJldmlldyhwYXJlbnRFbGVtZW50KTogSFRNTFZpZGVvRWxlbWVudCB7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5wcmV2aWV3KClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnRklOSVNIRURcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdG9wKClcXCcgYmVmb3JlJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5pc1NhZmFyaUJyb3dzZXIoKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICd0cnVlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHBhcmVudEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50RG9tID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocGFyZW50RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAocGFyZW50RWxlbWVudERvbSkge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gcGFyZW50RWxlbWVudERvbS5hcHBlbmRDaGlsZCh0aGlzLnZpZGVvUHJldmlldyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcuc3JjID0gdGhpcy52aWRlb1ByZXZpZXdTcmM7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9QcmV2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR3JhY2VmdWxseSBzdG9wcyBhbmQgY2xlYW5zIHRoZSBjdXJyZW50IHJlY29yZGluZyAoV0FSTklORzogaXQgaXMgY29tcGxldGVseSBkaXNtaXNzZWQpLiBTZXRzIFtbc3RhdGVdXSB0byBgUkVBRFlgIHNvIHRoZSByZWNvcmRpbmcgY2FuIHN0YXJ0IGFnYWluXG4gICAgICovXG4gICAgY2xlYW4oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGYgPSAoKSA9PiB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5ibG9iO1xuICAgICAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhUmVjb3JkZXI7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG4gICAgICAgICAgICBhLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBhLmRvd25sb2FkID0gdGhpcy5pZCArICcud2VibSc7XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmF3IEJsb2IgZmlsZS4gTWV0aG9kcyBwcmV2aWV3LCBkb3dubG9hZCwgdXBsb2FkQXNCaW5hcnkgYW5kIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSB1c2UgdGhpcyBzYW1lIGZpbGUgdG8gcGVyZm9ybSB0aGVpciBzcGVjaWZpYyBhY3Rpb25zLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZ2V0QmxvYigpOiBCbG9iIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdDYWxsIFxcJ0xvY2FsUmVjb3JkLnN0b3AoKVxcJyBiZWZvcmUgZ2V0dGluZyBCbG9iIGZpbGUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ibG9iITtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBsb2FkcyB0aGUgcmVjb3JkZWQgdmlkZW8gYXMgYSBiaW5hcnkgZmlsZSBwZXJmb3JtaW5nIGFuIEhUVFAvUE9TVCBvcGVyYXRpb24gdG8gVVJMIGBlbmRwb2ludGAuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGAuIE9wdGlvbmFsIEhUVFAgaGVhZGVycyBjYW4gYmUgcGFzc2VkIGFzIHNlY29uZCBwYXJhbWV0ZXIuIEZvciBleGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHZhciBoZWFkZXJzID0ge1xuICAgICAqICBcIkNvb2tpZVwiOiBcIiRWZXJzaW9uPTE7IFNraW49bmV3O1wiLFxuICAgICAqICBcIkF1dGhvcml6YXRpb25cIjpcIkJhc2ljIFFXeGhaR3BianB1SUhObGN0WlE9PVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB3aXRoIHRoZSBgaHR0cC5yZXNwb25zZVRleHRgIGZyb20gc2VydmVyIGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggdGhlIGZhaWxlZCBgaHR0cC5zdGF0dXNgIGlmIG5vdFxuICAgICAqL1xuICAgIHVwbG9hZEFzQmluYXJ5KGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoaHR0cC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBodHRwLnNlbmQodGhpcy5ibG9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIG11bHRpcGFydCBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90OlxuICAgICAqL1xuICAgIHVwbG9hZEFzTXVsdGlwYXJ0ZmlsZShlbmRwb2ludDogc3RyaW5nLCBoZWFkZXJzPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiEsIHRoaXMuaWQgKyAnLndlYm0nKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGh0dHAuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBodHRwLnNlbmQoc2VuZGFibGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBvblN0b3BEZWZhdWx0KCk6IHZvaWQge1xuICAgICAgICBsb2dnZXIubG9nKCdNZWRpYVJlY29yZGVyIHN0b3BwZWQgIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcblxuICAgICAgICB0aGlzLmJsb2IgPSBuZXcgQmxvYih0aGlzLmNodW5rcywgeyB0eXBlOiAndmlkZW8vd2VibScgfSk7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gW107XG5cbiAgICAgICAgdGhpcy52aWRlb1ByZXZpZXdTcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTCh0aGlzLmJsb2IpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQ7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgTG9jYWxSZWNvcmRlciB9IGZyb20gJy4vTG9jYWxSZWNvcmRlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuL1B1Ymxpc2hlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IERldmljZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvRGV2aWNlJztcbmltcG9ydCB7IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9PcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbic7XG5pbXBvcnQgeyBQdWJsaXNoZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9QdWJsaXNoZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9DdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzJztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlscyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0nO1xuXG5pbXBvcnQgKiBhcyBzY3JlZW5TaGFyaW5nQXV0byBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy1BdXRvJztcbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmcgZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9TY3JlZW5TaGFyaW5nL1NjcmVlbi1DYXB0dXJpbmcnO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvblwiO1xuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmltcG9ydCBScGNCdWlsZGVyID0gcmVxdWlyZSgnLi4vT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjJyk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBwYWNrYWdlSnNvbiA9IHJlcXVpcmUoJy4uLy4uL3BhY2thZ2UuanNvbicpO1xuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmRlY2xhcmUgdmFyIGNvcmRvdmE6IGFueTtcbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmxldCBwbGF0Zm9ybTogUGxhdGZvcm1VdGlscztcblxuLyoqXG4gKiBFbnRyeXBvaW50IG9mIE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS5cbiAqIFVzZSBpdCB0byBpbml0aWFsaXplIG9iamVjdHMgb2YgdHlwZSBbW1Nlc3Npb25dXSwgW1tQdWJsaXNoZXJdXSBhbmQgW1tMb2NhbFJlY29yZGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIE9wZW5WaWR1IHtcblxuICBwcml2YXRlIGpzb25ScGNDbGllbnQ6IGFueTtcbiAgcHJpdmF0ZSBtYXN0ZXJOb2RlSGFzQ3Jhc2hlZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZXNzaW9uOiBTZXNzaW9uO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHVibGlzaGVyczogUHVibGlzaGVyW10gPSBbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHdzVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBodHRwVXJpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZWNyZXQgPSAnJztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJlY29yZGVyID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBpY2VTZXJ2ZXJzOiBSVENJY2VTZXJ2ZXJbXTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHJvbGU6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGZpbmFsVXNlcklkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBtZWRpYVNlcnZlcjogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgd2VicnRjU3RhdHNJbnRlcnZhbDogbnVtYmVyID0gLTE7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kQnJvd3NlckxvZ3M6IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbiA9IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbi5kaXNhYmxlZDtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGlzUHJvOiBib29sZWFuID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBsaWJyYXJ5VmVyc2lvbjogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKClcblxuICBvbk9yaWVudGF0aW9uQ2hhbmdlZChoYW5kbGVyKTogdm9pZCB7XG4gICAgKDxhbnk+d2luZG93KS5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsIGhhbmRsZXIpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgdGhpcy5saWJyYXJ5VmVyc2lvbiA9IHBhY2thZ2VKc29uLnZlcnNpb247XG4gICAgbG9nZ2VyLmluZm8oXCJPcGVuVmlkdSBpbml0aWFsaXplZFwiKTtcbiAgICBsb2dnZXIuaW5mbygnUGxhdGZvcm0gZGV0ZWN0ZWQ6ICcgKyBwbGF0Zm9ybS5nZXREZXNjcmlwdGlvbigpKTtcbiAgICBsb2dnZXIuaW5mbygnb3BlbnZpZHUtYnJvd3NlciB2ZXJzaW9uOiAnICsgdGhpcy5saWJyYXJ5VmVyc2lvbik7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNNb2JpbGVEZXZpY2UoKSB8fCBwbGF0Zm9ybS5pc1JlYWN0TmF0aXZlKCkpIHtcbiAgICAgIC8vIExpc3RlbiB0byBvcmllbnRhdGlvbmNoYW5nZSBvbmx5IG9uIG1vYmlsZSBkZXZpY2VzXG4gICAgICB0aGlzLm9uT3JpZW50YXRpb25DaGFuZ2VkKCgpID0+IHtcbiAgICAgICAgdGhpcy5wdWJsaXNoZXJzLmZvckVhY2gocHVibGlzaGVyID0+IHtcbiAgICAgICAgICBpZiAocHVibGlzaGVyLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkICYmICEhcHVibGlzaGVyLnN0cmVhbSAmJiAhIXB1Ymxpc2hlci5zdHJlYW0uaGFzVmlkZW8pIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZE5ld1ZpZGVvRGltZW5zaW9uc0lmUmVxdWlyZWQocHVibGlzaGVyLCAnZGV2aWNlUm90YXRlZCcsIDc1LCAxMCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHNlbmROZXdWaWRlb0RpbWVuc2lvbnNJZlJlcXVpcmVkKHB1Ymxpc2hlcjogUHVibGlzaGVyLCByZWFzb246IHN0cmluZywgV0FJVF9JTlRFUlZBTDogbnVtYmVyLCBNQVhfQVRURU1QVFM6IG51bWJlcikge1xuICAgIGxldCBhdHRlbXB0cyA9IDA7XG4gICAgY29uc3Qgb2xkV2lkdGggPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy53aWR0aDtcbiAgICBjb25zdCBvbGRIZWlnaHQgPSBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG5cbiAgICBjb25zdCByZXBlYXRVbnRpbENoYW5nZU9yTWF4QXR0ZW1wdHM6IE5vZGVKUy5UaW1lb3V0ID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgYXR0ZW1wdHMrKztcbiAgICAgIGlmIChhdHRlbXB0cyA+IE1BWF9BVFRFTVBUUykge1xuICAgICAgICBjbGVhclRpbWVvdXQocmVwZWF0VW50aWxDaGFuZ2VPck1heEF0dGVtcHRzKTtcbiAgICAgIH1cbiAgICAgIHB1Ymxpc2hlci5nZXRWaWRlb0RpbWVuc2lvbnMocHVibGlzaGVyLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKS50aGVuKG5ld0RpbWVuc2lvbnMgPT4ge1xuICAgICAgICBpZiAobmV3RGltZW5zaW9ucy53aWR0aCAhPT0gb2xkV2lkdGggfHwgbmV3RGltZW5zaW9ucy5oZWlnaHQgIT09IG9sZEhlaWdodCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZU9yTWF4QXR0ZW1wdHMpO1xuICAgICAgICAgIHRoaXMuc2VuZFZpZGVvRGltZW5zaW9uc0NoYW5nZWRFdmVudChwdWJsaXNoZXIsIHJlYXNvbiwgb2xkV2lkdGgsIG9sZEhlaWdodCwgbmV3RGltZW5zaW9ucy53aWR0aCwgbmV3RGltZW5zaW9ucy5oZWlnaHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9LCBXQUlUX0lOVEVSVkFMKTtcbiAgfVxuXG4gIHNlbmRWaWRlb0RpbWVuc2lvbnNDaGFuZ2VkRXZlbnQocHVibGlzaGVyOiBQdWJsaXNoZXIsIHJlYXNvbjogc3RyaW5nLCBvbGRXaWR0aDogbnVtYmVyLCBvbGRIZWlnaHQ6IG51bWJlciwgbmV3V2lkdGg6IG51bWJlciwgbmV3SGVpZ2h0OiBudW1iZXIpIHtcbiAgICBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IHtcbiAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgaGVpZ2h0OiBuZXdIZWlnaHQgfHwgMFxuICAgIH07XG4gICAgdGhpcy5zZW5kUmVxdWVzdChcbiAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAge1xuICAgICAgICBzdHJlYW1JZDogcHVibGlzaGVyLnN0cmVhbS5zdHJlYW1JZCxcbiAgICAgICAgcHJvcGVydHk6ICd2aWRlb0RpbWVuc2lvbnMnLFxuICAgICAgICBuZXdWYWx1ZTogSlNPTi5zdHJpbmdpZnkocHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMpLFxuICAgICAgICByZWFzb25cbiAgICAgIH0sXG4gICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zZXNzaW9uLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCByZWFzb24pXSk7XG4gICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChwdWJsaXNoZXIsIHB1Ymxpc2hlci5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucywgeyB3aWR0aDogb2xkV2lkdGgsIGhlaWdodDogb2xkSGVpZ2h0IH0sIHJlYXNvbildKTtcbiAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YShwdWJsaXNoZXIpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogUmV0dXJucyBuZXcgc2Vzc2lvblxuICAgKi9cbiAgaW5pdFNlc3Npb24oKTogU2Vzc2lvbiB7XG4gICAgdGhpcy5zZXNzaW9uID0gbmV3IFNlc3Npb24odGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbjtcbiAgfVxuXG5cbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFB1Ymxpc2hlcjtcbiAgaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IHB1Ymxpc2hlclxuICAgKlxuICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGFuIGBhY2Nlc3NEaWFsb2dPcGVuZWRgIGV2ZW50LCBvbmx5IGlmIHRoZSBwb3AtdXAgc2hvd24gYnkgdGhlIGJyb3dzZXIgdG8gcmVxdWVzdCBwZXJtaXNzaW9ucyBmb3IgdGhlIGNhbWVyYSBpcyBvcGVuZWQuIFlvdSBjYW4gdXNlIHRoaXMgZXZlbnQgdG8gYWxlcnQgdGhlIHVzZXIgYWJvdXQgZ3JhbnRpbmcgcGVybWlzc2lvbnNcbiAgICogZm9yIHlvdXIgd2Vic2l0ZS4gQW4gYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgZXZlbnQgd2lsbCBhbHNvIGJlIGRpc3BhdGNoZWQgYWZ0ZXIgdXNlciBjbGlja3Mgb24gXCJBbGxvd1wiIG9yIFwiQmxvY2tcIiBpbiB0aGUgcG9wLXVwLlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYGFjY2Vzc0RlbmllZGAgZXZlbnQgb25jZSBpdCBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90LlxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnRDcmVhdGVkYCBldmVudCBvbmNlIGEgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2AgZXZlbnQgb25jZSB0aGUgbG9jYWwgc3RyZWFtcyBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgIEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXSkuIElmICpudWxsKiBvciAqdW5kZWZpbmVkKiBubyBkZWZhdWx0IHZpZGVvIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBQdWJsaXNoZXIuXG4gICAqIFlvdSBjYW4gYWx3YXlzIGNhbGwgbWV0aG9kIFtbUHVibGlzaGVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgaW5pdFB1Ymxpc2hlcmAgc3VjY2VlZHMsIGFuZCBpcyBkZWZpbmVkIGlmIGl0IGZhaWxzLlxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYGNvbXBsZXRpb25IYW5kbGVyYCBmdW5jdGlvbiBpcyBjYWxsZWQgYmVmb3JlIHRoZSBQdWJsaXNoZXIgZGlzcGF0Y2hlcyBhbiBgYWNjZXNzQWxsb3dlZGAgb3IgYW4gYGFjY2Vzc0RlbmllZGAgZXZlbnRcbiAgICovXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHBhcmFtMj8sIHBhcmFtMz8pOiBQdWJsaXNoZXIge1xuXG4gICAgbGV0IHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXM7XG5cbiAgICBpZiAoISFwYXJhbTIgJiYgKHR5cGVvZiBwYXJhbTIgIT09ICdmdW5jdGlvbicpKSB7XG5cbiAgICAgIC8vIE1hdGNoZXMgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcyknIG9yICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyKSdcblxuICAgICAgcHJvcGVydGllcyA9ICg8UHVibGlzaGVyUHJvcGVydGllcz5wYXJhbTIpO1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBhdWRpb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmF1ZGlvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICBmcmFtZVJhdGU6ICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5mcmFtZVJhdGUgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMuZnJhbWVSYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgIT09ICd1bmRlZmluZWQnKSA/ICgodHlwZW9mIHByb3BlcnRpZXMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3Byb3BlcnRpZXMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgbWlycm9yOiAodHlwZW9mIHByb3BlcnRpZXMubWlycm9yICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLm1pcnJvciA6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogKHR5cGVvZiBwcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoVmlkZW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaFZpZGVvIDogdHJ1ZSxcbiAgICAgICAgcmVzb2x1dGlvbjogKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykgPyB1bmRlZmluZWQgOiAoKHR5cGVvZiBwcm9wZXJ0aWVzLnJlc29sdXRpb24gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucmVzb2x1dGlvbiA6ICc2NDB4NDgwJyksXG4gICAgICAgIHZpZGVvU291cmNlOiAodHlwZW9mIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWQsXG4gICAgICAgIGZpbHRlcjogcHJvcGVydGllcy5maWx0ZXJcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gTWF0Y2hlcyAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50KScgb3IgJ2luaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY29tcGxldGlvbkhhbmRsZXIpJ1xuXG4gICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICBtaXJyb3I6IHRydWUsXG4gICAgICAgIHB1Ymxpc2hBdWRpbzogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiB0cnVlLFxuICAgICAgICByZXNvbHV0aW9uOiAnNjQweDQ4MCdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgcHVibGlzaGVyOiBQdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIHRoaXMpO1xuXG4gICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkO1xuICAgIGlmICghIXBhcmFtMiAmJiAodHlwZW9mIHBhcmFtMiA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0yO1xuICAgIH0gZWxzZSBpZiAoISFwYXJhbTMpIHtcbiAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgIH1cblxuICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW2Vycm9yXSk7XG4gICAgICB9KTtcblxuICAgIHRoaXMucHVibGlzaGVycy5wdXNoKHB1Ymxpc2hlcik7XG4gICAgcmV0dXJuIHB1Ymxpc2hlcjtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV1cbiAgICpcbiAgICogPiBXQVJOSU5HOiBldmVudHMgYGFjY2Vzc0RpYWxvZ09wZW5lZGAgYW5kIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIHdpbGwgbm90IGJlIGRpc3BhdGNoZWQgaWYgdXNpbmcgdGhpcyBtZXRob2QgaW5zdGVhZCBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKi9cbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxQdWJsaXNoZXI+O1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG5cbiAgaW5pdFB1Ymxpc2hlckFzeW5jKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzPzogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFB1Ymxpc2hlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICBsZXQgcHVibGlzaGVyOiBQdWJsaXNoZXI7XG5cbiAgICAgIGNvbnN0IGNhbGxiYWNrID0gKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzb2x2ZShwdWJsaXNoZXIpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHB1Ymxpc2hlciA9IHRoaXMuaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjYWxsYmFjayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBsb2NhbCByZWNvcmRlciBmb3IgcmVjb3JkaW5nIHN0cmVhbXMgc3RyYWlnaHQgYXdheSBmcm9tIHRoZSBicm93c2VyXG4gICAqIEBwYXJhbSBzdHJlYW0gIFN0cmVhbSB0byByZWNvcmRcbiAgICovXG4gIGluaXRMb2NhbFJlY29yZGVyKHN0cmVhbTogU3RyZWFtKTogTG9jYWxSZWNvcmRlciB7XG4gICAgcmV0dXJuIG5ldyBMb2NhbFJlY29yZGVyKHN0cmVhbSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHVcbiAgICogQHJldHVybnMgMSBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBPcGVuVmlkdSwgMCBvdGhlcndpc2VcbiAgICovXG4gIGNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCk6IG51bWJlciB7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJUGhvbmVPcklQYWQoKSkge1xuICAgICAgaWYgKHBsYXRmb3JtLmlzSU9TV2l0aFNhZmFyaSgpIHx8IHBsYXRmb3JtLmlzSW9uaWNJb3MoKSB8fFxuICAgICAgICBwbGF0Zm9ybS5pc0Nocm9tZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNPcGVyYU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvLyBBY2NlcHQ6IENocm9tZSAoZGVza3RvcCBhbmQgQW5kcm9pZCksIEZpcmVmb3ggKGRlc2t0b3AgYW5kIEFuZHJvaWQpLCBPcGVyYSAoZGVza3RvcCBhbmQgQW5kcm9pZCksXG4gICAgLy8gU2FmYXJpIChPU1ggYW5kIGlPUyksIEVkZ2UgQ2hyb21pdW0gKD49IDgwKSwgSW9uaWMgKEFuZHJvaWQgYW5kIGlPUyksIFNhbXN1bmcgSW50ZXJuZXQgQnJvd3NlciAoQW5kcm9pZClcbiAgICBpZiAocGxhdGZvcm0uaXNDaHJvbWVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHxcbiAgICAgIHBsYXRmb3JtLmlzRmlyZWZveEJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNPcGVyYUJyb3dzZXIoKSB8fFxuICAgICAgcGxhdGZvcm0uaXNPcGVyYU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8XG4gICAgICBwbGF0Zm9ybS5pc1NhZmFyaUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0FuZHJvaWRCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFbGVjdHJvbigpIHx8IHBsYXRmb3JtLmlzU2Ftc3VuZ0Jyb3dzZXIoKVxuICAgICkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIC8vIFJlamVjdCBpUGhvbmVzIGFuZCBpUGFkcyBpZiBub3QgU2FmYXJpICgnU2FmYXJpJyBhbHNvIGNvdmVycyBJb25pYyBmb3IgaU9TKVxuICAgIC8vIFJlamVjdCBvdGhlcnMgYnJvd3NlcnMgbm90IG1lbnRpb25lZCBhYm92ZVxuICAgIHJldHVybiAwO1xuXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIHNjcmVlbi1zaGFyaW5nLiBEZXNrdG9wIENocm9tZSwgRmlyZWZveCBhbmQgT3BlcmEgc3VwcG9ydCBzY3JlZW4tc2hhcmluZ1xuICAgKiBAcmV0dXJucyAxIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIHNjcmVlbi1zaGFyaW5nLCAwIG90aGVyd2lzZVxuICAgKi9cbiAgY2hlY2tTY3JlZW5TaGFyaW5nQ2FwYWJpbGl0aWVzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBwbGF0Zm9ybS5jYW5TY3JlZW5TaGFyZSgpO1xuICB9XG5cblxuICAvKipcbiAgICogQ29sbGVjdHMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1lZGlhIGlucHV0IGRldmljZXMgYXZhaWxhYmxlIG9uIHRoZSBzeXN0ZW0uIFlvdSBjYW4gcGFzcyBwcm9wZXJ0eSBgZGV2aWNlSWRgIG9mIGEgW1tEZXZpY2VdXSBvYmplY3QgYXMgdmFsdWUgb2YgYGF1ZGlvU291cmNlYCBvciBgdmlkZW9Tb3VyY2VgIHByb3BlcnRpZXMgaW4gW1tpbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAqL1xuICBnZXREZXZpY2VzKCk6IFByb21pc2U8RGV2aWNlW10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8RGV2aWNlW10+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcygpLnRoZW4oKGRldmljZUluZm9zKSA9PiB7XG4gICAgICAgIGNvbnN0IGRldmljZXM6IERldmljZVtdID0gW107XG5cbiAgICAgICAgLy8gSW9uaWMgQW5kcm9pZCAgZGV2aWNlc1xuICAgICAgICBpZiAocGxhdGZvcm0uaXNJb25pY0FuZHJvaWQoKSAmJiB0eXBlb2YgY29yZG92YSAhPSBcInVuZGVmaW5lZFwiICYmIGNvcmRvdmE/LnBsdWdpbnM/LkVudW1lcmF0ZURldmljZXNQbHVnaW4pIHtcbiAgICAgICAgICBjb3Jkb3ZhLnBsdWdpbnMuRW51bWVyYXRlRGV2aWNlc1BsdWdpbi5nZXRFbnVtZXJhdGVEZXZpY2VzKCkudGhlbigocGx1Z2luRGV2aWNlczogRGV2aWNlW10pID0+IHtcbiAgICAgICAgICAgIGxldCBwbHVnaW5BdWRpb0RldmljZXM6IERldmljZVtdID0gW107XG4gICAgICAgICAgICBsZXQgdmlkZW9EZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICAgICAgbGV0IGF1ZGlvRGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgICAgIHBsdWdpbkF1ZGlvRGV2aWNlcyA9IHBsdWdpbkRldmljZXMuZmlsdGVyKChkZXZpY2U6IERldmljZSkgPT4gZGV2aWNlLmtpbmQgPT09ICdhdWRpb2lucHV0Jyk7XG4gICAgICAgICAgICB2aWRlb0RldmljZXMgPSBkZXZpY2VJbmZvcy5maWx0ZXIoKGRldmljZTogRGV2aWNlKSA9PiBkZXZpY2Uua2luZCA9PT0gJ3ZpZGVvaW5wdXQnKTtcbiAgICAgICAgICAgIGF1ZGlvRGV2aWNlcyA9IGRldmljZUluZm9zLmZpbHRlcigoZGV2aWNlOiBEZXZpY2UpID0+IGRldmljZS5raW5kID09PSAnYXVkaW9pbnB1dCcpO1xuICAgICAgICAgICAgdmlkZW9EZXZpY2VzLmZvckVhY2goKGRldmljZUluZm8sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmICghZGV2aWNlSW5mby5sYWJlbCkge1xuICAgICAgICAgICAgICAgIGxldCBsYWJlbCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICBsYWJlbCA9IFwiRnJvbnQgQ2FtZXJhXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbmRleCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgbGFiZWwgPSBcIkJhY2sgQ2FtZXJhXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGxhYmVsID0gXCJVbmtub3duIENhbWVyYVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgICAgICBsYWJlbDogbGFiZWxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICBraW5kOiBkZXZpY2VJbmZvLmtpbmQsXG4gICAgICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYXVkaW9EZXZpY2VzLmZvckVhY2goKGRldmljZUluZm8sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmICghZGV2aWNlSW5mby5sYWJlbCkge1xuICAgICAgICAgICAgICAgIGxldCBsYWJlbCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChpbmRleCkge1xuICAgICAgICAgICAgICAgICAgY2FzZSAwOiAvLyBEZWZhdWx0IE1pY3JvcGhvbmVcbiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSAnRGVmYXVsdCc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSAxOiAvLyBNaWNyb3Bob25lICsgU3BlYWtlcnBob25lXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRNYXRjaCA9IHBsdWdpbkF1ZGlvRGV2aWNlcy5maWx0ZXIoKGQpID0+IGQubGFiZWwuaW5jbHVkZXMoJ0J1aWx0JykpWzBdO1xuICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IGRlZmF1bHRNYXRjaCA/IGRlZmF1bHRNYXRjaC5sYWJlbCA6ICdCdWlsdC1pbiBNaWNyb3Bob25lJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBjYXNlIDI6IC8vIEhlYWRzZXQgTWljcm9waG9uZVxuICAgICAgICAgICAgICAgICAgICBjb25zdCB3aXJlZE1hdGNoID0gcGx1Z2luQXVkaW9EZXZpY2VzLmZpbHRlcigoZCkgPT4gZC5sYWJlbC5pbmNsdWRlcygnV2lyZWQnKSlbMF07XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aXJlZE1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSB3aXJlZE1hdGNoLmxhYmVsO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gJ0hlYWRzZXQgZWFycGllY2UnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBjb25zdCB3aXJlbGVzc01hdGNoID0gcGx1Z2luQXVkaW9EZXZpY2VzLmZpbHRlcigoZCkgPT4gZC5sYWJlbC5pbmNsdWRlcygnQmx1ZXRvb3RoJykpWzBdO1xuICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHdpcmVsZXNzTWF0Y2ggPyB3aXJlbGVzc01hdGNoLmxhYmVsIDogJ1dpcmVsZXNzJztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IFwiVW5rbm93biBNaWNyb3Bob25lXCI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgICAgICBsYWJlbDogbGFiZWxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICBraW5kOiBkZXZpY2VJbmZvLmtpbmQsXG4gICAgICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVzb2x2ZShkZXZpY2VzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgIC8vIFJlc3Qgb2YgcGxhdGZvcm1zXG4gICAgICAgICAgZGV2aWNlSW5mb3MuZm9yRWFjaChkZXZpY2VJbmZvID0+IHtcbiAgICAgICAgICAgIGlmIChkZXZpY2VJbmZvLmtpbmQgPT09ICdhdWRpb2lucHV0JyB8fCBkZXZpY2VJbmZvLmtpbmQgPT09ICd2aWRlb2lucHV0Jykge1xuICAgICAgICAgICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgICBkZXZpY2VJZDogZGV2aWNlSW5mby5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICBsYWJlbDogZGV2aWNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXNvbHZlKGRldmljZXMpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBnZXR0aW5nIGRldmljZXMnLCBlcnJvcik7XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cblxuICAvKipcbiAgICogR2V0IGEgTWVkaWFTdHJlYW0gb2JqZWN0IHRoYXQgeW91IGNhbiBjdXN0b21pemUgYmVmb3JlIGNhbGxpbmcgW1tpbml0UHVibGlzaGVyXV0gKHBhc3MgX01lZGlhU3RyZWFtVHJhY2tfIHByb3BlcnR5IG9mIHRoZSBfTWVkaWFTdHJlYW1fIHZhbHVlIHJlc29sdmVkIGJ5IHRoZSBQcm9taXNlIGFzIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dKVxuICAgKlxuICAgKiBQYXJhbWV0ZXIgYG9wdGlvbnNgIGlzIHRoZSBzYW1lIGFzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIHNlY29uZCBwYXJhbWV0ZXIgKG9mIHR5cGUgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0pLCBidXQgb25seSB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgd2lsbCBiZSBhcHBsaWVkOiBgYXVkaW9Tb3VyY2VgLCBgdmlkZW9Tb3VyY2VgLCBgZnJhbWVSYXRlYCwgYHJlc29sdXRpb25gXG4gICAqXG4gICAqIFRvIGN1c3RvbWl6ZSB0aGUgUHVibGlzaGVyJ3MgdmlkZW8sIHRoZSBBUEkgZm9yIEhUTUxDYW52YXNFbGVtZW50IGlzIHZlcnkgdXNlZnVsLiBGb3IgZXhhbXBsZSwgdG8gZ2V0IGEgYmxhY2stYW5kLXdoaXRlIHZpZGVvIGF0IDEwIGZwcyBhbmQgSEQgcmVzb2x1dGlvbiB3aXRoIG5vIHNvdW5kOlxuICAgKiBgYGBcbiAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAqIHZhciBGUkFNRV9SQVRFID0gMTA7XG4gICAqXG4gICAqIE9WLmdldFVzZXJNZWRpYSh7XG4gICAqICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgdmlkZW9Tb3VyY2U6IHVuZGVmaW5lZCxcbiAgICogICAgcmVzb2x1dGlvbjogJzEyODB4NzIwJyxcbiAgICogICAgZnJhbWVSYXRlOiBGUkFNRV9SQVRFXG4gICAqIH0pXG4gICAqIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICpcbiAgICogICAgdmFyIHZpZGVvVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgKiAgICB2aWRlby5zcmNPYmplY3QgPSBuZXcgTWVkaWFTdHJlYW0oW3ZpZGVvVHJhY2tdKTtcbiAgICpcbiAgICogICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgKiAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAqICAgIGN0eC5maWx0ZXIgPSAnZ3JheXNjYWxlKDEwMCUpJztcbiAgICpcbiAgICogICAgdmlkZW8uYWRkRXZlbnRMaXN0ZW5lcigncGxheScsICgpID0+IHtcbiAgICogICAgICB2YXIgbG9vcCA9ICgpID0+IHtcbiAgICogICAgICAgIGlmICghdmlkZW8ucGF1c2VkICYmICF2aWRlby5lbmRlZCkge1xuICAgKiAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCAzMDAsIDE3MCk7XG4gICAqICAgICAgICAgIHNldFRpbWVvdXQobG9vcCwgMTAwMC8gRlJBTUVfUkFURSk7IC8vIERyYXdpbmcgYXQgMTAgZnBzXG4gICAqICAgICAgICB9XG4gICAqICAgICAgfTtcbiAgICogICAgICBsb29wKCk7XG4gICAqICAgIH0pO1xuICAgKiAgICB2aWRlby5wbGF5KCk7XG4gICAqXG4gICAqICAgIHZhciBncmF5VmlkZW9UcmFjayA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKEZSQU1FX1JBVEUpLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAqICAgIHZhciBwdWJsaXNoZXIgPSB0aGlzLk9WLmluaXRQdWJsaXNoZXIoXG4gICAqICAgICAgbXlIdG1sVGFyZ2V0LFxuICAgKiAgICAgIHtcbiAgICogICAgICAgIGF1ZGlvU291cmNlOiBmYWxzZSxcbiAgICogICAgICAgIHZpZGVvU291cmNlOiBncmF5VmlkZW9UcmFja1xuICAgKiAgICAgIH0pO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBnZXRVc2VyTWVkaWEob3B0aW9uczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8TWVkaWFTdHJlYW0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8TWVkaWFTdHJlYW0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgY29uc3QgYXNrRm9yQXVkaW9TdHJlYW1Pbmx5ID0gKHByZXZpb3VzTWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtLCBjb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cykgPT4ge1xuICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzQXV4OiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0geyBhdWRpbzogZGVmaW5lZEF1ZGlvQ29uc3RyYWludCwgdmlkZW86IGZhbHNlIH07XG4gICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgIC50aGVuKGF1ZGlvT25seVN0cmVhbSA9PiB7XG4gICAgICAgICAgICBwcmV2aW91c01lZGlhU3RyZWFtLmFkZFRyYWNrKGF1ZGlvT25seVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgIHJlc29sdmUocHJldmlvdXNNZWRpYVN0cmVhbSk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgcHJldmlvdXNNZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcHJldmlvdXNNZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVqZWN0KHRoaXMuZ2VuZXJhdGVBdWRpb0RldmljZUVycm9yKGVycm9yLCBjb25zdHJhaW50c0F1eCkpO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhvcHRpb25zKS50aGVuKG15Q29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgIGlmICghIW15Q29uc3RyYWludHMudmlkZW9UcmFjayAmJiAhIW15Q29uc3RyYWludHMuYXVkaW9UcmFjayB8fFxuICAgICAgICAgICEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LnZpZGVvID09PSBmYWxzZSB8fFxuICAgICAgICAgICEhbXlDb25zdHJhaW50cy52aWRlb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LmF1ZGlvID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgLy8gTm8gbmVlZCB0byBjYWxsIGdldFVzZXJNZWRpYSBhdCBhbGwuIEJvdGggdHJhY2tzIHByb3ZpZGVkLCBvciBvbmx5IEFVRElPIHRyYWNrIHByb3ZpZGVkIG9yIG9ubHkgVklERU8gdHJhY2sgcHJvdmlkZWRcbiAgICAgICAgICByZXNvbHZlKHRoaXMuYWRkQWxyZWFkeVByb3ZpZGVkVHJhY2tzKG15Q29uc3RyYWludHMsIG5ldyBNZWRpYVN0cmVhbSgpKSk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBnZXRVc2VyTWVkaWEgbXVzdCBiZSBjYWxsZWQuIEFVRElPIG9yIFZJREVPIGFyZSByZXF1ZXN0aW5nIGEgbmV3IHRyYWNrXG5cbiAgICAgICAgICAvLyBEZWxldGUgYWxyZWFkeSBwcm92aWRlZCBjb25zdHJhaW50cyBmb3IgYXVkaW8gb3IgdmlkZW9cbiAgICAgICAgICBpZiAoISFteUNvbnN0cmFpbnRzLnZpZGVvVHJhY2spIHtcbiAgICAgICAgICAgIGRlbGV0ZSBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrKSB7XG4gICAgICAgICAgICBkZWxldGUgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEuYXVkaW87XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGV0IG11c3RBc2tGb3JBdWRpb1RyYWNrTGF0ZXIgPSBmYWxzZTtcbiAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBWaWRlbyBpcyBkZXZpY2VJZCBvciBzY3JlZW4gc2hhcmluZ1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nIHx8XG4gICAgICAgICAgICAgIG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICd3aW5kb3cnIHx8XG4gICAgICAgICAgICAgIChwbGF0Zm9ybS5pc0VsZWN0cm9uKCkgJiYgb3B0aW9ucy52aWRlb1NvdXJjZS5zdGFydHNXaXRoKCdzY3JlZW46JykpKSB7XG4gICAgICAgICAgICAgIC8vIFZpZGVvIGlzIHNjcmVlbiBzaGFyaW5nXG4gICAgICAgICAgICAgIG11c3RBc2tGb3JBdWRpb1RyYWNrTGF0ZXIgPSAhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrICYmIChvcHRpb25zLmF1ZGlvU291cmNlICE9PSBudWxsICYmIG9wdGlvbnMuYXVkaW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICAgICAgICAgICAgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddICYmICFwbGF0Zm9ybS5pc0VsZWN0cm9uKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBnZXREaXNwbGF5TWVkaWEgc3VwcG9ydGVkXG4gICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10oeyB2aWRlbzogdHJ1ZSB9KVxuICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzLCBtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtdXN0QXNrRm9yQXVkaW9UcmFja0xhdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgYXNrRm9yQXVkaW9TdHJlYW1Pbmx5KG1lZGlhU3RyZWFtLCA8TWVkaWFTdHJlYW1Db25zdHJhaW50cz5teUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lOiBPcGVuVmlkdUVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZ2V0RGlzcGxheU1lZGlhIE5PVCBzdXBwb3J0ZWQuIENhbiBwZXJmb3JtIGdldFVzZXJNZWRpYSBiZWxvdyB3aXRoIGFscmVhZHkgY2FsY3VsYXRlZCBjb25zdHJhaW50c1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBWaWRlbyBpcyBkZXZpY2VJZC4gQ2FuIHBlcmZvcm0gZ2V0VXNlck1lZGlhIGJlbG93IHdpdGggYWxyZWFkeSBjYWxjdWxhdGVkIGNvbnN0cmFpbnRzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFVzZSBhbHJlYWR5IGNhbGN1bGF0ZWQgY29uc3RyYWludHNcbiAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eCA9IG11c3RBc2tGb3JBdWRpb1RyYWNrTGF0ZXIgPyB7IHZpZGVvOiBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyB9IDogbXlDb25zdHJhaW50cy5jb25zdHJhaW50cztcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5hZGRBbHJlYWR5UHJvdmlkZWRUcmFja3MobXlDb25zdHJhaW50cywgbWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICBpZiAobXVzdEFza0ZvckF1ZGlvVHJhY2tMYXRlcikge1xuICAgICAgICAgICAgICAgIGFza0ZvckF1ZGlvU3RyZWFtT25seShtZWRpYVN0cmVhbSwgPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc29sdmUobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmICghKG9wdGlvbnMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nKSkge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaCgoZXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1lbXB0eSAqL1xuICAvKipcbiAgICogRGlzYWJsZSBhbGwgbG9nZ2luZyBleGNlcHQgZXJyb3IgbGV2ZWxcbiAgICovXG4gIGVuYWJsZVByb2RNb2RlKCk6IHZvaWQge1xuICAgIGxvZ2dlci5lbmFibGVQcm9kTW9kZSgpO1xuICB9XG4gIC8qIHRzbGludDplbmFibGU6bm8tZW1wdHkgKi9cblxuXG4gIC8qKlxuICAgKiBTZXQgT3BlblZpZHUgYWR2YW5jZWQgY29uZmlndXJhdGlvbiBvcHRpb25zLiBDdXJyZW50bHkgYGNvbmZpZ3VyYXRpb25gIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllcyAoc2VlIFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb25dXSBmb3IgbW9yZSBkZXRhaWxzKTpcbiAgICogLSBgaWNlU2VydmVyc2A6IHNldCBjdXN0b20gU1RVTi9UVVJOIHNlcnZlcnMgdG8gYmUgdXNlZCBieSBPcGVuVmlkdSBCcm93c2VyXG4gICAqIC0gYHNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uYDogdXJsIHRvIGEgY3VzdG9tIHNjcmVlbiBzaGFyZSBleHRlbnNpb24gZm9yIENocm9tZSB0byBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgb25lLCBiYXNlZCBvbiBvdXJzIFtodHRwczovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbl0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5WaWR1L29wZW52aWR1LXNjcmVlbi1zaGFyaW5nLWNocm9tZS1leHRlbnNpb24pXG4gICAqIC0gYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2A6IGN1c3RvbSBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZSBhbmQgdGhlIFtTdHJlYW1NYW5hZ2VyRXZlbnQuc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2VdKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvY2xhc3Nlcy9zdHJlYW1tYW5hZ2VyZXZlbnQuaHRtbCkgZmVhdHVyZVxuICAgKiAtIGBmb3JjZU1lZGlhUmVjb25uZWN0aW9uQWZ0ZXJOZXR3b3JrRHJvcGA6IGFsd2F5cyBmb3JjZSBXZWJSVEMgcmVuZWdvdGlhdGlvbiBvZiBhbGwgdGhlIHN0cmVhbXMgb2YgYSBjbGllbnQgYWZ0ZXIgYSBuZXR3b3JrIGxvc3MgYW5kIHJlY29ubmVjdGlvbi4gVGhpcyBjYW4gaGVscCByZWR1Y2luZyBmcm96ZW4gdmlkZW9zIGluIGxvdyBxdWFsaXR5IG5ldHdvcmtzLlxuICAgKlxuICAgKiBDYWxsIHRoaXMgbWV0aG9kIHRvIG92ZXJyaWRlIHByZXZpb3VzIHZhbHVlcyBhdCBhbnkgbW9tZW50LlxuICAgKi9cbiAgc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uKGNvbmZpZ3VyYXRpb246IE9wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICB9XG5cblxuICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZW5lcmF0ZU1lZGlhQ29uc3RyYWludHMocHVibGlzaGVyUHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8Q3VzdG9tTWVkaWFTdHJlYW1Db25zdHJhaW50cz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxDdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGNvbnN0IG15Q29uc3RyYWludHM6IEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7XG4gICAgICAgIGF1ZGlvVHJhY2s6IHVuZGVmaW5lZCxcbiAgICAgICAgdmlkZW9UcmFjazogdW5kZWZpbmVkLFxuICAgICAgICBjb25zdHJhaW50czoge1xuICAgICAgICAgIGF1ZGlvOiB1bmRlZmluZWQsXG4gICAgICAgICAgdmlkZW86IHVuZGVmaW5lZFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBhdWRpb1NvdXJjZSA9IHB1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2U7XG4gICAgICBjb25zdCB2aWRlb1NvdXJjZSA9IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2U7XG5cbiAgICAgIC8vIENBU0UgMTogbnVsbC9mYWxzZVxuICAgICAgaWYgKGF1ZGlvU291cmNlID09PSBudWxsIHx8IGF1ZGlvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICAvLyBObyBhdWRpbyB0cmFja1xuICAgICAgICBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS5hdWRpbyA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKHZpZGVvU291cmNlID09PSBudWxsIHx8IHZpZGVvU291cmNlID09PSBmYWxzZSkge1xuICAgICAgICAvLyBObyB2aWRlbyB0cmFja1xuICAgICAgICBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLmF1ZGlvID09PSBmYWxzZSAmJiBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyA9PT0gZmFsc2UpIHtcbiAgICAgICAgLy8gRVJST1IhIGF1ZGlvU291cmNlIGFuZCB2aWRlb1NvdXJjZSBjYW5ub3QgYmUgYm90aCBmYWxzZSBhdCB0aGUgc2FtZSB0aW1lXG4gICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5OT19JTlBVVF9TT1VSQ0VfU0VULFxuICAgICAgICAgIFwiUHJvcGVydGllcyAnYXVkaW9Tb3VyY2UnIGFuZCAndmlkZW9Tb3VyY2UnIGNhbm5vdCBiZSBzZXQgdG8gZmFsc2Ugb3IgbnVsbCBhdCB0aGUgc2FtZSB0aW1lXCIpKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ0FTRSAyOiBNZWRpYVN0cmVhbVRyYWNrc1xuICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiBhdWRpb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgLy8gQWxyZWFkeSBwcm92aWRlZCBhdWRpbyB0cmFja1xuICAgICAgICBteUNvbnN0cmFpbnRzLmF1ZGlvVHJhY2sgPSBhdWRpb1NvdXJjZTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgdmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSB7XG4gICAgICAgIC8vIEFscmVhZHkgcHJvdmlkZWQgdmlkZW8gdHJhY2tcbiAgICAgICAgbXlDb25zdHJhaW50cy52aWRlb1RyYWNrID0gdmlkZW9Tb3VyY2U7XG4gICAgICB9XG5cbiAgICAgIC8vIENBU0UgMzogRGVmYXVsdCB0cmFja3NcbiAgICAgIGlmIChhdWRpb1NvdXJjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLmF1ZGlvID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh2aWRlb1NvdXJjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLnZpZGVvID0ge1xuICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICBpZGVhbDogNjQwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgIGlkZWFsOiA0ODBcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIENBU0UgMy41OiBnaXZlIHZhbHVlcyB0byByZXNvbHV0aW9uIGFuZCBmcmFtZVJhdGUgaWYgdmlkZW8gbm90IG51bGwvZmFsc2VcbiAgICAgIGlmICh2aWRlb1NvdXJjZSAhPT0gbnVsbCAmJiB2aWRlb1NvdXJjZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgaWYgKCEhcHVibGlzaGVyUHJvcGVydGllcy5yZXNvbHV0aW9uKSB7XG4gICAgICAgICAgY29uc3Qgd2lkdGhBbmRIZWlnaHQgPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24udG9Mb3dlckNhc2UoKS5zcGxpdCgneCcpO1xuICAgICAgICAgIGNvbnN0IGlkZWFsV2lkdGggPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMF0pO1xuICAgICAgICAgIGNvbnN0IGlkZWFsSGVpZ2h0ID0gTnVtYmVyKHdpZHRoQW5kSGVpZ2h0WzFdKTtcbiAgICAgICAgICBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyA9IHtcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgIGlkZWFsOiBpZGVhbFdpZHRoXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICAgIGlkZWFsOiBpZGVhbEhlaWdodFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSkge1xuICAgICAgICAgICg8TWVkaWFUcmFja0NvbnN0cmFpbnRzPm15Q29uc3RyYWludHMuY29uc3RyYWludHMhLnZpZGVvKS5mcmFtZVJhdGUgPSB7IGlkZWFsOiBwdWJsaXNoZXJQcm9wZXJ0aWVzLmZyYW1lUmF0ZSB9O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIENBU0UgNDogZGV2aWNlSWQgb3Igc2NyZWVuIHNoYXJpbmdcbiAgICAgIHRoaXMuY29uZmlndXJlRGV2aWNlSWRPclNjcmVlbnNoYXJpbmcobXlDb25zdHJhaW50cywgcHVibGlzaGVyUHJvcGVydGllcywgcmVzb2x2ZSwgcmVqZWN0KTtcblxuICAgICAgcmVzb2x2ZShteUNvbnN0cmFpbnRzKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSArICc/c2Vzc2lvbklkPScgKyB0aGlzLnNlc3Npb24uc2Vzc2lvbklkLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBpc21hc3Rlcm5vZGVjcmFzaGVkOiB0aGlzLmlzTWFzdGVyTm9kZUNyYXNoZWQuYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIHBhcnRpY2lwYW50Sm9pbmVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudEpvaW5lZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50UHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFB1Ymxpc2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50VW5wdWJsaXNoZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50VW5wdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudExlZnQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50TGVmdC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHBhcnRpY2lwYW50RXZpY3RlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRFdmljdGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcmVjb3JkaW5nU3RhcnRlZDogdGhpcy5zZXNzaW9uLm9uUmVjb3JkaW5nU3RhcnRlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0b3BwZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0b3BwZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzZW5kTWVzc2FnZTogdGhpcy5zZXNzaW9uLm9uTmV3TWVzc2FnZS5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHN0cmVhbVByb3BlcnR5Q2hhbmdlZDogdGhpcy5zZXNzaW9uLm9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZDogdGhpcy5zZXNzaW9uLm9uQ29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkOiB0aGlzLnNlc3Npb24ub25OZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZENoYW5nZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBmaWx0ZXJFdmVudERpc3BhdGNoZWQ6IHRoaXMuc2Vzc2lvbi5vbkZpbHRlckV2ZW50RGlzcGF0Y2hlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGljZUNhbmRpZGF0ZTogdGhpcy5zZXNzaW9uLnJlY3ZJY2VDYW5kaWRhdGUuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBtZWRpYUVycm9yOiB0aGlzLnNlc3Npb24ub25NZWRpYUVycm9yLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgbWFzdGVyTm9kZUNyYXNoZWROb3RpZmljYXRpb246IHRoaXMub25NYXN0ZXJOb2RlQ3Jhc2hlZE5vdGlmaWNhdGlvbi5iaW5kKHRoaXMpLFxuICAgICAgICBmb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXI6IHRoaXMuc2Vzc2lvbi5vbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlci5iaW5kKHRoaXMuc2Vzc2lvbilcbiAgICAgIH1cbiAgICB9O1xuICAgIHRoaXMuanNvblJwY0NsaWVudCA9IG5ldyBScGNCdWlsZGVyLmNsaWVudHMuSnNvblJwY0NsaWVudChjb25maWcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIG9uTWFzdGVyTm9kZUNyYXNoZWROb3RpZmljYXRpb24ocmVzcG9uc2UpOiB2b2lkIHtcbiAgICBjb25zb2xlLmVycm9yKCdNYXN0ZXIgTm9kZSBoYXMgY3Jhc2hlZCcpO1xuICAgIHRoaXMubWFzdGVyTm9kZUhhc0NyYXNoZWQgPSB0cnVlO1xuICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKFwibm9kZUNyYXNoZWRcIik7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LmNsb3NlKDQxMDMsIFwiTWFzdGVyIE5vZGUgaGFzIGNyYXNoZWRcIik7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0V3NSZWFkeVN0YXRlKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuanNvblJwY0NsaWVudC5nZXRSZWFkeVN0YXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgY2xvc2VXcygpOiB2b2lkIHtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoNDEwMiwgXCJDb25uZWN0aW9uIGNsb3NlZCBieSBjbGllbnRcIik7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VuZFJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHBhcmFtczogYW55LCBjYWxsYmFjaz8pOiB2b2lkIHtcbiAgICBpZiAocGFyYW1zICYmIHBhcmFtcyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBjYWxsYmFjayA9IHBhcmFtcztcbiAgICAgIHBhcmFtcyA9IHt9O1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoJ1NlbmRpbmcgcmVxdWVzdDoge21ldGhvZDpcIicgKyBtZXRob2QgKyAnXCIsIHBhcmFtczogJyArIEpTT04uc3RyaW5naWZ5KHBhcmFtcykgKyAnfScpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5zZW5kKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0V3NVcmkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy53c1VyaTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBnZXRTZWNyZXQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZWNyZXQ7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0UmVjb3JkZXIoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVjb3JkZXI7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2VuZXJhdGVBdWRpb0RldmljZUVycm9yKGVycm9yLCBjb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyk6IE9wZW5WaWR1RXJyb3Ige1xuICAgIGlmIChlcnJvci5uYW1lID09PSAnRXJyb3InKSB7XG4gICAgICAvLyBTYWZhcmkgT3ZlckNvbnN0cmFpbmVkRXJyb3IgaGFzIGFzIG5hbWUgcHJvcGVydHkgJ0Vycm9yJyBpbnN0ZWFkIG9mICdPdmVyQ29uc3RyYWluZWRFcnJvcidcbiAgICAgIGVycm9yLm5hbWUgPSBlcnJvci5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIH1cbiAgICBsZXQgZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2U6IHN0cmluZztcbiAgICBzd2l0Y2ggKGVycm9yLm5hbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHJldHVybiBuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSk7XG4gICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKTtcbiAgICAgIGNhc2UgJ292ZXJjb25zdHJhaW5lZGVycm9yJzpcbiAgICAgICAgaWYgKGVycm9yLmNvbnN0cmFpbnQudG9Mb3dlckNhc2UoKSA9PT0gJ2RldmljZWlkJykge1xuICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLlBVQkxJU0hFUl9QUk9QRVJUSUVTX0VSUk9SO1xuICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgY2FzZSAnbm90cmVhZGFibGVlcnJvcic6XG4gICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BTFJFQURZX0lOX1VTRTtcbiAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgcmV0dXJuIChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9HRU5FUklDX0VSUk9SLCBlcnJvci50b1N0cmluZygpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWRkQWxyZWFkeVByb3ZpZGVkVHJhY2tzKG15Q29uc3RyYWludHM6IEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMsIG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgIGlmICghIW15Q29uc3RyYWludHMudmlkZW9UcmFjaykge1xuICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2sobXlDb25zdHJhaW50cy52aWRlb1RyYWNrKTtcbiAgICB9XG4gICAgaWYgKCEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrKSB7XG4gICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhteUNvbnN0cmFpbnRzLmF1ZGlvVHJhY2spO1xuICAgIH1cbiAgICByZXR1cm4gbWVkaWFTdHJlYW07XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHJvdGVjdGVkIGNvbmZpZ3VyZURldmljZUlkT3JTY3JlZW5zaGFyaW5nKG15Q29uc3RyYWludHM6IEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMsIHB1Ymxpc2hlclByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbnN0IGF1ZGlvU291cmNlID0gcHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZTtcbiAgICBjb25zdCB2aWRlb1NvdXJjZSA9IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2U7XG4gICAgaWYgKHR5cGVvZiBhdWRpb1NvdXJjZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLmF1ZGlvID0geyBkZXZpY2VJZDogeyBleGFjdDogYXVkaW9Tb3VyY2UgfSB9O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgIGlmICghdGhpcy5pc1NjcmVlblNoYXJlKHZpZGVvU291cmNlKSkge1xuICAgICAgICB0aGlzLnNldFZpZGVvU291cmNlKG15Q29uc3RyYWludHMsIHZpZGVvU291cmNlKTtcblxuICAgICAgfSBlbHNlIHtcblxuICAgICAgICAvLyBTY3JlZW4gc2hhcmluZ1xuXG4gICAgICAgIGlmICghdGhpcy5jaGVja1NjcmVlblNoYXJpbmdDYXBhYmlsaXRpZXMoKSkge1xuICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUsIEZpcmVmb3gsIE9wZXJhLCBTYWZhcmkgKD49MTMuMCksIEVkZ2UgKD49IDgwKSBvciBFbGVjdHJvbi4gRGV0ZWN0ZWQgY2xpZW50OiAnICsgcGxhdGZvcm0uZ2V0TmFtZSgpICsgJyAnICsgcGxhdGZvcm0uZ2V0VmVyc2lvbigpKTtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICBpZiAocGxhdGZvcm0uaXNFbGVjdHJvbigpKSB7XG4gICAgICAgICAgICBjb25zdCBwcmVmaXggPSBcInNjcmVlbjpcIjtcbiAgICAgICAgICAgIGNvbnN0IHZpZGVvU291cmNlU3RyaW5nOiBzdHJpbmcgPSB2aWRlb1NvdXJjZTtcbiAgICAgICAgICAgIGNvbnN0IGVsZWN0cm9uU2NyZWVuSWQgPSB2aWRlb1NvdXJjZVN0cmluZy5zdWJzdHIodmlkZW9Tb3VyY2VTdHJpbmcuaW5kZXhPZihwcmVmaXgpICsgcHJlZml4Lmxlbmd0aCk7XG4gICAgICAgICAgICAoPGFueT5teUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbykgPSB7XG4gICAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2VJZDogZWxlY3Ryb25TY3JlZW5JZFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzb2x2ZShteUNvbnN0cmFpbnRzKTtcblxuICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIGlmICghIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uICYmICEocGxhdGZvcm0uaXNGaXJlZm94QnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRmlyZWZveE1vYmlsZUJyb3dzZXIoKSkgJiYgIW5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddKSB7XG5cbiAgICAgICAgICAgICAgLy8gQ3VzdG9tIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lIChhbmQgT3BlcmEpIGFuZCBubyBzdXBwb3J0IGZvciBNZWRpYURldmljZXMuZ2V0RGlzcGxheU1lZGlhKClcblxuICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldFNjcmVlbkNvbnN0cmFpbnRzKChlcnJvciwgc2NyZWVuQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvciB8fCAhIXNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeSAmJiBzY3JlZW5Db25zdHJhaW50cy5tYW5kYXRvcnkuY2hyb21lTWVkaWFTb3VyY2UgPT09ICdzY3JlZW4nKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgZXJyb3IgPT09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVELCAnWW91IG11c3QgYWxsb3cgYWNjZXNzIHRvIG9uZSB3aW5kb3cgb2YgeW91ciBkZXNrdG9wJyk7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgc3RhdHVzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gJ25vdC1pbnN0YWxsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgKDxzdHJpbmc+dGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cztcbiAgICAgICAgICAgICAgICAgIHJlc29sdmUobXlDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10pIHtcbiAgICAgICAgICAgICAgICAvLyBnZXREaXNwbGF5TWVkaWEgc3VwcG9ydCAoQ2hyb21lID49IDcyLCBGaXJlZm94ID49IDY2LCBTYWZhcmkgPj0gMTMpXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShteUNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBmb3IgQ2hyb21lL09wZXJhLCBvciBpcyBGaXJlZm94IDwgNjZcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJlZm94U3RyaW5nID0gKHBsYXRmb3JtLmlzRmlyZWZveEJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkpID8gcHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIHNjcmVlblNoYXJpbmdBdXRvLmdldFNjcmVlbklkKGZpcmVmb3hTdHJpbmcsIChlcnJvciwgc291cmNlSWQsIHNjcmVlbkNvbnN0cmFpbnRzKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgPT09ICdub3QtaW5zdGFsbGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4dGVuc2lvblVybCA9ICEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gPyB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbi5zY3JlZW5TaGFyZUNocm9tZUV4dGVuc2lvbiA6XG4gICAgICAgICAgICAgICAgICAgICAgICAnaHR0cHM6Ly9jaHJvbWUuZ29vZ2xlLmNvbS93ZWJzdG9yZS9kZXRhaWwvb3BlbnZpZHUtc2NyZWVuc2hhcmluZy9sZmNnZmVwYWZub2JkbG9lY2NobmZhY2xpYmVuam9sZCc7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVELCBleHRlbnNpb25VcmwpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVycm9yID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQsICdZb3UgbXVzdCBlbmFibGUgdGhlIHNjcmVlbiBleHRlbnNpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsICdVbmtub3duIGVycm9yIHdoZW4gYWNjZXNzaW5nIHNjcmVlbiBzaGFyZScpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLnZpZGVvID0gc2NyZWVuQ29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUobXlDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHByb3RlY3RlZCBzZXRWaWRlb1NvdXJjZShteUNvbnN0cmFpbnRzOiBDdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCB2aWRlb1NvdXJjZTogc3RyaW5nKSB7XG4gICAgaWYgKCFteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbykge1xuICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSB7fTtcbiAgICB9XG4gICAgKDxNZWRpYVRyYWNrQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8pWydkZXZpY2VJZCddID0geyBleGFjdDogdmlkZW9Tb3VyY2UgfTtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgbG9nZ2VyLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBsb2dnZXIud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICghdGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncmVjb25uZWN0aW5nJywgW10pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBsb2dnZXIud2FybignV2Vic29ja2V0IHJlY29ubmVjdGVkJyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5jb25uZWN0aW9uKSB7XG4gICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoJ2Nvbm5lY3QnLCB7IHNlc3Npb25JZDogdGhpcy5zZXNzaW9uLmNvbm5lY3Rpb24ucnBjU2Vzc2lvbklkIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNNYXN0ZXJOb2RlQ3Jhc2hlZCgpKSB7XG4gICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdNYXN0ZXIgTm9kZSBoYXMgY3Jhc2hlZCEnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdXZWJzb2NrZXQgd2FzIGFibGUgdG8gcmVjb25uZWN0IHRvIE9wZW5WaWR1IFNlcnZlciwgYnV0IHlvdXIgQ29ubmVjdGlvbiB3YXMgYWxyZWFkeSBkZXN0cm95ZWQgZHVlIHRvIHRpbWVvdXQuIFlvdSBhcmUgbm8gbG9uZ2VyIGEgcGFydGljaXBhbnQgb2YgdGhlIFNlc3Npb24gYW5kIHlvdXIgbWVkaWEgc3RyZWFtcyBoYXZlIGJlZW4gZGVzdHJveWVkJyk7XG4gICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKFwibmV0d29ya0Rpc2Nvbm5lY3RcIik7XG4gICAgICAgICAgICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSg0MTAxLCBcIlJlY29ubmVjdGlvbiBmYXVsdFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5qc29uUnBjQ2xpZW50LnJlc2V0UGluZygpO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIud2FybignVGhlcmUgd2FzIG5vIHByZXZpb3VzIGNvbm5lY3Rpb24gd2hlbiBydW5uaW5nIHJlY29ubmVjdGlvbiBjYWxsYmFjaycpO1xuICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudFxuICAgICAgICBjb25zdCBzZXNzaW9uRGlzY29ubmVjdEV2ZW50ID0gbmV3IFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCh0aGlzLnNlc3Npb24sICduZXR3b3JrRGlzY29ubmVjdCcpO1xuICAgICAgICB0aGlzLnNlc3Npb24uZWUuZW1pdEV2ZW50KCdzZXNzaW9uRGlzY29ubmVjdGVkJywgW3Nlc3Npb25EaXNjb25uZWN0RXZlbnRdKTtcbiAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc01hc3Rlck5vZGVDcmFzaGVkKCkge1xuICAgIHJldHVybiB0aGlzLm1hc3Rlck5vZGVIYXNDcmFzaGVkO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1Jvb21BdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuc2Vzc2lvbiBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIud2FybignU2Vzc2lvbiBpbnN0YW5jZSBub3QgZm91bmQnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzU2NyZWVuU2hhcmUodmlkZW9Tb3VyY2U6IHN0cmluZykge1xuICAgIHJldHVybiB2aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbicgfHxcbiAgICAgIHZpZGVvU291cmNlID09PSAnd2luZG93JyB8fFxuICAgICAgKHBsYXRmb3JtLmlzRWxlY3Ryb24oKSAmJiB2aWRlb1NvdXJjZS5zdGFydHNXaXRoKCdzY3JlZW46JykpXG4gIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4vRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9FbGVtZW50RXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9WaWRlb0VsZW1lbnRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IFBsYXRmb3JtVXRpbHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1V0aWxzL1BsYXRmb3JtJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG4vKipcbiAqIFBhY2tzIGxvY2FsIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBjYW4gcHVibGlzaCBpdCB0byBhIHNlc3Npb24uIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gKlxuICogIyMjIEF2YWlsYWJsZSBldmVudCBsaXN0ZW5lcnMgKGFuZCBldmVudHMgZGlzcGF0Y2hlZClcbiAqXG4gKiAtIGFjY2Vzc0FsbG93ZWRcbiAqIC0gYWNjZXNzRGVuaWVkXG4gKiAtIGFjY2Vzc0RpYWxvZ09wZW5lZFxuICogLSBhY2Nlc3NEaWFsb2dDbG9zZWRcbiAqIC0gc3RyZWFtQ3JlYXRlZCAoW1tTdHJlYW1FdmVudF1dKVxuICogLSBzdHJlYW1EZXN0cm95ZWQgKFtbU3RyZWFtRXZlbnRdXSlcbiAqIC0gX0FsbCBldmVudHMgaW5oZXJpdGVkIGZyb20gW1tTdHJlYW1NYW5hZ2VyXV0gY2xhc3NfXG4gKi9cbmV4cG9ydCBjbGFzcyBQdWJsaXNoZXIgZXh0ZW5kcyBTdHJlYW1NYW5hZ2VyIHtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFB1Ymxpc2hlciBoYXMgYmVlbiBncmFudGVkIGFjY2VzcyB0byB0aGUgcmVxdWVzdGVkIGlucHV0IGRldmljZXMgb3Igbm90XG4gICAgICovXG4gICAgYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB5b3UgaGF2ZSBjYWxsZWQgW1tQdWJsaXNoZXIuc3Vic2NyaWJlVG9SZW1vdGVdXSB3aXRoIHZhbHVlIGB0cnVlYCBvciBgZmFsc2VgICgqZmFsc2UqIGJ5IGRlZmF1bHQpXG4gICAgICovXG4gICAgaXNTdWJzY3JpYmVkVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSB0byB3aGljaCB0aGUgUHVibGlzaGVyIGJlbG9uZ3NcbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uOyAvLyBJbml0aWFsaXplZCBieSBTZXNzaW9uLnB1Ymxpc2goUHVibGlzaGVyKVxuXG4gICAgcHJpdmF0ZSBhY2Nlc3NEZW5pZWQgPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcztcbiAgICBwcml2YXRlIHBlcm1pc3Npb25EaWFsb2dUaW1lb3V0OiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3BlbnZpZHU6IE9wZW5WaWR1O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB2aWRlb1JlZmVyZW5jZTogSFRNTFZpZGVvRWxlbWVudDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbDogTm9kZUpTLlRpbWVyO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdFbDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcihuZXcgU3RyZWFtKCghIW9wZW52aWR1LnNlc3Npb24pID8gb3BlbnZpZHUuc2Vzc2lvbiA6IG5ldyBTZXNzaW9uKG9wZW52aWR1KSwgeyBwdWJsaXNoZXJQcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBtZWRpYUNvbnN0cmFpbnRzOiB7fSB9KSwgdGFyZ0VsKTtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcblxuICAgICAgICB0aGlzLnN0cmVhbS5lZS5vbignbG9jYWwtc3RyZWFtLWRlc3Ryb3llZCcsIChyZWFzb246IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgdGhpcywgJ3N0cmVhbURlc3Ryb3llZCcsIHRoaXMuc3RyZWFtLCByZWFzb24pO1xuICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqID4gX09ubHkgaWYgYFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpYCBoYXMgYmVlbiBjYWxsZWQgZm9yIHRoaXMgUHVibGlzaGVyX1xuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcImF1ZGlvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaEF1ZGlvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoQXVkaW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgY29uc3QgYWZmZWN0ZWRNZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0gPSB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSA/IHRoaXMuc3RyZWFtLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlISA6IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICBhZmZlY3RlZE1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbiAmJiAhIXRoaXMuc3RyZWFtLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHk6ICdhdWRpb0FjdGl2ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoQXVkaW8nXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICdhdWRpb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoQXVkaW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YSh0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgYXVkaW8gc3RyZWFtJyk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2ggb3IgdW5wdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqID4gX09ubHkgaWYgYFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpYCBoYXMgYmVlbiBjYWxsZWQgZm9yIHRoaXMgUHVibGlzaGVyX1xuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJ2aWRlb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHB1Ymxpc2ggdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnB1Ymxpc2ggaXRcbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW8odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgY29uc3QgYWZmZWN0ZWRNZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0gPSB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSA/IHRoaXMuc3RyZWFtLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlISA6IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICBhZmZlY3RlZE1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbiAmJiAhIXRoaXMuc3RyZWFtLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyxcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHk6ICd2aWRlb0FjdGl2ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoVmlkZW8nXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIHZhbHVlLCAhdmFsdWUsICdwdWJsaXNoVmlkZW8nKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuc3RyZWFtLCAndmlkZW9BY3RpdmUnLCB2YWx1ZSwgIXZhbHVlLCAncHVibGlzaFZpZGVvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YSh0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCInUHVibGlzaGVyJyBoYXMgXCIgKyAodmFsdWUgPyAncHVibGlzaGVkJyA6ICd1bnB1Ymxpc2hlZCcpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIENhbGwgdGhpcyBtZXRob2QgYmVmb3JlIFtbU2Vzc2lvbi5wdWJsaXNoXV0gaWYgeW91IHByZWZlciB0byBzdWJzY3JpYmUgdG8geW91ciBQdWJsaXNoZXIncyByZW1vdGUgc3RyZWFtIGluc3RlYWQgb2YgdXNpbmcgdGhlIGxvY2FsIHN0cmVhbSwgYXMgYW55IG90aGVyIHVzZXIgd291bGQgZG8uXG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9SZW1vdGUodmFsdWU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlICE9PSB1bmRlZmluZWQpID8gdmFsdWUgOiB0cnVlO1xuICAgICAgICB0aGlzLmlzU3Vic2NyaWJlZFRvUmVtb3RlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc3RyZWFtLnN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWUpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uXV1cbiAgICAgKi9cbiAgICBvbih0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBzdXBlci5vbih0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdyZW1vdGVWaWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgJiYgdGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0FsbG93ZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NBbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0FsbG93ZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NEZW5pZWQnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5hY2Nlc3NEZW5pZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGVuaWVkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VlIFtbRXZlbnREaXNwYXRjaGVyLm9uY2VdXVxuICAgICAqL1xuICAgIG9uY2UodHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogUHVibGlzaGVyIHtcbiAgICAgICAgc3VwZXIub25jZSh0eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uY2UoJ3N0cmVhbS1jcmVhdGVkLWJ5LXB1Ymxpc2hlcicsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3JlbW90ZVZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSAmJiB0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3JlbW90ZVZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICdyZW1vdGVWaWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzQWxsb3dlZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0FsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgdGhlIGN1cnJlbnQgdmlkZW8gb3IgYXVkaW8gdHJhY2sgd2l0aCBhIGRpZmZlcmVudCBvbmUuIFRoaXMgYWxsb3dzIHlvdSB0byByZXBsYWNlIGFuIG9uZ29pbmcgdHJhY2sgd2l0aCBhIGRpZmZlcmVudCBvbmVcbiAgICAgKiB3aXRob3V0IGhhdmluZyB0byByZW5lZ290aWF0ZSB0aGUgd2hvbGUgV2ViUlRDIGNvbm5lY3Rpb24gKHRoYXQgaXMsIGluaXRpYWxpemluZyBhIG5ldyBQdWJsaXNoZXIsIHVucHVibGlzaGluZyB0aGUgcHJldmlvdXMgb25lXG4gICAgICogYW5kIHB1Ymxpc2hpbmcgdGhlIG5ldyBvbmUpLlxuICAgICAqXG4gICAgICogWW91IGNhbiBnZXQgdGhpcyBuZXcgTWVkaWFTdHJlYW1UcmFjayBieSB1c2luZyB0aGUgbmF0aXZlIFdlYiBBUEkgb3Igc2ltcGx5IHdpdGggW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXSBtZXRob2QuXG4gICAgICpcbiAgICAgKiAqKldBUk5JTkc6IHRoaXMgbWV0aG9kIGhhcyBiZWVuIHByb3ZlbiB0byB3b3JrIGluIHRoZSBtYWpvcml0eSBvZiBjYXNlcywgYnV0IHRoZXJlIG1heSBiZSBzb21lIGNvbWJpbmF0aW9ucyBvZiBwdWJsaXNoZWQvcmVwbGFjZWQgdHJhY2tzIHRoYXQgbWF5IGJlIGluY29tcGF0aWJsZVxuICAgICAqIGJldHdlZW4gdGhlbSBhbmQgYnJlYWsgdGhlIGNvbm5lY3Rpb24gaW4gT3BlblZpZHUgU2VydmVyLiBBIGNvbXBsZXRlIHJlbmVnb3RpYXRpb24gbWF5IGJlIHRoZSBvbmx5IHNvbHV0aW9uIGluIHRoaXMgY2FzZS5cbiAgICAgKiBWaXNpdCBbUlRDUnRwU2VuZGVyLnJlcGxhY2VUcmFja10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JUQ1J0cFNlbmRlci9yZXBsYWNlVHJhY2spIGRvY3VtZW50YXRpb24gZm9yIGZ1cnRoZXIgZGV0YWlscy4qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHRyYWNrIFRoZSBbTWVkaWFTdHJlYW1UcmFja10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL01lZGlhU3RyZWFtVHJhY2spIG9iamVjdCB0byByZXBsYWNlIHRoZSBjdXJyZW50IG9uZS5cbiAgICAgKiBJZiBpdCBpcyBhbiBhdWRpbyB0cmFjaywgdGhlIGN1cnJlbnQgYXVkaW8gdHJhY2sgd2lsbCBiZSB0aGUgcmVwbGFjZWQgb25lLiBJZiBpdCBpcyBhIHZpZGVvIHRyYWNrLCB0aGUgY3VycmVudCB2aWRlbyB0cmFjayB3aWxsIGJlIHRoZSByZXBsYWNlZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHRyYWNrIHdhcyBzdWNjZXNzZnVsbHkgcmVwbGFjZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGluIG90aGVyIGNhc2VcbiAgICAgKi9cbiAgICBhc3luYyByZXBsYWNlVHJhY2sodHJhY2s6IE1lZGlhU3RyZWFtVHJhY2spOiBQcm9taXNlPHZvaWQ+IHtcblxuICAgICAgICBjb25zdCByZXBsYWNlVHJhY2tJbk1lZGlhU3RyZWFtID0gKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0gPSB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSA/IHRoaXMuc3RyZWFtLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlISA6IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgbGV0IHJlbW92ZWRUcmFjazogTWVkaWFTdHJlYW1UcmFjaztcbiAgICAgICAgICAgICAgICBpZiAodHJhY2sua2luZCA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVkVHJhY2sgPSBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZWRUcmFjayA9IG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKHJlbW92ZWRUcmFjayk7XG4gICAgICAgICAgICAgICAgcmVtb3ZlZFRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayh0cmFjayk7XG4gICAgICAgICAgICAgICAgaWYgKHRyYWNrLmtpbmQgPT09ICd2aWRlbycgJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmROZXdWaWRlb0RpbWVuc2lvbnNJZlJlcXVpcmVkKHRoaXMsICd0cmFja1JlcGxhY2VkJywgNTAsIDMwKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLnNlbmRWaWRlb0RhdGEodGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlciwgNSwgdHJ1ZSwgNSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVwbGFjZVRyYWNrSW5SdGNSdHBTZW5kZXIgPSAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRlcnM6IFJUQ1J0cFNlbmRlcltdID0gdGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5nZXRTZW5kZXJzKCk7XG4gICAgICAgICAgICAgICAgbGV0IHNlbmRlcjogUlRDUnRwU2VuZGVyIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGlmICh0cmFjay5raW5kID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbmRlciA9IHNlbmRlcnMuZmluZChzID0+ICEhcy50cmFjayAmJiBzLnRyYWNrLmtpbmQgPT09ICd2aWRlbycpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNlbmRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignVGhlcmVcXCdzIG5vIHJlcGxhY2VhYmxlIHRyYWNrIGZvciB0aGF0IGtpbmQgb2YgTWVkaWFTdHJlYW1UcmFjayBpbiB0aGlzIFB1Ymxpc2hlciBvYmplY3QnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VuZGVyID0gc2VuZGVycy5maW5kKHMgPT4gISFzLnRyYWNrICYmIHMudHJhY2sua2luZCA9PT0gJ2F1ZGlvJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2VuZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdUaGVyZVxcJ3Mgbm8gcmVwbGFjZWFibGUgdHJhY2sgZm9yIHRoYXQga2luZCBvZiBNZWRpYVN0cmVhbVRyYWNrIGluIHRoaXMgUHVibGlzaGVyIG9iamVjdCcpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1Vua25vd24gdHJhY2sga2luZCAnICsgdHJhY2sua2luZCkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIChzZW5kZXIgYXMgUlRDUnRwU2VuZGVyKS5yZXBsYWNlVHJhY2sodHJhY2spLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgZmllbGQgXCJlbmFibGVkXCIgb2YgdGhlIG5ldyB0cmFjayB0byB0aGUgcHJldmlvdXMgdmFsdWVcbiAgICAgICAgY29uc3QgdHJhY2tPcmlnaW5hbEVuYWJsZWRWYWx1ZTogYm9vbGVhbiA9IHRyYWNrLmVuYWJsZWQ7XG4gICAgICAgIGlmICh0cmFjay5raW5kID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdGhpcy5zdHJlYW0udmlkZW9BY3RpdmU7XG4gICAgICAgIH0gZWxzZSBpZiAodHJhY2sua2luZCA9PT0gJ2F1ZGlvJykge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHRoaXMuc3RyZWFtLmF1ZGlvQWN0aXZlO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgaWYgdGhlIFB1Ymxpc2hlciBoYXMgYmVlbiBwdWJsaXNoZWQgaXMgbmVjZXNzYXJ5IHRvIGNhbGwgbmF0aXZlIFdlYiBBUEkgUlRDUnRwU2VuZGVyLnJlcGxhY2VUcmFja1xuICAgICAgICAgICAgICAgIC8vIElmIGl0IGhhcyBub3QgYmVlbiBwdWJsaXNoZWQgeWV0LCByZXBsYWNpbmcgaXQgb24gdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpcyBlbm91Z2hcbiAgICAgICAgICAgICAgICBhd2FpdCByZXBsYWNlVHJhY2tJblJ0Y1J0cFNlbmRlcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCByZXBsYWNlVHJhY2tJbk1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFB1Ymxpc2hlciBub3QgcHVibGlzaGVkLiBTaW1wbHkgcmVwbGFjZSB0aGUgdHJhY2sgb24gdGhlIGxvY2FsIE1lZGlhU3RyZWFtXG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlcGxhY2VUcmFja0luTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB0cmFja09yaWdpbmFsRW5hYmxlZFZhbHVlO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxldCBjb25zdHJhaW50czogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHt9O1xuICAgICAgICAgICAgbGV0IGNvbnN0cmFpbnRzQXV4OiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge307XG4gICAgICAgICAgICBjb25zdCB0aW1lRm9yRGlhbG9nRXZlbnQgPSAxNTAwO1xuICAgICAgICAgICAgbGV0IHN0YXJ0VGltZTtcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JDYWxsYmFjayA9IChvcGVuVmlkdUVycm9yOiBPcGVuVmlkdUVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NEZW5pZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgUHVibGlzaGVyIGluaXRpYWxpemF0aW9uIGZhaWxlZC4gJHtvcGVuVmlkdUVycm9yLm5hbWV9OiAke29wZW5WaWR1RXJyb3IubWVzc2FnZX1gKVxuICAgICAgICAgICAgICAgIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0udmlkZW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUmVmZXJlbmNlKG1lZGlhU3RyZWFtKTtcblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgc3Vic2NyaWJlZCB0byBvdXIgcmVtb3RlIHdlIGRvbid0IHN0aWxsIHNldCB0aGUgTWVkaWFTdHJlYW0gb2JqZWN0IGluIHRoZSB2aWRlbyBlbGVtZW50cyB0b1xuICAgICAgICAgICAgICAgICAgICAvLyBhdm9pZCBlYXJseSAnc3RyZWFtUGxheWluZycgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udXBkYXRlTWVkaWFTdHJlYW1JblZpZGVvcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRWaWRlbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhhcyB2aWRlbyB0cmFja1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFZpZGVvRGltZW5zaW9ucyhtZWRpYVN0cmVhbSkudGhlbihkaW1lbnNpb25zID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogZGltZW5zaW9ucy53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGRpbWVuc2lvbnMuaGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgaW50ZXJ2YWwgdG8gbGlzdGVuIGZvciBzY3JlZW4gcmVzaXplIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2V0dGluZ3M6IE1lZGlhVHJhY2tTZXR0aW5ncyA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3V2lkdGggPSBzZXR0aW5ncy53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3SGVpZ2h0ID0gc2V0dGluZ3MuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5ld1dpZHRoICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGggfHwgbmV3SGVpZ2h0ICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kVmlkZW9EaW1lbnNpb25zQ2hhbmdlZEV2ZW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3NjcmVlblJlc2l6ZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMuaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1dpZHRoIHx8IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0IHx8IDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCA2NTApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSBhdWRpbyB0cmFjayAobm8gdmlkZW9EaW1lbnNpb25zKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgW10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBnZXRNZWRpYVN1Y2Nlc3MgPSAobWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtLCBkZWZpbmVkQXVkaW9Db25zdHJhaW50KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpICYmIHRoaXMuc3RyZWFtLmlzU2VuZEF1ZGlvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiBnZXR0aW5nIGRlc2t0b3AgYXMgdXNlciBtZWRpYSBhdWRpbyBjb25zdHJhaW50IG11c3QgYmUgZmFsc2UuIE5vdyB3ZSBjYW4gYXNrIGZvciBpdCBpZiByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LnZpZGVvID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKGF1ZGlvT25seVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayh0aGlzLm9wZW52aWR1LmdlbmVyYXRlQXVkaW9EZXZpY2VFcnJvcihlcnJvciwgY29uc3RyYWludHMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGdldE1lZGlhRXJyb3IgPSBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBnZXRNZWRpYUVycm9yOiAke2Vycm9yLnRvU3RyaW5nKCl9YCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWUsIHRpbWVGb3JEaWFsb2dFdmVudCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yLm5hbWUgPT09ICdFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIE92ZXJDb25zdHJhaW5lZEVycm9yIGhhcyBhcyBuYW1lIHByb3BlcnR5ICdFcnJvcicgaW5zdGVhZCBvZiAnT3ZlckNvbnN0cmFpbmVkRXJyb3InXG4gICAgICAgICAgICAgICAgICAgIGVycm9yLm5hbWUgPSBlcnJvci5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbm90Zm91bmRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuSU5QVVRfVklERU9fREVWSUNFX05PVF9GT1VORDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGFsbG93ZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSB0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSA/IE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCA6IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BQ0NFU1NfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiBjb25zdHJhaW50cy52aWRlb1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX0FVRElPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy5hdWRpbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSB3aXRoIGRldmljZUlkICdcIiArICg8Q29uc3RyYWluRE9NU3RyaW5nUGFyYW1ldGVycz4oPE1lZGlhVHJhY2tDb25zdHJhaW50cz5jb25zdHJhaW50cy52aWRlbykuZGV2aWNlSWQhISkuZXhhY3QgKyBcIicgbm90IGZvdW5kXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiVmlkZW8gaW5wdXQgZGV2aWNlIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgdmFsdWUgcGFzc2VkIGZvciBjb25zdHJhaW50ICdcIiArIGVycm9yLmNvbnN0cmFpbnQgKyBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYWJvcnRlcnJvcic6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdHJlYWRhYmxlZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FMUkVBRFlfSU5fVVNFO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gZXJyb3IudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuR0VORVJJQ19FUlJPUjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHRoaXMucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAudGhlbihteUNvbnN0cmFpbnRzID0+IHtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoISFteUNvbnN0cmFpbnRzLnZpZGVvVHJhY2sgJiYgISFteUNvbnN0cmFpbnRzLmF1ZGlvVHJhY2sgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LnZpZGVvID09PSBmYWxzZSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgISFteUNvbnN0cmFpbnRzLnZpZGVvVHJhY2sgJiYgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cz8uYXVkaW8gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBObyBuZWVkIHRvIGNhbGwgZ2V0VXNlck1lZGlhIGF0IGFsbC4gTWVkaWFTdHJlYW1UcmFja3MgYWxyZWFkeSBwcm92aWRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKHRoaXMub3BlbnZpZHUuYWRkQWxyZWFkeVByb3ZpZGVkVHJhY2tzKG15Q29uc3RyYWludHMsIG5ldyBNZWRpYVN0cmVhbSgpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXR1cm4gYXMgd2UgZG8gbm90IG5lZWQgdG8gcHJvY2VzcyBmdXJ0aGVyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50cyA9IG15Q29uc3RyYWludHMuY29uc3RyYWludHM7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0Ym91bmRTdHJlYW1PcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czogY29uc3RyYWludHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXJQcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2V0T3V0Ym91bmRTdHJlYW1PcHRpb25zKG91dGJvdW5kU3RyZWFtT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmaW5lZEF1ZGlvQ29uc3RyYWludCA9ICgoY29uc3RyYWludHMuYXVkaW8gPT09IHVuZGVmaW5lZCkgPyB0cnVlIDogY29uc3RyYWludHMuYXVkaW8pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC5hdWRpbyA9IHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpID8gZmFsc2UgOiBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzWydnZXREaXNwbGF5TWVkaWEnXSAmJiAhcGxhdGZvcm0uaXNFbGVjdHJvbigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzWydnZXREaXNwbGF5TWVkaWEnXSh7IHZpZGVvOiB0cnVlIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzLCBtZWRpYVN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1lZGlhU3VjY2VzcyhtZWRpYVN0cmVhbSwgZGVmaW5lZEF1ZGlvQ29uc3RyYWludCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNZWRpYUVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5hZGRBbHJlYWR5UHJvdmlkZWRUcmFja3MobXlDb25zdHJhaW50cywgbWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNZWRpYVN1Y2Nlc3MobWVkaWFTdHJlYW0sIGRlZmluZWRBdWRpb0NvbnN0cmFpbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWVkaWFFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqIFxuICAgICAqIFRvIG9idGFpbiB0aGUgdmlkZW9EaW1lbnNpb25zIHdlIHdhaXQgZm9yIHRoZSB2aWRlbyByZWZlcmVuY2UgdG8gaGF2ZSBlbm91Z2ggbWV0YWRhdGFcbiAgICAgKiBhbmQgdGhlbiB0cnkgdG8gdXNlIE1lZGlhU3RyZWFtVHJhY2suZ2V0U2V0dGluZ3NNZXRob2QoKS4gSWYgbm90IGF2YWlsYWJsZSwgdGhlbiB3ZVxuICAgICAqIHVzZSB0aGUgSFRNTFZpZGVvRWxlbWVudCBwcm9wZXJ0aWVzIHZpZGVvV2lkdGggYW5kIHZpZGVvSGVpZ2h0XG4gICAgICovXG4gICAgZ2V0VmlkZW9EaW1lbnNpb25zKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IFByb21pc2U8eyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIC8vIElvbmljIGlPUyBhbmQgU2FmYXJpIGlPUyBzdXBwb3NlZGx5IHJlcXVpcmUgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYWN0dWFsbHkgZXhpc3QgaW5zaWRlIHRoZSBET01cbiAgICAgICAgICAgIGNvbnN0IHJlcXVpcmVzRG9tSW5zZXJ0aW9uOiBib29sZWFuID0gcGxhdGZvcm0uaXNJb25pY0lvcygpIHx8IHBsYXRmb3JtLmlzSU9TV2l0aFNhZmFyaSgpO1xuXG4gICAgICAgICAgICBsZXQgbG9hZGVkbWV0YWRhdGFMaXN0ZW5lcjtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVEaW1lbnNpb25zID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB3aWR0aDogbnVtYmVyO1xuICAgICAgICAgICAgICAgIGxldCBoZWlnaHQ6IG51bWJlcjtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IHNldHRpbmdzLndpZHRoIHx8IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9XaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gc2V0dGluZ3MuaGVpZ2h0IHx8IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ01lZGlhU3RyZWFtVHJhY2sgZG9lcyBub3QgaGF2ZSBnZXRTZXR0aW5ncyBtZXRob2Qgb24gJyArIHBsYXRmb3JtLmdldERlc2NyaXB0aW9uKCkpO1xuICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9XaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy52aWRlb1JlZmVyZW5jZS52aWRlb0hlaWdodDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobG9hZGVkbWV0YWRhdGFMaXN0ZW5lciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2UucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9hZGVkbWV0YWRhdGEnLCBsb2FkZWRtZXRhZGF0YUxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlcXVpcmVzRG9tSW5zZXJ0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGhpcy52aWRlb1JlZmVyZW5jZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh7IHdpZHRoLCBoZWlnaHQgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvUmVmZXJlbmNlLnJlYWR5U3RhdGUgPj0gMSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB2aWRlbyBhbHJlYWR5IGhhcyBtZXRhZGF0YSBhdmFpbGFibGVcbiAgICAgICAgICAgICAgICAvLyBObyBuZWVkIG9mIGxvYWRlZG1ldGFkYXRhIGV2ZW50XG4gICAgICAgICAgICAgICAgcmVzb2x2ZURpbWVuc2lvbnMoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHZpZGVvIGRvZXMgbm90IGhhdmUgbWV0YWRhdGEgYXZhaWxhYmxlIHlldFxuICAgICAgICAgICAgICAgIC8vIE11c3QgbGlzdGVuIHRvIGxvYWRlZG1ldGFkYXRhIGV2ZW50XG4gICAgICAgICAgICAgICAgbG9hZGVkbWV0YWRhdGFMaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISF0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVEaW1lbnNpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgNDApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZURpbWVuc2lvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5hZGRFdmVudExpc3RlbmVyKCdsb2FkZWRtZXRhZGF0YScsIGxvYWRlZG1ldGFkYXRhTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlc0RvbUluc2VydGlvbikge1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMudmlkZW9SZWZlcmVuY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlZXN0YWJsaXNoU3RyZWFtUGxheWluZ0V2ZW50KCkge1xuICAgICAgICBpZiAodGhpcy5lZS5nZXRMaXN0ZW5lcnMoJ3N0cmVhbVBsYXlpbmcnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFBsYXlFdmVudFRvRmlyc3RWaWRlbygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1JlZmVyZW5jZShtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG4gICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2Uuc2V0QXR0cmlidXRlKCdtdXRlZCcsICd0cnVlJyk7XG4gICAgICAgIHRoaXMudmlkZW9SZWZlcmVuY2Uuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgaWYgKHBsYXRmb3JtLmlzU2FmYXJpQnJvd3NlcigpIHx8IChwbGF0Zm9ybS5pc0lQaG9uZU9ySVBhZCgpICYmIChwbGF0Zm9ybS5pc0Nocm9tZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNPcGVyYU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkpKSkge1xuICAgICAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJ3RydWUnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0cmVhbS5zZXRNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG4gICAgICAgIGlmICghIXRoaXMuZmlyc3RWaWRlb0VsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlVmlkZW9FbGVtZW50KHRoaXMuZmlyc3RWaWRlb0VsZW1lbnQudGFyZ2V0RWxlbWVudCwgPFZpZGVvSW5zZXJ0TW9kZT50aGlzLnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcbiAgICB9XG5cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuL0ZpbHRlcic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4vRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvUmVtb3RlQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgTG9jYWxDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0xvY2FsQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBDb25uZWN0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQnO1xuaW1wb3J0IHsgRXhjZXB0aW9uRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FeGNlcHRpb25FdmVudCc7XG5pbXBvcnQgeyBGaWx0ZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0ZpbHRlckV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFJlY29yZGluZ0V2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUmVjb3JkaW5nRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFNpZ25hbEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0Nvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWRFdmVudCc7XG5pbXBvcnQgeyBOZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUVycm9yLCBPcGVuVmlkdUVycm9yTmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvT3BlblZpZHVFcnJvcic7XG5pbXBvcnQgeyBWaWRlb0luc2VydE1vZGUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1ZpZGVvSW5zZXJ0TW9kZSc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IFBsYXRmb3JtVXRpbHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1V0aWxzL1BsYXRmb3JtJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSB2aWRlbyBjYWxsLiBJdCBjYW4gYWxzbyBiZSBzZWVuIGFzIGEgdmlkZW9jb25mZXJlbmNlIHJvb20gd2hlcmUgbXVsdGlwbGUgdXNlcnMgY2FuIGNvbm5lY3QuXG4gKiBQYXJ0aWNpcGFudHMgd2hvIHB1Ymxpc2ggdGhlaXIgdmlkZW9zIHRvIGEgc2Vzc2lvbiBjYW4gYmUgc2VlbiBieSB0aGUgcmVzdCBvZiB1c2VycyBjb25uZWN0ZWQgdG8gdGhhdCBzcGVjaWZpYyBzZXNzaW9uLlxuICogSW5pdGlhbGl6ZWQgd2l0aCBbW09wZW5WaWR1LmluaXRTZXNzaW9uXV0gbWV0aG9kLlxuICpcbiAqICMjIyBBdmFpbGFibGUgZXZlbnQgbGlzdGVuZXJzIChhbmQgZXZlbnRzIGRpc3BhdGNoZWQpXG4gKlxuICogLSBjb25uZWN0aW9uQ3JlYXRlZCAoW1tDb25uZWN0aW9uRXZlbnRdXSlcbiAqIC0gY29ubmVjdGlvbkRlc3Ryb3llZCAoW1tDb25uZWN0aW9uRXZlbnRdXSlcbiAqIC0gY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZCAoW1tDb25uZWN0aW9uUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSkgPGEgaHJlZj1cImh0dHBzOi8vZG9jcy5vcGVudmlkdS5pby9lbi9zdGFibGUvb3BlbnZpZHUtcHJvL1wiIHRhcmdldD1cIl9ibGFua1wiIHN0eWxlPVwiZGlzcGxheTogaW5saW5lLWJsb2NrOyBiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMCwgMTM2LCAxNzApOyBjb2xvcjogd2hpdGU7IGZvbnQtd2VpZ2h0OiBib2xkOyBwYWRkaW5nOiAwcHggNXB4OyBtYXJnaW4tcmlnaHQ6IDVweDsgYm9yZGVyLXJhZGl1czogM3B4OyBmb250LXNpemU6IDEzcHg7IGxpbmUtaGVpZ2h0OjIxcHg7IGZvbnQtZmFtaWx5OiBNb250c2VycmF0LCBzYW5zLXNlcmlmXCI+UFJPPC9hPlxuICogLSBzZXNzaW9uRGlzY29ubmVjdGVkIChbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dKVxuICogLSBzdHJlYW1DcmVhdGVkIChbW1N0cmVhbUV2ZW50XV0pXG4gKiAtIHN0cmVhbURlc3Ryb3llZCAoW1tTdHJlYW1FdmVudF1dKVxuICogLSBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQgKFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSlcbiAqIC0gcHVibGlzaGVyU3RhcnRTcGVha2luZyAoW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0pXG4gKiAtIHB1Ymxpc2hlclN0b3BTcGVha2luZyAoW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0pXG4gKiAtIHNpZ25hbCAoW1tTaWduYWxFdmVudF1dKVxuICogLSByZWNvcmRpbmdTdGFydGVkIChbW1JlY29yZGluZ0V2ZW50XV0pXG4gKiAtIHJlY29yZGluZ1N0b3BwZWQgKFtbUmVjb3JkaW5nRXZlbnRdXSlcbiAqIC0gbmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWQgKFtbTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudF1dKVxuICogLSByZWNvbm5lY3RpbmdcbiAqIC0gcmVjb25uZWN0ZWRcbiAqIC0gZXhjZXB0aW9uIChbW0V4Y2VwdGlvbkV2ZW50XV0pXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIGV4dGVuZHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIExvY2FsIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24uIFRoaXMgb2JqZWN0IGlzIGRlZmluZWQgb25seSBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCwgYW5kIGNhbiBiZSByZXRyaWV2ZWQgc3Vic2NyaWJpbmcgdG8gYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgU2Vzc2lvblxuICAgICAqL1xuICAgIHNlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdGlvbiBvZiBhbGwgU3RyZWFtTWFuYWdlcnMgb2YgdGhpcyBTZXNzaW9uIChbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSlcbiAgICAgKi9cbiAgICBzdHJlYW1NYW5hZ2VyczogU3RyZWFtTWFuYWdlcltdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBPYmplY3QgZGVmaW5pbmcgdGhlIG1ldGhvZHMgdGhhdCB0aGUgY2xpZW50IGlzIGFibGUgdG8gY2FsbC4gVGhlc2UgYXJlIGRlZmluZWQgYnkgdGhlIFtbQ29ubmVjdGlvbi5yb2xlXV0uXG4gICAgICogVGhpcyBvYmplY3QgaXMgb25seSBkZWZpbmVkIGFmdGVyIFtbU2Vzc2lvbi5jb25uZWN0XV0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHJlc29sdmVkXG4gICAgICovXG4gICAgY2FwYWJpbGl0aWVzOiBDYXBhYmlsaXRpZXM7XG5cbiAgICAvLyBUaGlzIG1hcCBpcyBvbmx5IHVzZWQgdG8gYXZvaWQgcmFjZSBjb25kaXRpb24gYmV0d2VlbiAnam9pblJvb20nIHJlc3BvbnNlIGFuZCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcgbm90aWZpY2F0aW9uXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVN0cmVhbXNDcmVhdGVkOiBNYXA8c3RyaW5nLCBib29sZWFuPiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVDb25uZWN0aW9uczogTWFwPHN0cmluZywgQ29ubmVjdGlvbj4gPSBuZXcgTWFwKCk7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wZW52aWR1OiBPcGVuVmlkdTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb3B0aW9uczogU2Vzc2lvbk9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByaXZhdGUgdmlkZW9EYXRhSW50ZXJ2YWw6IE5vZGVKUy5UaW1lb3V0O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIHZpZGVvRGF0YVRpbWVvdXQ6IE5vZGVKUy5UaW1lb3V0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wZW52aWR1OiBPcGVuVmlkdSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBwbGF0Zm9ybSA9IFBsYXRmb3JtVXRpbHMuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuICAgIH1cblxuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZyk6IFByb21pc2U8YW55PjtcbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcsIG1ldGFkYXRhOiBhbnkpOiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0cyB0byB0aGUgc2Vzc2lvbiB1c2luZyBgdG9rZW5gLiBQYXJhbWV0ZXIgYG1ldGFkYXRhYCBhbGxvd3MgeW91IHRvIHBhc3MgZXh0cmEgZGF0YSB0byBzaGFyZSB3aXRoIG90aGVyIHVzZXJzIHdoZW5cbiAgICAgKiB0aGV5IHJlY2VpdmUgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LiBUaGUgc3RydWN0dXJlIG9mIGBtZXRhZGF0YWAgc3RyaW5nIGlzIHVwIHRvIHlvdSAobWF5YmUgc29tZSBzdGFuZGFyZGl6ZWQgZm9ybWF0XG4gICAgICogYXMgSlNPTiBvciBYTUwgaXMgYSBnb29kIGlkZWEpLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRhZGF0YSBpcyBub3QgY29uc2lkZXJlZCBzZWN1cmUsIGFzIGl0IGlzIGdlbmVyYXRlZCBpbiB0aGUgY2xpZW50IHNpZGUuIFRvIHBhc3Mgc2VjdXJlIGRhdGEsIGFkZCBpdCBhcyBhIHBhcmFtZXRlciBpbiB0aGVcbiAgICAgKiB0b2tlbiBnZW5lcmF0aW9uIG9wZXJhdGlvbiAodGhyb3VnaCB0aGUgQVBJIFJFU1QsIG9wZW52aWR1LWphdmEtY2xpZW50IG9yIG9wZW52aWR1LW5vZGUtY2xpZW50KS5cbiAgICAgKlxuICAgICAqIE9ubHkgYWZ0ZXIgdGhlIHJldHVybmVkIFByb21pc2UgaXMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gb2JqZWN0IHdpbGwgYmUgYXZhaWxhYmxlIGFuZCBwcm9wZXJseSBkZWZpbmVkLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBmaXJzdCBkaXNwYXRjaCBvbmUgb3IgbW9yZSBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50cyB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2Q6XG4gICAgICogLSBGaXJzdCBvbmUgZm9yIHlvdXIgb3duIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0LCBzbyB5b3UgY2FuIHJldHJpZXZlIFtbU2Vzc2lvbi5jb25uZWN0aW9uXV0gcHJvcGVydHkuXG4gICAgICogLSBUaGVuIG9uZSBmb3IgZWFjaCByZW1vdGUgQ29ubmVjdGlvbiBwcmV2aW91c2x5IGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiwgaWYgYW55LiBBbnkgb3RoZXIgcmVtb3RlIHVzZXIgY29ubmVjdGluZyB0byB0aGUgU2Vzc2lvbiBhZnRlciB5b3UgaGF2ZVxuICAgICAqIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCB3aGVuIHRoZXkgZG8gc28uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgZm9yIGVhY2ggcmVtb3RlIGFjdGl2ZSBbW1B1Ymxpc2hlcl1dIHRoYXQgd2FzIGFscmVhZHkgc3RyZWFtaW5nXG4gICAgICogd2hlbiBjb25uZWN0aW5nLCBqdXN0IGFmdGVyIGRpc3BhdGNoaW5nIGFsbCByZW1vdGUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIFNlZSBbW0Nvbm5lY3Rpb25FdmVudF1dIGFuZCBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0byB3aGljaCB5b3UgbXVzdCBzdWJzY3JpYmUgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIFNlc3Npb24gd2FzIHN1Y2Nlc3NmdWwgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqXG4gICAgICovXG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YT86IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NUb2tlbih0b2tlbik7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLm9wZW52aWR1LmNoZWNrU3lzdGVtUmVxdWlyZW1lbnRzKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBFYXJseSBjb25maWd1cmF0aW9uIHRvIGRlYWN0aXZhdGUgYXV0b21hdGljIHN1YnNjcmlwdGlvbiB0byBzdHJlYW1zXG4gICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudElkOiB0b2tlbixcbiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE6ICEhbWV0YWRhdGEgPyB0aGlzLnN0cmluZ0NsaWVudE1ldGFkYXRhKG1ldGFkYXRhKSA6ICcnXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3RBdXgodG9rZW4pLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuQlJPV1NFUl9OT1RfU1VQUE9SVEVELCAnQnJvd3NlciAnICsgcGxhdGZvcm0uZ2V0TmFtZSgpICsgJyAodmVyc2lvbiAnICsgcGxhdGZvcm0uZ2V0VmVyc2lvbigpICsgJykgZm9yICcgKyBwbGF0Zm9ybS5nZXRGYW1pbHkoKSArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdScpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGVhdmVzIHRoZSBzZXNzaW9uLCBkZXN0cm95aW5nIGFsbCBzdHJlYW1zIGFuZCBkZWxldGluZyB0aGUgdXNlciBhcyBhIHBhcnRpY2lwYW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzZXNzaW9uRGlzY29ubmVjdGVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCBlYWNoIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCB0byBhdm9pZCB0aGlzIGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyBhbGwgdGhlIFN1YnNjcmliZXIgb2JqZWN0cyB5b3Vyc2VsZi5cbiAgICAgKiBTZWUgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUgdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IGlmIHRoZXJlIGlzIGEgW1tQdWJsaXNoZXJdXSBvYmplY3QgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvbi5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uICh0byBkbyBzbyBpdCBpcyBhIG1hbmRhdG9yeSByZXF1aXJlbWVudCB0byBjYWxsIGBTZXNzaW9uLnVucHVibGlzaCgpYFxuICAgICAqIG9yL2FuZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgIGluIHRoZSBwcmV2aW91cyBzZXNzaW9uKS4gU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlIGRpc2Nvbm5lY3RlZCBwYXJ0aWNpcGFudCB3YXMgcHVibGlzaGluZy5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSB1bnN1YnNjcmliZSB0aGUgU3Vic2NyaWJlciBvYmplY3QgZnJvbSB0aGUgc2Vzc2lvbiAodGhpcyBpbmNsdWRlcyBjbG9zaW5nIHRoZSBSVENQZWVyQ29ubmVjdGlvbiBhbmQgZGlzcG9zaW5nIGFsbCBNZWRpYVN0cmVhbVRyYWNrcylcbiAgICAgKiBhbmQgYWxzbyBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGF0IFN1YnNjcmliZXIgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudCBpbiBhbnkgY2FzZS4gU2VlIFtbQ29ubmVjdGlvbkV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKi9cbiAgICBkaXNjb25uZWN0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxlYXZlKGZhbHNlLCAnZGlzY29ubmVjdCcpO1xuICAgIH1cblxuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gYSBgc3RyZWFtYCwgYWRkaW5nIGEgbmV3IEhUTUwgdmlkZW8gZWxlbWVudCB0byBET00gd2l0aCBgc3Vic2NyaWJlclByb3BlcnRpZXNgIHNldHRpbmdzLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBpbiB0aGUgY2FsbGJhY2sgb2YgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAgICogW2xldCBPcGVuVmlkdSB0YWtlIGNhcmUgb2YgdGhlIHZpZGVvIHBsYXllcnNdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1QbGF5aW5nYCBldmVudCBvbmNlIHRoZSByZW1vdGUgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0cmVhbSBTdHJlYW0gb2JqZWN0IHRvIHN1YnNjcmliZSB0b1xuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFN1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dKS4gSWYgKm51bGwqIG9yICp1bmRlZmluZWQqIG5vIGRlZmF1bHQgdmlkZW8gd2lsbCBiZSBjcmVhdGVkIGZvciB0aGlzIFN1YnNjcmliZXIuXG4gICAgICogWW91IGNhbiBhbHdheXMgY2FsbCBtZXRob2QgW1tTdWJzY3JpYmVyLmFkZFZpZGVvRWxlbWVudF1dIG9yIFtbU3Vic2NyaWJlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICAgKiBAcGFyYW0gY29tcGxldGlvbkhhbmRsZXIgYGVycm9yYCBwYXJhbWV0ZXIgaXMgbnVsbCBpZiBgc3Vic2NyaWJlYCBzdWNjZWVkcywgYW5kIGlzIGRlZmluZWQgaWYgaXQgZmFpbHMuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcGFyYW0zPzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgU3Vic2NyaWJlclByb3BlcnRpZXMsIHBhcmFtND86ICgoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSk6IFN1YnNjcmliZXIge1xuICAgICAgICBsZXQgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgaWYgKCEhcGFyYW0zICYmIHR5cGVvZiBwYXJhbTMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0TW9kZTogKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSAhPT0gJ3VuZGVmaW5lZCcpID8gKCh0eXBlb2YgcGFyYW0zLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwYXJhbTMuaW5zZXJ0TW9kZV0gOiBwcm9wZXJ0aWVzLmluc2VydE1vZGUpIDogVmlkZW9JbnNlcnRNb2RlLkFQUEVORCxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb0F1ZGlvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9BdWRpbyA6IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogKHR5cGVvZiBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyAhPT0gJ3VuZGVmaW5lZCcpID8gcGFyYW0zLnN1YnNjcmliZVRvVmlkZW8gOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86IHRydWUsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9WaWRlbzogdHJ1ZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjb21wbGV0aW9uSGFuZGxlcjogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgKHR5cGVvZiBwYXJhbTMgPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtMztcbiAgICAgICAgfSBlbHNlIGlmICghIXBhcmFtNCkge1xuICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbkNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyB0aGlzLm5vdENvbm5lY3RlZEVycm9yKCk7XG4gICAgICAgIH1cblxuICAgICAgICBsb2dnZXIuaW5mbygnU3Vic2NyaWJpbmcgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG5cbiAgICAgICAgc3RyZWFtLnN1YnNjcmliZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1N1YnNjcmliZWQgY29ycmVjdGx5IHRvICcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzdWJzY3JpYmVyID0gbmV3IFN1YnNjcmliZXIoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzKTtcbiAgICAgICAgaWYgKCEhc3Vic2NyaWJlci50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBzdHJlYW0uc3RyZWFtTWFuYWdlci5jcmVhdGVWaWRlb0VsZW1lbnQoc3Vic2NyaWJlci50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnByb3BlcnRpZXMuaW5zZXJ0TW9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1YnNjcmliZXI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcm9taXNpZmllZCB2ZXJzaW9uIG9mIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXVxuICAgICAqL1xuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFByb21pc2U8U3Vic2NyaWJlcj47XG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj47XG5cbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBTdWJzY3JpYmVyUHJvcGVydGllcyk6IFByb21pc2U8U3Vic2NyaWJlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U3Vic2NyaWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbkNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Vic2NyaWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHN1YnNjcmliZXIgPSB0aGlzLnN1YnNjcmliZShzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIGZyb20gYHN1YnNjcmliZXJgLCBhdXRvbWF0aWNhbGx5IHJlbW92aW5nIGl0cyBhc3NvY2lhdGVkIEhUTUwgdmlkZW8gZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudCBmb3IgZWFjaCB2aWRlbyBhc3NvY2lhdGVkIHRvIGl0IHRoYXQgd2FzIHJlbW92ZWQgZnJvbSBET00uXG4gICAgICogT25seSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZFxuICAgICAqXG4gICAgICogU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcik6IFByb21pc2U8dm9pZD4ge1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdVbnN1YnNjcmliZWQgY29ycmVjdGx5IGZyb20gJyArIGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaGVzIHRvIHRoZSBTZXNzaW9uIHRoZSBQdWJsaXNoZXIgb2JqZWN0XG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgbG9jYWwgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCB1cG9uIHN1Y2Nlc3NmdWwgdGVybWluYXRpb24gb2YgdGhpcyBtZXRob2QuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIG9uY2UgdGhlIG1lZGlhIHN0cmVhbSBzdGFydHMgcGxheWluZy4gU2VlIFtbU3RyZWFtTWFuYWdlckV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQgc28gdGhleSBjYW4gc3Vic2NyaWJlIHRvIGl0LiBTZWUgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgb25seSBhZnRlciB0aGUgcHVibGlzaGVyIHdhcyBzdWNjZXNzZnVsbHkgcHVibGlzaGVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kVmlkZW9EYXRhKHB1Ymxpc2hlciwgOCwgdHJ1ZSwgNSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gJ1Nlc3Npb24udW5wdWJsaXNoKFB1Ymxpc2hlciknIGhhcyBiZWVuIGNhbGxlZC4gTXVzdCBpbml0aWFsaXplIGFnYWluIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5pbml0aWFsaXplKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZFN0cmVhbShwdWJsaXNoZXIuc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5yZWVzdGFibGlzaFN0cmVhbVBsYXlpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZFZpZGVvRGF0YShwdWJsaXNoZXIsIDgsIHRydWUsIDUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVucHVibGlzaGVzIGZyb20gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3QuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBUaGlzIGV2ZW50IHdpbGwgYXV0b21hdGljYWxseSBzdG9wIGFsbCBtZWRpYSB0cmFja3MgYW5kIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gdGhpcyBQdWJsaXNoZXJcbiAgICAgKiAob25seSB0aG9zZSB2aWRlb3MgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFB1Ymxpc2hlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgaWYgeW91IHdhbnQgdG8gY2xlYW4gdGhlIFB1Ymxpc2hlciBvYmplY3Qgb24geW91ciBvd24gb3IgcmUtcHVibGlzaCBpdCBpbiBhIGRpZmZlcmVudCBTZXNzaW9uLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKSBhbmRcbiAgICAgKiBkZWxldGUgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGl0IChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCB0byBhdm9pZCB0aGlzIGRlZmF1bHQgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBvbiB5b3VyIG93bi5cbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gYW5kIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIHVucHVibGlzaChwdWJsaXNoZXI6IFB1Ymxpc2hlcik6IFByb21pc2U8dm9pZD4ge1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLm5vdENvbm5lY3RlZEVycm9yKClcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gcHVibGlzaGVyLnN0cmVhbTtcblxuICAgICAgICAgICAgaWYgKCFzdHJlYW0uY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdUaGUgYXNzb2NpYXRlZCBDb25uZWN0aW9uIG9iamVjdCBvZiB0aGlzIFB1Ymxpc2hlciBpcyBub3QgeW91ciBsb2NhbCBDb25uZWN0aW9uLicgK1xuICAgICAgICAgICAgICAgICAgICBcIk9ubHkgbW9kZXJhdG9ycyBjYW4gZm9yY2UgdW5wdWJsaXNoIG9uIHJlbW90ZSBTdHJlYW1zIHZpYSAnZm9yY2VVbnB1Ymxpc2gnIG1ldGhvZFwiKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1VucHVibGlzaGluZyBsb2NhbCBtZWRpYSAoJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCArICcpJyk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd1bnB1Ymxpc2hWaWRlbycsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ01lZGlhIHVucHVibGlzaGVkIGNvcnJlY3RseScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbSA9PSBzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgQ29ubmVjdGlvbi5zdHJlYW0gbWF5IGhhdmUgY2hhbmdlZCBpZiBTZXNzaW9uLnB1Ymxpc2ggd2FzIGNhbGxlZCB3aXRoIG90aGVyIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHB1Ymxpc2hlciwgJ3N0cmVhbURlc3Ryb3llZCcsIHB1Ymxpc2hlci5zdHJlYW0sICd1bnB1Ymxpc2gnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZvcmNpbmcgZGlzY29ubmVjdCBmb3IgY29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAnZm9yY2VEaXNjb25uZWN0JyxcbiAgICAgICAgICAgICAgICB7IGNvbm5lY3Rpb25JZDogY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBmb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIENvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGEgZGlzY29ubmVjdGlvblwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIHVucHVibGlzaCBhIFN0cmVhbVxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIGJlaGF2aW9yIGlzIHRoZSBzYW1lIGFzIHdoZW4gc29tZSB1c2VyIGNhbGxzIFtbU2Vzc2lvbi51bnB1Ymxpc2hdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgXG4gICAgICpcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGFmZmVjdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHJlbW90ZSBTdHJlYW0gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHVucHVibGlzaGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlVW5wdWJsaXNoKHN0cmVhbTogU3RyZWFtKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGZvciBzdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdmb3JjZVVucHVibGlzaCcsXG4gICAgICAgICAgICAgICAgeyBzdHJlYW1JZDogc3RyZWFtLnN0cmVhbUlkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgZm9yY2luZyB1bnB1Ymxpc2ggZm9yIFN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggY29ycmVjdGx5IGZvciBTdHJlYW0gJyArIHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIG9uZSBzaWduYWwuIGBzaWduYWxgIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBwcm9wZXJ0aWVzOlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7ZGF0YTpzdHJpbmcsIHRvOkNvbm5lY3Rpb25bXSwgdHlwZTpzdHJpbmd9XG4gICAgICogYGBgXG4gICAgICogQWxsIHVzZXJzIHN1YnNjcmliZWQgdG8gdGhhdCBzaWduYWwgKGBzZXNzaW9uLm9uKCdzaWduYWw6dHlwZScsIC4uLilgIG9yIGBzZXNzaW9uLm9uKCdzaWduYWwnLCAuLi4pYCBmb3IgYWxsIHNpZ25hbHMpIGFuZCB3aG9zZSBDb25uZWN0aW9uIG9iamVjdHMgYXJlIGluIGB0b2AgYXJyYXkgd2lsbCByZWNlaXZlIGl0LiBUaGVpciBsb2NhbFxuICAgICAqIFNlc3Npb24gb2JqZWN0cyB3aWxsIGRpc3BhdGNoIGEgYHNpZ25hbGAgb3IgYHNpZ25hbDp0eXBlYCBldmVudC4gU2VlIFtbU2lnbmFsRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBtZXNzYWdlIHN1Y2Nlc3NmdWxseSByZWFjaGVkIG9wZW52aWR1LXNlcnZlciBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90LiBfVGhpcyBkb2Vzbid0XG4gICAgICogbWVhbiB0aGF0IG9wZW52aWR1LXNlcnZlciBjb3VsZCByZXNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHRoZSBsaXN0ZWQgcmVjZWl2ZXJzLl9cbiAgICAgKi9cbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuICAgIHNpZ25hbChzaWduYWw6IFNpZ25hbE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlc3Npb25Db25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJlamVjdCh0aGlzLm5vdENvbm5lY3RlZEVycm9yKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcblxuICAgICAgICAgICAgbGV0IHR5cGVBdXg6IHN0cmluZyA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnc2lnbmFsJztcbiAgICAgICAgICAgIGlmICghIXR5cGVBdXgpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZUF1eC5zdWJzdHJpbmcoMCwgNykgIT09ICdzaWduYWw6Jykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlQXV4ID0gJ3NpZ25hbDonICsgdHlwZUF1eDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSB0eXBlQXV4O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyogdHNsaW50OmVuYWJsZTpuby1zdHJpbmctbGl0ZXJhbCAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50IHwgTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCB8IEV4Y2VwdGlvbkV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICBzdXBlci5vbkF1eCh0eXBlLCBcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMgd2l0aCBhdWRpbywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIXJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5lbmFibGVIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uPy5zdHJlYW0/Lmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uIGFuZCBwdWJsaXNoaW5nIHdpdGggYXVkaW8sIGFsc28gZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBmb3IgdGhlIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcyB3aXRoIGF1ZGlvLCBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24/LnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBjb25uZWN0ZWQgdG8gdGhlIFNlc3Npb24gYW5kIHB1Ymxpc2hpbmcgd2l0aCBhdWRpbywgYWxzbyBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgZm9yIHRoZSBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZSh0eXBlOiBzdHJpbmcsIGhhbmRsZXI6IChldmVudDogU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHwgU2lnbmFsRXZlbnQgfCBTdHJlYW1FdmVudCB8IENvbm5lY3Rpb25FdmVudCB8IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfCBSZWNvcmRpbmdFdmVudCB8IE5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQgfCBFeGNlcHRpb25FdmVudCkgPT4gdm9pZCk6IFNlc3Npb24ge1xuXG4gICAgICAgIHN1cGVyLm9uY2VBdXgodHlwZSwgXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlIGJ5ICdTZXNzaW9uJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMgd2l0aCBhdWRpbywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCAob25jZSkgaW4gYWxsIG9mIHRoZW0gb25jZVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIXJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5lbmFibGVPbmNlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbj8uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIC8vIElmIGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiBhbmQgcHVibGlzaGluZyB3aXRoIGF1ZGlvLCBhbHNvIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgKG9uY2UpIGZvciB0aGUgUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lbmFibGVPbmNlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcyB3aXRoIGF1ZGlvLCBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgKG9uY2UpIGluIGFsbCBvZiB0aGVtIG9uY2VcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uPy5zdHJlYW0/Lmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uIGFuZCBwdWJsaXNoaW5nIHdpdGggYXVkaW8sIGFsc28gZW5hYmxlIGhhcmsgJ3N0b3BwZWRfc3BlYWtpbmcnIGV2ZW50IChvbmNlKSBmb3IgdGhlIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfCBTaWduYWxFdmVudCB8IFN0cmVhbUV2ZW50IHwgQ29ubmVjdGlvbkV2ZW50IHwgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB8IFJlY29yZGluZ0V2ZW50IHwgTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCB8IEV4Y2VwdGlvbkV2ZW50KSA9PiB2b2lkKTogU2Vzc2lvbiB7XG5cbiAgICAgICAgc3VwZXIub2ZmKHR5cGUsIGhhbmRsZXIpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIFNlc3Npb24gb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0/LnN0cmVhbU1hbmFnZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFN1YnNjcmliZXIgb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlLCByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtLmRpc2FibGVIYXJrU3BlYWtpbmdFdmVudChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24/LnN0cmVhbT8uc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBQdWJsaXNoZXIgb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmFueVNwZWVjaEV2ZW50TGlzdGVuZXJFbmFibGVkKCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgZmFsc2UsIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzYWJsZUhhcmtTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIFNlc3Npb24gb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgU3Vic2NyaWJlciBvYmplY3Qgc3RpbGwgaGFzIHNvbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmFueVNwZWVjaEV2ZW50TGlzdGVuZXJFbmFibGVkKCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBmYWxzZSwgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5kaXNhYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbj8uc3RyZWFtPy5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFB1Ymxpc2hlciBvYmplY3Qgc3RpbGwgaGFzIHNvbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYW55U3BlZWNoRXZlbnRMaXN0ZW5lckVuYWJsZWQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIGZhbHNlLCB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbU1hbmFnZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc2FibGVIYXJrU3RvcHBlZFNwZWFraW5nRXZlbnQoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKGV2ZW50OiBSZW1vdGVDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24oZXZlbnQuaWQsICcnKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ0Nvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBldmVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5zZXQoZXZlbnQuaWQsIGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChldmVudDogeyBjb25uZWN0aW9uSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnb25QYXJ0aWNpcGFudExlZnQnKS50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIGV2ZW50LnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWQuZGVsZXRlKHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zLmRlbGV0ZShjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIGV2ZW50LnJlYXNvbildKTtcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChldmVudDogUmVtb3RlQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuc2V0KGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBjb25uZWN0aW9uKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLmdldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCkpIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLnNldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCwgdHJ1ZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKGV2ZW50LmlkLCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIGV2ZW50Lm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdGVPcHRpb25zID0gZXZlbnQ7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhldmVudC5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91ciBzdHJlYW0gaGFzIGJlZW4gZm9yY2VkbHkgdW5wdWJsaXNoZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKGV2ZW50LnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJylcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSEsIGV2ZW50LnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbSEuc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWQuZGVsZXRlKHN0cmVhbUlkKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChldmVudDogeyBjb25uZWN0aW9uSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgZXZlbnQucmVhc29uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UoZXZlbnQ6IHsgdHlwZT86IHN0cmluZywgZGF0YT86IHN0cmluZywgZnJvbT86IHN0cmluZyB9KTogdm9pZCB7XG5cbiAgICAgICAgbG9nZ2VyLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShldmVudCkpO1xuXG4gICAgICAgIGNvbnN0IHN0cmlwcGVkVHlwZSA9ICEhZXZlbnQudHlwZSA/IGV2ZW50LnR5cGUucmVwbGFjZSgvXihzaWduYWw6KS8sICcnKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAoISFldmVudC5mcm9tKSB7XG4gICAgICAgICAgICAvLyBTaWduYWwgc2VudCBieSBvdGhlciBjbGllbnRcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihldmVudC5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgZXZlbnQuZnJvbSArIFwiJyB1bmtub3duIHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KHRoaXMucmVtb3RlQ29ubmVjdGlvbnMua2V5cygpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIHN0cmlwcGVkVHlwZSwgZXZlbnQuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXZlbnQudHlwZSAmJiBldmVudC50eXBlICE9PSAnc2lnbmFsJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoZXZlbnQudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBzdHJpcHBlZFR5cGUsIGV2ZW50LmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gU2lnbmFsIHNlbnQgYnkgc2VydmVyXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBzdHJpcHBlZFR5cGUsIGV2ZW50LmRhdGEsIHVuZGVmaW5lZCldKTtcbiAgICAgICAgICAgIGlmICghIWV2ZW50LnR5cGUgJiYgZXZlbnQudHlwZSAhPT0gJ3NpZ25hbCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudChldmVudC50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIHN0cmlwcGVkVHlwZSwgZXZlbnQuZGF0YSwgdW5kZWZpbmVkKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKGV2ZW50OiB7IGNvbm5lY3Rpb25JZDogc3RyaW5nLCBzdHJlYW1JZDogc3RyaW5nLCBwcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogYW55LCByZWFzb246IHN0cmluZyB9KTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoY29ubmVjdGlvbjogQ29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0gJiYgY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQgPT09IGV2ZW50LnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgbGV0IG9sZFZhbHVlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYXVkaW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IGV2ZW50Lm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50Lm5ld1ZhbHVlID0gZXZlbnQubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShldmVudC5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbHRlcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5maWx0ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IChPYmplY3Qua2V5cyhldmVudC5uZXdWYWx1ZSkubGVuZ3RoID4gMCkgPyBldmVudC5uZXdWYWx1ZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5uZXdWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlciA9IG5ldyBGaWx0ZXIoZXZlbnQubmV3VmFsdWUudHlwZSwgZXZlbnQubmV3VmFsdWUub3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlci5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50Lm5ld1ZhbHVlLmxhc3RFeGVjTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5maWx0ZXIubGFzdEV4ZWNNZXRob2QgPSBldmVudC5uZXdWYWx1ZS5sYXN0RXhlY01ldGhvZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQubmV3VmFsdWUgPSBzdHJlYW0uZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHN0cmVhbSwgZXZlbnQucHJvcGVydHksIGV2ZW50Lm5ld1ZhbHVlLCBvbGRWYWx1ZSwgZXZlbnQucmVhc29uKV0pO1xuICAgICAgICAgICAgICAgIGlmICghIXN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBldmVudC5wcm9wZXJ0eSwgZXZlbnQubmV3VmFsdWUsIG9sZFZhbHVlLCBldmVudC5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJObyBzdHJlYW0gd2l0aCBzdHJlYW1JZCAnXCIgKyBldmVudC5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBldmVudC5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGV2ZW50LmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91ciBzdHJlYW0gaGFzIGJlZW4gZm9yY2VkbHkgY2hhbmdlZCAoZmlsdGVyIGZlYXR1cmUpXG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKGV2ZW50LmNvbm5lY3Rpb25JZCwgJ29uU3RyZWFtUHJvcGVydHlDaGFuZ2VkJylcbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkNvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWQoZXZlbnQ6IHsgcHJvcGVydHk6IHN0cmluZywgbmV3VmFsdWU6IGFueSB9KTogdm9pZCB7XG4gICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgc3dpdGNoIChldmVudC5wcm9wZXJ0eSkge1xuICAgICAgICAgICAgY2FzZSAncm9sZSc6XG4gICAgICAgICAgICAgICAgb2xkVmFsdWUgPSB0aGlzLmNvbm5lY3Rpb24ucm9sZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5yb2xlID0gZXZlbnQubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmxvY2FsT3B0aW9ucyEucm9sZSA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncmVjb3JkJzpcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHRoaXMuY29ubmVjdGlvbi5yZWNvcmQ7XG4gICAgICAgICAgICAgICAgZXZlbnQubmV3VmFsdWUgPSBldmVudC5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5yZWNvcmQgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24ubG9jYWxPcHRpb25zIS5yZWNvcmQgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgQ29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuY29ubmVjdGlvbiwgZXZlbnQucHJvcGVydHksIGV2ZW50Lm5ld1ZhbHVlLCBvbGRWYWx1ZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZENoYW5nZWQoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIG5ld1ZhbHVlOiBudW1iZXIsIG9sZFZhbHVlOiBudW1iZXIgfSk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWQnLCBbbmV3IE5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQodGhpcywgZXZlbnQubmV3VmFsdWUsIGV2ZW50Lm9sZFZhbHVlLCB0aGlzLmNvbm5lY3Rpb24pXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGNvbm5lY3Rpb25JZCAnICsgZXZlbnQuY29ubmVjdGlvbklkKVxuICAgICAgICAgICAgICAgIC50aGVuKChjb25uZWN0aW9uOiBDb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCduZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZCcsIFtuZXcgTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCh0aGlzLCBldmVudC5uZXdWYWx1ZSwgZXZlbnQub2xkVmFsdWUsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKGV2ZW50OiB7IHNlbmRlckNvbm5lY3Rpb25JZDogc3RyaW5nLCBlbmRwb2ludE5hbWU6IHN0cmluZywgc2RwTUxpbmVJbmRleDogbnVtYmVyLCBzZHBNaWQ6IHN0cmluZywgY2FuZGlkYXRlOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZSA9IHtcbiAgICAgICAgICAgIGNhbmRpZGF0ZTogZXZlbnQuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBldmVudC5zZHBNaWQsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBldmVudC5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgY29tcG9uZW50OiBudWxsLFxuICAgICAgICAgICAgZm91bmRhdGlvbjogbnVsbCxcbiAgICAgICAgICAgIHBvcnQ6IG51bGwsXG4gICAgICAgICAgICBwcmlvcml0eTogbnVsbCxcbiAgICAgICAgICAgIHByb3RvY29sOiBudWxsLFxuICAgICAgICAgICAgcmVsYXRlZEFkZHJlc3M6IG51bGwsXG4gICAgICAgICAgICByZWxhdGVkUG9ydDogbnVsbCxcbiAgICAgICAgICAgIHRjcFR5cGU6IG51bGwsXG4gICAgICAgICAgICB1c2VybmFtZUZyYWdtZW50OiBudWxsLFxuICAgICAgICAgICAgdHlwZTogbnVsbCxcbiAgICAgICAgICAgIHRvSlNPTjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGNhbmRpZGF0ZTogZXZlbnQuY2FuZGlkYXRlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihldmVudC5zZW5kZXJDb25uZWN0aW9uSWQsICdDb25uZWN0aW9uIG5vdCBmb3VuZCBmb3IgY29ubmVjdGlvbklkICcgKyBldmVudC5zZW5kZXJDb25uZWN0aW9uSWQgKyAnIG93bmluZyBlbmRwb2ludCAnICsgZXZlbnQuZW5kcG9pbnROYW1lICsgJy4gSWNlIGNhbmRpZGF0ZSB3aWxsIGJlIGlnbm9yZWQ6ICcgKyBjYW5kaWRhdGUpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW06IFN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtITtcbiAgICAgICAgICAgICAgICBzdHJlYW0uZ2V0V2ViUnRjUGVlcigpLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlIGZvciAnICsgc3RyZWFtIS5zdHJlYW1JZFxuICAgICAgICAgICAgICAgICAgICAgICAgKyAnIHN0cmVhbSBvZiBlbmRwb2ludCAnICsgZXZlbnQuZW5kcG9pbnROYW1lICsgJzogJyArIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU2Vzc2lvbkNsb3NlZChtc2cpOiB2b2lkIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1Nlc3Npb24gY2xvc2VkOiAnICsgSlNPTi5zdHJpbmdpZnkobXNnKSk7XG4gICAgICAgIGNvbnN0IHMgPSBtc2cuc2Vzc2lvbklkO1xuICAgICAgICBpZiAocyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbi1jbG9zZWQnLCBbe1xuICAgICAgICAgICAgICAgIHNlc3Npb246IHNcbiAgICAgICAgICAgIH1dKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdTZXNzaW9uIHVuZGVmaW5lZCBvbiBzZXNzaW9uIGNsb3NlZCcsIG1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Mb3N0Q29ubmVjdGlvbihyZWFzb246IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBsb2dnZXIud2FybignTG9zdCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgISF0aGlzLmNvbm5lY3Rpb24gJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgdGhpcy5sZWF2ZSh0cnVlLCByZWFzb24pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3ZlcmVkQ29ubmVjdGlvbigpOiB2b2lkIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1JlY292ZXJlZCBjb25uZWN0aW9uIGluIFNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgdGhpcy5yZWNvbm5lY3RCcm9rZW5TdHJlYW1zKCk7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvbm5lY3RlZCcsIFtdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25NZWRpYUVycm9yKGV2ZW50OiB7IGVycm9yOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ01lZGlhIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcbiAgICAgICAgY29uc3QgZXJyID0gZXZlbnQuZXJyb3I7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdlcnJvci1tZWRpYScsIFt7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGVyclxuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1JlY2VpdmVkIHVuZGVmaW5lZCBtZWRpYSBlcnJvcjonLCBldmVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvcmRpbmdTdGFydGVkKGV2ZW50OiB7IGlkOiBzdHJpbmcsIG5hbWU6IHN0cmluZyB9KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdGFydGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RhcnRlZCcsIGV2ZW50LmlkLCBldmVudC5uYW1lKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0b3BwZWQoZXZlbnQ6IHsgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nLCByZWFzb246IHN0cmluZyB9KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZWNvcmRpbmdTdG9wcGVkJywgW25ldyBSZWNvcmRpbmdFdmVudCh0aGlzLCAncmVjb3JkaW5nU3RvcHBlZCcsIGV2ZW50LmlkLCBldmVudC5uYW1lLCBldmVudC5yZWFzb24pXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uRmlsdGVyRXZlbnREaXNwYXRjaGVkKGV2ZW50OiB7IGNvbm5lY3Rpb25JZDogc3RyaW5nLCBzdHJlYW1JZDogc3RyaW5nLCBmaWx0ZXJUeXBlOiBzdHJpbmcsIGV2ZW50VHlwZTogc3RyaW5nLCBkYXRhOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQ6IHN0cmluZyA9IGV2ZW50LmNvbm5lY3Rpb25JZDtcbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZCwgJ05vIGNvbm5lY3Rpb24gZm91bmQgZm9yIGNvbm5lY3Rpb25JZCAnICsgY29ubmVjdGlvbklkKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZpbHRlciBldmVudCBkaXNwYXRjaGVkJyk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtOiBTdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbSE7XG4gICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlciEuaGFuZGxlcnMuZ2V0KGV2ZW50LmV2ZW50VHlwZSk/LmNhbGwodGhpcywgbmV3IEZpbHRlckV2ZW50KHN0cmVhbS5maWx0ZXIhLCBldmVudC5ldmVudFR5cGUsIGV2ZW50LmRhdGEpKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlcihldmVudDogeyBjb25uZWN0aW9uSWQ6IHN0cmluZywgc3RyZWFtSWQ6IHN0cmluZywgc2RwT2ZmZXI6IHN0cmluZyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXInKVxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLnN0cmVhbSAmJiBjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCA9PT0gZXZlbnQuc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGNvbm5lY3Rpb24uc3RyZWFtO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZWFtLnNldHVwUmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyKHJlc29sdmUsIHJlamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmdvaW5nIHJlY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdhaXQgZm9yIHRoZSBldmVudCBlbWl0dGVyIHRvIGJlIGZyZWUgKHdpdGggc3VjY2VzcyBvciBlcnJvcikgYW5kIGNhbGwgdGhlIG1ldGhvZCBhZ2FpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIVsnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXJMYXN0RXZlbnQnXSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFR3byBvciBtb3JlIG9uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyIGV2ZW50cyB3ZXJlIHJlY2VpdmVkIHdoaWxlIGEgcmVjb25uZWN0aW9uIHByb2Nlc3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhlIHN1YnNjcmliZXIgd2FzIGFscmVhZHkgdGFraW5nIHBsYWNlLiBBbHdheXMgdXNlIHRoZSBsYXN0IG9uZSB0byByZXRyeSB0aGUgcmUtc3Vic2NyaXB0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByb2Nlc3MsIGFzIHRoYXQgU0RQIG9mZmVyIHdpbGwgYmUgdGhlIG9ubHkgb25lIGF2YWlsYWJsZSBhdCB0aGUgc2VydmVyIHNpZGUuIElnbm9yZSBwcmV2aW91cyBvbmVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXIhWydvbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlckxhc3RFdmVudCddID0gZXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgnT25nb2luZyBmb3JjZWQgc3Vic2NyaWJlciByZWNvbm5lY3Rpb24nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmUgb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXIgZXZlbiBoYXMgYmVlbiByZWNlaXZlZCB3aGlsZSBhIHJlY29ubmVjdGlvbiBwcm9jZXNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHRoZSBzdWJzY3JpYmVyIHdhcyBhbHJlYWR5IHRha2luZyBwbGFjZS4gU2V0IHVwIGEgbGlzdGVuZXIgdG8gd2FpdCBmb3IgaXQgdG8gcmV0cnkgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvcmNlZCByZWNvbm5lY3Rpb24gcHJvY2Vzc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIVsnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXJMYXN0RXZlbnQnXSA9IGV2ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50QXV4ID0gc3RyZWFtLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciFbJ29uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyTGFzdEV2ZW50J107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgc3RyZWFtLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciFbJ29uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyTGFzdEV2ZW50J107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyKGV2ZW50QXV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIS5vbmNlKCdzdWNjZXNzJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXIhLm9uY2UoJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmNvbXBsZXRlV2ViUnRjUGVlclJlY2VpdmUodHJ1ZSwgdHJ1ZSwgZXZlbnQuc2RwT2ZmZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gc3RyZWFtLmZpbmFsUmVzb2x2ZUZvclN1YnNjcmlwdGlvbih0cnVlLCByZXNvbHZlKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gc3RyZWFtLmZpbmFsUmVqZWN0Rm9yU3Vic2NyaXB0aW9uKHRydWUsIGBFcnJvciB3aGlsZSBmb3JjaWJseSByZWNvbm5lY3RpbmcgcmVtb3RlIHN0cmVhbSAke2V2ZW50LnN0cmVhbUlkfTogJHtlcnJvci50b1N0cmluZygpfWAsIHJlamVjdCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyTXNnID0gXCJObyBzdHJlYW0gd2l0aCBzdHJlYW1JZCAnXCIgKyBldmVudC5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBldmVudC5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJNc2cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVyck1zZyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3Qob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWNvbm5lY3RCcm9rZW5TdHJlYW1zKCk6IHZvaWQge1xuICAgICAgICBsb2dnZXIuaW5mbygnUmUtZXN0YWJsaXNoaW5nIG1lZGlhIGNvbm5lY3Rpb25zLi4uJyk7XG4gICAgICAgIGxldCBzb21lUmVjb25uZWN0aW9uID0gZmFsc2U7XG4gICAgICAgIC8vIFJlLWVzdGFibGlzaCBQdWJsaXNoZXIgc3RyZWFtXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbi5zdHJlYW0gJiYgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JY2VDb25uZWN0aW9uU3RhdGVCcm9rZW4oKSkge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1JlLWVzdGFibGlzaGluZyBQdWJsaXNoZXIgJyArIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pbml0V2ViUnRjUGVlclNlbmQodHJ1ZSk7XG4gICAgICAgICAgICBzb21lUmVjb25uZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZS1lc3RhYmxpc2ggU3Vic2NyaWJlciBzdHJlYW1zXG4gICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgIGlmICghIXJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtICYmIHJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUljZUNvbm5lY3Rpb25TdGF0ZUJyb2tlbigpKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1JlLWVzdGFibGlzaGluZyBTdWJzY3JpYmVyICcgKyByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKHRydWUpO1xuICAgICAgICAgICAgICAgIHNvbWVSZWNvbm5lY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFzb21lUmVjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbygnVGhlcmUgd2VyZSBubyBtZWRpYSBzdHJlYW1zIGluIG5lZWQgb2YgYSByZWNvbm5lY3Rpb24nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGVhdmUoZm9yY2VkOiBib29sZWFuLCByZWFzb246IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGZvcmNlZCA9ICEhZm9yY2VkO1xuICAgICAgICBsb2dnZXIuaW5mbygnTGVhdmluZyBTZXNzaW9uIChmb3JjZWQ9JyArIGZvcmNlZCArICcpJyk7XG4gICAgICAgIHRoaXMuc3RvcFZpZGVvRGF0YUludGVydmFscygpO1xuXG4gICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQgJiYgIWZvcmNlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2xlYXZlUm9vbScsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYGxlYXZlUm9vbSBlcnJvcjogJHtKU09OLnN0cmluZ2lmeShlcnJvcil9YCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5jbG9zZVdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3Rpb24uZGlzcG9zZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFNlc3Npb24gb2JqZWN0IGRpc3BhdGNoICdzZXNzaW9uRGlzY29ubmVjdGVkJyBldmVudCAoaWYgaXQgaXMgbm90IGFscmVhZHkgZGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudCA9IG5ldyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQodGhpcywgcmVhc29uKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcsIFtzZXNzaW9uRGlzY29ubmVjdEV2ZW50XSk7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybignWW91IHdlcmUgbm90IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB9XG4gICAgICAgIGxvZ2dlci5mbHVzaCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplUGFyYW1zKHRva2VuOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3Qgam9pblBhcmFtcyA9IHtcbiAgICAgICAgICAgIHRva2VuOiAoISF0b2tlbikgPyB0b2tlbiA6ICcnLFxuICAgICAgICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uSWQsXG4gICAgICAgICAgICBwbGF0Zm9ybTogISFwbGF0Zm9ybS5nZXREZXNjcmlwdGlvbigpID8gcGxhdGZvcm0uZ2V0RGVzY3JpcHRpb24oKSA6ICd1bmtub3duJyxcbiAgICAgICAgICAgIG1ldGFkYXRhOiAhIXRoaXMub3B0aW9ucy5tZXRhZGF0YSA/IHRoaXMub3B0aW9ucy5tZXRhZGF0YSA6ICcnLFxuICAgICAgICAgICAgc2VjcmV0OiB0aGlzLm9wZW52aWR1LmdldFNlY3JldCgpLFxuICAgICAgICAgICAgcmVjb3JkZXI6IHRoaXMub3BlbnZpZHUuZ2V0UmVjb3JkZXIoKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gam9pblBhcmFtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2VuZFZpZGVvRGF0YShzdHJlYW1NYW5hZ2VyOiBTdHJlYW1NYW5hZ2VyLCBpbnRlcnZhbFNlY29uZHM6IG51bWJlciA9IDEsIGRvSW50ZXJ2YWw6IGJvb2xlYW4gPSBmYWxzZSwgbWF4TG9vcHM6IG51bWJlciA9IDEpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgcGxhdGZvcm0uaXNDaHJvbWVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNPcGVyYUJyb3dzZXIoKSB8fFxuICAgICAgICAgICAgcGxhdGZvcm0uaXNPcGVyYU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWxlY3Ryb24oKSB8fFxuICAgICAgICAgICAgKHBsYXRmb3JtLmlzU2FmYXJpQnJvd3NlcigpICYmICFwbGF0Zm9ybS5pc0lvbmljSW9zKCkpIHx8IHBsYXRmb3JtLmlzQW5kcm9pZEJyb3dzZXIoKSB8fFxuICAgICAgICAgICAgcGxhdGZvcm0uaXNTYW1zdW5nQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzSW9uaWNBbmRyb2lkKCkgfHwgcGxhdGZvcm0uaXNJT1NXaXRoU2FmYXJpKClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCBvYnRhaW5BbmRTZW5kVmlkZW8gPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGMgPSBzdHJlYW1NYW5hZ2VyLnN0cmVhbS5nZXRSVENQZWVyQ29ubmVjdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChwYy5jb25uZWN0aW9uU3RhdGUgPT09ICdjb25uZWN0ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXRzTWFwID0gYXdhaXQgcGMuZ2V0U3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJyOiBhbnlbXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBzdGF0c01hcC5mb3JFYWNoKHN0YXRzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoXCJmcmFtZVdpZHRoXCIgaW4gc3RhdHMpICYmIChcImZyYW1lSGVpZ2h0XCIgaW4gc3RhdHMpICYmIChhcnIubGVuZ3RoID09PSAwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyci5wdXNoKHN0YXRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcnIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndmlkZW9EYXRhJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogYXJyWzBdLmZyYW1lSGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBhcnJbMF0uZnJhbWVXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogc3RyZWFtTWFuYWdlci5zdHJlYW0udmlkZW9BY3RpdmUgIT0gbnVsbCA/IHN0cmVhbU1hbmFnZXIuc3RyZWFtLnZpZGVvQWN0aXZlIDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHN0cmVhbU1hbmFnZXIuc3RyZWFtLmF1ZGlvQWN0aXZlICE9IG51bGwgPyBzdHJlYW1NYW5hZ2VyLnN0cmVhbS5hdWRpb0FjdGl2ZSA6IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3ZpZGVvRGF0YScgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRvSW50ZXJ2YWwpIHtcbiAgICAgICAgICAgICAgICBsZXQgbG9vcHMgPSAxO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9EYXRhSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb29wcyA8IG1heExvb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb29wcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2J0YWluQW5kU2VuZFZpZGVvKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMudmlkZW9EYXRhSW50ZXJ2YWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgaW50ZXJ2YWxTZWNvbmRzICogMTAwMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9EYXRhVGltZW91dCA9IHNldFRpbWVvdXQob2J0YWluQW5kU2VuZFZpZGVvLCBpbnRlcnZhbFNlY29uZHMgKiAxMDAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybS5pc0ZpcmVmb3hCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzSW9uaWNJb3MoKSB8fCBwbGF0Zm9ybS5pc1JlYWN0TmF0aXZlKCkpIHtcbiAgICAgICAgICAgIC8vIEJhc2ljIHZlcnNpb24gZm9yIEZpcmVmb3ggYW5kIElvbmljIGlPUy4gVGhleSBkbyBub3Qgc3VwcG9ydCBzdGF0c1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndmlkZW9EYXRhJywge1xuICAgICAgICAgICAgICAgIGhlaWdodDogc3RyZWFtTWFuYWdlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zPy5oZWlnaHQgfHwgMCxcbiAgICAgICAgICAgICAgICB3aWR0aDogc3RyZWFtTWFuYWdlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zPy53aWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiBzdHJlYW1NYW5hZ2VyLnN0cmVhbS52aWRlb0FjdGl2ZSAhPSBudWxsID8gc3RyZWFtTWFuYWdlci5zdHJlYW0udmlkZW9BY3RpdmUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogc3RyZWFtTWFuYWdlci5zdHJlYW0uYXVkaW9BY3RpdmUgIT0gbnVsbCA/IHN0cmVhbU1hbmFnZXIuc3RyZWFtLmF1ZGlvQWN0aXZlIDogZmFsc2VcbiAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyAndmlkZW9EYXRhJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Jyb3dzZXIgJyArIHBsYXRmb3JtLmdldE5hbWUoKSArICcgKHZlcnNpb24gJyArIHBsYXRmb3JtLmdldFZlcnNpb24oKSArICcpIGZvciAnICsgcGxhdGZvcm0uZ2V0RmFtaWx5KCkgKyAnIGlzIG5vdCBzdXBwb3J0ZWQgaW4gT3BlblZpZHUgZm9yIE5ldHdvcmsgUXVhbGl0eScpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNlc3Npb25Db25uZWN0ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb24gIT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbm90Q29ubmVjdGVkRXJyb3IoKTogT3BlblZpZHVFcnJvciB7XG4gICAgICAgIHJldHVybiBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9OT1RfQ09OTkVDVEVELCBcIlRoZXJlIGlzIG5vIGNvbm5lY3Rpb24gdG8gdGhlIHNlc3Npb24uIE1ldGhvZCAnU2Vzc2lvbi5jb25uZWN0JyBtdXN0IGJlIHN1Y2Nlc3NmdWxseSBjb21wbGV0ZWQgZmlyc3RcIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFueVNwZWVjaEV2ZW50TGlzdGVuZXJFbmFibGVkKGV2ZW50OiBzdHJpbmcsIG9ubHlPbmNlOiBib29sZWFuLCBzdHJlYW1NYW5hZ2VyPzogU3RyZWFtTWFuYWdlcik6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgaGFuZGxlcnNJblNlc3Npb24gPSB0aGlzLmVlLmdldExpc3RlbmVycyhldmVudCk7XG4gICAgICAgIGlmIChvbmx5T25jZSkge1xuICAgICAgICAgICAgaGFuZGxlcnNJblNlc3Npb24gPSBoYW5kbGVyc0luU2Vzc2lvbi5maWx0ZXIoaCA9PiAoaCBhcyBhbnkpLm9uY2UpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBsaXN0ZW5lcnNJblNlc3Npb24gPSBoYW5kbGVyc0luU2Vzc2lvbi5sZW5ndGg7XG4gICAgICAgIGlmIChsaXN0ZW5lcnNJblNlc3Npb24gPiAwKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgbGV0IGxpc3RlbmVyc0luU3RyZWFtTWFuYWdlciA9IDA7XG4gICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXIpIHtcbiAgICAgICAgICAgIGxldCBoYW5kbGVyc0luU3RyZWFtTWFuYWdlciA9IHN0cmVhbU1hbmFnZXIuZWUuZ2V0TGlzdGVuZXJzKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChvbmx5T25jZSkge1xuICAgICAgICAgICAgICAgIGhhbmRsZXJzSW5TdHJlYW1NYW5hZ2VyID0gaGFuZGxlcnNJblN0cmVhbU1hbmFnZXIuZmlsdGVyKGggPT4gKGggYXMgYW55KS5vbmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpc3RlbmVyc0luU3RyZWFtTWFuYWdlciA9IGhhbmRsZXJzSW5TdHJlYW1NYW5hZ2VyLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGlzdGVuZXJzSW5TdHJlYW1NYW5hZ2VyID4gMDtcbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnN0YXJ0V3MoKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGpvaW5QYXJhbXMgPSB0aGlzLmluaXRpYWxpemVQYXJhbXModG9rZW4pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2pvaW5Sb29tJywgam9pblBhcmFtcywgKGVycm9yLCByZXNwb25zZTogTG9jYWxDb25uZWN0aW9uT3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByb2Nlc3Mgam9pbiByb29tIHJlc3BvbnNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzSm9pblJvb21SZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb25maWd1cmUgSlNOTG9nc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9wZW5WaWR1TG9nZ2VyLmNvbmZpZ3VyZUpTTkxvZyh0aGlzLm9wZW52aWR1LCB0b2tlbik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBSZW1vdGVDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaCgocmVtb3RlQ29ubmVjdGlvbk9wdGlvbnM6IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZW1vdGVDb25uZWN0aW9uT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuc2V0KGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLnNldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFB1Ymxpc2hlclN0cmVhbShyZWFzb246IHN0cmluZykge1xuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAvLyBEaXNwb3NlIFB1Ymxpc2hlcidzICBsb2NhbCBzdHJlYW1cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBNYWtlIFB1Ymxpc2hlciBvYmplY3QgZGlzcGF0Y2ggJ3N0cmVhbURlc3Ryb3llZCcgZXZlbnQgaWYgdGhlIFN0cmVhbSB3YXMgcHVibGlzaGVkXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lZS5lbWl0RXZlbnQoJ2xvY2FsLXN0cmVhbS1kZXN0cm95ZWQnLCBbcmVhc29uXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BWaWRlb0RhdGFJbnRlcnZhbHMoKTogdm9pZCB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy52aWRlb0RhdGFJbnRlcnZhbCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnZpZGVvRGF0YVRpbWVvdXQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RyaW5nQ2xpZW50TWV0YWRhdGEobWV0YWRhdGE6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0YWRhdGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWV0YWRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIGVycm9yTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5nZXQoY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgPT09IGNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIGxvY2FsIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmVtb3RlQ29ubmVjdGlvbihjb25uZWN0aW9uSWQ6IHN0cmluZywgb3BlcmF0aW9uOiBzdHJpbmcpOiBQcm9taXNlPENvbm5lY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbm5lY3Rpb24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgcmVtb3RlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdGUgY29ubmVjdGlvbiBub3QgZm91bmQuIFJlamVjdCB3aXRoIE9wZW5WaWR1RXJyb3JcbiAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSAnUmVtb3RlIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb25JZCArIFwiIHVua25vd24gd2hlbiAnXCIgKyBvcGVyYXRpb24gKyBcIicuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgJ0V4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogJyArIEpTT04uc3RyaW5naWZ5KHRoaXMucmVtb3RlQ29ubmVjdGlvbnMua2V5cygpKTtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuR0VORVJJQ19FUlJPUiwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1Rva2VuKHRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSB0b2tlbi5tYXRjaCgvXih3c3M/XFw6KVxcL1xcLygoW146XFwvPyNdKikoPzpcXDooWzAtOV0rKSk/KShbXFwvXXswLDF9W14/I10qKShcXD9bXiNdKnwpKCMuKnwpJC8pO1xuICAgICAgICBpZiAoISFtYXRjaCkge1xuICAgICAgICAgICAgY29uc3QgdXJsID0ge1xuICAgICAgICAgICAgICAgIHByb3RvY29sOiBtYXRjaFsxXSxcbiAgICAgICAgICAgICAgICBob3N0OiBtYXRjaFsyXSxcbiAgICAgICAgICAgICAgICBob3N0bmFtZTogbWF0Y2hbM10sXG4gICAgICAgICAgICAgICAgcG9ydDogbWF0Y2hbNF0sXG4gICAgICAgICAgICAgICAgcGF0aG5hbWU6IG1hdGNoWzVdLFxuICAgICAgICAgICAgICAgIHNlYXJjaDogbWF0Y2hbNl0sXG4gICAgICAgICAgICAgICAgaGFzaDogbWF0Y2hbN11cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHRva2VuLnNwbGl0KCc/Jyk7XG4gICAgICAgICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IGRlY29kZVVSSShwYXJhbXNbMV0pXG4gICAgICAgICAgICAgICAgLnNwbGl0KCcmJylcbiAgICAgICAgICAgICAgICAubWFwKHBhcmFtID0+IHBhcmFtLnNwbGl0KCc9JykpXG4gICAgICAgICAgICAgICAgLnJlZHVjZSgodmFsdWVzLCBba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzW2tleV0gPSB2YWx1ZVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWVzXG4gICAgICAgICAgICAgICAgfSwge30pO1xuXG4gICAgICAgICAgICB0aGlzLnNlc3Npb25JZCA9IDxzdHJpbmc+cXVlcnlQYXJhbXNbJ3Nlc3Npb25JZCddO1xuICAgICAgICAgICAgY29uc3Qgc2VjcmV0ID0gcXVlcnlQYXJhbXNbJ3NlY3JldCddO1xuICAgICAgICAgICAgY29uc3QgcmVjb3JkZXIgPSBxdWVyeVBhcmFtc1sncmVjb3JkZXInXTtcbiAgICAgICAgICAgIGNvbnN0IHdlYnJ0Y1N0YXRzSW50ZXJ2YWwgPSBxdWVyeVBhcmFtc1snd2VicnRjU3RhdHNJbnRlcnZhbCddO1xuICAgICAgICAgICAgY29uc3Qgc2VuZEJyb3dzZXJMb2dzID0gcXVlcnlQYXJhbXNbJ3NlbmRCcm93c2VyTG9ncyddO1xuXG4gICAgICAgICAgICBpZiAoISFzZWNyZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHNlY3JldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXJlY29yZGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF3ZWJydGNTdGF0c0ludGVydmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS53ZWJydGNTdGF0c0ludGVydmFsID0gK3dlYnJ0Y1N0YXRzSW50ZXJ2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISFzZW5kQnJvd3NlckxvZ3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRCcm93c2VyTG9ncyA9IHNlbmRCcm93c2VyTG9ncztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaXNQcm8gPSAhIXdlYnJ0Y1N0YXRzSW50ZXJ2YWwgJiYgISFzZW5kQnJvd3NlckxvZ3M7XG5cbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUud3NVcmkgPSAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdSc7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1Lmh0dHBVcmkgPSAnaHR0cHM6Ly8nICsgdXJsLmhvc3Q7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ1Rva2VuIFwiJyArIHRva2VuICsgJ1wiIGlzIG5vdCB2YWxpZCcpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHByb2Nlc3NKb2luUm9vbVJlc3BvbnNlKG9wdHM6IExvY2FsQ29ubmVjdGlvbk9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSBvcHRzLnNlc3Npb247XG4gICAgICAgIGlmIChvcHRzLmNvdHVybklwICE9IG51bGwgJiYgb3B0cy50dXJuVXNlcm5hbWUgIT0gbnVsbCAmJiBvcHRzLnR1cm5DcmVkZW50aWFsICE9IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHR1cm5VcmwxID0gJ3R1cm46JyArIG9wdHMuY290dXJuSXAgKyAnOjM0NzgnO1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5pY2VTZXJ2ZXJzID0gW1xuICAgICAgICAgICAgICAgIHsgdXJsczogW3R1cm5VcmwxXSwgdXNlcm5hbWU6IG9wdHMudHVyblVzZXJuYW1lLCBjcmVkZW50aWFsOiBvcHRzLnR1cm5DcmVkZW50aWFsIH1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiU1RVTi9UVVJOIHNlcnZlciBJUDogXCIgKyBvcHRzLmNvdHVybklwKTtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coJ1RVUk4gdGVtcCBjcmVkZW50aWFscyBbJyArIG9wdHMudHVyblVzZXJuYW1lICsgJzonICsgb3B0cy50dXJuQ3JlZGVudGlhbCArICddJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcGVudmlkdS5yb2xlID0gb3B0cy5yb2xlO1xuICAgICAgICB0aGlzLm9wZW52aWR1LmZpbmFsVXNlcklkID0gb3B0cy5maW5hbFVzZXJJZDtcbiAgICAgICAgdGhpcy5vcGVudmlkdS5tZWRpYVNlcnZlciA9IG9wdHMubWVkaWFTZXJ2ZXI7XG4gICAgICAgIHRoaXMuY2FwYWJpbGl0aWVzID0ge1xuICAgICAgICAgICAgc3Vic2NyaWJlOiB0cnVlLFxuICAgICAgICAgICAgcHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlICE9PSAnU1VCU0NSSUJFUicsXG4gICAgICAgICAgICBmb3JjZVVucHVibGlzaDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJyxcbiAgICAgICAgICAgIGZvcmNlRGlzY29ubmVjdDogdGhpcy5vcGVudmlkdS5yb2xlID09PSAnTU9ERVJBVE9SJ1xuICAgICAgICB9O1xuICAgICAgICBsb2dnZXIuaW5mbyhcIm9wZW52aWR1LXNlcnZlciB2ZXJzaW9uOiBcIiArIG9wdHMudmVyc2lvbik7XG4gICAgICAgIGlmIChvcHRzLnZlcnNpb24gIT09IHRoaXMub3BlbnZpZHUubGlicmFyeVZlcnNpb24pIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdPcGVuVmlkdSBTZXJ2ZXIgKCcgKyBvcHRzLnZlcnNpb24gK1xuICAgICAgICAgICAgICAgICcpIGFuZCBPcGVuVmlkdSBCcm93c2VyICgnICsgdGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbiArXG4gICAgICAgICAgICAgICAgJykgdmVyc2lvbnMgZG8gTk9UIG1hdGNoLiBUaGVyZSBtYXkgYmUgaW5jb21wYXRpYmlsaXRpZXMnKVxuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuL0ZpbHRlcic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuL1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBJbmJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0luYm91bmRTdHJlYW1PcHRpb25zJztcbmltcG9ydCB7IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL091dGJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBXZWJSdGNQZWVyLCBXZWJSdGNQZWVyU2VuZG9ubHksIFdlYlJ0Y1BlZXJSZWN2b25seSwgV2ViUnRjUGVlclNlbmRyZWN2LCBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjUGVlci9XZWJSdGNQZWVyJztcbmltcG9ydCB7IFdlYlJ0Y1N0YXRzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9XZWJSdGNTdGF0cy9XZWJSdGNTdGF0cyc7XG5pbXBvcnQgeyBFeGNlcHRpb25FdmVudCwgRXhjZXB0aW9uRXZlbnROYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXhjZXB0aW9uRXZlbnQnO1xuaW1wb3J0IHsgUHVibGlzaGVyU3BlYWtpbmdFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1B1Ymxpc2hlclNwZWFraW5nRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9VdGlscy9QbGF0Zm9ybSc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcbi8qKlxuICogQGhpZGRlblxuICovXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmxldCBwbGF0Zm9ybTogUGxhdGZvcm1VdGlscztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtLiBJZiB0aGUgc3RyZWFtIGJlbG9uZ3MgdG8gYS4uLlxuICAgICAqIC0gU3Vic2NyaWJlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgb25seSBkZWZpbmVkIGFmdGVyIHN1Y2Nlc3NmdWwgZXhlY3V0aW9uIG9mIFtbU2Vzc2lvbi5wdWJsaXNoXV1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgc3RyZWFtIHdhcyBjcmVhdGVkIGluIE9wZW5WaWR1IFNlcnZlciAoVVRDIG1pbGxpc2Vjb25kcykuIERlcGVuZGluZyBvbiB0aGUgb3duZXIgb2YgdGhpcyBzdHJlYW06XG4gICAgICogLSBTdWJzY3JpYmVyIG9iamVjdDogcHJvcGVydHkgYGNyZWF0aW9uVGltZWAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBjcmVhdGlvblRpbWVgIGlzIG9ubHkgZGVmaW5lZCBhZnRlciBzdWNjZXNzZnVsIGV4ZWN1dGlvbiBvZiBbW1Nlc3Npb24ucHVibGlzaF1dXG4gICAgICovXG4gICAgY3JlYXRpb25UaW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDYW4gYmU6XG4gICAgICogLSBgXCJDQU1FUkFcImA6IHdoZW4gdGhlIHZpZGVvIHNvdXJjZSBjb21lcyBmcm9tIGEgd2ViY2FtLlxuICAgICAqIC0gYFwiU0NSRUVOXCJgOiB3aGVuIHRoZSB2aWRlbyBzb3VyY2UgY29tZXMgZnJvbSBzY3JlZW4tc2hhcmluZy5cbiAgICAgKiAtIGBcIkNVU1RPTVwiYDogd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBpbiB0aGUgUHVibGlzaGVyIHNpZGUgd2l0aCBhIGN1c3RvbSBNZWRpYVN0cmVhbVRyYWNrIHdoZW4gY2FsbGluZyBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSkuXG4gICAgICogLSBgXCJJUENBTVwiYDogd2hlbiB0aGUgdmlkZW8gc291cmNlIGNvbWVzIGZyb20gYW4gSVAgY2FtZXJhIHBhcnRpY2lwYW50IGluc3RlYWQgb2YgYSByZWd1bGFyIHBhcnRpY2lwYW50IChzZWUgW0lQIGNhbWVyYXNdKC9lbi9zdGFibGUvYWR2YW5jZWQtZmVhdHVyZXMvaXAtY2FtZXJhcy8pKS5cbiAgICAgKlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFN0cmVhbU1hbmFnZXIgb2JqZWN0IChbW1B1Ymxpc2hlcl1dIG9yIFtbU3Vic2NyaWJlcl1dKSBpbiBjaGFyZ2Ugb2YgZGlzcGxheWluZyB0aGlzIHN0cmVhbSBpbiB0aGUgRE9NXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcjogU3RyZWFtTWFuYWdlcjtcblxuICAgIC8qKlxuICAgICAqIFdpZHRoIGFuZCBoZWlnaHQgaW4gcGl4ZWxzIG9mIHRoZSBlbmNvZGVkIHZpZGVvIHN0cmVhbS4gSWYgW1toYXNWaWRlb11dIGlzIGZhbHNlLCB0aGlzIHByb3BlcnR5IGlzIHVuZGVmaW5lZFxuICAgICAqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBtYXkgY2hhbmdlIGlmIHRoZSBQdWJsaXNoZXIgdGhhdCBpcyBwdWJsaXNoaW5nOlxuICAgICAqIC0gSWYgaXQgaXMgYSBtb2JpbGUgZGV2aWNlLCB3aGVuZXZlciB0aGUgdXNlciByb3RhdGVzIHRoZSBkZXZpY2UuXG4gICAgICogLSBJZiBpdCBpcyBzY3JlZW4tc2hhcmluZywgd2hlbmV2ZXIgdGhlIHVzZXIgY2hhbmdlcyB0aGUgc2l6ZSBvZiB0aGUgY2FwdHVyZWQgd2luZG93LlxuICAgICAqXG4gICAgICogV2hlbmV2ZXIgdGhpcyBoYXBwZW5zIGEgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9EaW1lbnNpb25zOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH07XG5cbiAgICAvKipcbiAgICAgKiAqKldBUk5JTkcqKjogZXhwZXJpbWVudGFsIG9wdGlvbi4gVGhpcyBpbnRlcmZhY2UgbWF5IGNoYW5nZSBpbiB0aGUgbmVhciBmdXR1cmVcbiAgICAgKlxuICAgICAqIEZpbHRlciBhcHBsaWVkIHRvIHRoZSBTdHJlYW0uIFlvdSBjYW4gYXBwbHkgZmlsdGVycyBieSBjYWxsaW5nIFtbU3RyZWFtLmFwcGx5RmlsdGVyXV0sIGV4ZWN1dGUgbWV0aG9kcyBvZiB0aGUgYXBwbGllZCBmaWx0ZXIgd2l0aFxuICAgICAqIFtbRmlsdGVyLmV4ZWNNZXRob2RdXSBhbmQgcmVtb3ZlIGl0IHdpdGggW1tTdHJlYW0ucmVtb3ZlRmlsdGVyXV0uIEJlIGF3YXJlIHRoYXQgdGhlIGNsaWVudCBjYWxsaW5nIHRoaXMgbWV0aG9kcyBtdXN0IGhhdmUgdGhlXG4gICAgICogbmVjZXNzYXJ5IHBlcm1pc3Npb25zOiB0aGUgdG9rZW4gb3duZWQgYnkgdGhlIGNsaWVudCBtdXN0IGhhdmUgYmVlbiBpbml0aWFsaXplZCB3aXRoIHRoZSBhcHByb3ByaWF0ZWQgYGFsbG93ZWRGaWx0ZXJzYCBhcnJheS5cbiAgICAgKi9cbiAgICBmaWx0ZXI/OiBGaWx0ZXI7XG5cbiAgICBwcm90ZWN0ZWQgd2ViUnRjUGVlcjogV2ViUnRjUGVlcjtcbiAgICBwcm90ZWN0ZWQgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbTtcbiAgICBwcml2YXRlIHdlYlJ0Y1N0YXRzOiBXZWJSdGNTdGF0cztcblxuICAgIHByaXZhdGUgaXNTdWJzY3JpYmVUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHB1Ymxpc2hlZE9uY2UgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbjogU2Vzc2lvbjtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5ib3VuZFN0cmVhbU9wdHM6IEluYm91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3BlZWNoRXZlbnQ6IGFueTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFya1NwZWFraW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrU3BlYWtpbmdFbmFibGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZE9uY2UgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhcmtPcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBsb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZT86IE1lZGlhU3RyZWFtO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyOiBFdmVudEVtaXR0ZXIgfCB1bmRlZmluZWQ7XG5cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBvcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyB8IE91dGJvdW5kU3RyZWFtT3B0aW9ucyB8IHt9KSB7XG5cbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2lkJykpIHtcbiAgICAgICAgICAgIC8vIEluYm91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFN1YnNjcmliZXJcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMgPSA8SW5ib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtSWQgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmlkO1xuICAgICAgICAgICAgdGhpcy5jcmVhdGlvblRpbWUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc0F1ZGlvO1xuICAgICAgICAgICAgdGhpcy5oYXNWaWRlbyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuaGFzVmlkZW87XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmF1ZGlvQWN0aXZlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy52aWRlb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gKCF0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvKSA/IHVuZGVmaW5lZCA6IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudHlwZU9mVmlkZW87XG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVJhdGUgPSAodGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5mcmFtZVJhdGUgPT09IC0xKSA/IHVuZGVmaW5lZCA6IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9EaW1lbnNpb25zID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZpbHRlciAmJiAoT2JqZWN0LmtleXModGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIpLmxlbmd0aCA+IDApKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2QgJiYgT2JqZWN0LmtleXModGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2QpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIubGFzdEV4ZWNNZXRob2Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdXRib3VuZFN0cmVhbU9wdGlvbnM6IHN0cmVhbSBiZWxvbmdzIHRvIGEgUHVibGlzaGVyXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IDxPdXRib3VuZFN0cmVhbU9wdGlvbnM+b3B0aW9ucztcblxuICAgICAgICAgICAgdGhpcy5oYXNBdWRpbyA9IHRoaXMuaXNTZW5kQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmlzU2VuZFZpZGVvKCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0FjdGl2ZSA9ICEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoQXVkaW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5mcmFtZVJhdGU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gJ0NVU1RPTSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IHRoaXMuaXNTZW5kU2NyZWVuKCkgPyAnU0NSRUVOJyA6ICdDQU1FUkEnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIgPSB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZpbHRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZWUub24oJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIudXBkYXRlTWVkaWFTdHJlYW0odGhpcy5tZWRpYVN0cmVhbSEpO1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKCdWaWRlbyBzcmNPYmplY3QgWycgKyB0aGlzLm1lZGlhU3RyZWFtICsgJ10gdXBkYXRlZCBpbiBzdHJlYW0gWycgKyB0aGlzLnN0cmVhbUlkICsgJ10nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBSZWNyZWF0ZXMgdGhlIG1lZGlhIGNvbm5lY3Rpb24gd2l0aCB0aGUgc2VydmVyLiBUaGlzIGVudGFpbHMgdGhlIGRpc3Bvc2FsIG9mIHRoZSBwcmV2aW91cyBSVENQZWVyQ29ubmVjdGlvbiBhbmQgdGhlIHJlLW5lZ290aWF0aW9uXG4gICAgICogb2YgYSBuZXcgb25lLCB0aGF0IHdpbGwgYXBwbHkgdGhlIHNhbWUgcHJvcGVydGllcy5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VmdWwgaW4gdGhvc2Ugc2l0dWF0aW9ucyB3ZXJlIHRoZXJlIHRoZSBtZWRpYSBjb25uZWN0aW9uIGJyZWFrcyBhbmQgT3BlblZpZHUgaXMgbm90IGFibGUgdG8gcmVjb3ZlciBvbiBpdHMgb3duXG4gICAgICogZm9yIGFueSBraW5kIG9mIHVuYW50aWNpcGF0ZWQgcmVhc29uIChzZWUgW0F1dG9tYXRpYyByZWNvbm5lY3Rpb25dKC9lbi9sYXRlc3QvYWR2YW5jZWQtZmVhdHVyZXMvYXV0b21hdGljLXJlY29ubmVjdGlvbi8pKS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb25uZWN0aW9uIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcHVibGljIHJlY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVjb25uZWN0U3RyZWFtKCdBUEknKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGFuIGF1ZGlvL3ZpZGVvIGZpbHRlciB0byB0aGUgc3RyZWFtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHR5cGUgVHlwZSBvZiBmaWx0ZXIgYXBwbGllZC4gU2VlIFtbRmlsdGVyLnR5cGVdXVxuICAgICAqIEBwYXJhbSBvcHRpb25zIFBhcmFtZXRlcnMgdXNlZCB0byBpbml0aWFsaXplIHRoZSBmaWx0ZXIuIFNlZSBbW0ZpbHRlci5vcHRpb25zXV1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCB0byB0aGUgYXBwbGllZCBmaWx0ZXIgaWYgc3VjY2VzcyBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgYXBwbHlGaWx0ZXIodHlwZTogc3RyaW5nLCBvcHRpb25zOiBPYmplY3QpOiBQcm9taXNlPEZpbHRlcj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbi5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZWplY3QodGhpcy5zZXNzaW9uLm5vdENvbm5lY3RlZEVycm9yKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsb2dnZXIuaW5mbygnQXBwbHlpbmcgZmlsdGVyIHRvIHN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCk7XG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyAhPSBudWxsID8gb3B0aW9ucyA6IHt9O1xuICAgICAgICAgICAgbGV0IG9wdGlvbnNTdHJpbmcgPSBvcHRpb25zO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zU3RyaW5nICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIG9wdGlvbnNTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zU3RyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAnYXBwbHlGaWx0ZXInLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtSWQsIHR5cGUsIG9wdGlvbnM6IG9wdGlvbnNTdHJpbmcgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBhcHBseWluZyBmaWx0ZXIgZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBhcHBseSBhIGZpbHRlclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRmlsdGVyIHN1Y2Nlc3NmdWxseSBhcHBsaWVkIG9uIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZTogRmlsdGVyID0gdGhpcy5maWx0ZXIhO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIgPSBuZXcgRmlsdGVyKHR5cGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIuc3RyZWFtID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zZXNzaW9uLCB0aGlzLCAnZmlsdGVyJywgdGhpcy5maWx0ZXIsIG9sZFZhbHVlLCAnYXBwbHlGaWx0ZXInKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciwgb2xkVmFsdWUsICdhcHBseUZpbHRlcicpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuZmlsdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW4gYXVkaW8vdmlkZW8gZmlsdGVyIHByZXZpb3VzbHkgYXBwbGllZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcHJldmlvdXNseSBhcHBsaWVkIGZpbHRlciBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaW4gb3RoZXIgY2FzZVxuICAgICAqL1xuICAgIHJlbW92ZUZpbHRlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlc3Npb24uc2Vzc2lvbkNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KHRoaXMuc2Vzc2lvbi5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1JlbW92aW5nIGZpbHRlciBvZiBzdHJlYW0gJyArIHRoaXMuc3RyZWFtSWQpO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICdyZW1vdmVGaWx0ZXInLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciByZW1vdmluZyBmaWx0ZXIgZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byByZW1vdmUgYSBmaWx0ZXJcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZpbHRlciBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBmcm9tIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHRoaXMuZmlsdGVyITtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpbHRlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zZXNzaW9uLCB0aGlzLCAnZmlsdGVyJywgdGhpcy5maWx0ZXIhLCBvbGRWYWx1ZSwgJ2FwcGx5RmlsdGVyJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCB0aGlzLCAnZmlsdGVyJywgdGhpcy5maWx0ZXIhLCBvbGRWYWx1ZSwgJ2FwcGx5RmlsdGVyJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGludGVybmFsIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHRvIHRoaXMgc3RyZWFtIChodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUlRDUGVlckNvbm5lY3Rpb24pXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBOYXRpdmUgUlRDUGVlckNvbm5lY3Rpb24gV2ViIEFQSSBvYmplY3RcbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaW50ZXJuYWwgTWVkaWFTdHJlYW0gb2JqZWN0IGFzc29jaWF0ZWQgdG8gdGhpcyBzdHJlYW0gKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9NZWRpYVN0cmVhbSlcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIE5hdGl2ZSBNZWRpYVN0cmVhbSBXZWIgQVBJIG9iamVjdFxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW0hO1xuICAgIH1cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2V0TWVkaWFTdHJlYW0obWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBtZWRpYVN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdXBkYXRlTWVkaWFTdHJlYW1JblZpZGVvcygpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ21lZGlhc3RyZWFtLXVwZGF0ZWQnLCBbXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFdlYlJ0Y1BlZXIoKTogV2ViUnRjUGVlciB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvTXlSZW1vdGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE91dGJvdW5kU3RyZWFtT3B0aW9ucyhvdXRib3VuZFN0cmVhbU9wdHM6IE91dGJvdW5kU3RyZWFtT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA9IG91dGJvdW5kU3RyZWFtT3B0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3Vic2NyaWJlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclJlY2VpdmUoZmFsc2UpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJTZW5kKGZhbHNlKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vbmNlKCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlV2ViUnRjUGVlcigpOiB2b2lkIHtcbiAgICAgICAgbGV0IHdlYnJ0Y0lkO1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1BlZXIpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5kaXNwb3NlKCk7XG4gICAgICAgICAgICB3ZWJydGNJZCA9IHRoaXMud2ViUnRjUGVlci5nZXRJZCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKCghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzID8gJ091dGJvdW5kICcgOiAnSW5ib3VuZCAnKSArIFwiUlRDUGVlckNvbm5lY3Rpb24gd2l0aCBpZCBbXCIgKyB3ZWJydGNJZCArIFwiXSBmcm9tICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW1JZCArICddIGlzIG5vdyBjbG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZU1lZGlhU3RyZWFtKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHN1YnNjcmliZVRvUmVtb3RlIGxvY2FsIE1lZGlhU3RyZWFtIG11c3QgYmUgc3RvcHBlZFxuICAgICAgICBpZiAodGhpcy5sb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZSkge1xuICAgICAgICAgICAgdGhpcy5sb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQuc3RvcCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3BlZWNoRXZlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmluZm8oKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwgJyA6ICdSZW1vdGUgJykgKyBcIk1lZGlhU3RyZWFtIGZyb20gJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbUlkICsgJ10gaXMgbm93IGRpc3Bvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc3BsYXlNeVJlbW90ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kQXVkaW8oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRWaWRlbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFNjcmVlbigpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHNjcmVlbiA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgPT09ICdzY3JlZW4nO1xuICAgICAgICBpZiAocGxhdGZvcm0uaXNFbGVjdHJvbigpKSB7XG4gICAgICAgICAgICBzY3JlZW4gPSB0eXBlb2YgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlLnN0YXJ0c1dpdGgoJ3NjcmVlbjonKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyAmJiBzY3JlZW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZUhhcmtTcGVha2luZ0V2ZW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldEhhcmtMaXN0ZW5lcklmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy5oYXJrU3BlYWtpbmdFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7IC8vIERpc2FibGUgJ29uY2UnIHZlcnNpb24gaWYgJ29uJyB2ZXJzaW9uIHdhcyB0cmlnZ2VyZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VIYXJrU3BlYWtpbmdFdmVudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpO1xuICAgICAgICBpZiAoIXRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbmNlKCdzcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3BlYWtpbmdFbmFibGVkT25jZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgaGFzIGJlZW4gZGlzYWJsZWQgaW4gdGhlIG1lYW50aW1lIChmb3IgZXhhbXBsZSBieSB0aGUgJ29uJyB2ZXJzaW9uKSBkbyBub3QgdHJpZ2dlciB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc3RyZWFtTWFuYWdlciwgJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUhhcmtTcGVha2luZ0V2ZW50KHRydWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYWJsZUhhcmtTcGVha2luZ0V2ZW50KGRpc2FibGVkQnlPbmNlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChkaXNhYmxlZEJ5T25jZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlICdvbicgdmVyc2lvbiBvZiB0aGlzIHNhbWUgZXZlbnQgaXMgZW5hYmxlZCB0b28uIERvIG5vdCByZW1vdmUgdGhlIGhhcmsgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3BlYWtpbmdFbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTaHV0dGluZyBkb3duIHRoZSBoYXJrIGV2ZW50XG4gICAgICAgICAgICBpZiAodGhpcy5oYXJrVm9sdW1lQ2hhbmdlRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gU29tZSBvdGhlciBoYXJrIGV2ZW50IGlzIGVuYWJsZWQuIENhbm5vdCBzdG9wIHRoZSBoYXJrIHByb2Nlc3MsIGp1c3QgcmVtb3ZlIHRoZSBzcGVjaWZpYyBsaXN0ZW5lclxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCdzcGVha2luZycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBObyBvdGhlciBoYXJrIGV2ZW50IGlzIGVuYWJsZWQuIFdlIGNhbiBnZXQgZW50aXJlbHkgcmlkIG9mIGl0XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3BlZWNoRXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW5hYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldEhhcmtMaXN0ZW5lcklmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCdzdG9wcGVkX3NwZWFraW5nJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc3RyZWFtTWFuYWdlciwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkT25jZSA9IGZhbHNlOyAvLyBEaXNhYmxlICdvbmNlJyB2ZXJzaW9uIGlmICdvbicgdmVyc2lvbiB3YXMgdHJpZ2dlcmVkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbmFibGVPbmNlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldEhhcmtMaXN0ZW5lcklmTm90RXhpc3RzKCk7XG4gICAgICAgIGlmICghdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub25jZSgnc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIGhhcyBiZWVuIGRpc2FibGVkIGluIHRoZSBtZWFudGltZSAoZm9yIGV4YW1wbGUgYnkgdGhlICdvbicgdmVyc2lvbikgZG8gbm90IHRyaWdnZXIgdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCh0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBkaXNhYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KGRpc2FibGVkQnlPbmNlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoZGlzYWJsZWRCeU9uY2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgY2FuY2VsbGluZyB0aGUgJ29uY2UnIGxpc3RlbmVyIGZvciB0aGlzIGV2ZW50LCBidXQgdGhlICdvbicgdmVyc2lvblxuICAgICAgICAgICAgICAgICAgICAvLyBvZiB0aGlzIHNhbWUgZXZlbnQgaXMgZW5hYmxlZCB0b28uIERvIG5vdCByZW1vdmUgdGhlIGhhcmsgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2h1dHRpbmcgZG93biB0aGUgaGFyayBldmVudFxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyBTb21lIG90aGVyIGhhcmsgZXZlbnQgaXMgZW5hYmxlZC4gQ2Fubm90IHN0b3AgdGhlIGhhcmsgcHJvY2VzcywganVzdCByZW1vdmUgdGhlIHNwZWNpZmljIGxpc3RlbmVyXG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vZmYoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gTm8gb3RoZXIgaGFyayBldmVudCBpcyBlbmFibGVkLiBXZSBjYW4gZ2V0IGVudGlyZWx5IHJpZCBvZiBpdFxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNwZWVjaEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudChmb3JjZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgfHwgZm9yY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCd2b2x1bWVfY2hhbmdlJywgaGFya0V2ZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHsgbmV3VmFsdWU6IGhhcmtFdmVudCwgb2xkVmFsdWUgfTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbGRWb2x1bWVWYWx1ZSA9IGhhcmtFdmVudDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScsIHZhbHVlKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2hlbmV2ZXIgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpcyBhdmFpbGFibGUsIHRoZSBldmVudCBsaXN0ZW5lciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWRcbiAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VIYXJrVm9sdW1lQ2hhbmdlRXZlbnQoZm9yY2U6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0SGFya0xpc3RlbmVySWZOb3RFeGlzdHMoKSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSB8fCBmb3JjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uY2UoJ3ZvbHVtZV9jaGFuZ2UnLCBoYXJrRXZlbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHRoaXMuc3BlZWNoRXZlbnQub2xkVm9sdW1lVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0geyBuZXdWYWx1ZTogaGFya0V2ZW50LCBvbGRWYWx1ZSB9O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlID0gaGFya0V2ZW50O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVIYXJrVm9sdW1lQ2hhbmdlRXZlbnQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnLCB2YWx1ZSldKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdoZW5ldmVyIHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaXMgYXZhaWxhYmxlLCB0aGUgZXZlbnQgbGlzdGVuZXIgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGFkZGVkXG4gICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudChkaXNhYmxlZEJ5T25jZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGRpc2FibGVkQnlPbmNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGNhbmNlbGxpbmcgdGhlICdvbmNlJyBsaXN0ZW5lciBmb3IgdGhpcyBldmVudCwgYnV0IHRoZSAnb24nIHZlcnNpb25cbiAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhpcyBzYW1lIGV2ZW50IGlzIGVuYWJsZWQgdG9vLiBEbyBub3QgcmVtb3ZlIHRoZSBoYXJrIGxpc3RlbmVyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNodXR0aW5nIGRvd24gdGhlIGhhcmsgZXZlbnRcbiAgICAgICAgICAgIGlmICh0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gU29tZSBvdGhlciBoYXJrIGV2ZW50IGlzIGVuYWJsZWQuIENhbm5vdCBzdG9wIHRoZSBoYXJrIHByb2Nlc3MsIGp1c3QgcmVtb3ZlIHRoZSBzcGVjaWZpYyBsaXN0ZW5lclxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCd2b2x1bWVfY2hhbmdlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE5vIG90aGVyIGhhcmsgZXZlbnQgaXMgZW5hYmxlZC4gV2UgY2FuIGdldCBlbnRpcmVseSByaWQgb2YgaXRcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zcGVlY2hFdmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtSWNlQ29ubmVjdGlvblN0YXRlQnJva2VuKCkge1xuICAgICAgICBpZiAoIXRoaXMuZ2V0V2ViUnRjUGVlcigpIHx8ICF0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0xvY2FsKCkgJiYgISF0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmZvcmNlTWVkaWFSZWNvbm5lY3Rpb25BZnRlck5ldHdvcmtEcm9wKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihgT3BlblZpZHUgQnJvd3NlciBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbiBcImZvcmNlTWVkaWFSZWNvbm5lY3Rpb25BZnRlck5ldHdvcmtEcm9wXCIgaXMgZW5hYmxlZC4gU3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSkgd2lsbCBmb3JjZSBhIHJlY29ubmVjdGlvbmApO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaWNlQ29ubmVjdGlvblN0YXRlOiBSVENJY2VDb25uZWN0aW9uU3RhdGUgPSB0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuaWNlQ29ubmVjdGlvblN0YXRlO1xuICAgICAgICByZXR1cm4gaWNlQ29ubmVjdGlvblN0YXRlICE9PSAnY29ubmVjdGVkJyAmJiBpY2VDb25uZWN0aW9uU3RhdGUgIT09ICdjb21wbGV0ZWQnO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSAhIXRoaXMuaGFya09wdGlvbnMgPyB0aGlzLmhhcmtPcHRpb25zIDogKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9KTtcbiAgICAgICAgICAgICAgICBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9ICh0eXBlb2YgaGFya09wdGlvbnMuaW50ZXJ2YWwgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLmludGVydmFsIDogMTAwO1xuICAgICAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXR1cFJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcihyZXNvbHZlOiAodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZCwgcmVqZWN0OiAocmVhc29uPzogYW55KSA9PiB2b2lkKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICh0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciA9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIG9uZ29pbmcgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICB0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9uZ29pbmcgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFRyeWluZyB0byByZWNvbm5lY3Qgc3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7dGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJ30pIGJ1dCBhbiBvbmdvaW5nIHJlY29ubmVjdGlvbiBwcm9jZXNzIGlzIGFjdGl2ZS4gV2FpdGluZyBmb3IgcmVzcG9uc2UuLi5gKTtcbiAgICAgICAgICAgIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyLm9uY2UoJ3N1Y2Nlc3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlci5vbmNlKCdlcnJvcicsIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0V2ViUnRjUGVlclNlbmQocmVjb25uZWN0OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR1cFJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcihyZXNvbHZlLCByZWplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9uZ29pbmcgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE1lZGlhU3RyZWFtIHdpbGwgYWxyZWFkeSBoYXZlIGhhcmsgZXZlbnRzIGZvciByZWNvbm5lY3RlZCBzdHJlYW1zXG4gICAgICAgICAgICAgICAgdGhpcy5pbml0SGFya0V2ZW50cygpOyAvLyBJbml0IGhhcmsgZXZlbnRzIGZvciB0aGUgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbmFsUmVzb2x2ZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyPy5lbWl0RXZlbnQoJ3N1Y2Nlc3MnKTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbmFsUmVqZWN0ID0gZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI/LmVtaXRFdmVudCgnZXJyb3InLCBbZXJyb3JdKTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzT2ZmZXJDYWxsYmFjayA9IChzZHBPZmZlclBhcmFtKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKCdTZW5kaW5nIFNEUCBvZmZlciB0byBwdWJsaXNoIGFzICdcbiAgICAgICAgICAgICAgICAgICAgKyB0aGlzLnN0cmVhbUlkLCBzZHBPZmZlclBhcmFtKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG1ldGhvZCA9IHJlY29ubmVjdCA/ICdyZWNvbm5lY3RTdHJlYW0nIDogJ3B1Ymxpc2hWaWRlbyc7XG4gICAgICAgICAgICAgICAgbGV0IHBhcmFtcztcbiAgICAgICAgICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbTogdGhpcy5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNkcFN0cmluZzogc2RwT2ZmZXJQYXJhbVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHR5cGVPZlZpZGVvID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvID0gKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykgPyAnQ1VTVE9NJyA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gJ1NDUkVFTicgOiAnQ0FNRVJBJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9Mb29wYmFjazogdGhpcy5kaXNwbGF5TXlSZW1vdGUoKSB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0F1ZGlvOiB0aGlzLmlzU2VuZEF1ZGlvKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNWaWRlbzogdGhpcy5pc1NlbmRWaWRlbygpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IHRoaXMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWRlb0FjdGl2ZTogdGhpcy52aWRlb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvLFxuICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWVSYXRlOiAhIXRoaXMuZnJhbWVSYXRlID8gdGhpcy5mcmFtZVJhdGUgOiAtMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvRGltZW5zaW9uczogSlNPTi5zdHJpbmdpZnkodGhpcy52aWRlb0RpbWVuc2lvbnMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyOiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZpbHRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNkcE9mZmVyOiBzZHBPZmZlclBhcmFtXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QobWV0aG9kLCBwYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gcHVibGlzaFwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVqZWN0KCdFcnJvciBvbiBwdWJsaXNoVmlkZW86ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NSZW1vdGVBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1JZCA9IHJlc3BvbnNlLmlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IHJlc3BvbnNlLmNyZWF0ZWRBdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxNZWRpYVN0cmVhbVdoZW5TdWJzY3JpYmVkVG9SZW1vdGUgPSB0aGlzLm1lZGlhU3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQocmVjb25uZWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlY29ubmVjdGVkLWJ5LXB1Ymxpc2hlcicsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCBbXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCInUHVibGlzaGVyJyAoXCIgKyB0aGlzLnN0cmVhbUlkICsgXCIpIHN1Y2Nlc3NmdWxseSBcIiArIChyZWNvbm5lY3QgPyBcInJlY29ubmVjdGVkXCIgOiBcInB1Ymxpc2hlZFwiKSArIFwiIHRvIHNlc3Npb25cIik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZzogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uZW5hYmxlU2ltdWxjYXN0RXhwZXJpbWVudGFsIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgIG9uSWNlQ2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgb25JY2VDb25uZWN0aW9uU3RhdGVFeGNlcHRpb246IChleGNlcHRpb25OYW1lOiBFeGNlcHRpb25FdmVudE5hbWUsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IGFueSkgPT4geyB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdleGNlcHRpb24nLCBbbmV3IEV4Y2VwdGlvbkV2ZW50KHRoaXMuc2Vzc2lvbiwgZXhjZXB0aW9uTmFtZSwgdGhpcywgbWVzc2FnZSwgZGF0YSldKSB9LFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbTogdGhpcy5tZWRpYVN0cmVhbSxcbiAgICAgICAgICAgICAgICBtZWRpYVNlcnZlcjogdGhpcy5zZXNzaW9uLm9wZW52aWR1Lm1lZGlhU2VydmVyXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRyZWN2KGNvbmZpZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyU2VuZG9ubHkoY29uZmlnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5hZGRJY2VDb25uZWN0aW9uU3RhdGVDaGFuZ2VMaXN0ZW5lcigncHVibGlzaGVyIG9mICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5jcmVhdGVPZmZlcigpLnRoZW4oc2RwT2ZmZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzTG9jYWxPZmZlcihzZHBPZmZlcilcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc09mZmVyQ2FsbGJhY2soc2RwT2ZmZXIuc2RwKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIHByb2Nlc3MgbG9jYWwgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgZmluYWxSZWplY3QobmV3IEVycm9yKCcocHVibGlzaCkgU0RQIGNyZWF0ZSBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaW5hbFJlc29sdmVGb3JTdWJzY3JpcHRpb24ocmVjb25uZWN0OiBib29sZWFuLCByZXNvbHZlOiAodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZCkge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIidTdWJzY3JpYmVyJyAoXCIgKyB0aGlzLnN0cmVhbUlkICsgXCIpIHN1Y2Nlc3NmdWxseSBcIiArIChyZWNvbm5lY3QgPyBcInJlY29ubmVjdGVkXCIgOiBcInN1YnNjcmliZWRcIikpO1xuICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZChyZWNvbm5lY3QpO1xuICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICB0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcj8uZW1pdEV2ZW50KCdzdWNjZXNzJyk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBmaW5hbFJlamVjdEZvclN1YnNjcmlwdGlvbihyZWNvbm5lY3Q6IGJvb2xlYW4sIGVycm9yOiBhbnksIHJlamVjdDogKHJlYXNvbj86IGFueSkgPT4gdm9pZCkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBmb3IgJ1N1YnNjcmliZXInIChcIiArIHRoaXMuc3RyZWFtSWQgKyBcIikgd2hpbGUgdHJ5aW5nIHRvIFwiICsgKHJlY29ubmVjdCA/IFwicmVjb25uZWN0XCIgOiBcInN1YnNjcmliZVwiKSArIFwiOiBcIiArIGVycm9yLnRvU3RyaW5nKCkpO1xuICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICB0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcj8uZW1pdEV2ZW50KCdlcnJvcicsIFtlcnJvcl0pO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyO1xuICAgICAgICB9XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyUmVjZWl2ZShyZWNvbm5lY3Q6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHVwUmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyKHJlc29sdmUsIHJlamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT25nb2luZyByZWNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5tZWRpYVNlcnZlciA9PT0gJ21lZGlhc291cCcpIHtcblxuICAgICAgICAgICAgICAgIC8vIFNlcnZlciBpbml0aWF0ZXMgbmVnb3RpYXRpb25cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlRnJvbVNlcnZlcihyZWNvbm5lY3QpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuZmluYWxSZXNvbHZlRm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdCwgcmVzb2x2ZSkpXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB0aGlzLmZpbmFsUmVqZWN0Rm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdCwgZXJyb3IsIHJlamVjdCkpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gQ2xpZW50IGluaXRpYXRlcyBuZWdvdGlhdGlvblxuXG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclJlY2VpdmVGcm9tQ2xpZW50KHJlY29ubmVjdClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5maW5hbFJlc29sdmVGb3JTdWJzY3JpcHRpb24ocmVjb25uZWN0LCByZXNvbHZlKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuZmluYWxSZWplY3RGb3JTdWJzY3JpcHRpb24ocmVjb25uZWN0LCBlcnJvciwgcmVqZWN0KSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyUmVjZWl2ZUZyb21DbGllbnQocmVjb25uZWN0OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbXBsZXRlV2ViUnRjUGVlclJlY2VpdmUocmVjb25uZWN0LCBmYWxzZSkudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NSZW1vdGVBbnN3ZXIocmVzcG9uc2Uuc2RwQW5zd2VyKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0V2ViUnRjUGVlclJlY2VpdmVGcm9tU2VydmVyKHJlY29ubmVjdDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgLy8gU2VydmVyIGluaXRpYXRlcyBuZWdvdGlhdGlvblxuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdwcmVwYXJlUmVjZWl2ZVZpZGVvRnJvbScsIHsgc2VuZGVyOiB0aGlzLnN0cmVhbUlkLCByZWNvbm5lY3QgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiBwcmVwYXJlUmVjZWl2ZVZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGxldGVXZWJSdGNQZWVyUmVjZWl2ZShyZWNvbm5lY3QsIGZhbHNlLCByZXNwb25zZS5zZHBPZmZlcilcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb21wbGV0ZVdlYlJ0Y1BlZXJSZWNlaXZlKHJlY29ubmVjdDogYm9vbGVhbiwgZm9yY2libHlSZWNvbm5lY3Q6IGJvb2xlYW4sIHNkcE9mZmVyQnlTZXJ2ZXI/OiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoXCInU2Vzc2lvbi5zdWJzY3JpYmUoU3RyZWFtKScgY2FsbGVkXCIpO1xuXG4gICAgICAgICAgICBjb25zdCBzZW5kU2RwVG9TZXJ2ZXIgPSAoc2RwU3RyaW5nOiBzdHJpbmcpID0+IHtcblxuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgU2VuZGluZyBsb2NhbCBTRFAgJHsoISFzZHBPZmZlckJ5U2VydmVyID8gJ2Fuc3dlcicgOiAnb2ZmZXInKX0gdG8gc3Vic2NyaWJlIHRvICR7dGhpcy5zdHJlYW1JZH1gLCBzZHBTdHJpbmcpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbWV0aG9kID0gcmVjb25uZWN0ID8gJ3JlY29ubmVjdFN0cmVhbScgOiAncmVjZWl2ZVZpZGVvRnJvbSc7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFyYW1zID0ge307XG4gICAgICAgICAgICAgICAgcGFyYW1zW3JlY29ubmVjdCA/ICdzdHJlYW0nIDogJ3NlbmRlciddID0gdGhpcy5zdHJlYW1JZDtcbiAgICAgICAgICAgICAgICBpZiAoISFzZHBPZmZlckJ5U2VydmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtc1tyZWNvbm5lY3QgPyAnc2RwU3RyaW5nJyA6ICdzZHBBbnN3ZXInXSA9IHNkcFN0cmluZztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbJ3NkcE9mZmVyJ10gPSBzZHBTdHJpbmc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zWydmb3JjaWJseVJlY29ubmVjdCddID0gZm9yY2libHlSZWNvbm5lY3Q7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gJyArIG1ldGhvZCArICcgOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgY29uZmlnOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDogZmFsc2UsXG4gICAgICAgICAgICAgICAgb25JY2VDYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBvbkljZUNvbm5lY3Rpb25TdGF0ZUV4Y2VwdGlvbjogKGV4Y2VwdGlvbk5hbWU6IEV4Y2VwdGlvbkV2ZW50TmFtZSwgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogYW55KSA9PiB7IHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ2V4Y2VwdGlvbicsIFtuZXcgRXhjZXB0aW9uRXZlbnQodGhpcy5zZXNzaW9uLCBleGNlcHRpb25OYW1lLCB0aGlzLCBtZXNzYWdlLCBkYXRhKV0pIH0sXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIG1lZGlhU2VydmVyOiB0aGlzLnNlc3Npb24ub3BlbnZpZHUubWVkaWFTZXJ2ZXJcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlciA9IG5ldyBXZWJSdGNQZWVyUmVjdm9ubHkoY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5hZGRJY2VDb25uZWN0aW9uU3RhdGVDaGFuZ2VMaXN0ZW5lcih0aGlzLnN0cmVhbUlkKTtcblxuICAgICAgICAgICAgaWYgKCEhc2RwT2ZmZXJCeVNlcnZlcikge1xuXG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NSZW1vdGVPZmZlcihzZHBPZmZlckJ5U2VydmVyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmNyZWF0ZUFuc3dlcigpLnRoZW4oc2RwQW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzTG9jYWxBbnN3ZXIoc2RwQW5zd2VyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kU2RwVG9TZXJ2ZXIoc2RwQW5zd2VyLnNkcCEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBwcm9jZXNzIGxvY2FsIGFuc3dlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBjcmVhdGUgYW5zd2VyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIHByb2Nlc3MgcmVtb3RlIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuY3JlYXRlT2ZmZXIoKS50aGVuKHNkcE9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLnByb2Nlc3NMb2NhbE9mZmVyKHNkcE9mZmVyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRTZHBUb1NlcnZlcihzZHBPZmZlci5zZHAhKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIHByb2Nlc3MgbG9jYWwgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgY3JlYXRlIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZChyZWNvbm5lY3Q6IGJvb2xlYW4pOiB2b2lkIHtcblxuICAgICAgICBpZiAocmVjb25uZWN0ICYmIHRoaXMubWVkaWFTdHJlYW0gIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gTm93IHdlIGNhbiBkZXN0cm95IHRoZSBleGlzdGluZyBNZWRpYVN0cmVhbVxuICAgICAgICAgICAgdGhpcy5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBuZXcgTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgbGV0IHJlY2VpdmVyOiBSVENSdHBSZWNlaXZlcjtcbiAgICAgICAgZm9yIChyZWNlaXZlciBvZiB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVjZWl2ZXJzKCkpIHtcbiAgICAgICAgICAgIGlmICghIXJlY2VpdmVyLnRyYWNrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5hZGRUcmFjayhyZWNlaXZlci50cmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbU1hbmFnZXIgaW5zdGFuY2VvZiBTdWJzY3JpYmVyKSB7XG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgU3Vic2NyaWJlclByb3BlcnRpZXMuc3Vic2NyaWJlVG9BdWRpbyBhbmQgU3Vic2NyaWJlclByb3BlcnRpZXMuc3Vic2NyaWJlVG9WaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmFibGVkID0gcmVjb25uZWN0ID8gdGhpcy5hdWRpb0FjdGl2ZSA6ICEhKCh0aGlzLnN0cmVhbU1hbmFnZXIgYXMgU3Vic2NyaWJlcikucHJvcGVydGllcy5zdWJzY3JpYmVUb0F1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9IHJlY29ubmVjdCA/IHRoaXMudmlkZW9BY3RpdmUgOiAhISgodGhpcy5zdHJlYW1NYW5hZ2VyIGFzIFN1YnNjcmliZXIpLnByb3BlcnRpZXMuc3Vic2NyaWJlVG9WaWRlbyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gZW5hYmxlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXBkYXRlTWVkaWFTdHJlYW1JblZpZGVvcygpO1xuICAgICAgICAgICAgdGhpcy5pbml0SGFya0V2ZW50cygpOyAvLyBJbml0IGhhcmsgZXZlbnRzIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0SGFya0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSEuZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgLy8gSGFyayBldmVudHMgY2FuIG9ubHkgYmUgc2V0IGlmIGF1ZGlvIHRyYWNrIGlzIGF2YWlsYWJsZVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRydWUsIHRoaXMuc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZU9uY2VIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlLCB0aGlzLnN0cmVhbU1hbmFnZXIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdHJ1ZSwgdGhpcy5zdHJlYW1NYW5hZ2VyKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgZmFsc2UsIHRoaXMuc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVPbmNlSGFya1ZvbHVtZUNoYW5nZUV2ZW50KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudCh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25JY2VDb25uZWN0aW9uU3RhdGVFeGNlcHRpb25IYW5kbGVyKGV4Y2VwdGlvbk5hbWU6IEV4Y2VwdGlvbkV2ZW50TmFtZSwgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogYW55KTogdm9pZCB7XG4gICAgICAgIHN3aXRjaCAoZXhjZXB0aW9uTmFtZSkge1xuICAgICAgICAgICAgY2FzZSBFeGNlcHRpb25FdmVudE5hbWUuSUNFX0NPTk5FQ1RJT05fRkFJTEVEOlxuICAgICAgICAgICAgICAgIHRoaXMub25JY2VDb25uZWN0aW9uRmFpbGVkKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEV4Y2VwdGlvbkV2ZW50TmFtZS5JQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5vbkljZUNvbm5lY3Rpb25EaXNjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdleGNlcHRpb24nLCBbbmV3IEV4Y2VwdGlvbkV2ZW50KHRoaXMuc2Vzc2lvbiwgZXhjZXB0aW9uTmFtZSwgdGhpcywgbWVzc2FnZSwgZGF0YSldKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uSWNlQ29ubmVjdGlvbkZhaWxlZCgpIHtcbiAgICAgICAgLy8gSW1tZWRpYXRlbHkgcmVjb25uZWN0LCBhcyB0aGlzIGlzIGEgdGVybWluYWwgZXJyb3JcbiAgICAgICAgbG9nZ2VyLmxvZyhgW0lDRV9DT05ORUNUSU9OX0ZBSUxFRF0gSGFuZGxpbmcgSUNFX0NPTk5FQ1RJT05fRkFJTEVEIGV2ZW50LiBSZWNvbm5lY3Rpbmcgc3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSlgKTtcbiAgICAgICAgdGhpcy5yZWNvbm5lY3RTdHJlYW1BbmRMb2dSZXN1bHRpbmdJY2VDb25uZWN0aW9uU3RhdGUoRXhjZXB0aW9uRXZlbnROYW1lLklDRV9DT05ORUNUSU9OX0ZBSUxFRCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkljZUNvbm5lY3Rpb25EaXNjb25uZWN0ZWQoKSB7XG4gICAgICAgIC8vIFdhaXQgdG8gc2VlIGlmIHRoZSBJQ0UgY29ubmVjdGlvbiBpcyBhYmxlIHRvIHJlY29ubmVjdFxuICAgICAgICBsb2dnZXIubG9nKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBIYW5kbGluZyBJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQgZXZlbnQuIFdhaXRpbmcgZm9yIElDRSB0byBiZSByZXN0b3JlZCBhbmQgcmVjb25uZWN0IHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9ICgkeyh0aGlzLmlzTG9jYWwoKSA/ICdQdWJsaXNoZXInIDogJ1N1YnNjcmliZXInKX0pIGlmIG5vdCBwb3NzaWJsZWApO1xuICAgICAgICBjb25zdCB0aW1lb3V0ID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VDb25uZWN0aW9uRGlzY29ubmVjdGVkRXhjZXB0aW9uVGltZW91dCB8fCA0MDAwO1xuICAgICAgICB0aGlzLmF3YWl0V2ViUnRjUGVlckNvbm5lY3Rpb25TdGF0ZSh0aW1lb3V0KS50aGVuKHN0YXRlID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdmYWlsZWQnOlxuICAgICAgICAgICAgICAgICAgICAvLyBEbyBub3RoaW5nLCBhcyBhbiBJQ0VfQ09OTkVDVElPTl9GQUlMRUQgZXZlbnQgd2lsbCBoYXZlIGFscmVhZHkgcmFpc2VkXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBJQ0UgY29ubmVjdGlvbiBvZiBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBpcyBub3cgZmFpbGVkIGFmdGVyIElDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRGApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjb25uZWN0ZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coYFtJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURURdIElDRSBjb25uZWN0aW9uIG9mIHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9ICgkeyh0aGlzLmlzTG9jYWwoKSA/ICdQdWJsaXNoZXInIDogJ1N1YnNjcmliZXInKX0pIGF1dG9tYXRpY2FsbHkgcmVzdG9yZWQgYWZ0ZXIgSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVELiBDdXJyZW50IElDRSBjb25uZWN0aW9uIHN0YXRlOiAke3N0YXRlfWApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNraW5nJzpcbiAgICAgICAgICAgICAgICBjYXNlICduZXcnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2Rpc2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc3Qgb2Ygc3RhdGVzXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBJQ0UgY29ubmVjdGlvbiBvZiBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBjb3VsZG4ndCBiZSByZXN0b3JlZCBhZnRlciBJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQgZXZlbnQuIEN1cnJlbnQgSUNFIGNvbm5lY3Rpb24gc3RhdGUgYWZ0ZXIgJHt0aW1lb3V0fSBtczogJHtzdGF0ZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RTdHJlYW1BbmRMb2dSZXN1bHRpbmdJY2VDb25uZWN0aW9uU3RhdGUoRXhjZXB0aW9uRXZlbnROYW1lLklDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlY29ubmVjdFN0cmVhbUFuZExvZ1Jlc3VsdGluZ0ljZUNvbm5lY3Rpb25TdGF0ZShldmVudDogc3RyaW5nKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaW5hbEljZVN0YXRlQWZ0ZXJSZWNvbm5lY3Rpb24gPSBhd2FpdCB0aGlzLnJlY29ubmVjdFN0cmVhbUFuZFJldHVybkljZUNvbm5lY3Rpb25TdGF0ZShldmVudCk7XG4gICAgICAgICAgICBzd2l0Y2ggKGZpbmFsSWNlU3RhdGVBZnRlclJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnY29tcGxldGVkJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhgWyR7ZXZlbnR9XSBTdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBzdWNjZXNzZnVsbHkgcmVjb25uZWN0ZWQgYWZ0ZXIgJHtldmVudH0uIEN1cnJlbnQgSUNFIGNvbm5lY3Rpb24gc3RhdGU6ICR7ZmluYWxJY2VTdGF0ZUFmdGVyUmVjb25uZWN0aW9ufWApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYFske2V2ZW50fV0gU3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSkgZmFpbGVkIHRvIHJlY29ubmVjdCBhZnRlciAke2V2ZW50fS4gQ3VycmVudCBJQ0UgY29ubmVjdGlvbiBzdGF0ZTogJHtmaW5hbEljZVN0YXRlQWZ0ZXJSZWNvbm5lY3Rpb259YCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBbJHtldmVudH1dIEVycm9yIHJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhZnRlciAke2V2ZW50fTogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVjb25uZWN0U3RyZWFtQW5kUmV0dXJuSWNlQ29ubmVjdGlvblN0YXRlKGV2ZW50OiBzdHJpbmcpOiBQcm9taXNlPFJUQ0ljZUNvbm5lY3Rpb25TdGF0ZT4ge1xuICAgICAgICBsb2dnZXIubG9nKGBbJHtldmVudH1dIFJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhZnRlciBldmVudCAke2V2ZW50fWApO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZWNvbm5lY3RTdHJlYW0oZXZlbnQpO1xuICAgICAgICAgICAgY29uc3QgdGltZW91dCA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlQ29ubmVjdGlvbkRpc2Nvbm5lY3RlZEV4Y2VwdGlvblRpbWVvdXQgfHwgNDAwMDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmF3YWl0V2ViUnRjUGVlckNvbm5lY3Rpb25TdGF0ZSh0aW1lb3V0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbJHtldmVudH1dIEVycm9yIHJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KS4gUmVhc29uOiAke2Vycm9yfWApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXdhaXRXZWJSdGNQZWVyQ29ubmVjdGlvblN0YXRlKDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZWNvbm5lY3RTdHJlYW0oZXZlbnQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCBpc1dzQ29ubmVjdGVkID0gYXdhaXQgdGhpcy5pc1dlYnNvY2tldENvbm5lY3RlZChldmVudCwgMzAwMCk7XG4gICAgICAgIGlmIChpc1dzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgICAvLyBUaGVyZSBpcyBjb25uZWN0aW9uIHRvIG9wZW52aWR1LXNlcnZlci4gVGhlIFJUQ1BlZXJDb25uZWN0aW9uIGlzIHRoZSBvbmx5IG9uZSBicm9rZW5cbiAgICAgICAgICAgIGxvZ2dlci5sb2coYFske2V2ZW50fV0gVHJ5aW5nIHRvIHJlY29ubmVjdCBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhbmQgdGhlIHdlYnNvY2tldCBpcyBvcGVuZWRgKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCh0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlcmUgaXMgbm8gY29ubmVjdGlvbiB0byBvcGVudmlkdS1zZXJ2ZXIuIE5vdGhpbmcgY2FuIGJlIGRvbmUuIFRoZSBhdXRvbWF0aWMgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICAvLyBmZWF0dXJlIHNob3VsZCBoYW5kbGUgYSBwb3NzaWJsZSByZWNvbm5lY3Rpb24gb2YgUlRDUGVlckNvbm5lY3Rpb24gaW4gY2FzZSBuZXR3b3JrIGNvbWVzIGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGVycm9yTXNnID0gYFske2V2ZW50fV0gVHJ5aW5nIHRvIHJlY29ubmVjdCBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBidXQgdGhlIHdlYnNvY2tldCB3YXNuJ3Qgb3BlbmVkYDtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvck1zZyk7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcihlcnJvck1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGlzV2Vic29ja2V0Q29ubmVjdGVkKGV2ZW50OiBzdHJpbmcsIG1zUmVzcG9uc2VUaW1lb3V0OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdzUmVhZHlTdGF0ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5nZXRXc1JlYWR5U3RhdGUoKTtcbiAgICAgICAgICAgIGlmICh3c1JlYWR5U3RhdGUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZVRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbJHtldmVudH1dIFdlYnNvY2tldCB0aW1lb3V0IG9mICR7bXNSZXNwb25zZVRpbWVvdXR9bXNgKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgICAgICAgICAgICAgfSwgbXNSZXNwb25zZVRpbWVvdXQpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgnZWNobycsIHt9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZVRpbWVvdXQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbJHtldmVudH1dIFdlYnNvY2tldCAnZWNobycgcmV0dXJuZWQgZXJyb3I6ICR7ZXJyb3J9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbJHtldmVudH1dIFdlYnNvY2tldCByZWFkeVN0YXRlIGlzICR7d3NSZWFkeVN0YXRlfWApO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGF3YWl0V2ViUnRjUGVlckNvbm5lY3Rpb25TdGF0ZSh0aW1lb3V0OiBudW1iZXIpOiBQcm9taXNlPFJUQ0ljZUNvbm5lY3Rpb25TdGF0ZT4ge1xuICAgICAgICBsZXQgc3RhdGUgPSB0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuaWNlQ29ubmVjdGlvblN0YXRlO1xuICAgICAgICBjb25zdCBpbnRlcnZhbCA9IDE1MDtcbiAgICAgICAgY29uc3QgaW50ZXJ2YWxzID0gTWF0aC5jZWlsKHRpbWVvdXQgLyBpbnRlcnZhbCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW50ZXJ2YWxzOyBpKyspIHtcbiAgICAgICAgICAgIHN0YXRlID0gdGhpcy5nZXRSVENQZWVyQ29ubmVjdGlvbigpLmljZUNvbm5lY3Rpb25TdGF0ZTtcbiAgICAgICAgICAgIGlmIChzdGF0ZSA9PT0gJ2Nvbm5lY3RlZCcgfHwgc3RhdGUgPT09ICdjb21wbGV0ZWQnKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBTbGVlcFxuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgaW50ZXJ2YWwpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cyA9IG5ldyBXZWJSdGNTdGF0cyh0aGlzKTtcbiAgICAgICAgdGhpcy53ZWJSdGNTdGF0cy5pbml0V2ViUnRjU3RhdHMoKTtcblxuICAgICAgICAvL1RPRE86IHNlbmQgY29tbW9uIHdlYnJ0YyBzdGF0cyBmcm9tIGNsaWVudCB0byBvcGVudmlkdS1zZXJ2ZXJcbiAgICAgICAgLyppZiAodGhpcy5zZXNzaW9uLm9wZW52aWR1LndlYnJ0Y1N0YXRzSW50ZXJ2YWwgPiAwKSB7XG4gICAgICAgICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5nYXRoZXJTdGF0c0ZvclBlZXIoKS50aGVuKGpzb25TdGF0cyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJvZHkgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbi5zZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNpcGFudFByaXZhdGVJZDogdGhpcy5jb25uZWN0aW9uLnJwY1Nlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzOiBqc29uU3RhdHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHhoci5vcGVuKCdQT1NUJywgdGhpcy5zZXNzaW9uLm9wZW52aWR1Lmh0dHBVcmkgKyAnL2VsYXN0aWNzZWFyY2gvd2VicnRjLXN0YXRzJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgICAgICAgICAgICAgICB4aHIuc2VuZChKU09OLnN0cmluZ2lmeShib2R5KSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0sIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS53ZWJydGNTdGF0c0ludGVydmFsICogMTAwMCk7XG4gICAgICAgIH0qL1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RvcFdlYlJ0Y1N0YXRzKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLndlYlJ0Y1N0YXRzICYmIHRoaXMud2ViUnRjU3RhdHMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuc3RvcFdlYlJ0Y1N0YXRzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEljZVNlcnZlcnNDb25mKCk6IFJUQ0ljZVNlcnZlcltdIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgbGV0IHJldHVyblZhbHVlO1xuICAgICAgICBpZiAoISF0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzID09PSAnZnJlZWljZScgP1xuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCA6XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5pY2VTZXJ2ZXJzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2F0aGVyU3RhdHNGb3JQZWVyKCk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0xvY2FsKCkpIHtcblxuICAgICAgICAgICAgICAgIC8vIFB1Ymxpc2hlciBzdHJlYW0gc3RhdHNcblxuICAgICAgICAgICAgICAgIHRoaXMuZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5nZXRTZW5kZXJzKCkuZm9yRWFjaChzZW5kZXIgPT4gc2VuZGVyLmdldFN0YXRzKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuZm9yRWFjaChyZXBvcnQgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzUmVwb3J0V2FudGVkKHJlcG9ydCkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmluYWxSZXBvcnQgPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3R5cGUnXSA9IHJlcG9ydC50eXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3RpbWVzdGFtcCddID0gcmVwb3J0LnRpbWVzdGFtcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydpZCddID0gcmVwb3J0LmlkO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21tb24gdG8gQ2hyb21lLCBGaXJlZm94IGFuZCBTYWZhcmlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnc3NyYyddID0gcmVwb3J0LnNzcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2ZpckNvdW50J10gPSByZXBvcnQuZmlyQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3BsaUNvdW50J10gPSByZXBvcnQucGxpQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ25hY2tDb3VudCddID0gcmVwb3J0Lm5hY2tDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncXBTdW0nXSA9IHJlcG9ydC5xcFN1bTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBtZWRpYSB0eXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVwb3J0LmtpbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ21lZGlhVHlwZSddID0gcmVwb3J0LmtpbmQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghIXJlcG9ydC5tZWRpYVR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ21lZGlhVHlwZSddID0gcmVwb3J0Lm1lZGlhVHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTYWZhcmkgZG9lcyBub3QgaGF2ZSAnbWVkaWFUeXBlJyBkZWZpbmVkIGZvciBpbmJvdW5kLXJ0cC4gTXVzdCBiZSBpbmZlcnJlZCBmcm9tICdpZCcgZmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ21lZGlhVHlwZSddID0gKHJlcG9ydC5pZC5pbmRleE9mKCdWaWRlb1N0cmVhbScpICE9PSAtMSkgPyAndmlkZW8nIDogJ2F1ZGlvJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmluYWxSZXBvcnRbJ21lZGlhVHlwZSddID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydmcmFtZXNFbmNvZGVkJ10gPSByZXBvcnQuZnJhbWVzRW5jb2RlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncGFja2V0c1NlbnQnXSA9IHJlcG9ydC5wYWNrZXRzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYnl0ZXNTZW50J10gPSByZXBvcnQuYnl0ZXNTZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGZvciBDaHJvbWUgYW5kIFNhZmFyaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC50eXBlID09PSAnY2FuZGlkYXRlLXBhaXInICYmIHJlcG9ydC50b3RhbFJvdW5kVHJpcFRpbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGZpbmFsIHNlbGVjdGVkIGNhbmRpZGF0ZSBwYWlyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2F2YWlsYWJsZU91dGdvaW5nQml0cmF0ZSddID0gcmVwb3J0LmF2YWlsYWJsZU91dGdvaW5nQml0cmF0ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncnR0J10gPSByZXBvcnQuY3VycmVudFJvdW5kVHJpcFRpbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2F2ZXJhZ2VSdHQnXSA9IHJlcG9ydC50b3RhbFJvdW5kVHJpcFRpbWUgLyByZXBvcnQucmVzcG9uc2VzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgZm9yIEZpcmVmb3ggPj0gNjYuMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC50eXBlID09PSAncmVtb3RlLWluYm91bmQtcnRwJyB8fCByZXBvcnQudHlwZSA9PT0gJ3JlbW90ZS1vdXRib3VuZC1ydHAnKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhmaW5hbFJlcG9ydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBTdWJzY3JpYmVyIHN0cmVhbSBzdGF0c1xuXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRSVENQZWVyQ29ubmVjdGlvbigpLmdldFJlY2VpdmVycygpLmZvckVhY2gocmVjZWl2ZXIgPT4gcmVjZWl2ZXIuZ2V0U3RhdHMoKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5mb3JFYWNoKHJlcG9ydCA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNSZXBvcnRXYW50ZWQocmVwb3J0KSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaW5hbFJlcG9ydCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndHlwZSddID0gcmVwb3J0LnR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsndGltZXN0YW1wJ10gPSByZXBvcnQudGltZXN0YW1wO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2lkJ10gPSByZXBvcnQuaWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENvbW1vbiB0byBDaHJvbWUsIEZpcmVmb3ggYW5kIFNhZmFyaVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC50eXBlID09PSAnaW5ib3VuZC1ydHAnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3NzcmMnXSA9IHJlcG9ydC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydmaXJDb3VudCddID0gcmVwb3J0LmZpckNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydwbGlDb3VudCddID0gcmVwb3J0LnBsaUNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WyduYWNrQ291bnQnXSA9IHJlcG9ydC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3FwU3VtJ10gPSByZXBvcnQucXBTdW07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgbWVkaWEgdHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlcG9ydC5raW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5raW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISFyZXBvcnQubWVkaWFUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5tZWRpYVR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIGRvZXMgbm90IGhhdmUgJ21lZGlhVHlwZScgZGVmaW5lZCBmb3IgaW5ib3VuZC1ydHAuIE11c3QgYmUgaW5mZXJyZWQgZnJvbSAnaWQnIGZpZWxkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IChyZXBvcnQuaWQuaW5kZXhPZignVmlkZW9TdHJlYW0nKSAhPT0gLTEpID8gJ3ZpZGVvJyA6ICdhdWRpbyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnZnJhbWVzRGVjb2RlZCddID0gcmVwb3J0LmZyYW1lc0RlY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3BhY2tldHNSZWNlaXZlZCddID0gcmVwb3J0LnBhY2tldHNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncGFja2V0c0xvc3QnXSA9IHJlcG9ydC5wYWNrZXRzTG9zdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnaml0dGVyJ10gPSByZXBvcnQuaml0dGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydieXRlc1JlY2VpdmVkJ10gPSByZXBvcnQuYnl0ZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmb3IgQ2hyb21lIGFuZCBTYWZhcmlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ2NhbmRpZGF0ZS1wYWlyJyAmJiByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBmaW5hbCBzZWxlY3RlZCBjYW5kaWRhdGUgcGFpclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmFpbGFibGVJbmNvbWluZ0JpdHJhdGUnXSA9IHJlcG9ydC5hdmFpbGFibGVJbmNvbWluZ0JpdHJhdGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3J0dCddID0gcmVwb3J0LmN1cnJlbnRSb3VuZFRyaXBUaW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmVyYWdlUnR0J10gPSByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lIC8gcmVwb3J0LnJlc3BvbnNlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGZvciBGaXJlZm94ID49IDY2LjBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ3JlbW90ZS1pbmJvdW5kLXJ0cCcgfHwgcmVwb3J0LnR5cGUgPT09ICdyZW1vdGUtb3V0Ym91bmQtcnRwJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIubG9nKGZpbmFsUmVwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1JlcG9ydFdhbnRlZChyZXBvcnQ6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gcmVwb3J0LnR5cGUgPT09ICdpbmJvdW5kLXJ0cCcgJiYgIXRoaXMuaXNMb2NhbCgpIHx8XG4gICAgICAgICAgICByZXBvcnQudHlwZSA9PT0gJ291dGJvdW5kLXJ0cCcgJiYgdGhpcy5pc0xvY2FsKCkgfHxcbiAgICAgICAgICAgIChyZXBvcnQudHlwZSA9PT0gJ2NhbmRpZGF0ZS1wYWlyJyAmJiByZXBvcnQubm9taW5hdGVkICYmIHJlcG9ydC5ieXRlc1NlbnQgPiAwKTtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4vRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJWaWRlbyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvU3RyZWFtTWFuYWdlclZpZGVvJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9VdGlscy9QbGF0Zm9ybSc7XG5pbXBvcnQgeyBFeGNlcHRpb25FdmVudCwgRXhjZXB0aW9uRXZlbnROYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXhjZXB0aW9uRXZlbnQnO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5sZXQgcGxhdGZvcm06IFBsYXRmb3JtVXRpbHM7XG5cbi8qKlxuICogSW50ZXJmYWNlIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoZSBtZWRpYSBzdHJlYW1zIGluIHRoZSBIVE1MIERPTS4gVGhpcyB3cmFwcyBhbnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gb2JqZWN0LlxuICogWW91IGNhbiBpbnNlcnQgYXMgbWFueSB2aWRlbyBwbGF5ZXJzIGZvIHRoZSBzYW1lIFN0cmVhbSBhcyB5b3Ugd2FudCBieSBjYWxsaW5nIFtbU3RyZWFtTWFuYWdlci5hZGRWaWRlb0VsZW1lbnRdXSBvclxuICogW1tTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudF1dLlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqXG4gKiAjIyMgQXZhaWxhYmxlIGV2ZW50IGxpc3RlbmVycyAoYW5kIGV2ZW50cyBkaXNwYXRjaGVkKVxuICpcbiAqIC0gdmlkZW9FbGVtZW50Q3JlYXRlZCAoW1tWaWRlb0VsZW1lbnRFdmVudF1dKVxuICogLSB2aWRlb0VsZW1lbnREZXN0cm95ZWQgKFtbVmlkZW9FbGVtZW50RXZlbnRdXSlcbiAqIC0gc3RyZWFtUGxheWluZyAoW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSlcbiAqIC0gc3RyZWFtUHJvcGVydHlDaGFuZ2VkIChbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0pXG4gKiAtIHB1Ymxpc2hlclN0YXJ0U3BlYWtpbmcgKFtbUHVibGlzaGVyU3BlYWtpbmdFdmVudF1dKVxuICogLSBwdWJsaXNoZXJTdG9wU3BlYWtpbmcgKFtbUHVibGlzaGVyU3BlYWtpbmdFdmVudF1dKVxuICogLSBzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZSAoW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSlcbiAqXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHJlYW1NYW5hZ2VyIGV4dGVuZHMgRXZlbnREaXNwYXRjaGVyIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBTdHJlYW0gcmVwcmVzZW50ZWQgaW4gdGhlIERPTSBieSB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXJcbiAgICAgKi9cbiAgICBzdHJlYW06IFN0cmVhbTtcblxuICAgIC8qKlxuICAgICAqIEFsbCB0aGUgdmlkZW9zIGRpc3BsYXlpbmcgdGhlIFN0cmVhbSBvZiB0aGlzIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgdmlkZW9zOiBTdHJlYW1NYW5hZ2VyVmlkZW9bXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gaXMgbG9jYWwgb3IgcmVtb3RlXG4gICAgICogLSBgZmFsc2VgIGZvciBbW1B1Ymxpc2hlcl1dXG4gICAgICogLSBgdHJ1ZWAgZm9yIFtbU3Vic2NyaWJlcl1dXG4gICAgICovXG4gICAgcmVtb3RlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIERPTSBIVE1MRWxlbWVudCBhc3NpZ25lZCBhcyB0YXJnZXQgZWxlbWVudCB3aGVuIGNyZWF0aW5nIHRoZSB2aWRlbyBmb3IgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZjpcbiAgICAgKiAtIFtbUHVibGlzaGVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKiAtIFtbU3Vic2NyaWJlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqL1xuICAgIHRhcmdldEVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogYGlkYCBhdHRyaWJ1dGUgb2YgdGhlIERPTSB2aWRlbyBlbGVtZW50IGRpc3BsYXlpbmcgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyJ3Mgc3RyZWFtLiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgZGVmaW5lZCBpZjpcbiAgICAgKiAtIFtbUHVibGlzaGVyXV0gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBtZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKiAtIFtbU3Vic2NyaWJlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSB3aXRoIGEgdmFsaWQgYHRhcmdldEVsZW1lbnRgIHBhcmFtZXRlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGZpcnN0VmlkZW9FbGVtZW50PzogU3RyZWFtTWFuYWdlclZpZGVvO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjYW5QbGF5TGlzdGVuZXI6IEV2ZW50TGlzdGVuZXI7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByaXZhdGUgc3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dD86IE5vZGVKUy5UaW1lb3V0O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIGxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudD86IEhUTUxFbGVtZW50IHwgc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHBsYXRmb3JtID0gUGxhdGZvcm1VdGlscy5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlciA9IHRoaXM7XG4gICAgICAgIHRoaXMucmVtb3RlID0gIXRoaXMuc3RyZWFtLmlzTG9jYWwoKTtcblxuICAgICAgICBpZiAoISF0YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICBsZXQgdGFyZ0VsO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRhcmdFbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSB0YXJnZXRFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0YXJnRWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcnN0VmlkZW9FbGVtZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpLFxuICAgICAgICAgICAgICAgICAgICBpZDogJycsXG4gICAgICAgICAgICAgICAgICAgIGNhbnBsYXlMaXN0ZW5lckFkZGVkOiBmYWxzZVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHBsYXRmb3JtLmlzU2FmYXJpQnJvd3NlcigpIHx8IChwbGF0Zm9ybS5pc0lQaG9uZU9ySVBhZCgpICYmIChwbGF0Zm9ybS5pc0Nocm9tZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNPcGVyYU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpcnN0VmlkZW9FbGVtZW50LnZpZGVvLnNldEF0dHJpYnV0ZSgncGxheXNpbmxpbmUnLCAndHJ1ZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQgPSB0YXJnRWw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jYW5QbGF5TGlzdGVuZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmRlYWN0aXZhdGVTdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5yZW1vdGUpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIlJlbW90ZSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ10gdmlkZW8gaXMgbm93IHBsYXlpbmcnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJZb3VyIGxvY2FsICdTdHJlYW0nIHdpdGggaWQgW1wiICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnXSB2aWRlbyBpcyBub3cgcGxheWluZycpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJZb3VyIG93biByZW1vdGUgJ1N0cmVhbScgd2l0aCBpZCBbXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArICddIHZpZGVvIGlzIG5vdyBwbGF5aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdyZW1vdGVWaWRlb1BsYXlpbmcnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAncmVtb3RlVmlkZW9QbGF5aW5nJyldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMsICdzdHJlYW1QbGF5aW5nJywgdW5kZWZpbmVkKV0pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb24odHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEV2ZW50KSA9PiB2b2lkKTogRXZlbnREaXNwYXRjaGVyIHtcblxuICAgICAgICBzdXBlci5vbkF1eCh0eXBlLCBcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBoYW5kbGVyKVxuXG4gICAgICAgIGlmICh0eXBlID09PSAndmlkZW9FbGVtZW50Q3JlYXRlZCcpIHtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtICYmIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtUGxheWluZycgfHwgdHlwZSA9PT0gJ3ZpZGVvUGxheWluZycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnZpZGVvc1swXSAmJiB0aGlzLnZpZGVvc1swXS52aWRlbyAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmN1cnJlbnRUaW1lID4gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnBhdXNlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5lbmRlZCA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzLCAnc3RyZWFtUGxheWluZycsIHVuZGVmaW5lZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9QbGF5aW5nJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh0aGlzLnZpZGVvc1swXS52aWRlbywgdGhpcywgJ3ZpZGVvUGxheWluZycpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZW5hYmxlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RvcFNwZWFraW5nJykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lbmFibGVIYXJrVm9sdW1lQ2hhbmdlRXZlbnQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlKHR5cGU6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuXG4gICAgICAgIHN1cGVyLm9uY2VBdXgodHlwZSwgXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnIHx8IHR5cGUgPT09ICd2aWRlb1BsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcywgJ3N0cmVhbVBsYXlpbmcnLCB1bmRlZmluZWQpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvUGxheWluZycsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb1BsYXlpbmcnKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5oYXNBdWRpbykge1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVuYWJsZU9uY2VIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lbmFibGVPbmNlSGFya1ZvbHVtZUNoYW5nZUV2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmYodHlwZTogc3RyaW5nLCBoYW5kbGVyPzogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IFN0cmVhbU1hbmFnZXIge1xuXG4gICAgICAgIHN1cGVyLm9mZih0eXBlLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBCb3RoIFN0cmVhbU1hbmFnZXIgYW5kIFNlc3Npb24gY2FuIGhhdmUgXCJwdWJsaXNoZXJTdGFydFNwZWFraW5nXCIgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgICAgICBjb25zdCByZW1haW5pbmdTdGFydFNwZWFraW5nRXZlbnRMaXN0ZW5lcnMgPSB0aGlzLmVlLmdldExpc3RlbmVycyh0eXBlKS5sZW5ndGggKyB0aGlzLnN0cmVhbS5zZXNzaW9uLmVlLmdldExpc3RlbmVycyh0eXBlKS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAocmVtYWluaW5nU3RhcnRTcGVha2luZ0V2ZW50TGlzdGVuZXJzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzYWJsZUhhcmtTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIEJvdGggU3RyZWFtTWFuYWdlciBhbmQgU2Vzc2lvbiBjYW4gaGF2ZSBcInB1Ymxpc2hlclN0b3BTcGVha2luZ1wiIGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nU3RvcFNwZWFraW5nRXZlbnRMaXN0ZW5lcnMgPSB0aGlzLmVlLmdldExpc3RlbmVycyh0eXBlKS5sZW5ndGggKyB0aGlzLnN0cmVhbS5zZXNzaW9uLmVlLmdldExpc3RlbmVycyh0eXBlKS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAocmVtYWluaW5nU3RvcFNwZWFraW5nRXZlbnRMaXN0ZW5lcnMgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5kaXNhYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJykge1xuICAgICAgICAgICAgLy8gT25seSBTdHJlYW1NYW5hZ2VyIGNhbiBoYXZlIFwic3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2VcIiBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgICAgIGNvbnN0IHJlbWFpbmluZ1ZvbHVtZUV2ZW50TGlzdGVuZXJzID0gdGhpcy5lZS5nZXRMaXN0ZW5lcnModHlwZSkubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1ZvbHVtZUV2ZW50TGlzdGVuZXJzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudChmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyBgdmlkZW9gIGVsZW1lbnQgcGFyYW1ldGVyIGRpc3BsYXkgdGhpcyBbW3N0cmVhbV1dLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmVcbiAgICAgKiBbbWFuYWdpbmcgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jeW91LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycylcbiAgICAgKlxuICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2l0aCBhIHZpZGVvIGFscmVhZHkgYWRkZWQgdG8gb3RoZXIgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBjYXVzZSB0aGUgdmlkZW8gZWxlbWVudCB0byBiZVxuICAgICAqIGRpc2Fzc29jaWF0ZWQgZnJvbSB0aGF0IHByZXZpb3VzIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCB0byBiZSBhc3NvY2lhdGVkIHRvIHRoaXMgb25lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgMSBpZiB0aGUgdmlkZW8gd2Fzbid0IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgYWRkZWQgdG8gdGhpcyBvbmUuXG4gICAgICogMCBpZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgYWRkZWQgdG8gdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlci4gLTEgaWYgdGhlIHZpZGVvIHdhcyBwcmV2aW91c2x5IGFzc29jaWF0ZWQgdG8gYW55IG90aGVyXG4gICAgICogUHVibGlzaGVyL1N1YnNjcmliZXIgYW5kIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBvbmUgYW5kIHByb3Blcmx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqL1xuICAgIGFkZFZpZGVvRWxlbWVudCh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IG51bWJlciB7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBpZiAoIXRoaXMucmVtb3RlICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICBpZiAodmlkZW8uc3JjT2JqZWN0ICE9PSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpKSB7XG4gICAgICAgICAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSB2aWRlbyBlbGVtZW50IGlzIGFscmVhZHkgcGFydCBvZiB0aGlzIFN0cmVhbU1hbmFnZXIgZG8gbm90aGluZ1xuICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdGhpcy52aWRlb3MpIHtcbiAgICAgICAgICAgIGlmICh2LnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJldHVybk51bWJlciA9IDE7XG5cbiAgICAgICAgZm9yIChjb25zdCBzdHJlYW1NYW5hZ2VyIG9mIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMpIHtcbiAgICAgICAgICAgIGlmIChzdHJlYW1NYW5hZ2VyLmRpc2Fzc29jaWF0ZVZpZGVvKHZpZGVvKSkge1xuICAgICAgICAgICAgICAgIHJldHVybk51bWJlciA9IC0xO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vycy5mb3JFYWNoKHN0cmVhbU1hbmFnZXIgPT4ge1xuICAgICAgICAgICAgc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyh7XG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZCxcbiAgICAgICAgICAgIGNhbnBsYXlMaXN0ZW5lckFkZGVkOiBmYWxzZVxuICAgICAgICB9KTtcblxuICAgICAgICBsb2dnZXIuaW5mbygnTmV3IHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byAnLCB0aGlzKTtcblxuICAgICAgICByZXR1cm4gcmV0dXJuTnVtYmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBhbGxvd3MgeW91IHRvIGhhdmUgbXVsdGlwbGUgdmlkZW8gZWxlbWVudHMgZGlzcGxheWluZyB0aGUgc2FtZSBtZWRpYSBzdHJlYW0uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgUHVibGlzaGVyL1N1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXVxuICAgICAqXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgUHVibGlzaGVyL1N1YnNjcmliZXIgd2lsbCBiZSBpbnNlcnRlZFxuICAgICAqIEBwYXJhbSBpbnNlcnRNb2RlIEhvdyB0aGUgdmlkZW8gZWxlbWVudCB3aWxsIGJlIGluc2VydGVkIGFjY29yZGluZ2x5IHRvIGB0YXJnZXRFbGVtZXRgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3JlYXRlZCBIVE1MVmlkZW9FbGVtZW50XG4gICAgICovXG4gICAgY3JlYXRlVmlkZW9FbGVtZW50KHRhcmdldEVsZW1lbnQ/OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgaW5zZXJ0TW9kZT86IFZpZGVvSW5zZXJ0TW9kZSk6IEhUTUxWaWRlb0VsZW1lbnQge1xuICAgICAgICBsZXQgdGFyZ0VsO1xuICAgICAgICBpZiAodHlwZW9mIHRhcmdldEVsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIGlmICghdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHByb3ZpZGVkICd0YXJnZXRFbGVtZW50JyBjb3VsZG4ndCBiZSByZXNvbHZlZCB0byBhbnkgSFRNTCBlbGVtZW50OiBcIiArIHRhcmdldEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRhcmdldEVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZpZGVvID0gdGhpcy5jcmVhdGVWaWRlbygpO1xuICAgICAgICB0aGlzLmluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW8pO1xuXG4gICAgICAgIGxldCBpbnNNb2RlID0gISFpbnNlcnRNb2RlID8gaW5zZXJ0TW9kZSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQ7XG4gICAgICAgIHN3aXRjaCAoaW5zTW9kZSkge1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQUZURVI6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5uZXh0U2libGluZyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQ6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLmFwcGVuZENoaWxkKHZpZGVvKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkJFRk9SRTpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlBSRVBFTkQ6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLmluc2VydEJlZm9yZSh2aWRlbywgdGFyZ0VsLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuUkVQTEFDRTpcbiAgICAgICAgICAgICAgICB0YXJnRWwucGFyZW50Tm9kZSEhLnJlcGxhY2VDaGlsZCh2aWRlbywgdGFyZ0VsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgaW5zTW9kZSA9IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQ7XG4gICAgICAgICAgICAgICAgdGFyZ0VsLmFwcGVuZENoaWxkKHZpZGVvKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHY6IFN0cmVhbU1hbmFnZXJWaWRlbyA9IHtcbiAgICAgICAgICAgIHRhcmdldEVsZW1lbnQ6IHRhcmdFbCxcbiAgICAgICAgICAgIHZpZGVvLFxuICAgICAgICAgICAgaW5zZXJ0TW9kZTogaW5zTW9kZSxcbiAgICAgICAgICAgIGlkOiB2aWRlby5pZCxcbiAgICAgICAgICAgIGNhbnBsYXlMaXN0ZW5lckFkZGVkOiBmYWxzZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8odik7XG5cbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHYudmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gISF0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgIHJldHVybiB2aWRlbztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBbW1B1Ymxpc2hlclNwZWFraW5nRXZlbnRdXSBmZWF0dXJlIGFuZCB0aGUgW1N0cmVhbU1hbmFnZXJFdmVudC5zdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZV0oL2VuL3N0YWJsZS9hcGkvb3BlbnZpZHUtYnJvd3Nlci9jbGFzc2VzL3N0cmVhbW1hbmFnZXJldmVudC5odG1sKSBmZWF0dXJlIGZvciB0aGlzIHNwZWNpZmljXG4gICAgICogU3RyZWFtTWFuYWdlciBhdWRpbyBzdHJlYW0sIG92ZXJyaWRpbmcgdGhlIGdsb2JhbCBvcHRpb25zIHNldCB3aXRoIFtbT3BlblZpZHUuc2V0QWR2YW5jZWRDb25maWd1cmF0aW9uXV0uIFRoaXMgd2F5IHlvdSBjYW4gY3VzdG9taXplIHRoZSBhdWRpbyBldmVudHMgb3B0aW9uc1xuICAgICAqIGZvciBlYWNoIHNwZWNpZmljIFN0cmVhbU1hbmFnZXIgYW5kIGNoYW5nZSB0aGVtIGR5bmFtaWNhbGx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyBOZXcgb3B0aW9ucyB0byBiZSBhcHBsaWVkIHRvIHRoaXMgU3RyZWFtTWFuYWdlcidzIGF1ZGlvIHN0cmVhbS4gSXQgaXMgYW4gb2JqZWN0IHdoaWNoIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmcgb3B0aW9uYWwgcHJvcGVydGllczpcbiAgICAgKiAtIGBpbnRlcnZhbGA6IChudW1iZXIpIGhvdyBmcmVxdWVudGx5IHRoZSBhbmFseXNlciBwb2xscyB0aGUgYXVkaW8gc3RyZWFtIHRvIGNoZWNrIGlmIHNwZWFraW5nIGhhcyBzdGFydGVkL3N0b3BwZWQgb3IgYXVkaW8gdm9sdW1lIGhhcyBjaGFuZ2VkLiBEZWZhdWx0ICoqMTAwKiogKG1zKVxuICAgICAqIC0gYHRocmVzaG9sZGA6IChudW1iZXIpIHRoZSB2b2x1bWUgYXQgd2hpY2ggX3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmdfLCBfcHVibGlzaGVyU3RvcFNwZWFraW5nXyBldmVudHMgd2lsbCBiZSBmaXJlZC4gRGVmYXVsdCAqKi01MCoqIChkQilcbiAgICAgKi9cbiAgICB1cGRhdGVQdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnMocHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zOiB7IGludGVydmFsPzogbnVtYmVyLCB0aHJlc2hvbGQ/OiBudW1iZXIgfSk6IHZvaWQge1xuICAgICAgICBjb25zdCBjdXJyZW50SGFya09wdGlvbnMgPSAhIXRoaXMuc3RyZWFtLmhhcmtPcHRpb25zID8gdGhpcy5zdHJlYW0uaGFya09wdGlvbnMgOiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9KTtcbiAgICAgICAgY29uc3QgbmV3SW50ZXJ2YWwgPSAodHlwZW9mIHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID9cbiAgICAgICAgICAgIHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucy5pbnRlcnZhbCA6ICgodHlwZW9mIGN1cnJlbnRIYXJrT3B0aW9ucy5pbnRlcnZhbCA9PT0gJ251bWJlcicpID8gY3VycmVudEhhcmtPcHRpb25zLmludGVydmFsIDogMTAwKTtcbiAgICAgICAgY29uc3QgbmV3VGhyZXNob2xkID0gKHR5cGVvZiBwdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgP1xuICAgICAgICAgICAgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zLnRocmVzaG9sZCA6ICgodHlwZW9mIGN1cnJlbnRIYXJrT3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSA/IGN1cnJlbnRIYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTApO1xuICAgICAgICB0aGlzLnN0cmVhbS5oYXJrT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGludGVydmFsOiBuZXdJbnRlcnZhbCxcbiAgICAgICAgICAgIHRocmVzaG9sZDogbmV3VGhyZXNob2xkXG4gICAgICAgIH07XG4gICAgICAgIGlmICghIXRoaXMuc3RyZWFtLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zcGVlY2hFdmVudC5zZXRJbnRlcnZhbChuZXdJbnRlcnZhbCk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zcGVlY2hFdmVudC5zZXRUaHJlc2hvbGQobmV3VGhyZXNob2xkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbzogSFRNTFZpZGVvRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoISghdGhpcy5yZW1vdGUgJiYgdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpKSB7XG4gICAgICAgICAgICAvLyBBdm9pZCBzZXR0aW5nIHRoZSBNZWRpYVN0cmVhbSBpbnRvIHRoZSBzcmNPYmplY3QgaWYgcmVtb3RlIHN1YnNjcmlwdGlvbiBiZWZvcmUgcHVibGlzaGluZ1xuICAgICAgICAgICAgaWYgKHZpZGVvLnNyY09iamVjdCAhPT0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHNyY09iamVjdCBhbHJlYWR5IHNldCBkb24ndCBkbyBpdCBhZ2FpblxuICAgICAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW8uYXV0b3BsYXkgPSB0cnVlO1xuICAgICAgICB2aWRlby5jb250cm9scyA9IGZhbHNlO1xuXG4gICAgICAgIGlmIChwbGF0Zm9ybS5pc1NhZmFyaUJyb3dzZXIoKSB8fCAocGxhdGZvcm0uaXNJUGhvbmVPcklQYWQoKSAmJiAocGxhdGZvcm0uaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzT3BlcmFNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpKSkpIHtcbiAgICAgICAgICAgIHZpZGVvLnNldEF0dHJpYnV0ZSgncGxheXNpbmxpbmUnLCAndHJ1ZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF2aWRlby5pZCkge1xuICAgICAgICAgICAgdmlkZW8uaWQgPSAodGhpcy5yZW1vdGUgPyAncmVtb3RlLScgOiAnbG9jYWwtJykgKyAndmlkZW8tJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkO1xuICAgICAgICAgICAgLy8gREVQUkVDQVRFRCBwcm9wZXJ0eTogYXNzaWduIG9uY2UgdGhlIHByb3BlcnR5IGlkIGlmIHRoZSB1c2VyIHByb3ZpZGVkIGEgdmFsaWQgdGFyZ2V0RWxlbWVudFxuICAgICAgICAgICAgaWYgKCF0aGlzLmlkICYmICEhdGhpcy50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pZCA9IHZpZGVvLmlkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiAhdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLm11dGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh2aWRlby5zdHlsZS50cmFuc2Zvcm0gPT09ICdyb3RhdGVZKDE4MGRlZyknICYmICF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgcm90YXRlZCBhbmQgbm93IGlzIHNldCB0byBub3QgbWlycm9yXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVNaXJyb3JWaWRlbyh2aWRlbyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvciAmJiAhdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIGxpc3RlbmVyLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyAmJiAhIXN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8uY2FucGxheUxpc3RlbmVyQWRkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHRoaXMucmVtb3ZlU3JjT2JqZWN0KHN0cmVhbU1hbmFnZXJWaWRlbyk7XG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBjb2xsZWN0aW9uIG9mIHZpZGVvcyBldmVyeSB2aWRlbyBtYW5hZ2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICAgICAgICAgIHRoaXMudmlkZW9zLmZpbHRlcih2ID0+ICF2LnRhcmdldEVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zW2ldLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIGRpc2Fzc29jaWF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAoIXRoaXMudmlkZW9zWzBdLmNhbnBsYXlMaXN0ZW5lckFkZGVkKSkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmF0ZVN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQoKTtcbiAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS5jYW5wbGF5TGlzdGVuZXJBZGRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdXBkYXRlTWVkaWFTdHJlYW0obWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLmZvckVhY2goc3RyZWFtTWFuYWdlclZpZGVvID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5pc0lvbmljSW9zKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBpT1MgSW9uaWMuIExJTUlUQVRJT046IG11c3QgcmVpbnNlcnQgdGhlIHZpZGVvIGluIHRoZSBET00gZm9yXG4gICAgICAgICAgICAgICAgLy8gdGhlIG1lZGlhIHN0cmVhbSB0byBiZSB1cGRhdGVkXG4gICAgICAgICAgICAgICAgY29uc3QgdlBhcmVudCA9IHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1ZpZGVvID0gc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvO1xuICAgICAgICAgICAgICAgIHZQYXJlbnQhIS5yZXBsYWNlQ2hpbGQobmV3VmlkZW8sIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvID0gbmV3VmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAqIEBoaWRkZW5cbiAgICAqL1xuICAgIGNyZWF0ZVZpZGVvKCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3JjT2JqZWN0KHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICB0aGlzLmRlYWN0aXZhdGVTdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0KCk7XG4gICAgfVxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcm90ZWN0ZWQgcHVzaE5ld1N0cmVhbU1hbmFnZXJWaWRlbyhzdHJlYW1NYW5hZ2VyVmlkZW86IFN0cmVhbU1hbmFnZXJWaWRlbykge1xuICAgICAgICB0aGlzLnZpZGVvcy5wdXNoKHN0cmVhbU1hbmFnZXJWaWRlbyk7XG4gICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmluZGV4T2YodGhpcykgPT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLnB1c2godGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1pcnJvclZpZGVvKHZpZGVvKTogdm9pZCB7XG4gICAgICAgIGlmICghcGxhdGZvcm0uaXNJb25pY0lvcygpKSB7XG4gICAgICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAncm90YXRlWSgxODBkZWcpJztcbiAgICAgICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdmVNaXJyb3JWaWRlbyh2aWRlbyk6IHZvaWQge1xuICAgICAgICB2aWRlby5zdHlsZS50cmFuc2Zvcm0gPSAndW5zZXQnO1xuICAgICAgICB2aWRlby5zdHlsZS53ZWJraXRUcmFuc2Zvcm0gPSAndW5zZXQnO1xuICAgIH1cblxuICAgIHByaXZhdGUgYWN0aXZhdGVTdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0KCkge1xuICAgICAgICBpZiAoIXRoaXMucmVtb3RlKSB7XG4gICAgICAgICAgICAvLyBFeGNlcHRpb25FdmVudCBOT19TVFJFQU1fUExBWUlOR19FVkVOVCBpcyBvbmx5IGZvciBzdWJzY3JpYmVyc1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gVGhlIHRpbWVvdXQgaXMgYWxyZWFkeSBhY3RpdmF0ZWRcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBUcmlnZ2VyIEV4Y2VwdGlvbkV2ZW50IE5PX1NUUkVBTV9QTEFZSU5HX0VWRU5UIGlmIGFmdGVyIHRpbWVvdXQgdGhlcmUgaXMgbm8gJ2NhbnBsYXknIGV2ZW50XG4gICAgICAgIGNvbnN0IG1zVGltZW91dCA9IHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLm5vU3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dCB8fCA0MDAwO1xuICAgICAgICB0aGlzLnN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG1zZyA9ICdTdHJlYW1NYW5hZ2VyIG9mIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnICgnICsgKHRoaXMucmVtb3RlID8gJ1N1YnNjcmliZXInIDogJ1B1Ymxpc2hlcicpICsgJykgZGlkIG5vdCB0cmlnZ2VyIFwic3RyZWFtUGxheWluZ1wiIGV2ZW50IGluICcgKyBtc1RpbWVvdXQgKyAnIG1zJztcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKG1zZyk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLmVtaXRFdmVudCgnZXhjZXB0aW9uJywgW25ldyBFeGNlcHRpb25FdmVudCh0aGlzLnN0cmVhbS5zZXNzaW9uLCBFeGNlcHRpb25FdmVudE5hbWUuTk9fU1RSRUFNX1BMQVlJTkdfRVZFTlQsICg8YW55PnRoaXMpIGFzIFN1YnNjcmliZXIsIG1zZyldKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQ7XG4gICAgICAgIH0sIG1zVGltZW91dCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkZWFjdGl2YXRlU3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dCgpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuc3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dCBhcyBhbnkpO1xuICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0O1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIFBhY2tzIHJlbW90ZSBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgYXV0b21hdGljYWxseSByZWNlaXZlIHRoZW0gd2hlbiBvdGhlcnMgcHVibGlzaCB0aGVpciBzdHJlYW1zLiBJbml0aWFsaXplZCB3aXRoIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBtZXRob2RcbiAqIFxuICogIyMjIEF2YWlsYWJsZSBldmVudCBsaXN0ZW5lcnMgKGFuZCBldmVudHMgZGlzcGF0Y2hlZClcbiAqXG4gKiAtIF9BbGwgZXZlbnRzIGluaGVyaXRlZCBmcm9tIFtbU3RyZWFtTWFuYWdlcl1dIGNsYXNzX1xuICovXG5leHBvcnQgY2xhc3MgU3Vic2NyaWJlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHN0cmVhbTogU3RyZWFtLCB0YXJnRWw6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcykge1xuICAgICAgICBzdXBlcihzdHJlYW0sIHRhcmdFbCk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSBhdWRpbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvQXVkaW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRBdWRpb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIidTdWJzY3JpYmVyJyBoYXMgXCIgKyAodmFsdWUgPyAnc3Vic2NyaWJlZCB0bycgOiAndW5zdWJzY3JpYmVkIGZyb20nKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgb3IgdW5zdWJzY3JpYmUgZnJvbSB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSB2YWx1ZSB3aWxsIGhhdmUgbm8gZWZmZWN0XG4gICAgICogQHBhcmFtIHZhbHVlIGB0cnVlYCB0byBzdWJzY3JpYmUgdG8gdGhlIHZpZGVvIHN0cmVhbSwgYGZhbHNlYCB0byB1bnN1YnNjcmliZSBmcm9tIGl0XG4gICAgICovXG4gICAgc3Vic2NyaWJlVG9WaWRlbyh2YWx1ZTogYm9vbGVhbik6IFN1YnNjcmliZXIge1xuICAgICAgICB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlID0gdmFsdWU7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiJ1N1YnNjcmliZXInIGhhcyBcIiArICh2YWx1ZSA/ICdzdWJzY3JpYmVkIHRvJyA6ICd1bnN1YnNjcmliZWQgZnJvbScpICsgJyBpdHMgdmlkZW8gc3RyZWFtJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBEZWZpbmVzIHByb3BlcnR5IFtbT3BlblZpZHVFcnJvci5uYW1lXV1cbiAqL1xuZXhwb3J0IGVudW0gT3BlblZpZHVFcnJvck5hbWUge1xuXG4gICAgLyoqXG4gICAgICogQnJvd3NlciBpcyBub3Qgc3VwcG9ydGVkIGJ5IE9wZW5WaWR1LlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbU2Vzc2lvbi5jb25uZWN0XV1cbiAgICAgKi9cbiAgICBCUk9XU0VSX05PVF9TVVBQT1JURUQgPSAnQlJPV1NFUl9OT1RfU1VQUE9SVEVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIHRoZSByZXF1aXJlZCBpbnB1dCBkZXZpY2Ugd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSBpcyBwcm9iYWJseSBiZWluZyB1c2VkIGJ5IG90aGVyIHByb2Nlc3Mgd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgaXQuXG4gICAgICogVGhpcyBlcnJvciBjYW4gYWxzbyBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgdXNlciBncmFudGVkIHBlcm1pc3Npb24gdG8gdXNlIHRoZSBkZXZpY2VzIGJ1dCBhIGhhcmR3YXJlXG4gICAgICogZXJyb3Igb2NjdXJyZWQgYXQgdGhlIE9TLCBicm93c2VyIG9yIHdlYiBwYWdlIGxldmVsLCB3aGljaCBwcmV2ZW50ZWQgYWNjZXNzIHRvIHRoZSBkZXZpY2UuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BTFJFQURZX0lOX1VTRSA9IFwiREVWSUNFX0FMUkVBRFlfSU5fVVNFXCIsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIFRoZXJlIHdhcyBhbiB1bmtub3duIGVycm9yIHdoZW4gdHJ5aW5nIHRvIGFjY2VzcyB0aGUgc3BlY2lmaWVkIGF1ZGlvIGRldmljZVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfR0VORVJJQ19FUlJPUiA9ICdJTlBVVF9BVURJT19ERVZJQ0VfR0VORVJJQ19FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBQVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUiA9ICdQVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgY2xpZW50IHRyaWVkIHRvIGNhbGwgYSBtZXRob2Qgd2l0aG91dCB0aGUgcmVxdWlyZWQgcGVybWlzc2lvbnMuIFRoaXMgY2FuIG9jY3VyIGZvciBtZXRob2RzIFtbU2Vzc2lvbi5wdWJsaXNoXV0sXG4gICAgICogW1tTZXNzaW9uLmZvcmNlVW5wdWJsaXNoXV0sIFtbU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3RdXSwgW1tTdHJlYW0uYXBwbHlGaWx0ZXJdXSwgW1tTdHJlYW0ucmVtb3ZlRmlsdGVyXV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGVyZSBpcyBubyBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIGVycm9yIHdpbGwgYmUgdGhyb3duIHdoZW4gYW55IG1ldGhvZCByZXF1aXJpbmcgYSBjb25uZWN0aW9uIHRvXG4gICAgICogb3BlbnZpZHUtc2VydmVyIGlzIGNhbGxlZCBiZWZvcmUgc3VjY2Vzc2Z1bGx5IGNhbGxpbmcgbWV0aG9kIFtbU2Vzc2lvbi5jb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogR2VuZXJpYyBlcnJvclxuICAgICAqL1xuICAgIEdFTkVSSUNfRVJST1IgPSAnR0VORVJJQ19FUlJPUidcbn1cblxuLyoqXG4gKiBTaW1wbGUgb2JqZWN0IHRvIGlkZW50aWZ5IHJ1bnRpbWUgZXJyb3JzIG9uIHRoZSBjbGllbnQgc2lkZVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHVFcnJvciB7XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWVseSBpZGVudGlmeWluZyBuYW1lIG9mIHRoZSBlcnJvclxuICAgICAqL1xuICAgIG5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuXG4gICAgLyoqXG4gICAgICogRnVsbCBkZXNjcmlwdGlvbiBvZiB0aGUgZXJyb3JcbiAgICAgKi9cbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogT3BlblZpZHVFcnJvck5hbWUsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4vKipcbiAqIEhvdyB0aGUgdmlkZW8gd2lsbCBiZSBpbnNlcnRlZCBpbiB0aGUgRE9NIGZvciBQdWJsaXNoZXJzIGFuZCBTdWJzY3JpYmVycy4gU2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0gYW5kIFtbU3Vic2NyaWJlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dXG4gKi9cbmV4cG9ydCBlbnVtIFZpZGVvSW5zZXJ0TW9kZSB7XG5cbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhZnRlciB0aGUgdGFyZ2V0IGVsZW1lbnQgKGFzIG5leHQgc2libGluZylcbiAgICAgKi9cbiAgICBBRlRFUiA9ICdBRlRFUicsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYXMgbGFzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBBUFBFTkQgPSAnQVBQRU5EJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBiZWZvcmUgdGhlIHRhcmdldCBlbGVtZW50IChhcyBwcmV2aW91cyBzaWJsaW5nKVxuICAgICAqL1xuICAgIEJFRk9SRSA9ICdCRUZPUkUnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGZpcnN0IGNoaWxkIG9mIHRoZSB0YXJnZXQgZWxlbWVudFxuICAgICAqL1xuICAgIFBSRVBFTkQgPSAnUFJFUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gcmVwbGFjZXMgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBSRVBMQUNFID0gJ1JFUExBQ0UnXG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBjb25uZWN0aW9uQ3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYWZ0ZXIgYSBuZXcgdXNlciBoYXMgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uXG4gKiAtIGBjb25uZWN0aW9uRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhZnRlciBhIG5ldyB1c2VyIGhhcyBsZWZ0IHRoZSBzZXNzaW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGb3IgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50OlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHRoZSByZW1vdGUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHRoZSByZW1vdGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgb3RoZXIgdXNlciBjYWxsaW5nIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYFxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICogLSBcIm5vZGVDcmFzaGVkXCI6IGEgbm9kZSBoYXMgY3Jhc2hlZCBpbiB0aGUgc2VydmVyIHNpZGVcbiAgICAgKlxuICAgICAqIEZvciBgY29ubmVjdGlvbkNyZWF0ZWRgIGV2ZW50IGFuIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBjb25uZWN0aW9uOiBDb25uZWN0aW9uLCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihjYW5jZWxhYmxlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBjb25uZWN0aW9uO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5cbi8qKlxuICogKipUaGlzIGZlYXR1cmUgaXMgcGFydCBvZiBPcGVuVmlkdSBQcm8gdGllcioqIDxhIGhyZWY9XCJodHRwczovL2RvY3Mub3BlbnZpZHUuaW8vZW4vc3RhYmxlL29wZW52aWR1LXByby9cIiB0YXJnZXQ9XCJfYmxhbmtcIiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9jazsgYmFja2dyb3VuZC1jb2xvcjogcmdiKDAsIDEzNiwgMTcwKTsgY29sb3I6IHdoaXRlOyBmb250LXdlaWdodDogYm9sZDsgcGFkZGluZzogMHB4IDVweDsgbWFyZ2luLXJpZ2h0OiA1cHg7IGJvcmRlci1yYWRpdXM6IDNweDsgZm9udC1zaXplOiAxM3B4OyBsaW5lLWhlaWdodDoyMXB4OyBmb250LWZhbWlseTogTW9udHNlcnJhdCwgc2Fucy1zZXJpZlwiPlBSTzwvYT5cbiAqIFxuICogRGVmaW5lcyBldmVudCBgY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZGAgZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBvYmplY3QuXG4gKiBUaGlzIGV2ZW50IGlzIGZpcmVkIHdoZW4gYW55IHByb3BlcnR5IG9mIHRoZSBsb2NhbCBbW0Nvbm5lY3Rpb25dXSBvYmplY3QgY2hhbmdlcy5cbiAqIFRoZSBwcm9wZXJ0aWVzIHRoYXQgbWF5IGNoYW5nZSBhcmUgW1tDb25uZWN0aW9uLnJvbGVdXSBhbmQgW1tDb25uZWN0aW9uLnJlY29yZF1dLlxuICogXG4gKiBUaGUgb25seSB3YXkgdGhlIENvbm5lY3Rpb24gcHJvcGVydGllcyBtYXkgY2hhbmdlIGlzIGJ5IHVwZGF0aW5nIHRoZW0gdGhyb3VnaDpcbiAqIFxuICogLSBbQVBJIFJFU1RdKC9lbi9zdGFibGUvcmVmZXJlbmNlLWRvY3MvUkVTVC1BUEkvI3BhdGNoLW9wZW52aWR1YXBpc2Vzc2lvbnNsdHNlc3Npb25faWRndGNvbm5lY3Rpb25sdGNvbm5lY3Rpb25faWRndClcbiAqIC0gW29wZW52aWR1LWphdmEtY2xpZW50XSgvZW4vc3RhYmxlL3JlZmVyZW5jZS1kb2NzL29wZW52aWR1LWphdmEtY2xpZW50LyN1cGRhdGUtYS1jb25uZWN0aW9uKVxuICogLSBbb3BlbnZpZHUtbm9kZS1jbGllbnRdKC9lbi9zdGFibGUvcmVmZXJlbmNlLWRvY3Mvb3BlbnZpZHUtbm9kZS1jbGllbnQvI3VwZGF0ZS1hLWNvbm5lY3Rpb24pPGJyPjxicj5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIHdob3NlIHByb3BlcnR5IGhhcyBjaGFuZ2VkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwcm9wZXJ0eSBvZiB0aGUgc3RyZWFtIHRoYXQgY2hhbmdlZC4gVGhpcyB2YWx1ZSBpcyBlaXRoZXIgYFwicm9sZVwiYCBvciBgXCJyZWNvcmRcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgKGFmdGVyIGNoYW5nZSwgY3VycmVudCB2YWx1ZSlcbiAgICAgKi9cbiAgICBuZXdWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogUHJldmlvdXMgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChiZWZvcmUgY2hhbmdlKVxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBPYmplY3Q7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCBjb25uZWN0aW9uOiBDb25uZWN0aW9uLCBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZywgbmV3VmFsdWU6IE9iamVjdCwgb2xkVmFsdWU6IE9iamVjdCkge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZCcpO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBjb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmNoYW5nZWRQcm9wZXJ0eSA9IGNoYW5nZWRQcm9wZXJ0eTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9GaWx0ZXInO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciB8IEZpbHRlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIgfCBGaWx0ZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgZXZlbnQuIFRoZSBmb2xsb3dpbmcgZXZlbnRzIGhhdmUgYSBkZWZhdWx0IGJlaGF2aW9yOlxuICAgICAqXG4gICAgICogLSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gb2JqZWN0LCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHByb3BlcnR5IFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIEV4Y2VwdGlvbkV2ZW50TmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGVyZSB3YXMgYW4gdW5leHBlY3RlZCBlcnJvciBvbiB0aGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBhbiBJQ0UgY2FuZGlkYXRlIGdlbmVyYXRlZCBhbmQgc2VudCBieSB0aGUgY2xpZW50LXNpZGUuXG4gICAgICogXG4gICAgICogW1tFeGNlcHRpb25FdmVudF1dIG9iamVjdHMgd2l0aCB0aGlzIFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dIHdpbGwgaGF2ZSBhcyBbW0V4Y2VwdGlvbkV2ZW50Lm9yaWdpbl1dIHByb3BlcnR5IGEgW1tTZXNzaW9uXV0gb2JqZWN0LlxuICAgICAqL1xuICAgIElDRV9DQU5ESURBVEVfRVJST1IgPSAnSUNFX0NBTkRJREFURV9FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgW0lDRSBjb25uZWN0aW9uIHN0YXRlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUlRDUGVlckNvbm5lY3Rpb24vaWNlQ29ubmVjdGlvblN0YXRlKVxuICAgICAqIG9mIGFuIFtSVENQZWVyQ29ubmVjdGlvbl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JUQ1BlZXJDb25uZWN0aW9uKSByZWFjaGVkIGBmYWlsZWRgIHN0YXR1cy5cbiAgICAgKiBcbiAgICAgKiBUaGlzIGlzIGEgdGVybWluYWwgZXJyb3IgdGhhdCB3b24ndCBoYXZlIGFueSBraW5kIG9mIHBvc3NpYmxlIHJlY292ZXJ5LiBJZiB0aGUgY2xpZW50IGlzIHN0aWxsIGNvbm5lY3RlZCB0byBPcGVuVmlkdSBTZXJ2ZXIsXG4gICAgICogdGhlbiBhbiBhdXRvbWF0aWMgcmVjb25uZWN0aW9uIHByb2Nlc3Mgb2YgdGhlIG1lZGlhIHN0cmVhbSBpcyBpbW1lZGlhdGVseSBwZXJmb3JtZWQuIElmIHRoZSBJQ0UgY29ubmVjdGlvbiBoYXMgYnJva2VuIGR1ZSB0b1xuICAgICAqIGEgdG90YWwgbmV0d29yayBkcm9wLCB0aGVuIG5vIGF1dG9tYXRpYyByZWNvbm5lY3Rpb24gcHJvY2VzcyB3aWxsIGJlIHBvc3NpYmxlLlxuICAgICAqIFxuICAgICAqIFtbRXhjZXB0aW9uRXZlbnRdXSBvYmplY3RzIHdpdGggdGhpcyBbW0V4Y2VwdGlvbkV2ZW50Lm5hbWVdXSB3aWxsIGhhdmUgYXMgW1tFeGNlcHRpb25FdmVudC5vcmlnaW5dXSBwcm9wZXJ0eSBhIFtbU3RyZWFtXV0gb2JqZWN0LlxuICAgICAqL1xuICAgIElDRV9DT05ORUNUSU9OX0ZBSUxFRCA9ICdJQ0VfQ09OTkVDVElPTl9GQUlMRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIFtJQ0UgY29ubmVjdGlvbiBzdGF0ZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JUQ1BlZXJDb25uZWN0aW9uL2ljZUNvbm5lY3Rpb25TdGF0ZSlcbiAgICAgKiBvZiBhbiBbUlRDUGVlckNvbm5lY3Rpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SVENQZWVyQ29ubmVjdGlvbikgcmVhY2hlZCBgZGlzY29ubmVjdGVkYCBzdGF0dXMuXG4gICAgICogXG4gICAgICogVGhpcyBpcyBub3QgYSB0ZXJtaW5hbCBlcnJvciwgYW5kIGl0IGlzIHBvc3NpYmxlIGZvciB0aGUgSUNFIGNvbm5lY3Rpb24gdG8gYmUgcmVjb25uZWN0ZWQuIElmIHRoZSBjbGllbnQgaXMgc3RpbGwgY29ubmVjdGVkIHRvXG4gICAgICogT3BlblZpZHUgU2VydmVyIGFuZCBhZnRlciBjZXJ0YWluIHRpbWVvdXQgdGhlIElDRSBjb25uZWN0aW9uIGhhcyBub3QgcmVhY2hlZCBhIHN1Y2Nlc3Mgb3IgdGVybWluYWwgc3RhdHVzLCB0aGVuIGFuIGF1dG9tYXRpY1xuICAgICAqIHJlY29ubmVjdGlvbiBwcm9jZXNzIG9mIHRoZSBtZWRpYSBzdHJlYW0gaXMgcGVyZm9ybWVkLiBJZiB0aGUgSUNFIGNvbm5lY3Rpb24gaGFzIGJyb2tlbiBkdWUgdG8gYSB0b3RhbCBuZXR3b3JrIGRyb3AsIHRoZW4gbm9cbiAgICAgKiBhdXRvbWF0aWMgcmVjb25uZWN0aW9uIHByb2Nlc3Mgd2lsbCBiZSBwb3NzaWJsZS5cbiAgICAgKiBcbiAgICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGUgdGltZW91dCBmb3IgdGhlIHJlY29ubmVjdGlvbiBhdHRlbXB0IHdpdGggcHJvcGVydHkgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VDb25uZWN0aW9uRGlzY29ubmVjdGVkRXhjZXB0aW9uVGltZW91dF1dLFxuICAgICAqIHdoaWNoIGJ5IGRlZmF1bHQgaXMgNDAwMCBtaWxsaXNlY29uZHMuXG4gICAgICogXG4gICAgICogW1tFeGNlcHRpb25FdmVudF1dIG9iamVjdHMgd2l0aCB0aGlzIFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dIHdpbGwgaGF2ZSBhcyBbW0V4Y2VwdGlvbkV2ZW50Lm9yaWdpbl1dIHByb3BlcnR5IGEgW1tTdHJlYW1dXSBvYmplY3QuXG4gICAgICovXG4gICAgSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEID0gJ0lDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBBIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBoYXMgbm90IGZpcmVkIGV2ZW50IGBzdHJlYW1QbGF5aW5nYCBhZnRlciBjZXJ0YWluIHRpbWVvdXQuIGBzdHJlYW1QbGF5aW5nYCBldmVudCBiZWxvbmdzIHRvIFtbU3RyZWFtTWFuYWdlckV2ZW50XV1cbiAgICAgKiBjYXRlZ29yeS4gSXQgd3JhcHMgV2ViIEFQSSBuYXRpdmUgZXZlbnQgW2NhbnBsYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MTWVkaWFFbGVtZW50L2NhbnBsYXlfZXZlbnQpLlxuICAgICAqIFxuICAgICAqIE9wZW5WaWR1IEJyb3dzZXIgY2FuIHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVycyAoc2VlIFtoZXJlXSgvZW4vbGF0ZXN0L2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLFxuICAgICAqIG9yIHlvdSBjYW4gdGFrZSBjYXJlIG9mIHZpZGVvIHBsYXllcnMgb24geW91ciBvd24gKHNlZSBbaGVyZV0oL2VuL2xhdGVzdC9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBFaXRoZXIgd2F5LCB3aGVuZXZlciBhIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBpcyBjb21tYW5kZWQgdG8gYXR0YWNoIGl0cyBbW1N0cmVhbV1dIHRvIGEgdmlkZW8gZWxlbWVudCwgaXQgaXMgc3VwcG9zZWQgdG8gZmlyZSBgc3RyZWFtUGxheWluZ2BcbiAgICAgKiBldmVudCBzaG9ydGx5IGFmdGVyLiBJZiBpdCBkb2VzIG5vdCwgdGhlbiB3ZSBjYW4gc2FmZWx5IGFzc3VtZSB0aGF0IHNvbWV0aGluZyB3cm9uZyBoYXMgaGFwcGVuZWQgd2hpbGUgcGxheWluZyB0aGUgcmVtb3RlIHZpZGVvIGFuZCB0aGUgXG4gICAgICogYXBwbGljYXRpb24gbWF5IGJlIG5vdGlmaWVkIHRocm91Z2ggdGhpcyBzcGVjaWZpYyBFeGNlcHRpb25FdmVudC5cbiAgICAgKiBcbiAgICAgKiBUaGUgdGltZW91dCBjYW4gYmUgY29uZmlndXJlZCB3aXRoIHByb3BlcnR5IFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24ubm9TdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0XV0uIEJ5IGRlZmF1bHQgaXQgaXMgNDAwMCBtaWxsaXNlY29uZHMuXG4gICAgICogXG4gICAgICogVGhpcyBpcyBqdXN0IGFuIGluZm9ybWF0aXZlIGV4Y2VwdGlvbi4gSXQgb25seSBtZWFucyB0aGF0IGEgcmVtb3RlIFN0cmVhbSB0aGF0IGlzIHN1cHBvc2VkIHRvIGJlIHBsYXlpbmcgYnkgYSB2aWRlbyBwbGF5ZXIgaGFzIG5vdCBkb25lIHNvXG4gICAgICogaW4gYSByZWFzb25hYmxlIHRpbWUuIEJ1dCB0aGUgbGFjayBvZiB0aGUgZXZlbnQgY2FuIGJlIGNhdXNlZCBieSBtdWx0aXBsZSByZWFzb25zLiBJZiBhIFN1YnNjcmliZXIgaXMgbm90IHBsYXlpbmcgaXRzIFN0cmVhbSwgdGhlIG9yaWdpblxuICAgICAqIG9mIHRoZSBwcm9ibGVtIGNvdWxkIGJlIGxvY2F0ZWQgYXQgdGhlIFB1Ymxpc2hlciBzaWRlLiBPciBtYXkgYmUgY2F1c2VkIGJ5IGEgdHJhbnNpZW50IG5ldHdvcmsgcHJvYmxlbS4gQnV0IGl0IGFsc28gY291bGQgYmUgYSBwcm9ibGVtIHdpdGhcbiAgICAgKiBhdXRvcGxheSBwZXJtaXNzaW9ucy4gQm90dG9tIGxpbmUsIHRoZSBjYXVzZSBjYW4gYmUgdmVyeSB2YXJpZWQsIGFuZCBkZXBlbmRpbmcgb24gdGhlIGFwcGxpY2F0aW9uIHRoZSBsYWNrIG9mIHRoZSBldmVudCBjb3VsZCBldmVuIGJlIGV4cGVjdGVkLlxuICAgICAqIFxuICAgICAqIFtbRXhjZXB0aW9uRXZlbnRdXSBvYmplY3RzIHdpdGggdGhpcyBbW0V4Y2VwdGlvbkV2ZW50Lm5hbWVdXSB3aWxsIGhhdmUgYXMgW1tFeGNlcHRpb25FdmVudC5vcmlnaW5dXSBwcm9wZXJ0eSBhIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAgICAgKi9cbiAgICBOT19TVFJFQU1fUExBWUlOR19FVkVOVCA9ICdOT19TVFJFQU1fUExBWUlOR19FVkVOVCdcbn1cblxuLyoqXG4gKiBEZWZpbmVzIGV2ZW50IGBleGNlcHRpb25gIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gb2JqZWN0LlxuICogXG4gKiBUaGlzIGV2ZW50IGFjdHMgYXMgYSBnbG9iYWwgaGFuZGxlciBmb3IgYXN5bmNocm9ub3VzIGVycm9ycyB0aGF0IG1heSBiZSB0cmlnZ2VyZWQgZm9yIG11bHRpcGxlIHJlYXNvbnMgYW5kIGZyb20gbXVsdGlwbGUgb3JpZ2lucy4gVG8gc2VlIHRoZSBkaWZmZXJlbnRcbiAqIHR5cGVzIG9mIGV4Y2VwdGlvbnMgZ28gdG8gW1tFeGNlcHRpb25FdmVudE5hbWVdXS5cbiAqL1xuZXhwb3J0IGNsYXNzIEV4Y2VwdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgZXhjZXB0aW9uXG4gICAgICovXG4gICAgbmFtZTogRXhjZXB0aW9uRXZlbnROYW1lO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGFmZmVjdGVkIGJ5IHRoZSBleGNlcHRpb24uIERlcGVuZGluZyBvbiB0aGUgW1tFeGNlcHRpb25FdmVudC5uYW1lXV0gcHJvcGVydHk6XG4gICAgICogLSBbW1Nlc3Npb25dXTogYElDRV9DQU5ESURBVEVfRVJST1JgXG4gICAgICogLSBbW1N0cmVhbV1dOiBgSUNFX0NPTk5FQ1RJT05fRkFJTEVEYCwgYElDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRGBcbiAgICAgKiAtIFtbU3Vic2NyaWJlcl1dOiBgTk9fU1RSRUFNX1BMQVlJTkdfRVZFTlRgXG4gICAgICovXG4gICAgb3JpZ2luOiBTZXNzaW9uIHwgU3RyZWFtIHwgU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIEluZm9ybWF0aXZlIGRlc2NyaXB0aW9uIG9mIHRoZSBleGNlcHRpb25cbiAgICAgKi9cbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBBbnkgZXh0cmEgaW5mb3JtYXRpb24gYXNzb2NpYXRlZCB0byB0aGUgZXhjZXB0aW9uXG4gICAgICovXG4gICAgZGF0YT86IGFueTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBuYW1lOiBFeGNlcHRpb25FdmVudE5hbWUsIG9yaWdpbjogU2Vzc2lvbiB8IFN0cmVhbSB8IFN1YnNjcmliZXIsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IGFueSkge1xuICAgICAgICBzdXBlcihmYWxzZSwgc2Vzc2lvbiwgJ2V4Y2VwdGlvbicpO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9yaWdpbiA9IG9yaWdpbjtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9GaWx0ZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVyeSBldmVudCBkaXNwYXRjaGVkIGJ5IGF1ZGlvL3ZpZGVvIHN0cmVhbSBmaWx0ZXJzLiBZb3UgY2FuIHN1YnNjcmliZSB0byBmaWx0ZXIgZXZlbnRzIGJ5IGNhbGxpbmcgW1tGaWx0ZXIuYWRkRXZlbnRMaXN0ZW5lcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXJFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIERhdGEgb2YgdGhlIGV2ZW50XG4gICAgICovXG4gICAgZGF0YTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogRmlsdGVyLCBldmVudFR5cGU6IHN0cmluZywgZGF0YTogT2JqZWN0KSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIGV2ZW50VHlwZSk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuXG4vKipcbiAqICoqVGhpcyBmZWF0dXJlIGlzIHBhcnQgb2YgT3BlblZpZHUgUHJvIHRpZXIqKiA8YSBocmVmPVwiaHR0cHM6Ly9kb2NzLm9wZW52aWR1LmlvL2VuL3N0YWJsZS9vcGVudmlkdS1wcm8vXCIgdGFyZ2V0PVwiX2JsYW5rXCIgc3R5bGU9XCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGJhY2tncm91bmQtY29sb3I6IHJnYigwLCAxMzYsIDE3MCk7IGNvbG9yOiB3aGl0ZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHBhZGRpbmc6IDBweCA1cHg7IG1hcmdpbi1yaWdodDogNXB4OyBib3JkZXItcmFkaXVzOiAzcHg7IGZvbnQtc2l6ZTogMTNweDsgbGluZS1oZWlnaHQ6MjFweDsgZm9udC1mYW1pbHk6IE1vbnRzZXJyYXQsIHNhbnMtc2VyaWZcIj5QUk88L2E+XG4gKiBcbiAqIERlZmluZXMgZXZlbnQgYG5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkYCBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dLlxuICogVGhpcyBldmVudCBpcyBmaXJlZCB3aGVuIHRoZSBuZXR3b3JrIHF1YWxpdHkgbGV2ZWwgb2YgYSBbW0Nvbm5lY3Rpb25dXSBjaGFuZ2VzLiBTZWUgW25ldHdvcmsgcXVhbGl0eV0oL2VuL3N0YWJsZS9hZHZhbmNlZC1mZWF0dXJlcy9uZXR3b3JrLXF1YWxpdHkvKVxuICovXG5leHBvcnQgY2xhc3MgTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIE5ldyB2YWx1ZSBvZiB0aGUgbmV0d29yayBxdWFsaXR5IGxldmVsXG4gICAgICovXG4gICAgbmV3VmFsdWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIE9sZCB2YWx1ZSBvZiB0aGUgbmV0d29yayBxdWFsaXR5IGxldmVsXG4gICAgICovXG4gICAgb2xkVmFsdWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENvbm5lY3Rpb24gZm9yIHdob20gdGhlIG5ldHdvcmsgcXVhbGl0eSBsZXZlbCBjaGFuZ2VkXG4gICAgICovXG4gICAgY29ubmVjdGlvbjogQ29ubmVjdGlvblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgbmV3VmFsdWU6IG51bWJlciwgb2xkVmFsdWU6IG51bWJlciwgY29ubmVjdGlvbjogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnbmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWQnKTtcbiAgICAgICAgdGhpcy5uZXdWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLm9sZFZhbHVlID0gb2xkVmFsdWU7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcHVibGlzaGVyU3RhcnRTcGVha2luZ2A6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtTWFuYWdlcl1dIHdoZW4gYSB1c2VyIGhhcyBzdGFydGVkIHNwZWFraW5nXG4gKiAtIGBwdWJsaXNoZXJTdG9wU3BlYWtpbmdgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFuZCBbW1N0cmVhbU1hbmFnZXJdXSB3aGVuIGEgdXNlciBoYXMgc3RvcHBlZCBzcGVha2luZ1xuICpcbiAqIE1vcmUgaW5mb3JtYXRpb246XG4gKiAtIFRoaXMgZXZlbnRzIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgZm9yICoqc3RyZWFtcyB0aGF0IGhhdmUgYXVkaW8gdHJhY2tzKiogKFtbU3RyZWFtLmhhc0F1ZGlvXV0gbXVzdCBiZSB0cnVlKVxuICogLSBZb3UgY2FuIGZ1cnRoZXIgY29uZmlndXJlIGhvdyB0aGUgZXZlbnRzIGFyZSBkaXNwYXRjaGVkIGJ5IHNldHRpbmcgcHJvcGVydHkgYHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uc2AgaW4gdGhlIGNhbGwgb2YgW1tPcGVuVmlkdS5zZXRBZHZhbmNlZENvbmZpZ3VyYXRpb25dXVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHN0cmVhbUlkOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuc3RyZWFtSWQgPSBzdHJlYW1JZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgcmVjb3JkaW5nU3RhcnRlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYWZ0ZXIgdGhlIHNlc3Npb24gaGFzIHN0YXJ0ZWQgYmVpbmcgcmVjb3JkZWRcbiAqIC0gYHJlY29yZGluZ1N0b3BwZWRgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFmdGVyIHRoZSBzZXNzaW9uIGhhcyBzdG9wcGVkIGJlaW5nIHJlY29yZGVkXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdyZWNvcmRpbmdTdG9wcGVkJyBldmVudDpcbiAgICAgKiAtIFwicmVjb3JkaW5nU3RvcHBlZEJ5U2VydmVyXCI6IHRoZSByZWNvcmRpbmcgaGFzIGJlZW4gZ3JhY2VmdWxseSBzdG9wcGVkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJhdXRvbWF0aWNTdG9wXCI6IHNlZSBbQXV0b21hdGljIHN0b3Agb2YgcmVjb3JkaW5nc10oL2VuL3N0YWJsZS9hZHZhbmNlZC1mZWF0dXJlcy9yZWNvcmRpbmcvI2F1dG9tYXRpYy1zdG9wLW9mLXJlY29yZGluZ3MpXG4gICAgICogLSBcIm5vZGVDcmFzaGVkXCI6IGEgbm9kZSBoYXMgY3Jhc2hlZCBpbiB0aGUgc2VydmVyIHNpZGVcbiAgICAgKlxuICAgICAqIEZvciAncmVjb3JkaW5nU3RhcnRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHJlYXNvbj86IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICBpZiAobmFtZSAhPT0gaWQpIHtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cblxuLyoqXG4gKiBEZWZpbmVzIGV2ZW50IGBzZXNzaW9uRGlzY29ubmVjdGVkYCBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIGFmdGVyIHRoZSBsb2NhbCB1c2VyIGhhcyBsZWZ0IHRoZSBzZXNzaW9uLiBUaGlzIGlzIHRoZSBsb2NhbCB2ZXJzaW9uIG9mIHRoZSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQsIHdoaWNoIGlzIG9ubHkgZGlzcGF0Y2hlZCBieSByZW1vdGUgdXNlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZC4gQmVmb3JlIGEgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHdpdGggdGhpcyByZWFzb24gaXMgdHJpZ2dlcmVkLFxuICAgICAqICAgICAgU2Vzc2lvbiBvYmplY3Qgd2lsbCBhbHdheXMgaGF2ZSBwcmV2aW91c2x5IGRpc3BhdGNoZWQgYSBgcmVjb25uZWN0aW5nYCBldmVudC4gSWYgdGhlIHJlY29ubmVjdGlvbiBwcm9jZXNzIHN1Y2NlZWRzLFxuICAgICAqICAgICAgU2Vzc2lvbiBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGByZWNvbm5lY3RlZGAgZXZlbnQuIElmIGl0IGZhaWxzLCBTZXNzaW9uIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XG4gICAgICogICAgICB3aXRoIHJlYXNvbiBcIm5ldHdvcmtEaXNjb25uZWN0XCJcbiAgICAgKiAtIFwibm9kZUNyYXNoZWRcIjogYSBub2RlIGhhcyBjcmFzaGVkIGluIHRoZSBzZXJ2ZXIgc2lkZS4gWW91IGNhbiB1c2UgdGhpcyByZWFzb24gdG8gYXNrIHlvdXIgYXBwbGljYXRpb24ncyBiYWNrZW5kIHRvIHJlY29ubmVjdCBcbiAgICAgKiB0byBhIG5ldyBzZXNzaW9uIHRvIHJlcGxhY2UgdGhlIGNyYXNoZWQgb25lXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcih0cnVlLCB0YXJnZXQsICdzZXNzaW9uRGlzY29ubmVjdGVkJyk7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkge1xuXG4gICAgICAgIGxvZ2dlci5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW9yIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuXG4gICAgICAgIGNvbnN0IHNlc3Npb24gPSA8U2Vzc2lvbj50aGlzLnRhcmdldDtcblxuICAgICAgICAvLyBEaXNwb3NlIGFuZCBkZWxldGUgYWxsIHJlbW90ZSBDb25uZWN0aW9uc1xuICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmZvckVhY2gocmVtb3RlQ29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSByZW1vdGVDb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbSEuZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5zdHJlYW0hLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5zdHJlYW0hLnN0cmVhbU1hbmFnZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9ucy5nZXQoY29ubmVjdGlvbklkKT8uc3RyZWFtIS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbT8uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVTdHJlYW1zQ3JlYXRlZC5kZWxldGUoc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmRlbGV0ZShjb25uZWN0aW9uSWQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBzaWduYWxgOiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dIHdoZW4gYSBzaWduYWwgaXMgcmVjZWl2ZWRcbiAqIC0gYHNpZ25hbDpUWVBFYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSB3aGVuIGEgc2lnbmFsIG9mIHR5cGUgVFlQRSBpcyByZWNlaXZlZFxuICovXG5leHBvcnQgY2xhc3MgU2lnbmFsRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBzaWduYWwuIEl0IGlzIHN0cmluZyBgXCJzaWduYWxcImAgZm9yIHRob3NlIHNpZ25hbHMgc2VudCB3aXRoIG5vIFtbU2lnbmFsT3B0aW9ucy50eXBlXV0gcHJvcGVydHksIGFuZCBgXCJzaWduYWw6dHlwZVwiYCBpZiB3YXMgc2VudCB3aXRoIGEgXG4gICAgICogdmFsaWQgW1tTaWduYWxPcHRpb25zLnR5cGVdXSBwcm9wZXJ0eS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzcGVjaWZpY2FsbHkgc3Vic2NyaWJlZCB0byBgU2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCBmdW5jdGlvbihzaWduYWxFdmVudCkgey4uLn0pYCB0byB0cmlnZ2VyIHRoYXQgdHlwZSBvZiBzaWduYWwuXG4gICAgICpcbiAgICAgKiBTdWJzY3JpYmluZyB0byBgU2Vzc2lvbi5vbignc2lnbmFsJywgZnVuY3Rpb24oc2lnbmFsRXZlbnQpIHsuLi59KWAgd2lsbCB0cmlnZ2VyIGFsbCBzaWduYWxzLCBubyBtYXR0ZXIgdGhlaXIgdHlwZS5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW1wdHkpXG4gICAgICovXG4gICAgZGF0YT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzZW50IHRoZSBzaWduYWwuIFRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkIGlmIHRoZSBzaWduYWxcbiAgICAgKiB3YXMgZGlyZWN0bHkgZ2VuZXJhdGVkIGJ5IHRoZSBhcHBsaWNhdGlvbiBzZXJ2ZXIgKG5vdCBieSBvdGhlciBjbGllbnQpXG4gICAgICovXG4gICAgZnJvbT86IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlPzogc3RyaW5nLCBkYXRhPzogc3RyaW5nLCBmcm9tPzogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc2lnbmFsJyk7XG4gICAgICAgIGlmICghIXR5cGUpIHtcbiAgICAgICAgICAgIHRoaXMudHlwZSA9ICdzaWduYWw6JyArIHR5cGU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBzdHJlYW1DcmVhdGVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhbmQgW1tQdWJsaXNoZXJdXSBhZnRlciBzb21lIHVzZXIgaGFzIHN0YXJ0ZWQgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvblxuICogLSBgc3RyZWFtRGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1Nlc3Npb25dXSBhbmQgW1tQdWJsaXNoZXJdXSBhZnRlciBzb21lIHVzZXIgaGFzIHN0b3BwZWQgcHVibGlzaGluZyB0byB0aGUgc2Vzc2lvblxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW0gb2JqZWN0IHRoYXQgd2FzIGNyZWF0ZWQgb3IgZGVzdHJveWVkXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBGb3IgJ3N0cmVhbURlc3Ryb3llZCcgZXZlbnQ6XG4gICAgICogLSBcInVucHVibGlzaFwiOiBtZXRob2QgYFNlc3Npb24udW5wdWJsaXNoKClgIGhhcyBiZWVuIGNhbGxlZFxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IG1ldGhvZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgIGhhcyBiZWVuIGNhbGxlZFxuICAgICAqIC0gXCJmb3JjZVVucHVibGlzaEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZVVucHVibGlzaCgpYCBvdmVyIHRoZSBTdHJlYW1cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCI6IHNvbWUgdXNlciBoYXMgY2FsbGVkIGBTZXNzaW9uLmZvcmNlRGlzY29ubmVjdCgpYCBvdmVyIHRoZSBTdHJlYW1cbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVNlcnZlclwiOiB0aGUgdXNlcidzIHN0cmVhbSBoYXMgYmVlbiB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJmb3JjZURpc2Nvbm5lY3RCeVNlcnZlclwiOiB0aGUgdXNlciBoYXMgYmVlbiBldmljdGVkIGZyb20gdGhlIFNlc3Npb24gYnkgdGhlIGFwcGxpY2F0aW9uXG4gICAgICogLSBcInNlc3Npb25DbG9zZWRCeVNlcnZlclwiOiB0aGUgU2Vzc2lvbiBoYXMgYmVlbiBjbG9zZWQgYnkgdGhlIGFwcGxpY2F0aW9uXG4gICAgICogLSBcIm5ldHdvcmtEaXNjb25uZWN0XCI6IHRoZSB1c2VyJ3MgbmV0d29yayBjb25uZWN0aW9uIGhhcyBkcm9wcGVkXG4gICAgICogLSBcIm5vZGVDcmFzaGVkXCI6IGEgbm9kZSBoYXMgY3Jhc2hlZCBpbiB0aGUgc2VydmVyIHNpZGVcbiAgICAgKlxuICAgICAqIEZvciAnc3RyZWFtQ3JlYXRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuY2VsYWJsZTogYm9vbGVhbiwgdGFyZ2V0OiBTZXNzaW9uIHwgUHVibGlzaGVyLCB0eXBlOiBzdHJpbmcsIHN0cmVhbTogU3RyZWFtLCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcihjYW5jZWxhYmxlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7XG4gICAgICAgIGlmICh0aGlzLnR5cGUgPT09ICdzdHJlYW1EZXN0cm95ZWQnKSB7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnRhcmdldCBpbnN0YW5jZW9mIFNlc3Npb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdGUgU3RyZWFtXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnU2Vzc2lvbidcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBQdWJsaXNoZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBMb2NhbCBTdHJlYW1cbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkNhbGxpbmcgZGVmYXVsdCBiZWhhdmlvciB1cG9uICdcIiArIHRoaXMudHlwZSArIFwiJyBldmVudCBkaXNwYXRjaGVkIGJ5ICdQdWJsaXNoZXInXCIpO1xuICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoKDxQdWJsaXNoZXI+dGhpcy50YXJnZXQpLnNjcmVlblNoYXJlUmVzaXplSW50ZXJ2YWwpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1SZWFkeVRvUHVibGlzaCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRlIFB1Ymxpc2hlciBvYmplY3QgZnJvbSBPcGVuVmlkdSBwdWJsaXNoZXJzIGFycmF5XG4gICAgICAgICAgICAgICAgY29uc3Qgb3BlbnZpZHVQdWJsaXNoZXJzID0gKDxQdWJsaXNoZXI+dGhpcy50YXJnZXQpLm9wZW52aWR1LnB1Ymxpc2hlcnM7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcGVudmlkdVB1Ymxpc2hlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wZW52aWR1UHVibGlzaGVyc1tpXSA9PT0gKDxQdWJsaXNoZXI+dGhpcy50YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcGVudmlkdVB1Ymxpc2hlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIERpc3Bvc2UgdGhlIE1lZGlhU3RyZWFtIGxvY2FsIG9iamVjdFxuICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzcG9zZU1lZGlhU3RyZWFtKCk7XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSBmcm9tIERPTSBhbGwgdmlkZW8gZWxlbWVudHMgYXNzb2NpYXRlZCB0byB0aGlzIFN0cmVhbSwgaWYgdGhlcmUncyBhIFN0cmVhbU1hbmFnZXIgZGVmaW5lZFxuICAgICAgICAgICAgLy8gKG1ldGhvZCBTZXNzaW9uLnN1YnNjcmliZSBtdXN0IGhhdmUgYmVlbiBjYWxsZWQpXG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlcikgdGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlci5yZW1vdmVBbGxWaWRlb3MoKTtcblxuICAgICAgICAgICAgLy8gRGVsZXRlIHN0cmVhbSBmcm9tIFNlc3Npb24ucmVtb3RlU3RyZWFtc0NyZWF0ZWQgbWFwXG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkLmRlbGV0ZSh0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBTdHJlYW1PcHRpb25zU2VydmVyIGZyb20gcmVtb3RlIENvbm5lY3Rpb25cbiAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNvbm5lY3Rpb24gPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldCh0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uICYmICEhcmVtb3RlQ29ubmVjdGlvbi5yZW1vdGVPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtT3B0aW9uc1NlcnZlciA9IHJlbW90ZUNvbm5lY3Rpb24ucmVtb3RlT3B0aW9ucy5zdHJlYW1zO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1PcHRpb25zU2VydmVyLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1PcHRpb25zU2VydmVyW2ldLmlkID09PSB0aGlzLnN0cmVhbS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtT3B0aW9uc1NlcnZlci5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgdGhlIGZvbGxvd2luZyBldmVudHM6XG4gKiAtIGBzdHJlYW1QbGF5aW5nYDogZGlzcGF0Y2hlZCBieSBbW1N0cmVhbU1hbmFnZXJdXSAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pIHdoZW5ldmVyIGl0cyBtZWRpYSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcgKG9uZSBvZiBpdHMgdmlkZW9zIGhhcyBtZWRpYVxuICogYW5kIGhhcyBiZWd1biB0byBwbGF5KS4gVGhpcyBldmVudCB3aWxsIGJlIGRpc3BhdGNoZWQgd2hlbiB0aGVzZSAzIGNvbmRpdGlvbnMgYXJlIG1ldDpcbiAqICAgMS4gVGhlIFN0cmVhbU1hbmFnZXIgaGFzIG5vIHZpZGVvIGFzc29jaWF0ZWQgaW4gdGhlIERPTVxuICogICAyLiBJdCBpcyBhc3NvY2lhdGVkIHRvIG9uZSB2aWRlb1xuICogICAzLiBUaGF0IHZpZGVvIHN0YXJ0cyBwbGF5aW5nLiBJbnRlcm5hbGx5IHRoZSBleHBlY3RlZCBXZWIgQVBJIGV2ZW50IGlzIFtIVE1MTWVkaWFFbGVtZW50LmNhbnBsYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MTWVkaWFFbGVtZW50L2NhbnBsYXlfZXZlbnQpXG4gKiAtIGBzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZWA6IGRpc3BhdGNoZWQgYnkgW1tTdHJlYW1NYW5hZ2VyXV0gKFtbUHVibGlzaGVyXV0gYW5kIFtbU3Vic2NyaWJlcl1dKSB3aGVuIHRoZSB2b2x1bWUgb2YgaXRzIFN0cmVhbSdzIGF1ZGlvIHRyYWNrXG4gKiBjaGFuZ2VzLiBPbmx5IGFwcGxpZXMgaWYgW1tTdHJlYW0uaGFzQXVkaW9dXSBpcyBgdHJ1ZWAuIFRoZSBmcmVxdWVuY3kgdGhpcyBldmVudCBpcyBmaXJlZCB3aXRoIGlzIGRlZmluZWQgYnkgcHJvcGVydHkgYGludGVydmFsYCBvZlxuICogW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbi5wdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnNdXSAoZGVmYXVsdCAxMDBtcylcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbU1hbmFnZXJFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIEZvciBgc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2VgIGV2ZW50OlxuICAgICAqIC0gYHtuZXdWYWx1ZTogbnVtYmVyLCBvbGRWYWx1ZTogbnVtYmVyfWA6IG5ldyBhbmQgb2xkIGF1ZGlvIHZvbHVtZSB2YWx1ZXMuIFRoZXNlIHZhbHVlcyBhcmUgYmV0d2VlbiAtMTAwIChzaWxlbmNlKSBhbmQgMCAobG91ZGVzdCBwb3NzaWJsZSB2b2x1bWUpLlxuICAgICAqIFRoZXkgYXJlIG5vdCBleGFjdCBhbmQgZGVwZW5kIG9uIGhvdyB0aGUgYnJvd3NlciBpcyBtYW5hZ2luZyB0aGUgYXVkaW8gdHJhY2ssIGJ1dCAtMTAwIGFuZCAwIGNhbiBiZSB0YWtlbiBhcyBsaW1pdCB2YWx1ZXMuXG4gICAgICogXG4gICAgICogRm9yIGBzdHJlYW1QbGF5aW5nYCBldmVudCB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB2YWx1ZTogT2JqZWN0IHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nLCB2YWx1ZTogT2JqZWN0IHwgdW5kZWZpbmVkKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMCBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIGV2ZW50IGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gYXMgd2VsbCBhcyBieSBbW1N0cmVhbU1hbmFnZXJdXSAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pLlxuICogVGhpcyBldmVudCBpcyBmaXJlZCB3aGVuIGFueSByZW1vdGUgc3RyZWFtIChvd25lZCBieSBhIFN1YnNjcmliZXIpIG9yIGxvY2FsIHN0cmVhbSAob3duZWQgYnkgYSBQdWJsaXNoZXIpIHVuZGVyZ29lc1xuICogYW55IGNoYW5nZSBpbiBhbnkgb2YgaXRzIG11dGFibGUgcHJvcGVydGllcyAoc2VlIFtbY2hhbmdlZFByb3BlcnR5XV0pLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHdob3NlIHByb3BlcnR5IGhhcyBjaGFuZ2VkLiBZb3UgY2FuIGFsd2F5cyBpZGVudGlmeSB0aGUgdXNlciBwdWJsaXNoaW5nIHRoZSBjaGFuZ2VkIHN0cmVhbSBieSBjb25zdWx0aW5nIHByb3BlcnR5IFtbU3RyZWFtLmNvbm5lY3Rpb25dXVxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHByb3BlcnR5IG9mIHRoZSBzdHJlYW0gdGhhdCBjaGFuZ2VkLiBUaGlzIHZhbHVlIGlzIGVpdGhlciBgXCJ2aWRlb0FjdGl2ZVwiYCwgYFwiYXVkaW9BY3RpdmVcImAsIGBcInZpZGVvRGltZW5zaW9uc1wiYCBvciBgXCJmaWx0ZXJcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgLCBgXCJzY3JlZW5SZXNpemVkXCJgIG9yIGBcInRyYWNrUmVwbGFjZWRcImBcbiAgICAgKiAtIEZvciBgZmlsdGVyYDogYFwiYXBwbHlGaWx0ZXJcImAsIGBcImV4ZWNGaWx0ZXJNZXRob2RcImAgb3IgYFwicmVtb3ZlRmlsdGVyXCJgXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBOZXcgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChhZnRlciBjaGFuZ2UsIGN1cnJlbnQgdmFsdWUpXG4gICAgICovXG4gICAgbmV3VmFsdWU6IE9iamVjdDtcblxuICAgIC8qKlxuICAgICAqIFByZXZpb3VzIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSAoYmVmb3JlIGNoYW5nZSlcbiAgICAgKi9cbiAgICBvbGRWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHN0cmVhbTogU3RyZWFtLCBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZywgbmV3VmFsdWU6IE9iamVjdCwgb2xkVmFsdWU6IE9iamVjdCwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcpO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5jaGFuZ2VkUHJvcGVydHkgPSBjaGFuZ2VkUHJvcGVydHk7XG4gICAgICAgIHRoaXMubmV3VmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgdGhpcy5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIwIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBmb2xsb3dpbmcgZXZlbnRzOlxuICogLSBgdmlkZW9FbGVtZW50Q3JlYXRlZGA6IGRpc3BhdGNoZWQgYnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gd2hlbmV2ZXIgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGluc2VydGVkIGludG8gRE9NIGJ5IE9wZW5WaWR1IEJyb3dzZXIgbGlicmFyeS4gU2VlXG4gKiBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uLlxuICogLSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYDogZGlzcGF0Y2hlZCBieSBbW1B1Ymxpc2hlcl1dIGFuZCBbW1N1YnNjcmliZXJdXSB3aGVuZXZlciBhbiBIVE1MIHZpZGVvIGVsZW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIERPTSBieSBPcGVuVmlkdSBCcm93c2VyIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBWaWRlb0VsZW1lbnRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFZpZGVvIGVsZW1lbnQgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBlbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQsIHRhcmdldDogU3RyZWFtTWFuYWdlciwgdHlwZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIHR5cGUpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn0iLCJmdW5jdGlvbiBNYXBwZXIoKSB7XG4gIHZhciBzb3VyY2VzID0ge307XG5cblxuICB0aGlzLmZvckVhY2ggPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlcykge1xuICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNba2V5XTtcblxuICAgICAgZm9yICh2YXIga2V5MiBpbiBzb3VyY2UpXG4gICAgICAgIGNhbGxiYWNrKHNvdXJjZVtrZXkyXSk7XG4gICAgfTtcbiAgfTtcblxuICB0aGlzLmdldCA9IGZ1bmN0aW9uIChpZCwgc291cmNlKSB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZiAoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4gaWRzW2lkXTtcbiAgfTtcblxuICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uIChpZCwgc291cmNlKSB7XG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZiAoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcblxuICAgIGRlbGV0ZSBpZHNbaWRdO1xuXG4gICAgLy8gQ2hlY2sgaXQncyBlbXB0eVxuICAgIGZvciAodmFyIGkgaW4gaWRzKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICBkZWxldGUgc291cmNlc1tzb3VyY2VdO1xuICB9O1xuXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24gKHZhbHVlLCBpZCwgc291cmNlKSB7XG4gICAgaWYgKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiB0aGlzLnJlbW92ZShpZCwgc291cmNlKTtcblxuICAgIHZhciBpZHMgPSBzb3VyY2VzW3NvdXJjZV07XG4gICAgaWYgKGlkcyA9PSB1bmRlZmluZWQpXG4gICAgICBzb3VyY2VzW3NvdXJjZV0gPSBpZHMgPSB7fTtcblxuICAgIGlkc1tpZF0gPSB2YWx1ZTtcbiAgfTtcbn07XG5cblxuTWFwcGVyLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbiAoaWQsIHNvdXJjZSkge1xuICB2YXIgdmFsdWUgPSB0aGlzLmdldChpZCwgc291cmNlKTtcbiAgaWYgKHZhbHVlID09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gIHJldHVybiB2YWx1ZTtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBNYXBwZXI7IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNCBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbnZhciBKc29uUnBjQ2xpZW50ID0gcmVxdWlyZSgnLi9qc29ucnBjY2xpZW50Jyk7XG5cblxuZXhwb3J0cy5Kc29uUnBjQ2xpZW50ID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi8nKTtcbnZhciBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gcmVxdWlyZSgnLi90cmFuc3BvcnRzL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcbnZhciBPcGVuVmlkdUxvZ2dlciA9IHJlcXVpcmUoJy4uLy4uLy4uL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcicpLk9wZW5WaWR1TG9nZ2VyO1xuXG5EYXRlLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlO1xufTtcblxudmFyIFBJTkdfSU5URVJWQUwgPSA1MDAwO1xuXG52YXIgUkVDT05ORUNUSU5HID0gJ1JFQ09OTkVDVElORyc7XG52YXIgQ09OTkVDVEVEID0gJ0NPTk5FQ1RFRCc7XG52YXIgRElTQ09OTkVDVEVEID0gJ0RJU0NPTk5FQ1RFRCc7XG5cbnZhciBMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqXG4gKiBoZWFydGJlYXQ6IGludGVydmFsIGluIG1zIGZvciBlYWNoIGhlYXJ0YmVhdCBtZXNzYWdlLFxuICogPHByZT5cbiAqIHdzIDoge1xuICogXHR1cmkgOiBVUkkgdG8gY29ubnRlY3QgdG8sXG4gKiBcdG9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbiAqIFx0b25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QgKG1heCByZXRyaWVzIGZvciByZWNvbm5lY3RpbmcgcmVhY2hlZCksXG4gKiBcdG9ucmVjb25uZWN0aW5nIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgaXMgcmVjb25uZWN0aW5nLFxuICogXHRvbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG4gKiBcdG9uZXJyb3IgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3JcbiAqIH0sXG4gKiBycGMgOiB7XG4gKiBcdHJlcXVlc3RUaW1lb3V0IDogdGltZW91dCBmb3IgYSByZXF1ZXN0LFxuICogXHRzZXNzaW9uU3RhdHVzQ2hhbmdlZDogY2FsbGJhY2sgbWV0aG9kIGZvciBjaGFuZ2VzIGluIHNlc3Npb24gc3RhdHVzLFxuICogXHRtZWRpYVJlbmVnb3RpYXRpb246IG1lZGlhUmVuZWdvdGlhdGlvblxuICogfVxuICogPC9wcmU+XG4gKi9cbmZ1bmN0aW9uIEpzb25ScGNDbGllbnQoY29uZmlndXJhdGlvbikge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHdzQ29uZmlnID0gY29uZmlndXJhdGlvbi53cztcblxuICAgIHZhciBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gLTE7XG5cbiAgICB2YXIgcGluZ05leHROdW0gPSAwO1xuICAgIHZhciBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgIHZhciBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICB2YXIgcGluZ0ludGVydmFsO1xuXG4gICAgdmFyIHN0YXR1cyA9IERJU0NPTk5FQ1RFRDtcblxuICAgIHZhciBvbnJlY29ubmVjdGluZyA9IHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nO1xuICAgIHZhciBvbnJlY29ubmVjdGVkID0gd3NDb25maWcub25yZWNvbm5lY3RlZDtcbiAgICB2YXIgb25jb25uZWN0ZWQgPSB3c0NvbmZpZy5vbmNvbm5lY3RlZDtcbiAgICB2YXIgb25lcnJvciA9IHdzQ29uZmlnLm9uZXJyb3I7XG5cbiAgICBjb25maWd1cmF0aW9uLnJwYy5wdWxsID0gZnVuY3Rpb24gKHBhcmFtcywgcmVxdWVzdCkge1xuICAgICAgICByZXF1ZXN0LnJlcGx5KG51bGwsIFwicHVzaFwiKTtcbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbnJlY29ubmVjdGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OUkVDT05ORUNUSU5HIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBSRUNPTk5FQ1RJTkcpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIFJFQ09OTkVDVElORyBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVElORyBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHN0b3BQaW5nKCk7XG5cbiAgICAgICAgc3RhdHVzID0gUkVDT05ORUNUSU5HO1xuICAgICAgICBpZiAob25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0aW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbnJlY29ubmVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RFRCAtLS0tLS0tLS0tLVwiKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJXZWJzb2NrZXQgYWxyZWFkeSBpbiBDT05ORUNURUQgc3RhdGUgd2hlbiByZWNlaXZpbmcgYSBuZXcgT05SRUNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpO1xuXG4gICAgICAgIGlmIChvbnJlY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbnJlY29ubmVjdGVkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3c0NvbmZpZy5vbmNvbm5lY3RlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9OQ09OTkVDVEVEIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBDT05ORUNURUQpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIENPTk5FQ1RFRCBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTkNPTk5FQ1RFRCBtZXNzYWdlLiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdGF0dXMgPSBDT05ORUNURUQ7XG5cbiAgICAgICAgZW5hYmxlZFBpbmdzID0gdHJ1ZTtcbiAgICAgICAgdXNlUGluZygpO1xuXG4gICAgICAgIGlmIChvbmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgb25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uZXJyb3IgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiLS0tLS0tLS0tIE9ORVJST1IgLS0tLS0tLS0tLS1cIik7XG5cbiAgICAgICAgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgICAgIHN0b3BQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uZXJyb3IpIHtcbiAgICAgICAgICAgIG9uZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHdzID0gbmV3IFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24od3NDb25maWcpO1xuXG4gICAgTG9nZ2VyLmRlYnVnKCdDb25uZWN0aW5nIHdlYnNvY2tldCB0byBVUkk6ICcgKyB3c0NvbmZpZy51cmkpO1xuXG4gICAgdmFyIHJwY0J1aWxkZXJPcHRpb25zID0ge1xuICAgICAgICByZXF1ZXN0X3RpbWVvdXQ6IGNvbmZpZ3VyYXRpb24ucnBjLnJlcXVlc3RUaW1lb3V0LFxuICAgICAgICBwaW5nX3JlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMuaGVhcnRiZWF0UmVxdWVzdFRpbWVvdXRcbiAgICB9O1xuXG4gICAgdmFyIHJwYyA9IG5ldyBScGNCdWlsZGVyKFJwY0J1aWxkZXIucGFja2Vycy5Kc29uUlBDLCBycGNCdWlsZGVyT3B0aW9ucywgd3MsXG4gICAgICAgIGZ1bmN0aW9uIChyZXF1ZXN0KSB7XG5cbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZygnUmVjZWl2ZWQgcmVxdWVzdDogJyArIEpTT04uc3RyaW5naWZ5KHJlcXVlc3QpKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IGNvbmZpZ3VyYXRpb24ucnBjW3JlcXVlc3QubWV0aG9kXTtcblxuICAgICAgICAgICAgICAgIGlmIChmdW5jID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWV0aG9kIFwiICsgcmVxdWVzdC5tZXRob2QgKyBcIiBub3QgcmVnaXN0ZXJlZCBpbiBjbGllbnRcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyhyZXF1ZXN0LnBhcmFtcywgcmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKCdFeGNlcHRpb24gcHJvY2Vzc2luZyByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHRoaXMuc2VuZCA9IGZ1bmN0aW9uIChtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spIHtcblxuICAgICAgICB2YXIgcmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHJwYy5lbmNvZGUobWV0aG9kLCBwYXJhbXMsIGZ1bmN0aW9uIChlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJFUlJPUjpcIiArIGVycm9yLm1lc3NhZ2UgKyBcIiBpbiBSZXF1ZXN0OiBtZXRob2Q6XCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kICsgXCIgcGFyYW1zOlwiICsgSlNPTi5zdHJpbmdpZnkocGFyYW1zKSArIFwiIHJlcXVlc3Q6XCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IucmVxdWVzdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJFUlJPUiBEQVRBOlwiICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IuZGF0YSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0VGltZSA9IHJlcXVlc3RUaW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPSB1bmRlZmluZWQgJiYgcmVzdWx0LnZhbHVlICE9PSAncG9uZycpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKCdSZXNwb25zZTogJyArIEpTT04uc3RyaW5naWZ5KHJlc3VsdCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlTm90UmVjb25uZWN0SWZMZXNzVGhhbigpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwibm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiA9IFwiICsgcGluZ05leHROdW0gKyAnIChvbGQ9JyArXG4gICAgICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuICsgJyknKTtcbiAgICAgICAgbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbiA9IHBpbmdOZXh0TnVtO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNlbmRQaW5nKCkge1xuICAgICAgICBpZiAoZW5hYmxlZFBpbmdzKSB7XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0gbnVsbDtcbiAgICAgICAgICAgIGlmIChwaW5nTmV4dE51bSA9PSAwIHx8IHBpbmdOZXh0TnVtID09IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVydmFsOiBjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCB8fCBQSU5HX0lOVEVSVkFMXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBpbmdOZXh0TnVtKys7XG5cbiAgICAgICAgICAgIHNlbGYuc2VuZCgncGluZycsIHBhcmFtcywgKGZ1bmN0aW9uIChwaW5nTnVtKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiRXJyb3IgaW4gcGluZyByZXF1ZXN0ICNcIiArIHBpbmdOdW0gKyBcIiAoXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UgKyBcIilcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGluZ051bSA+IG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU2VydmVyIGRpZCBub3QgcmVzcG9uZCB0byBwaW5nIG1lc3NhZ2UgI1wiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGluZ051bSArIFwiLiBSZWNvbm5lY3RpbmcuLi4gXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KShwaW5nTmV4dE51bSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiVHJ5aW5nIHRvIHNlbmQgcGluZywgYnV0IHBpbmcgaXMgbm90IGVuYWJsZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKlxuICAgICAqIElmIGNvbmZpZ3VyYXRpb24uaGVhcmJlYXQgaGFzIGFueSB2YWx1ZSwgdGhlIHBpbmctcG9uZyB3aWxsIHdvcmsgd2l0aCB0aGUgaW50ZXJ2YWxcbiAgICAgKiBvZiBjb25maWd1cmF0aW9uLmhlYXJiZWF0XG4gICAgICovXG4gICAgZnVuY3Rpb24gdXNlUGluZygpIHtcbiAgICAgICAgaWYgKCFwaW5nUG9uZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIlN0YXJ0aW5nIHBpbmcgKGlmIGNvbmZpZ3VyZWQpXCIpXG4gICAgICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5oZWFydGJlYXQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGluZ0ludGVydmFsID0gc2V0SW50ZXJ2YWwoc2VuZFBpbmcsIGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0KTtcbiAgICAgICAgICAgICAgICBzZW5kUGluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3RvcFBpbmcoKSB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwocGluZ0ludGVydmFsKTtcbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICBwaW5nTmV4dE51bSA9IC0xO1xuICAgICAgICBycGMuY2FuY2VsKCk7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uIChjb2RlLCByZWFzb24pIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2luZyAgd2l0aCBjb2RlOiBcIiArIGNvZGUgKyBcIiBiZWNhdXNlOiBcIiArIHJlYXNvbik7XG4gICAgICAgIGlmIChwaW5nSW50ZXJ2YWwgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDbGVhcmluZyBwaW5nIGludGVydmFsXCIpO1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChwaW5nSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICBlbmFibGVkUGluZ3MgPSBmYWxzZTtcbiAgICAgICAgd3MuY2xvc2UoY29kZSwgcmVhc29uKTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIG1ldGhvZCBpcyBvbmx5IGZvciB0ZXN0aW5nXG4gICAgdGhpcy5mb3JjZUNsb3NlID0gZnVuY3Rpb24gKG1pbGxpcykge1xuICAgICAgICB3cy5mb3JjZUNsb3NlKG1pbGxpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWNvbm5lY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHdzLnJlY29ubmVjdFdzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZXNldFBpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgICAgIHBpbmdOZXh0TnVtID0gMDtcbiAgICAgICAgdXNlUGluZygpO1xuICAgIH1cblxuICAgIHRoaXMuZ2V0UmVhZHlTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHdzLmdldFJlYWR5U3RhdGUoKTtcbiAgICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbiA9IHJlcXVpcmUoJy4vd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xuXG5leHBvcnRzLldlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTMtMjAxNSBLdXJlbnRvIChodHRwOi8va3VyZW50by5vcmcvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgT3BlblZpZHVMb2dnZXIgPSByZXF1aXJlKCcuLi8uLi8uLi8uLi9Mb2dnZXIvT3BlblZpZHVMb2dnZXInKS5PcGVuVmlkdUxvZ2dlcjtcbnZhciBMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG52YXIgTUFYX1JFVFJJRVMgPSAyMDAwOyAvLyBGb3JldmVyLi4uXG52YXIgUkVUUllfVElNRV9NUyA9IDMwMDA7IC8vIEZJWE1FOiBJbXBsZW1lbnQgZXhwb25lbnRpYWwgd2FpdCB0aW1lcy4uLlxuXG52YXIgQ09OTkVDVElORyA9IDA7XG52YXIgT1BFTiA9IDE7XG52YXIgQ0xPU0lORyA9IDI7XG52YXIgQ0xPU0VEID0gMztcblxuLypcbmNvbmZpZyA9IHtcbnVyaSA6IHdzVXJpLFxub25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxub25kaXNjb25uZWN0IDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjb25uZWN0aW9uIGlzIGxvc3QgKG1heCByZXRyaWVzIGZvciByZWNvbm5lY3RpbmcgcmVhY2hlZCksXG5vbnJlY29ubmVjdGluZyA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY2xpZW50IGlzIHJlY29ubmVjdGluZyxcbm9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbn07XG4qL1xuZnVuY3Rpb24gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbihjb25maWcpIHtcbiAgICB2YXIgY2xvc2luZyA9IGZhbHNlO1xuICAgIHZhciByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyO1xuICAgIHZhciB3c1VyaSA9IGNvbmZpZy51cmk7XG4gICAgdmFyIHJlY29ubmVjdGluZyA9IGZhbHNlO1xuXG4gICAgdmFyIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG5cbiAgICB3cy5vbm9wZW4gPSAoKSA9PiB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIldlYlNvY2tldCBjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSk7XG4gICAgICAgIGlmIChjb25maWcub25jb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIGNvbmZpZy5vbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uZXJyb3IgPSBlcnJvciA9PiB7XG4gICAgICAgIExvZ2dlci5lcnJvcihcbiAgICAgICAgICAgIFwiQ291bGQgbm90IGNvbm5lY3QgdG8gXCIgKyB3c1VyaSArIFwiIChpbnZva2luZyBvbmVycm9yIGlmIGRlZmluZWQpXCIsXG4gICAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICBpZiAoY29uZmlnLm9uZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbmZpZy5vbmVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgcmVjb25uZWN0aW9uT25DbG9zZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHdzLnJlYWR5U3RhdGUgPT09IENMT1NFRCkge1xuICAgICAgICAgICAgaWYgKGNsb3NpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJDb25uZWN0aW9uIGNsb3NlZCBieSB1c2VyXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLmlzbWFzdGVybm9kZWNyYXNoZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJNYXN0ZXIgTm9kZSBoYXMgY3Jhc2hlZC4gU3RvcHBpbmcgcmVjb25uZWN0aW9uIHByb2Nlc3NcIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgdW5leHBlY3RlZGx5LiBSZWNvbm5lY3RpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdChNQVhfUkVUUklFUywgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ2xvc2UgY2FsbGJhY2sgZnJvbSBwcmV2aW91cyB3ZWJzb2NrZXQuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0KG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgXCJyZWNvbm5lY3QgKGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyArIFwiLCBtYXg9XCIgKyBtYXhSZXRyaWVzICsgXCIpXCJcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKG51bVJldHJpZXMgPT09IDEpIHtcbiAgICAgICAgICAgIGlmIChyZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICAgICAgXCJUcnlpbmcgdG8gcmVjb25uZWN0IHdoZW4gYWxyZWFkeSByZWNvbm5lY3RpbmcuLi4gSWdub3JpbmcgdGhpcyByZWNvbm5lY3Rpb24uXCJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25maWcub25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZWNvbm5lY3RBdXgobWF4UmV0cmllcywgbnVtUmV0cmllcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVjb25uZWN0QXV4KG1heFJldHJpZXMsIG51bVJldHJpZXMpIHtcbiAgICAgICAgTG9nZ2VyLmRlYnVnKFwiUmVjb25uZWN0aW9uIGF0dGVtcHQgI1wiICsgbnVtUmV0cmllcyk7XG4gICAgICAgIHdzLmNsb3NlKCk7XG4gICAgICAgIHdzID0gbmV3IFdlYlNvY2tldCh3c1VyaSk7XG5cbiAgICAgICAgd3Mub25vcGVuID0gKCkgPT4ge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgIFwiUmVjb25uZWN0ZWQgdG8gXCIgKyB3c1VyaSArIFwiIGFmdGVyIFwiICsgbnVtUmV0cmllcyArIFwiIGF0dGVtcHRzLi4uXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICAgICAgICAgIGlmIChjb25maWcub25yZWNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdzLm9uY2xvc2UgPSByZWNvbm5lY3Rpb25PbkNsb3NlO1xuICAgICAgICB9O1xuXG4gICAgICAgIHdzLm9uZXJyb3IgPSBlcnJvciA9PiB7XG4gICAgICAgICAgICBMb2dnZXIud2FybihcIlJlY29ubmVjdGlvbiBlcnJvcjogXCIsIGVycm9yKTtcbiAgICAgICAgICAgIGlmIChudW1SZXRyaWVzID09PSBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5vbmRpc2Nvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLm9uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlY29ubmVjdChtYXhSZXRyaWVzLCBudW1SZXRyaWVzICsgMSk7XG4gICAgICAgICAgICAgICAgfSwgUkVUUllfVElNRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZSA9ICgpID0+IHtcbiAgICAgICAgY2xvc2luZyA9IHRydWU7XG4gICAgICAgIHdzLmNsb3NlKCk7XG4gICAgfTtcblxuICAgIHRoaXMucmVjb25uZWN0V3MgPSAoKSA9PiB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcInJlY29ubmVjdFdzXCIpO1xuICAgICAgICByZWNvbm5lY3QoTUFYX1JFVFJJRVMsIDEpO1xuICAgIH07XG5cbiAgICB0aGlzLnNlbmQgPSBtZXNzYWdlID0+IHtcbiAgICAgICAgd3Muc2VuZChtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gKHR5cGUsIGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICB3cy5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcigpO1xuICAgIH07XG5cbiAgICB0aGlzLmdldFJlYWR5U3RhdGUgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiB3cy5yZWFkeVN0YXRlO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBXZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uOyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5cbnZhciBkZWZpbmVQcm9wZXJ0eV9JRTggPSBmYWxzZVxuaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkge1xuICB0cnkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGRlZmluZVByb3BlcnR5X0lFOCA9IHRydWVcbiAgfVxufVxuXG4vLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9GdW5jdGlvbi9iaW5kXG5pZiAoIUZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kKSB7XG4gIEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKG9UaGlzKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBjbG9zZXN0IHRoaW5nIHBvc3NpYmxlIHRvIHRoZSBFQ01BU2NyaXB0IDVcbiAgICAgIC8vIGludGVybmFsIElzQ2FsbGFibGUgZnVuY3Rpb25cbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kIC0gd2hhdCBpcyB0cnlpbmcgdG8gYmUgYm91bmQgaXMgbm90IGNhbGxhYmxlJyk7XG4gICAgfVxuXG4gICAgdmFyIGFBcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgIGZUb0JpbmQgPSB0aGlzLFxuICAgICAgZk5PUCA9IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgZkJvdW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZlRvQmluZC5hcHBseSh0aGlzIGluc3RhbmNlb2YgZk5PUCAmJiBvVGhpcyA/XG4gICAgICAgICAgdGhpcyA6XG4gICAgICAgICAgb1RoaXMsXG4gICAgICAgICAgYUFyZ3MuY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgIH07XG5cbiAgICBmTk9QLnByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuICAgIGZCb3VuZC5wcm90b3R5cGUgPSBuZXcgZk5PUCgpO1xuXG4gICAgcmV0dXJuIGZCb3VuZDtcbiAgfTtcbn1cblxuXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG52YXIgcGFja2VycyA9IHJlcXVpcmUoJy4vcGFja2VycycpO1xudmFyIE1hcHBlciA9IHJlcXVpcmUoJy4vTWFwcGVyJyk7XG5cblxudmFyIEJBU0VfVElNRU9VVCA9IDUwMDA7XG5cblxuZnVuY3Rpb24gdW5pZnlSZXNwb25zZU1ldGhvZHMocmVzcG9uc2VNZXRob2RzKSB7XG4gIGlmICghcmVzcG9uc2VNZXRob2RzKSByZXR1cm4ge307XG5cbiAgZm9yICh2YXIga2V5IGluIHJlc3BvbnNlTWV0aG9kcykge1xuICAgIHZhciB2YWx1ZSA9IHJlc3BvbnNlTWV0aG9kc1trZXldO1xuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJylcbiAgICAgIHJlc3BvbnNlTWV0aG9kc1trZXldID0ge1xuICAgICAgICByZXNwb25zZTogdmFsdWVcbiAgICAgIH1cbiAgfTtcblxuICByZXR1cm4gcmVzcG9uc2VNZXRob2RzO1xufTtcblxuZnVuY3Rpb24gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KSB7XG4gIGlmICghdHJhbnNwb3J0KSByZXR1cm47XG5cbiAgLy8gVHJhbnNwb3J0IGFzIGEgZnVuY3Rpb25cbiAgaWYgKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB7XG4gICAgICBzZW5kOiB0cmFuc3BvcnRcbiAgICB9O1xuXG4gIC8vIFdlYlNvY2tldCAmIERhdGFDaGFubmVsXG4gIGlmICh0cmFuc3BvcnQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKVxuICAgIHJldHVybiB0cmFuc3BvcnQ7XG5cbiAgLy8gTWVzc2FnZSBBUEkgKEludGVyLXdpbmRvdyAmIFdlYldvcmtlcilcbiAgaWYgKHRyYW5zcG9ydC5wb3N0TWVzc2FnZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQucG9zdE1lc3NhZ2U7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFN0cmVhbSBBUElcbiAgaWYgKHRyYW5zcG9ydC53cml0ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgdHJhbnNwb3J0LnNlbmQgPSB0cmFuc3BvcnQud3JpdGU7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuXG4gIC8vIFRyYW5zcG9ydHMgdGhhdCBvbmx5IGNhbiByZWNlaXZlIG1lc3NhZ2VzLCBidXQgbm90IHNlbmRcbiAgaWYgKHRyYW5zcG9ydC5vbm1lc3NhZ2UgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICBpZiAodHJhbnNwb3J0LnBhdXNlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHJldHVybjtcblxuICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUcmFuc3BvcnQgaXMgbm90IGEgZnVuY3Rpb24gbm9yIGEgdmFsaWQgb2JqZWN0XCIpO1xufTtcblxuXG4vKipcbiAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIG5vdGlmaWNhdGlvblxuICpcbiAqIEBjbGFzc1xuICpcbiAqIEBjb25zdHJ1Y3RvclxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKiBAcGFyYW0gcGFyYW1zIC0gcGFyYW1ldGVycyBvZiB0aGUgbm90aWZpY2F0aW9uXG4gKi9cbmZ1bmN0aW9uIFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcykge1xuICBpZiAoZGVmaW5lUHJvcGVydHlfSUU4KSB7XG4gICAgdGhpcy5tZXRob2QgPSBtZXRob2RcbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtc1xuICB9IGVsc2Uge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnbWV0aG9kJywge1xuICAgICAgdmFsdWU6IG1ldGhvZCxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BhcmFtcycsIHtcbiAgICAgIHZhbHVlOiBwYXJhbXMsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFja2VyXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbdHJhbnNwb3J0XVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvblJlcXVlc3RdXG4gKi9cbmZ1bmN0aW9uIFJwY0J1aWxkZXIocGFja2VyLCBvcHRpb25zLCB0cmFuc3BvcnQsIG9uUmVxdWVzdCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKCFwYWNrZXIpXG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdQYWNrZXIgaXMgbm90IGRlZmluZWQnKTtcblxuICBpZiAoIXBhY2tlci5wYWNrIHx8ICFwYWNrZXIudW5wYWNrKVxuICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignUGFja2VyIGlzIGludmFsaWQnKTtcblxuICB2YXIgcmVzcG9uc2VNZXRob2RzID0gdW5pZnlSZXNwb25zZU1ldGhvZHMocGFja2VyLnJlc3BvbnNlTWV0aG9kcyk7XG5cblxuICBpZiAob3B0aW9ucyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgaWYgKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIG9uUmVxdWVzdFwiKTtcblxuICAgIG9uUmVxdWVzdCA9IG9wdGlvbnM7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgIG9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gIH07XG5cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICBpZiAodHJhbnNwb3J0ICYmICEodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gb3B0aW9ucztcbiAgICBvcHRpb25zID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmICh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGlmIChvblJlcXVlc3QgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSB0cmFuc3BvcnQ7XG4gICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmICh0cmFuc3BvcnQgJiYgdHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICBpZiAob25SZXF1ZXN0ICYmICEob25SZXF1ZXN0IGluc3RhbmNlb2YgRnVuY3Rpb24pKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiT25seSBhIGZ1bmN0aW9uIGNhbiBiZSBhZnRlciB0cmFuc3BvcnRcIik7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblxuICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICBpZiAob25SZXF1ZXN0KVxuICAgIHRoaXMub24oJ3JlcXVlc3QnLCBvblJlcXVlc3QpO1xuXG5cbiAgaWYgKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICB0aGlzLnBlZXJJRCA9IG9wdGlvbnMucGVlcklEXG4gIGVsc2VcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3BlZXJJRCcsIHtcbiAgICAgIHZhbHVlOiBvcHRpb25zLnBlZXJJRFxuICAgIH0pO1xuXG4gIHZhciBtYXhfcmV0cmllcyA9IG9wdGlvbnMubWF4X3JldHJpZXMgfHwgMDtcblxuXG4gIGZ1bmN0aW9uIHRyYW5zcG9ydE1lc3NhZ2UoZXZlbnQpIHtcbiAgICBzZWxmLmRlY29kZShldmVudC5kYXRhIHx8IGV2ZW50KTtcbiAgfTtcblxuICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuICB9XG4gIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgLy8gUmVtb3ZlIGxpc3RlbmVyIGZyb20gb2xkIHRyYW5zcG9ydFxuICAgIGlmICh0cmFuc3BvcnQpIHtcbiAgICAgIC8vIFczQyB0cmFuc3BvcnRzXG4gICAgICBpZiAodHJhbnNwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYgKHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgdHJhbnNwb3J0LnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFNldCBsaXN0ZW5lciBvbiBuZXcgdHJhbnNwb3J0XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYgKHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCB0cmFuc3BvcnRNZXNzYWdlKTtcblxuICAgICAgLy8gTm9kZS5qcyBTdHJlYW1zIEFQSVxuICAgICAgZWxzZSBpZiAodmFsdWUuYWRkTGlzdGVuZXIpXG4gICAgICAgIHZhbHVlLmFkZExpc3RlbmVyKCdkYXRhJywgdHJhbnNwb3J0TWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHZhbHVlKTtcbiAgfVxuXG4gIGlmICghZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAndHJhbnNwb3J0Jywge1xuICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgfSlcblxuICB0aGlzLnNldFRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG5cbiAgdmFyIHJlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucmVxdWVzdF90aW1lb3V0IHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIHBpbmdfcmVxdWVzdF90aW1lb3V0ID0gb3B0aW9ucy5waW5nX3JlcXVlc3RfdGltZW91dCB8fCByZXF1ZXN0X3RpbWVvdXQ7XG4gIHZhciByZXNwb25zZV90aW1lb3V0ID0gb3B0aW9ucy5yZXNwb25zZV90aW1lb3V0IHx8IEJBU0VfVElNRU9VVDtcbiAgdmFyIGR1cGxpY2F0ZXNfdGltZW91dCA9IG9wdGlvbnMuZHVwbGljYXRlc190aW1lb3V0IHx8IEJBU0VfVElNRU9VVDtcblxuXG4gIHZhciByZXF1ZXN0SUQgPSAwO1xuXG4gIHZhciByZXF1ZXN0cyA9IG5ldyBNYXBwZXIoKTtcbiAgdmFyIHJlc3BvbnNlcyA9IG5ldyBNYXBwZXIoKTtcbiAgdmFyIHByb2Nlc3NlZFJlc3BvbnNlcyA9IG5ldyBNYXBwZXIoKTtcblxuICB2YXIgbWVzc2FnZTJLZXkgPSB7fTtcblxuXG4gIC8qKlxuICAgKiBTdG9yZSB0aGUgcmVzcG9uc2UgdG8gcHJldmVudCB0byBwcm9jZXNzIGR1cGxpY2F0ZSByZXF1ZXN0IGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVJlc3BvbnNlKG1lc3NhZ2UsIGlkLCBkZXN0KSB7XG4gICAgdmFyIHJlc3BvbnNlID0ge1xuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIC8qKiBUaW1lb3V0IHRvIGF1dG8tY2xlYW4gb2xkIHJlc3BvbnNlcyAqL1xuICAgICAgdGltZW91dDogc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmVzcG9uc2VzLnJlbW92ZShpZCwgZGVzdCk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlc3BvbnNlX3RpbWVvdXQpXG4gICAgfTtcblxuICAgIHJlc3BvbnNlcy5zZXQocmVzcG9uc2UsIGlkLCBkZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIGlnbm9yZSBkdXBsaWNhdGVkIG1lc3NhZ2VzIGxhdGVyXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZVByb2Nlc3NlZFJlc3BvbnNlKGFjaywgZnJvbSkge1xuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5yZW1vdmUoYWNrLCBmcm9tKTtcbiAgICAgIH0sXG4gICAgICBkdXBsaWNhdGVzX3RpbWVvdXQpO1xuXG4gICAgcHJvY2Vzc2VkUmVzcG9uc2VzLnNldCh0aW1lb3V0LCBhY2ssIGZyb20pO1xuICB9O1xuXG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudGF0aW9uIG9mIGEgUlBDIHJlcXVlc3RcbiAgICpcbiAgICogQGNsYXNzXG4gICAqIEBleHRlbmRzIFJwY05vdGlmaWNhdGlvblxuICAgKlxuICAgKiBAY29uc3RydWN0b3JcbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHBhcmFtcyAtIHBhcmFtZXRlcnMgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGlkIC0gaWRlbnRpZmllciBvZiB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0gW2Zyb21dIC0gc291cmNlIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICovXG4gIGZ1bmN0aW9uIFJwY1JlcXVlc3QobWV0aG9kLCBwYXJhbXMsIGlkLCBmcm9tLCB0cmFuc3BvcnQpIHtcbiAgICBScGNOb3RpZmljYXRpb24uY2FsbCh0aGlzLCBtZXRob2QsIHBhcmFtcyk7XG5cbiAgICB0aGlzLmdldFRyYW5zcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIHRoaXMuc2V0VHJhbnNwb3J0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgaWYgKCFkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsIHtcbiAgICAgICAgZ2V0OiB0aGlzLmdldFRyYW5zcG9ydC5iaW5kKHRoaXMpLFxuICAgICAgICBzZXQ6IHRoaXMuc2V0VHJhbnNwb3J0LmJpbmQodGhpcylcbiAgICAgIH0pXG5cbiAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcblxuICAgIC8qKlxuICAgICAqIEBjb25zdGFudCB7Qm9vbGVhbn0gZHVwbGljYXRlZFxuICAgICAqL1xuICAgIGlmICghKHRyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpKSkge1xuICAgICAgaWYgKGRlZmluZVByb3BlcnR5X0lFOClcbiAgICAgICAgdGhpcy5kdXBsaWNhdGVkID0gQm9vbGVhbihyZXNwb25zZSlcbiAgICAgIGVsc2VcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdkdXBsaWNhdGVkJywge1xuICAgICAgICAgIHZhbHVlOiBCb29sZWFuKHJlc3BvbnNlKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcmVzcG9uc2VNZXRob2QgPSByZXNwb25zZU1ldGhvZHNbbWV0aG9kXTtcblxuICAgIHRoaXMucGFjayA9IHBhY2tlci5wYWNrLmJpbmQocGFja2VyLCB0aGlzLCBpZClcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBbZXJyb3JdXG4gICAgICogQHBhcmFtIHsqfSBbcmVzdWx0XVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnJlcGx5ID0gZnVuY3Rpb24gKGVycm9yLCByZXN1bHQsIHRyYW5zcG9ydCkge1xuICAgICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IGVycm9yICYmIGVycm9yLnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IGVycm9yO1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgICBlcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgRnVuY3Rpb24gfHxcbiAgICAgICAgcmVzdWx0ICYmIHJlc3VsdC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgaWYgKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICB9O1xuXG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAvLyBEdXBsaWNhdGVkIHJlcXVlc3QsIHJlbW92ZSBvbGQgcmVzcG9uc2UgdGltZW91dFxuICAgICAgaWYgKHJlc3BvbnNlKVxuICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG5cbiAgICAgIGlmIChmcm9tICE9IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgZXJyb3IuZGVzdCA9IGZyb207XG5cbiAgICAgICAgaWYgKHJlc3VsdClcbiAgICAgICAgICByZXN1bHQuZGVzdCA9IGZyb207XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWVzc2FnZTtcblxuICAgICAgLy8gTmV3IHJlcXVlc3Qgb3Igb3ZlcnJpZGVuIG9uZSwgY3JlYXRlIG5ldyByZXNwb25zZSB3aXRoIHByb3ZpZGVkIGRhdGFcbiAgICAgIGlmIChlcnJvciB8fCByZXN1bHQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICBlcnJvci5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmVzdWx0LmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByb3RvY29sIGluZGljYXRlcyB0aGF0IHJlc3BvbnNlcyBoYXMgb3duIHJlcXVlc3QgbWV0aG9kc1xuICAgICAgICBpZiAocmVzcG9uc2VNZXRob2QpIHtcbiAgICAgICAgICBpZiAocmVzcG9uc2VNZXRob2QuZXJyb3IgPT0gdW5kZWZpbmVkICYmIGVycm9yKVxuICAgICAgICAgICAgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kID0gZXJyb3IgP1xuICAgICAgICAgICAgICByZXNwb25zZU1ldGhvZC5lcnJvciA6XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWV0aG9kLnJlc3BvbnNlO1xuXG4gICAgICAgICAgICBtZXNzYWdlID0ge1xuICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBlcnJvciB8fCByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2VcbiAgICAgICAgICBtZXNzYWdlID0ge1xuICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgcmVzdWx0OiByZXN1bHRcbiAgICAgICAgICB9O1xuXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIER1cGxpY2F0ZSAmIG5vdC1vdmVycmlkZW4gcmVxdWVzdCwgcmUtc2VuZCBvbGQgcmVzcG9uc2VcbiAgICAgIGVsc2UgaWYgKHJlc3BvbnNlKVxuICAgICAgICBtZXNzYWdlID0gcmVzcG9uc2UubWVzc2FnZTtcblxuICAgICAgLy8gTmV3IGVtcHR5IHJlcGx5LCByZXNwb25zZSBudWxsIHZhbHVlXG4gICAgICBlbHNlXG4gICAgICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayh7XG4gICAgICAgICAgcmVzdWx0OiBudWxsXG4gICAgICAgIH0sIGlkKTtcblxuICAgICAgLy8gU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBhIGR1cGxpY2F0ZWQgcmVxdWVzdCBsYXRlclxuICAgICAgc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZnJvbSk7XG5cbiAgICAgIC8vIFJldHVybiB0aGUgc3RvcmVkIHJlc3BvbnNlIHNvIGl0IGNhbiBiZSBkaXJlY3RseSBzZW5kIGJhY2tcbiAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCB0aGlzLmdldFRyYW5zcG9ydCgpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG5cbiAgICAgIGlmICh0cmFuc3BvcnQpXG4gICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuICB9O1xuICBpbmhlcml0cyhScGNSZXF1ZXN0LCBScGNOb3RpZmljYXRpb24pO1xuXG5cbiAgZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpIHtcbiAgICB2YXIga2V5ID0gbWVzc2FnZTJLZXlbbWVzc2FnZV07XG4gICAgaWYgKCFrZXkpIHJldHVybjtcblxuICAgIGRlbGV0ZSBtZXNzYWdlMktleVttZXNzYWdlXTtcblxuICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMucG9wKGtleS5pZCwga2V5LmRlc3QpO1xuICAgIGlmICghcmVxdWVzdCkgcmV0dXJuO1xuXG4gICAgY2xlYXJUaW1lb3V0KHJlcXVlc3QudGltZW91dCk7XG5cbiAgICAvLyBTdGFydCBkdXBsaWNhdGVkIHJlc3BvbnNlcyB0aW1lb3V0XG4gICAgc3RvcmVQcm9jZXNzZWRSZXNwb25zZShrZXkuaWQsIGtleS5kZXN0KTtcbiAgfTtcblxuICAvKipcbiAgICogQWxsb3cgdG8gY2FuY2VsIGEgcmVxdWVzdCBhbmQgZG9uJ3Qgd2FpdCBmb3IgYSByZXNwb25zZVxuICAgKlxuICAgKiBJZiBgbWVzc2FnZWAgaXMgbm90IGdpdmVuLCBjYW5jZWwgYWxsIHRoZSByZXF1ZXN0XG4gICAqL1xuICB0aGlzLmNhbmNlbCA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgaWYgKG1lc3NhZ2UpIHJldHVybiBjYW5jZWwobWVzc2FnZSk7XG5cbiAgICBmb3IgKHZhciBtZXNzYWdlIGluIG1lc3NhZ2UyS2V5KVxuICAgICAgY2FuY2VsKG1lc3NhZ2UpO1xuICB9O1xuXG5cbiAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBQcmV2ZW50IHRvIHJlY2VpdmUgbmV3IG1lc3NhZ2VzXG4gICAgdmFyIHRyYW5zcG9ydCA9IHRoaXMuZ2V0VHJhbnNwb3J0KCk7XG4gICAgaWYgKHRyYW5zcG9ydCAmJiB0cmFuc3BvcnQuY2xvc2UpXG4gICAgICB0cmFuc3BvcnQuY2xvc2UoNDAwMywgXCJDYW5jZWwgcmVxdWVzdFwiKTtcblxuICAgIC8vIFJlcXVlc3QgJiBwcm9jZXNzZWQgcmVzcG9uc2VzXG4gICAgdGhpcy5jYW5jZWwoKTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG5cbiAgICAvLyBSZXNwb25zZXNcbiAgICByZXNwb25zZXMuZm9yRWFjaChmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGNsZWFyVGltZW91dChyZXNwb25zZS50aW1lb3V0KTtcbiAgICB9KTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYW5kIGVuY29kZSBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCAtbWV0aG9kIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHBhcmFtcyAtIHBhcmFtZXRlcnMgb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0gW2Rlc3RdIC0gZGVzdGluYXRpb24gb2YgdGhlIG5vdGlmaWNhdGlvblxuICAgKiBAcGFyYW0ge29iamVjdH0gW3RyYW5zcG9ydF0gLSB0cmFuc3BvcnQgd2hlcmUgdG8gc2VuZCB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0gW2NhbGxiYWNrXSAtIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIGEgcmVzcG9uc2UgdG8gdGhpcyByZXF1ZXN0IGlzXG4gICAqICAgcmVjZWl2ZWQuIElmIG5vdCBkZWZpbmVkLCBhIG5vdGlmaWNhdGlvbiB3aWxsIGJlIHNlbmQgaW5zdGVhZFxuICAgKlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBBIHJhdyBKc29uUlBDIDIuMCByZXF1ZXN0IG9yIG5vdGlmaWNhdGlvbiBzdHJpbmdcbiAgICovXG4gIHRoaXMuZW5jb2RlID0gZnVuY3Rpb24gKG1ldGhvZCwgcGFyYW1zLCBkZXN0LCB0cmFuc3BvcnQsIGNhbGxiYWNrKSB7XG4gICAgLy8gRml4IG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBpZiAocGFyYW1zIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGlmIChkZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgICBkZXN0ID0gdW5kZWZpbmVkO1xuICAgICAgcGFyYW1zID0gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSBpZiAoZGVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBpZiAodHJhbnNwb3J0ICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgPSBkZXN0O1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2UgaWYgKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBpZiAoY2FsbGJhY2sgIT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJUaGVyZSBjYW4ndCBiZSBwYXJhbWV0ZXJzIGFmdGVyIGNhbGxiYWNrXCIpO1xuXG4gICAgICBjYWxsYmFjayA9IHRyYW5zcG9ydDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgaWYgKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCkge1xuICAgICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuXG4gICAgICBwYXJhbXMuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgIH07XG5cbiAgICBpZiAoZGVzdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmRlc3QgPSBkZXN0O1xuICAgIH07XG5cbiAgICAvLyBFbmNvZGUgbWVzc2FnZVxuICAgIHZhciBtZXNzYWdlID0ge1xuICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICBwYXJhbXM6IHBhcmFtc1xuICAgIH07XG5cbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIHZhciBpZCA9IHJlcXVlc3RJRCsrO1xuICAgICAgdmFyIHJldHJpZWQgPSAwO1xuXG4gICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuXG4gICAgICBmdW5jdGlvbiBkaXNwYXRjaENhbGxiYWNrKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgc2VsZi5jYW5jZWwobWVzc2FnZSk7XG5cbiAgICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgICB9O1xuXG4gICAgICB2YXIgcmVxdWVzdCA9IHtcbiAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgICAgY2FsbGJhY2s6IGRpc3BhdGNoQ2FsbGJhY2ssXG4gICAgICAgIHJlc3BvbnNlTWV0aG9kczogcmVzcG9uc2VNZXRob2RzW21ldGhvZF0gfHwge31cbiAgICAgIH07XG5cbiAgICAgIHZhciBlbmNvZGVfdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgZnVuY3Rpb24gc2VuZFJlcXVlc3QodHJhbnNwb3J0KSB7XG4gICAgICAgIHZhciBydCA9IChtZXRob2QgPT09ICdwaW5nJyA/IHBpbmdfcmVxdWVzdF90aW1lb3V0IDogcmVxdWVzdF90aW1lb3V0KTtcbiAgICAgICAgcmVxdWVzdC50aW1lb3V0ID0gc2V0VGltZW91dCh0aW1lb3V0LCBydCAqIE1hdGgucG93KDIsIHJldHJpZWQrKykpO1xuICAgICAgICBtZXNzYWdlMktleVttZXNzYWdlXSA9IHtcbiAgICAgICAgICBpZDogaWQsXG4gICAgICAgICAgZGVzdDogZGVzdFxuICAgICAgICB9O1xuICAgICAgICByZXF1ZXN0cy5zZXQocmVxdWVzdCwgaWQsIGRlc3QpO1xuXG4gICAgICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCBlbmNvZGVfdHJhbnNwb3J0IHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICAgIGlmICh0cmFuc3BvcnQpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gcmV0cnkodHJhbnNwb3J0KSB7XG4gICAgICAgIHRyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgY29uc29sZS53YXJuKHJldHJpZWQgKyAnIHJldHJ5IGZvciByZXF1ZXN0IG1lc3NhZ2U6JywgbWVzc2FnZSk7XG5cbiAgICAgICAgdmFyIHRpbWVvdXQgPSBwcm9jZXNzZWRSZXNwb25zZXMucG9wKGlkLCBkZXN0KTtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIHJldHVybiBzZW5kUmVxdWVzdCh0cmFuc3BvcnQpO1xuICAgICAgfTtcblxuICAgICAgZnVuY3Rpb24gdGltZW91dCgpIHtcbiAgICAgICAgaWYgKHJldHJpZWQgPCBtYXhfcmV0cmllcylcbiAgICAgICAgICByZXR1cm4gcmV0cnkodHJhbnNwb3J0KTtcblxuICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgaGFzIHRpbWVkIG91dCcpO1xuICAgICAgICBlcnJvci5yZXF1ZXN0ID0gbWVzc2FnZTtcblxuICAgICAgICBlcnJvci5yZXRyeSA9IHJldHJ5O1xuXG4gICAgICAgIGRpc3BhdGNoQ2FsbGJhY2soZXJyb3IpXG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICB9O1xuXG4gICAgLy8gUmV0dXJuIHRoZSBwYWNrZWQgbWVzc2FnZVxuICAgIG1lc3NhZ2UgPSBwYWNrZXIucGFjayhtZXNzYWdlKTtcblxuICAgIHRyYW5zcG9ydCA9IHRyYW5zcG9ydCB8fCB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmICh0cmFuc3BvcnQpXG4gICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBwcm9jZXNzIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBtZXNzYWdlXG4gICAqXG4gICAqIEByZXR1cm5zIHtScGNOb3RpZmljYXRpb258UnBjUmVxdWVzdHx1bmRlZmluZWR9IC0gdGhlIHJlcHJlc2VudGF0aW9uIG9mIHRoZVxuICAgKiAgIG5vdGlmaWNhdGlvbiBvciB0aGUgcmVxdWVzdC4gSWYgYSByZXNwb25zZSB3YXMgcHJvY2Vzc2VkLCBpdCB3aWxsIHJldHVyblxuICAgKiAgIGB1bmRlZmluZWRgIHRvIG5vdGlmeSB0aGF0IGl0IHdhcyBwcm9jZXNzZWRcbiAgICpcbiAgICogQHRocm93cyB7VHlwZUVycm9yfSAtIE1lc3NhZ2UgaXMgbm90IGRlZmluZWRcbiAgICovXG4gIHRoaXMuZGVjb2RlID0gZnVuY3Rpb24gKG1lc3NhZ2UsIHRyYW5zcG9ydCkge1xuICAgIGlmICghbWVzc2FnZSlcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXCIpO1xuXG4gICAgdHJ5IHtcbiAgICAgIG1lc3NhZ2UgPSBwYWNrZXIudW5wYWNrKG1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIElnbm9yZSBpbnZhbGlkIG1lc3NhZ2VzXG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhlLCBtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgdmFyIGlkID0gbWVzc2FnZS5pZDtcbiAgICB2YXIgYWNrID0gbWVzc2FnZS5hY2s7XG4gICAgdmFyIG1ldGhvZCA9IG1lc3NhZ2UubWV0aG9kO1xuICAgIHZhciBwYXJhbXMgPSBtZXNzYWdlLnBhcmFtcyB8fCB7fTtcblxuICAgIHZhciBmcm9tID0gcGFyYW1zLmZyb207XG4gICAgdmFyIGRlc3QgPSBwYXJhbXMuZGVzdDtcblxuICAgIC8vIElnbm9yZSBtZXNzYWdlcyBzZW5kIGJ5IHVzXG4gICAgaWYgKHNlbGYucGVlcklEICE9IHVuZGVmaW5lZCAmJiBmcm9tID09IHNlbGYucGVlcklEKSByZXR1cm47XG5cbiAgICAvLyBOb3RpZmljYXRpb25cbiAgICBpZiAoaWQgPT0gdW5kZWZpbmVkICYmIGFjayA9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBub3RpZmljYXRpb24gPSBuZXcgUnBjTm90aWZpY2F0aW9uKG1ldGhvZCwgcGFyYW1zKTtcblxuICAgICAgaWYgKHNlbGYuZW1pdCgncmVxdWVzdCcsIG5vdGlmaWNhdGlvbikpIHJldHVybjtcbiAgICAgIHJldHVybiBub3RpZmljYXRpb247XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QoKSB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIGEgdHJhbnNwb3J0IGFuZCBpdCdzIGEgZHVwbGljYXRlZCByZXF1ZXN0LCByZXBseSBpbm1lZGlhdGx5XG4gICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpIHx8IHNlbGYuZ2V0VHJhbnNwb3J0KCk7XG4gICAgICBpZiAodHJhbnNwb3J0KSB7XG4gICAgICAgIHZhciByZXNwb25zZSA9IHJlc3BvbnNlcy5nZXQoaWQsIGZyb20pO1xuICAgICAgICBpZiAocmVzcG9uc2UpXG4gICAgICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKHJlc3BvbnNlLm1lc3NhZ2UpO1xuICAgICAgfTtcblxuICAgICAgdmFyIGlkQWNrID0gKGlkICE9IHVuZGVmaW5lZCkgPyBpZCA6IGFjaztcbiAgICAgIHZhciByZXF1ZXN0ID0gbmV3IFJwY1JlcXVlc3QobWV0aG9kLCBwYXJhbXMsIGlkQWNrLCBmcm9tLCB0cmFuc3BvcnQpO1xuXG4gICAgICBpZiAoc2VsZi5lbWl0KCdyZXF1ZXN0JywgcmVxdWVzdCkpIHJldHVybjtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCkge1xuICAgICAgcmVxdWVzdC5jYWxsYmFjayhlcnJvciwgcmVzdWx0KTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZHVwbGljYXRlZFJlc3BvbnNlKHRpbWVvdXQpIHtcbiAgICAgIGNvbnNvbGUud2FybihcIlJlc3BvbnNlIGFscmVhZHkgcHJvY2Vzc2VkXCIsIG1lc3NhZ2UpO1xuXG4gICAgICAvLyBVcGRhdGUgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pO1xuICAgIH07XG5cblxuICAgIC8vIFJlcXVlc3QsIG9yIHJlc3BvbnNlIHdpdGggb3duIG1ldGhvZFxuICAgIGlmIChtZXRob2QpIHtcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICAgIGlmIChkZXN0ID09IHVuZGVmaW5lZCB8fCBkZXN0ID09IHNlbGYucGVlcklEKSB7XG4gICAgICAgIHZhciByZXF1ZXN0ID0gcmVxdWVzdHMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmIChyZXF1ZXN0KSB7XG4gICAgICAgICAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHJlcXVlc3QucmVzcG9uc2VNZXRob2RzO1xuXG4gICAgICAgICAgaWYgKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMuZXJyb3IpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIHBhcmFtcyk7XG5cbiAgICAgICAgICBpZiAobWV0aG9kID09IHJlc3BvbnNlTWV0aG9kcy5yZXNwb25zZSlcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgbnVsbCwgcGFyYW1zKTtcblxuICAgICAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgICAgaWYgKHByb2Nlc3NlZClcbiAgICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlcXVlc3RcbiAgICAgIHJldHVybiBwcm9jZXNzUmVxdWVzdCgpO1xuICAgIH07XG5cbiAgICB2YXIgZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIHZhciByZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcblxuICAgIC8vIElnbm9yZSByZXNwb25zZXMgbm90IHNlbmQgdG8gdXNcbiAgICBpZiAoZXJyb3IgJiYgZXJyb3IuZGVzdCAmJiBlcnJvci5kZXN0ICE9IHNlbGYucGVlcklEKSByZXR1cm47XG4gICAgaWYgKHJlc3VsdCAmJiByZXN1bHQuZGVzdCAmJiByZXN1bHQuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gUmVzcG9uc2VcbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgIGlmICghcmVxdWVzdCkge1xuICAgICAgdmFyIHByb2Nlc3NlZCA9IHByb2Nlc3NlZFJlc3BvbnNlcy5nZXQoYWNrLCBmcm9tKTtcbiAgICAgIGlmIChwcm9jZXNzZWQpXG4gICAgICAgIHJldHVybiBkdXBsaWNhdGVkUmVzcG9uc2UocHJvY2Vzc2VkKTtcblxuICAgICAgcmV0dXJuIGNvbnNvbGUud2FybihcIk5vIGNhbGxiYWNrIHdhcyBkZWZpbmVkIGZvciB0aGlzIG1lc3NhZ2VcIiwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIC8vIFByb2Nlc3MgcmVzcG9uc2VcbiAgICBwcm9jZXNzUmVzcG9uc2UocmVxdWVzdCwgZXJyb3IsIHJlc3VsdCk7XG4gIH07XG59O1xuaW5oZXJpdHMoUnBjQnVpbGRlciwgRXZlbnRFbWl0dGVyKTtcblxuXG5ScGNCdWlsZGVyLlJwY05vdGlmaWNhdGlvbiA9IFJwY05vdGlmaWNhdGlvbjtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFJwY0J1aWxkZXI7XG5cbnZhciBjbGllbnRzID0gcmVxdWlyZSgnLi9jbGllbnRzJyk7XG52YXIgdHJhbnNwb3J0cyA9IHJlcXVpcmUoJy4vY2xpZW50cy90cmFuc3BvcnRzJyk7XG5cblJwY0J1aWxkZXIuY2xpZW50cyA9IGNsaWVudHM7XG5ScGNCdWlsZGVyLmNsaWVudHMudHJhbnNwb3J0cyA9IHRyYW5zcG9ydHM7XG5ScGNCdWlsZGVyLnBhY2tlcnMgPSBwYWNrZXJzOyIsIi8qKlxuICogSnNvblJQQyAyLjAgcGFja2VyXG4gKi9cblxuLyoqXG4gKiBQYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBtZXNzYWdlIC0gb2JqZWN0IHRvIGJlIHBhY2thZ2VkLiBJdCByZXF1aXJlcyB0byBoYXZlIGFsbCB0aGVcbiAqICAgZmllbGRzIG5lZWRlZCBieSB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSB0aGF0IGl0J3MgZ29pbmcgdG8gYmUgZ2VuZXJhdGVkXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSAtIHRoZSBzdHJpbmdpZmllZCBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHBhY2sobWVzc2FnZSwgaWQpIHtcbiAgdmFyIHJlc3VsdCA9IHtcbiAgICBqc29ucnBjOiBcIjIuMFwiXG4gIH07XG5cbiAgLy8gUmVxdWVzdFxuICBpZiAobWVzc2FnZS5tZXRob2QpIHtcbiAgICByZXN1bHQubWV0aG9kID0gbWVzc2FnZS5tZXRob2Q7XG5cbiAgICBpZiAobWVzc2FnZS5wYXJhbXMpXG4gICAgICByZXN1bHQucGFyYW1zID0gbWVzc2FnZS5wYXJhbXM7XG5cbiAgICAvLyBSZXF1ZXN0IGlzIGEgbm90aWZpY2F0aW9uXG4gICAgaWYgKGlkICE9IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5pZCA9IGlkO1xuICB9XG5cbiAgLy8gUmVzcG9uc2VcbiAgZWxzZSBpZiAoaWQgIT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKG1lc3NhZ2UuZXJyb3IpIHtcbiAgICAgIGlmIChtZXNzYWdlLnJlc3VsdCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQm90aCByZXN1bHQgYW5kIGVycm9yIGFyZSBkZWZpbmVkXCIpO1xuXG4gICAgICByZXN1bHQuZXJyb3IgPSBtZXNzYWdlLmVycm9yO1xuICAgIH0gZWxzZSBpZiAobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJlc3VsdC5yZXN1bHQgPSBtZXNzYWdlLnJlc3VsdDtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWRcIik7XG5cbiAgICByZXN1bHQuaWQgPSBpZDtcbiAgfTtcblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzdWx0KTtcbn07XG5cbi8qKlxuICogVW5wYWNrIGEgSnNvblJQQyAyLjAgbWVzc2FnZVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIC0gc3RyaW5nIHdpdGggdGhlIGNvbnRlbnQgb2YgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IC0gSW52YWxpZCBKc29uUlBDIHZlcnNpb25cbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gb2JqZWN0IGZpbGxlZCB3aXRoIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlIGNvbnRlbnRcbiAqL1xuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpIHtcbiAgdmFyIHJlc3VsdCA9IG1lc3NhZ2U7XG5cbiAgaWYgKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJyB8fCBtZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgcmVzdWx0ID0gSlNPTi5wYXJzZShtZXNzYWdlKTtcbiAgfVxuXG4gIC8vIENoZWNrIGlmIGl0J3MgYSB2YWxpZCBtZXNzYWdlXG5cbiAgdmFyIHZlcnNpb24gPSByZXN1bHQuanNvbnJwYztcbiAgaWYgKHZlcnNpb24gIT09ICcyLjAnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIEpzb25SUEMgdmVyc2lvbiAnXCIgKyB2ZXJzaW9uICsgXCInOiBcIiArIG1lc3NhZ2UpO1xuXG4gIC8vIFJlc3BvbnNlXG4gIGlmIChyZXN1bHQubWV0aG9kID09IHVuZGVmaW5lZCkge1xuICAgIGlmIChyZXN1bHQuaWQgPT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgbWVzc2FnZTogXCIgKyBtZXNzYWdlKTtcblxuICAgIHZhciByZXN1bHRfZGVmaW5lZCA9IHJlc3VsdC5yZXN1bHQgIT09IHVuZGVmaW5lZDtcbiAgICB2YXIgZXJyb3JfZGVmaW5lZCA9IHJlc3VsdC5lcnJvciAhPT0gdW5kZWZpbmVkO1xuXG4gICAgLy8gQ2hlY2sgb25seSByZXN1bHQgb3IgZXJyb3IgaXMgZGVmaW5lZCwgbm90IGJvdGggb3Igbm9uZVxuICAgIGlmIChyZXN1bHRfZGVmaW5lZCAmJiBlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZDogXCIgKyBtZXNzYWdlKTtcblxuICAgIGlmICghcmVzdWx0X2RlZmluZWQgJiYgIWVycm9yX2RlZmluZWQpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm8gcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQ6IFwiICsgbWVzc2FnZSk7XG5cbiAgICByZXN1bHQuYWNrID0gcmVzdWx0LmlkO1xuICAgIGRlbGV0ZSByZXN1bHQuaWQ7XG4gIH1cblxuICAvLyBSZXR1cm4gdW5wYWNrZWQgbWVzc2FnZVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuXG5leHBvcnRzLnBhY2sgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7IiwiZnVuY3Rpb24gcGFjayhtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZnVuY3Rpb24gdW5wYWNrKG1lc3NhZ2UpIHtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG59O1xuXG5leHBvcnRzLnBhY2sgPSBwYWNrO1xuZXhwb3J0cy51bnBhY2sgPSB1bnBhY2s7IiwidmFyIEpzb25SUEMgPSByZXF1aXJlKCcuL0pzb25SUEMnKTtcbnZhciBYbWxSUEMgPSByZXF1aXJlKCcuL1htbFJQQycpO1xuXG5cbmV4cG9ydHMuSnNvblJQQyA9IEpzb25SUEM7XG5leHBvcnRzLlhtbFJQQyA9IFhtbFJQQzsiLCJ0eXBlIENvbnNvbGVGdW5jdGlvbiA9ICguLi5kYXRhOiBhbnkpID0+IHZvaWQ7XG5leHBvcnQgY2xhc3MgQ29uc29sZUxvZ2dlciB7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbG9nZ2VyOiBDb25zb2xlXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbG9nOiBDb25zb2xlRnVuY3Rpb25cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmZvOiBDb25zb2xlRnVuY3Rpb25cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkZWJ1ZzogQ29uc29sZUZ1bmN0aW9uXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgd2FybjogQ29uc29sZUZ1bmN0aW9uXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZXJyb3I6IENvbnNvbGVGdW5jdGlvblxuXG4gICAgY29uc3RydWN0b3IoY29uc29sZTogQ29uc29sZSkge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGNvbnNvbGU7XG4gICAgICAgIHRoaXMubG9nID0gd2luZG93LmNvbnNvbGUubG9nLFxuICAgICAgICB0aGlzLmluZm8gPSB3aW5kb3cuY29uc29sZS5pbmZvLFxuICAgICAgICB0aGlzLmRlYnVnID0gd2luZG93LmNvbnNvbGUuZGVidWcsXG4gICAgICAgIHRoaXMud2FybiA9IHdpbmRvdy5jb25zb2xlLndhcm4sXG4gICAgICAgIHRoaXMuZXJyb3IgPSB3aW5kb3cuY29uc29sZS5lcnJvclxuICAgIH1cbn0iLCJpbXBvcnQgeyBKTCB9IGZyb20gJ2pzbmxvZydcbmltcG9ydCB7IE9wZW5WaWR1IH0gZnJvbSBcIi4uLy4uL09wZW5WaWR1L09wZW5WaWR1XCI7XG5pbXBvcnQgeyBDb25zb2xlTG9nZ2VyIH0gZnJvbSAnLi9Db25zb2xlTG9nZ2VyJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbiB9IGZyb20gXCIuL09wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvblwiO1xuXG5leHBvcnQgY2xhc3MgT3BlblZpZHVMb2dnZXIge1xuXG5cdHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBPcGVuVmlkdUxvZ2dlcjtcblxuXHRwcml2YXRlIEpTTkxPR19VUkw6IHN0cmluZyA9IFwiL29wZW52aWR1L2Vsay9vcGVudmlkdS1icm93c2VyLWxvZ3NcIjtcblx0cHJpdmF0ZSBNQVhfSlNOTE9HX0JBVENIX0xPR19NRVNTQUdFUzogbnVtYmVyID0gMTAwO1xuXHRwcml2YXRlIE1BWF9NU0VDT05EU19CQVRDSF9NRVNTQUdFUzogbnVtYmVyID0gNTAwMDtcblx0cHJpdmF0ZSBNQVhfTEVOR1RIX1NUUklOR19KU09OOiBudW1iZXIgPSAxMDAwO1xuXG5cdHByaXZhdGUgZGVmYXVsdENvbnNvbGVMb2dnZXI6IENvbnNvbGVMb2dnZXIgPSBuZXcgQ29uc29sZUxvZ2dlcih3aW5kb3cuY29uc29sZSk7XG5cblx0cHJpdmF0ZSBjdXJyZW50QXBwZW5kZXI6IGFueTtcblxuXHRwcml2YXRlIGlzUHJvZE1vZGUgPSBmYWxzZTtcblx0cHJpdmF0ZSBpc0pTTkxvZ1NldHVwID0gZmFsc2U7XG5cblx0Ly8gVGhpcyB0d28gdmFyaWFibGVzIGFyZSB1c2VkIHRvIHJlc3RhcnQgSlNOTG9nXG5cdC8vIG9uIGRpZmZlcmVudCBzZXNzaW9ucyBhbmQgZGlmZmVyZW50IHVzZXJJZHNcblx0cHJpdmF0ZSBsb2dnaW5nU2Vzc2lvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHN0YXRpYyBjb25maWd1cmVKU05Mb2cob3BlblZpZHU6IE9wZW5WaWR1LCB0b2tlbjogc3RyaW5nKSB7XG5cdFx0dHJ5IHtcblx0XHRcdC8vIElmIGRldiBtb2RlIG9yLi4uXG5cdFx0XHRpZiAoKHdpbmRvd1snTE9HX0pTTkxPR19SRVNVTFRTJ10pIHx8XG5cdFx0XHRcdC8vIElmIGluc3RhbmNlIGlzIGNyZWF0ZWQgYW5kIGl0IGlzIE9wZW5WaWR1IFByb1xuXHRcdFx0XHQodGhpcy5pbnN0YW5jZSAmJiBvcGVuVmlkdS5pc1Byb1xuXHRcdFx0XHRcdC8vIElmIGxvZ3MgYXJlIGVuYWJsZWRcblx0XHRcdFx0XHQmJiB0aGlzLmluc3RhbmNlLmlzT3BlblZpZHVCcm93c2VyTG9nc0RlYnVnQWN0aXZlKG9wZW5WaWR1KVxuXHRcdFx0XHRcdC8vIE9ubHkgcmVjb25maWd1cmUgaXQgaWYgc2Vzc2lvbiBvciBmaW5hbFVzZXJJZCBoYXMgY2hhbmdlZFxuXHRcdFx0XHRcdCYmIHRoaXMuaW5zdGFuY2UuY2FuQ29uZmlndXJlSlNOTG9nKG9wZW5WaWR1LCB0aGlzLmluc3RhbmNlKSkpIHtcblxuXHRcdFx0XHQvLyBDaGVjayBpZiBhcHAgbG9ncyBjYW4gYmUgc2VudFxuXHRcdFx0XHQvLyBhbmQgcmVwbGFjZSBjb25zb2xlLmxvZyBmdW5jdGlvbiB0byBzZW5kXG5cdFx0XHRcdC8vIGxvZ3Mgb2YgdGhlIGFwcGxpY2F0aW9uXG5cdFx0XHRcdGlmIChvcGVuVmlkdS5zZW5kQnJvd3NlckxvZ3MgPT09IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbi5kZWJ1Z19hcHApIHtcblx0XHRcdFx0XHR0aGlzLmluc3RhbmNlLnJlcGxhY2VXaW5kb3dDb25zb2xlKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpc0pTTkxvZ1NldHVwIHdpbGwgbm90IGJlIHRydWUgdW50aWwgY29tcGxldGVkIHNldHVwXG5cdFx0XHRcdHRoaXMuaW5zdGFuY2UuaXNKU05Mb2dTZXR1cCA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLmluc3RhbmNlLmluZm8oXCJDb25maWd1cmluZyBKU05Mb2dzLlwiKTtcblxuXHRcdFx0XHRjb25zdCBmaW5hbFVzZXJJZCA9IG9wZW5WaWR1LmZpbmFsVXNlcklkO1xuXHRcdFx0XHRjb25zdCBzZXNzaW9uSWQgPSBvcGVuVmlkdS5zZXNzaW9uLnNlc3Npb25JZDtcblxuXHRcdFx0XHRjb25zdCBiZWZvcmVTZW5kQ2FsbGJhY2sgPSAoeGhyKSA9PiB7XG5cdFx0XHRcdFx0Ly8gSWYgNDAxIG9yIDQwMyBvciA0MDQgbW9kaWZ5IHJlYWR5IGFuZCBzdGF0dXMgc28gSlNOTG9nIGRvbid0IHJldHJ5IHRvIHNlbmQgbG9nc1xuXHRcdFx0XHRcdC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tcGVyZGVjay9qc25sb2cuanMvYmxvYi92Mi4zMC4wL2pzbmxvZy50cyNMODA1LUw4MThcblx0XHRcdFx0XHRjb25zdCBwYXJlbnRSZWFkeVN0YXRlRnVuY3Rpb24gPSB4aHIub25yZWFkeXN0YXRlY2hhbmdlO1xuXHRcdFx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5pc0ludmFsaWRSZXNwb25zZSh4aHIpKSB7XG5cdFx0XHRcdFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh4aHIsIFwicmVhZHlTdGF0ZVwiLCB7IHZhbHVlOiA0IH0pO1xuXHRcdFx0XHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoeGhyLCBcInN0YXR1c1wiLCB7IHZhbHVlOiAyMDAgfSk7XG5cdFx0XHRcdFx0XHRcdC8vIERpc2FibGUgSlNOTG9nIHRvbyB0byBub3Qgc2VuZCBwZXJpb2RpY2FsbHkgZXJyb3JzXG5cdFx0XHRcdFx0XHRcdHRoaXMuaW5zdGFuY2UuZGlzYWJsZUxvZ2dlcigpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0cGFyZW50UmVhZHlTdGF0ZUZ1bmN0aW9uKCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gSGVhZGVycyB0byBpZGVudGlmeSBhbmQgYXV0aGVudGljYXRlIGxvZ3Ncblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlcignQXV0aG9yaXphdGlvbicsIFwiQmFzaWMgXCIgKyBidG9hKGAke2ZpbmFsVXNlcklkfSUvJSR7c2Vzc2lvbklkfWAgKyBcIjpcIiArIHRva2VuKSk7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoJ1gtUmVxdWVzdGVkLVdpdGgnLCAnWE1MSHR0cFJlcXVlc3QnKVxuXHRcdFx0XHRcdC8vIEFkZGl0aW9uYWwgaGVhZGVycyBmb3IgT3BlblZpZHVcblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlcignT1YtRmluYWwtVXNlci1JZCcsIGZpbmFsVXNlcklkKTtcblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlcignT1YtU2Vzc2lvbi1JZCcsIHNlc3Npb25JZCk7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoJ09WLVRva2VuJywgdG9rZW4pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQ3JlYXRpb24gb2YgdGhlIGFwcGVuZGVyLlxuXHRcdFx0XHR0aGlzLmluc3RhbmNlLmN1cnJlbnRBcHBlbmRlciA9IEpMLmNyZWF0ZUFqYXhBcHBlbmRlcihgYXBwZW5kZXItJHtmaW5hbFVzZXJJZH0tJHtzZXNzaW9uSWR9YCk7XG5cdFx0XHRcdHRoaXMuaW5zdGFuY2UuY3VycmVudEFwcGVuZGVyLnNldE9wdGlvbnMoe1xuXHRcdFx0XHRcdGJlZm9yZVNlbmQ6IGJlZm9yZVNlbmRDYWxsYmFjayxcblx0XHRcdFx0XHRtYXhCYXRjaFNpemU6IDEwMDAsXG5cdFx0XHRcdFx0YmF0Y2hTaXplOiB0aGlzLmluc3RhbmNlLk1BWF9KU05MT0dfQkFUQ0hfTE9HX01FU1NBR0VTLFxuXHRcdFx0XHRcdGJhdGNoVGltZW91dDogdGhpcy5pbnN0YW5jZS5NQVhfTVNFQ09ORFNfQkFUQ0hfTUVTU0FHRVNcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gQXZvaWQgY2lyY3VsYXIgZGVwZW5kZW5jaWVzXG5cdFx0XHRcdGNvbnN0IGxvZ1NlcmlhbGl6ZXIgPSAob2JqKTogc3RyaW5nID0+IHtcblx0XHRcdFx0XHRjb25zdCBnZXRDaXJjdWxhclJlcGxhY2VyID0gKCkgPT4ge1xuXHRcdFx0XHRcdFx0Y29uc3Qgc2VlbiA9IG5ldyBXZWFrU2V0KCk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gKGtleSwgdmFsdWUpID0+IHtcblx0XHRcdFx0XHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJiB2YWx1ZSAhPSBudWxsKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHNlZW4uaGFzKHZhbHVlKSB8fCAoSFRNTEVsZW1lbnQgJiYgdmFsdWUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0c2Vlbi5hZGQodmFsdWUpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIEN1dCBsb25nIG1lc3NhZ2VzXG5cdFx0XHRcdFx0bGV0IHN0cmluZ2lmeUpzb24gPSBKU09OLnN0cmluZ2lmeShvYmosIGdldENpcmN1bGFyUmVwbGFjZXIoKSk7XG5cdFx0XHRcdFx0aWYgKHN0cmluZ2lmeUpzb24ubGVuZ3RoID4gdGhpcy5pbnN0YW5jZS5NQVhfTEVOR1RIX1NUUklOR19KU09OKSB7XG5cdFx0XHRcdFx0XHRzdHJpbmdpZnlKc29uID0gYCR7c3RyaW5naWZ5SnNvbi5zdWJzdHJpbmcoMCwgdGhpcy5pbnN0YW5jZS5NQVhfTEVOR1RIX1NUUklOR19KU09OKX0uLi5gO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICh3aW5kb3dbJ0xPR19KU05MT0dfUkVTVUxUUyddKSB7XG5cdFx0XHRcdFx0XHRjb25zb2xlLmxvZyhzdHJpbmdpZnlKc29uKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gc3RyaW5naWZ5SnNvbjtcblx0XHRcdFx0fTtcblxuXHRcdFx0XHQvLyBJbml0aWFsaXplIEpMIHRvIHNlbmQgbG9nc1xuXHRcdFx0XHRKTC5zZXRPcHRpb25zKHtcblx0XHRcdFx0XHRkZWZhdWx0QWpheFVybDogb3BlblZpZHUuaHR0cFVyaSArIHRoaXMuaW5zdGFuY2UuSlNOTE9HX1VSTCxcblx0XHRcdFx0XHRzZXJpYWxpemU6IGxvZ1NlcmlhbGl6ZXIsXG5cdFx0XHRcdFx0ZW5hYmxlZDogdHJ1ZVxuXHRcdFx0XHR9KTtcblx0XHRcdFx0SkwoKS5zZXRPcHRpb25zKHtcblx0XHRcdFx0XHRhcHBlbmRlcnM6IFt0aGlzLmluc3RhbmNlLmN1cnJlbnRBcHBlbmRlcl1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0dGhpcy5pbnN0YW5jZS5pc0pTTkxvZ1NldHVwID0gdHJ1ZTtcblx0XHRcdFx0dGhpcy5pbnN0YW5jZS5sb2dnaW5nU2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuXHRcdFx0XHR0aGlzLmluc3RhbmNlLmluZm8oXCJKU05Mb2cgY29uZmlndXJlZC5cIik7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0Ly8gUHJpbnQgZXJyb3Jcblx0XHRcdGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjb25maWd1cmluZyBKU05Mb2c6IFwiKTtcblx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdFx0XHQvLyBSZXN0b3JlIGRlZmF1bHRzIHZhbHVlcyBqdXN0IGluIGNhc2UgYW55IGV4Y2VwdGlvbiBoYXBwZW4tXG5cdFx0XHR0aGlzLmluc3RhbmNlLmRpc2FibGVMb2dnZXIoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0c3RhdGljIGdldEluc3RhbmNlKCk6IE9wZW5WaWR1TG9nZ2VyIHtcblx0XHRpZiAoIU9wZW5WaWR1TG9nZ2VyLmluc3RhbmNlKSB7XG5cdFx0XHRPcGVuVmlkdUxvZ2dlci5pbnN0YW5jZSA9IG5ldyBPcGVuVmlkdUxvZ2dlcigpO1xuXHRcdH1cblx0XHRyZXR1cm4gT3BlblZpZHVMb2dnZXIuaW5zdGFuY2U7XG5cdH1cblxuXHRwcml2YXRlIHN0YXRpYyBpc0ludmFsaWRSZXNwb25zZSh4aHI6IFhNTEh0dHBSZXF1ZXN0KSB7XG5cdFx0cmV0dXJuIHhoci5zdGF0dXMgPT0gNDAxIHx8IHhoci5zdGF0dXMgPT0gNDAzIHx8IHhoci5zdGF0dXMgPT0gNDA0IHx8IHhoci5zdGF0dXMgPT0gMDtcblx0fVxuXG5cdHByaXZhdGUgY2FuQ29uZmlndXJlSlNOTG9nKG9wZW5WaWR1OiBPcGVuVmlkdSwgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlcik6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBvcGVuVmlkdS5zZXNzaW9uLnNlc3Npb25JZCAhPSBsb2dnZXIubG9nZ2luZ1Nlc3Npb25JZFxuXHR9XG5cblx0cHJpdmF0ZSBpc09wZW5WaWR1QnJvd3NlckxvZ3NEZWJ1Z0FjdGl2ZShvcGVuVmlkdTogT3BlblZpZHUpIHtcblx0XHRyZXR1cm4gb3BlblZpZHUuc2VuZEJyb3dzZXJMb2dzID09PSBPcGVuVmlkdUxvZ2dlckNvbmZpZ3VyYXRpb24uZGVidWcgfHxcblx0XHRcdG9wZW5WaWR1LnNlbmRCcm93c2VyTG9ncyA9PT0gT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uLmRlYnVnX2FwcDtcblx0fVxuXG5cdC8vIFJldHVybiBjb25zb2xlIGZ1bmN0aW9ucyB3aXRoIGpzbmxvZyBpbnRlZ3JhdGlvblxuXHRwcml2YXRlIGdldENvbnNvbGVXaXRoSlNOTG9nKCkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAob3BlblZpZHVMb2dnZXI6IE9wZW5WaWR1TG9nZ2VyKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRsb2c6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG5cdFx0XHRcdFx0b3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nLmFwcGx5KG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHRcdFx0XHRpZiAob3BlblZpZHVMb2dnZXIuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0XHRcdFx0SkwoKS5pbmZvKGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRpbmZvOiBmdW5jdGlvbiAoLi4uYXJncykge1xuXHRcdFx0XHRcdG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmluZm8uYXBwbHkob3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdFx0XHRcdGlmIChvcGVuVmlkdUxvZ2dlci5pc0pTTkxvZ1NldHVwKSB7XG5cdFx0XHRcdFx0XHRKTCgpLmluZm8oYXJndW1lbnRzKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGRlYnVnOiBmdW5jdGlvbiAoLi4uYXJncykge1xuXHRcdFx0XHRcdG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmRlYnVnLmFwcGx5KG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0d2FybjogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0XHRcdFx0XHRvcGVuVmlkdUxvZ2dlci5kZWZhdWx0Q29uc29sZUxvZ2dlci53YXJuLmFwcGx5KG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHRcdFx0XHRpZiAob3BlblZpZHVMb2dnZXIuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0XHRcdFx0SkwoKS53YXJuKGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRlcnJvcjogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0XHRcdFx0XHRvcGVuVmlkdUxvZ2dlci5kZWZhdWx0Q29uc29sZUxvZ2dlci5lcnJvci5hcHBseShvcGVuVmlkdUxvZ2dlci5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0aWYgKG9wZW5WaWR1TG9nZ2VyLmlzSlNOTG9nU2V0dXApIHtcblx0XHRcdFx0XHRcdEpMKCkuZXJyb3IoYXJndW1lbnRzKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSh0aGlzKTtcblx0fVxuXG5cdHByaXZhdGUgcmVwbGFjZVdpbmRvd0NvbnNvbGUoKSB7XG5cdFx0d2luZG93LmNvbnNvbGUgPSB0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlcjtcblx0XHR3aW5kb3cuY29uc29sZS5sb2cgPSB0aGlzLmdldENvbnNvbGVXaXRoSlNOTG9nKCkubG9nO1xuXHRcdHdpbmRvdy5jb25zb2xlLmluZm8gPSB0aGlzLmdldENvbnNvbGVXaXRoSlNOTG9nKCkuaW5mbztcblx0XHR3aW5kb3cuY29uc29sZS5kZWJ1ZyA9IHRoaXMuZ2V0Q29uc29sZVdpdGhKU05Mb2coKS5kZWJ1Zztcblx0XHR3aW5kb3cuY29uc29sZS53YXJuID0gdGhpcy5nZXRDb25zb2xlV2l0aEpTTkxvZygpLndhcm47XG5cdFx0d2luZG93LmNvbnNvbGUuZXJyb3IgPSB0aGlzLmdldENvbnNvbGVXaXRoSlNOTG9nKCkuZXJyb3I7XG5cdH1cblxuXHRwcml2YXRlIGRpc2FibGVMb2dnZXIoKSB7XG5cdFx0Skwuc2V0T3B0aW9ucyh7IGVuYWJsZWQ6IGZhbHNlIH0pO1xuXHRcdHRoaXMuaXNKU05Mb2dTZXR1cCA9IGZhbHNlO1xuXHRcdHRoaXMubG9nZ2luZ1Nlc3Npb25JZCA9IHVuZGVmaW5lZDtcblx0XHR0aGlzLmN1cnJlbnRBcHBlbmRlciA9IHVuZGVmaW5lZDtcblx0XHR3aW5kb3cuY29uc29sZSA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyO1xuXHRcdHdpbmRvdy5jb25zb2xlLmxvZyA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nO1xuXHRcdHdpbmRvdy5jb25zb2xlLmluZm8gPSB0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmluZm87XG5cdFx0d2luZG93LmNvbnNvbGUuZGVidWcgPSB0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmRlYnVnO1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4gPSB0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLndhcm47XG5cdFx0d2luZG93LmNvbnNvbGUuZXJyb3IgPSB0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmVycm9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdGxvZyguLi5hcmdzOiBhbnlbXSkge1xuXHRcdGlmICghdGhpcy5pc1Byb2RNb2RlKSB7XG5cdFx0XHR0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZy5hcHBseSh0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0SkwoKS5pbmZvKGFyZ3VtZW50cyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdGRlYnVnKC4uLmFyZ3M6IGFueVtdKSB7XG5cdFx0aWYgKCF0aGlzLmlzUHJvZE1vZGUpIHtcblx0XHRcdHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuZGVidWcuYXBwbHkodGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdGluZm8oLi4uYXJnczogYW55W10pIHtcblx0XHRpZiAoIXRoaXMuaXNQcm9kTW9kZSkge1xuXHRcdFx0dGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5pbmZvLmFwcGx5KHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5pc0pTTkxvZ1NldHVwKSB7XG5cdFx0XHRKTCgpLmluZm8oYXJndW1lbnRzKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0d2FybiguLi5hcmdzOiBhbnlbXSkge1xuXHRcdGlmICghdGhpcy5pc1Byb2RNb2RlKSB7XG5cdFx0XHR0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLndhcm4uYXBwbHkodGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmlzSlNOTG9nU2V0dXApIHtcblx0XHRcdEpMKCkud2Fybihhcmd1bWVudHMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRlcnJvciguLi5hcmdzOiBhbnlbXSkge1xuXHRcdHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuZXJyb3IuYXBwbHkodGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0aWYgKHRoaXMuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0SkwoKS5lcnJvcihhcmd1bWVudHMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRmbHVzaCgpIHtcblx0XHRpZiAodGhpcy5pc0pTTkxvZ1NldHVwICYmIHRoaXMuY3VycmVudEFwcGVuZGVyICE9IG51bGwpIHtcblx0XHRcdHRoaXMuY3VycmVudEFwcGVuZGVyLnNlbmRCYXRjaCgpO1xuXHRcdH1cblx0fVxuXG5cdGVuYWJsZVByb2RNb2RlKCkge1xuXHRcdHRoaXMuaXNQcm9kTW9kZSA9IHRydWU7XG5cdH1cblxufVxuIiwiZXhwb3J0IGVudW0gT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uIHtcbiAgICBkaXNhYmxlZCA9ICdkaXNhYmxlZCcsXG4gICAgZGVidWcgPSAnZGVidWcnLFxuICAgIGRlYnVnX2FwcCA9ICdkZWJ1Z19hcHAnXG59IiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG5cbiAgICBpZihtaWNyb3NvZnRFZGdlKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXREaXNwbGF5TWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MpY2F0Y2gob25GYWlsdXJlKTtcbiAgICB9XG59LCAncGFzcyBzZWNvbmQgcGFyYW1ldGVyIG9ubHkgaWYgeW91IHdhbnQgc3lzdGVtIGF1ZGlvJyk7XG4qL1xuXG53aW5kb3cuZ2V0U2NyZWVuSWQgPSBmdW5jdGlvbiAoZmlyZWZveFN0cmluZywgY2FsbGJhY2ssIGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdFZGdlJykgIT09IC0xICYmICghIW5hdmlnYXRvci5tc1NhdmVPck9wZW5CbG9iIHx8ICEhbmF2aWdhdG9yLm1zU2F2ZUJsb2IpKSB7XG4gICAgICAgIC8vIG1pY3Jvc29mdCBlZGdlID0+IG5hdmlnYXRvci5nZXREaXNwbGF5TWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbiAgICAgICAgY2FsbGJhY2soe1xuICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICAvLyBzb3VyY2VJZCA9PSAnZmlyZWZveCdcbiAgICAvLyBzY3JlZW5fY29uc3RyYWludHMgPSB7Li4ufVxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgJ2ZpcmVmb3gnLCB7XG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIG1vek1lZGlhU291cmNlOiBmaXJlZm94U3RyaW5nLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiBmaXJlZm94U3RyaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSB3aW5kb3cuZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG5cbmlmKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50ICE9PSAndW5kZWZpbmVkJyl7XG4gICAgdmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG4gICAgdmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG4gICAgfSk7XG59XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCJpbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKFwicGxhdGZvcm1cIik7XG5cbmV4cG9ydCBjbGFzcyBQbGF0Zm9ybVV0aWxzIHtcblx0cHJvdGVjdGVkIHN0YXRpYyBpbnN0YW5jZTogUGxhdGZvcm1VdGlscztcblx0Y29uc3RydWN0b3IoKSB7IH1cblxuXHRzdGF0aWMgZ2V0SW5zdGFuY2UoKTogUGxhdGZvcm1VdGlscyB7XG5cdFx0aWYgKCF0aGlzLmluc3RhbmNlKSB7XG5cdFx0XHR0aGlzLmluc3RhbmNlID0gbmV3IFBsYXRmb3JtVXRpbHMoKTtcblx0XHR9XG5cdFx0cmV0dXJuIFBsYXRmb3JtVXRpbHMuaW5zdGFuY2U7XG5cdH1cblxuXHRwdWJsaWMgaXNDaHJvbWVCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIkNocm9tZVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc1NhZmFyaUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiU2FmYXJpXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzQ2hyb21lTW9iaWxlQnJvd3NlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0ubmFtZSA9PT0gXCJDaHJvbWUgTW9iaWxlXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzRmlyZWZveEJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiRmlyZWZveFwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIkZpcmVmb3ggTW9iaWxlXCIgfHwgcGxhdGZvcm0ubmFtZSA9PT0gXCJGaXJlZm94IGZvciBpT1NcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNPcGVyYUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiT3BlcmFcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNPcGVyYU1vYmlsZUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiT3BlcmEgTW9iaWxlXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzRWRnZUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgdmVyc2lvbiA9IHBsYXRmb3JtPy52ZXJzaW9uID8gcGFyc2VGbG9hdChwbGF0Zm9ybS52ZXJzaW9uKSA6IC0xO1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIk1pY3Jvc29mdCBFZGdlXCIgJiYgdmVyc2lvbiA+PSA4MDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNFZGdlTW9iaWxlQnJvd3NlcigpOiBib29sZWFuIHtcblx0XHRjb25zdCB2ZXJzaW9uID0gcGxhdGZvcm0/LnZlcnNpb24gPyBwYXJzZUZsb2F0KHBsYXRmb3JtLnZlcnNpb24pIDogLTE7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiTWljcm9zb2Z0IEVkZ2VcIiAmJiAocGxhdGZvcm0ub3M/LmZhbWlseSA9PT0gJ0FuZHJvaWQnIHx8IHBsYXRmb3JtLm9zPy5mYW1pbHkgPT09ICdpT1MnKSAmJiB2ZXJzaW9uID4gNDU7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzQW5kcm9pZEJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiQW5kcm9pZCBCcm93c2VyXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzRWxlY3Ryb24oKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiRWxlY3Ryb25cIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNTYW1zdW5nQnJvd3NlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0cGxhdGZvcm0ubmFtZSA9PT0gXCJTYW1zdW5nIEludGVybmV0IE1vYmlsZVwiIHx8XG5cdFx0XHRwbGF0Zm9ybS5uYW1lID09PSBcIlNhbXN1bmcgSW50ZXJuZXRcIlxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzSVBob25lT3JJUGFkKCk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IHVzZXJBZ2VudCA9ICEhcGxhdGZvcm0udWEgPyBwbGF0Zm9ybS51YSA6IG5hdmlnYXRvci51c2VyQWdlbnQ7XG5cdFx0Y29uc3QgaXNUb3VjaGFibGUgPSBcIm9udG91Y2hlbmRcIiBpbiBkb2N1bWVudDtcblx0XHRjb25zdCBpc0lQYWQgPSAvXFxiKFxcdypNYWNpbnRvc2hcXHcqKVxcYi8udGVzdCh1c2VyQWdlbnQpICYmIGlzVG91Y2hhYmxlO1xuXHRcdGNvbnN0IGlzSVBob25lID1cblx0XHRcdC9cXGIoXFx3KmlQaG9uZVxcdyopXFxiLy50ZXN0KHVzZXJBZ2VudCkgJiZcblx0XHRcdC9cXGIoXFx3Kk1vYmlsZVxcdyopXFxiLy50ZXN0KHVzZXJBZ2VudCkgJiZcblx0XHRcdGlzVG91Y2hhYmxlO1xuXHRcdHJldHVybiBpc0lQYWQgfHwgaXNJUGhvbmU7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzSU9TV2l0aFNhZmFyaSgpOiBib29sZWFuIHtcblx0XHRjb25zdCB1c2VyQWdlbnQgPSAhIXBsYXRmb3JtLnVhID8gcGxhdGZvcm0udWEgOiBuYXZpZ2F0b3IudXNlckFnZW50O1xuXHRcdHJldHVybiB0aGlzLmlzSVBob25lT3JJUGFkKCkgJiYgKFxuXHRcdFx0L1xcYihcXHcqQXBwbGVcXHcqKVxcYi8udGVzdChuYXZpZ2F0b3IudmVuZG9yKSAmJlxuXHRcdFx0L1xcYihcXHcqU2FmYXJpXFx3KilcXGIvLnRlc3QodXNlckFnZW50KSAmJlxuXHRcdFx0IS9cXGIoXFx3KkNyaU9TXFx3KilcXGIvLnRlc3QodXNlckFnZW50KSAmJlxuXHRcdFx0IS9cXGIoXFx3KkZ4aU9TXFx3KilcXGIvLnRlc3QodXNlckFnZW50KVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzSW9uaWNJb3MoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuaXNJUGhvbmVPcklQYWQoKSAmJiBwbGF0Zm9ybS51YSEhLmluZGV4T2YoXCJTYWZhcmlcIikgPT09IC0xO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0lvbmljQW5kcm9pZCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0cGxhdGZvcm0ub3MhIS5mYW1pbHkgPT09IFwiQW5kcm9pZFwiICYmIHBsYXRmb3JtLm5hbWUgPT0gXCJBbmRyb2lkIEJyb3dzZXJcIlxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzTW9iaWxlRGV2aWNlKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5vcyEhLmZhbWlseSA9PT0gXCJpT1NcIiB8fCBwbGF0Zm9ybS5vcyEhLmZhbWlseSA9PT0gXCJBbmRyb2lkXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzUmVhY3ROYXRpdmUoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0Nocm9taXVtKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLmlzQ2hyb21lQnJvd3NlcigpIHx8IHRoaXMuaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHxcblx0XHRcdHRoaXMuaXNPcGVyYUJyb3dzZXIoKSB8fCB0aGlzLmlzT3BlcmFNb2JpbGVCcm93c2VyKCkgfHxcblx0XHRcdHRoaXMuaXNFZGdlQnJvd3NlcigpIHx8IHRoaXMuaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzU2Ftc3VuZ0Jyb3dzZXIoKSB8fFxuXHRcdFx0dGhpcy5pc0lvbmljQW5kcm9pZCgpIHx8IHRoaXMuaXNJb25pY0lvcygpIHx8XG5cdFx0XHR0aGlzLmlzRWxlY3Ryb24oKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgY2FuU2NyZWVuU2hhcmUoKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgdmVyc2lvbiA9IHBsYXRmb3JtPy52ZXJzaW9uID8gcGFyc2VGbG9hdChwbGF0Zm9ybS52ZXJzaW9uKSA6IC0xO1xuXHRcdC8vIFJlamVjdCBtb2JpbGUgZGV2aWNlc1xuXHRcdGlmICh0aGlzLmlzTW9iaWxlRGV2aWNlKCkpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIChcblx0XHRcdHRoaXMuaXNDaHJvbWVCcm93c2VyKCkgfHxcblx0XHRcdHRoaXMuaXNGaXJlZm94QnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzT3BlcmFCcm93c2VyKCkgfHxcblx0XHRcdHRoaXMuaXNFbGVjdHJvbigpIHx8XG5cdFx0XHR0aGlzLmlzRWRnZUJyb3dzZXIoKSB8fFxuXHRcdFx0KHRoaXMuaXNTYWZhcmlCcm93c2VyKCkgJiYgdmVyc2lvbiA+PSAxMylcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBnZXROYW1lKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgfHwgXCJcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgZ2V0VmVyc2lvbigpOiBzdHJpbmcge1xuXHRcdHJldHVybiBwbGF0Zm9ybS52ZXJzaW9uIHx8IFwiXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGdldEZhbWlseSgpOiBzdHJpbmcge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5vcyEhLmZhbWlseSB8fCBcIlwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBnZXREZXNjcmlwdGlvbigpOiBzdHJpbmcge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5kZXNjcmlwdGlvbiB8fCBcIlwiO1xuXHR9XG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IGZyZWVpY2UgPSByZXF1aXJlKCdmcmVlaWNlJyk7XG5pbXBvcnQgeyB2NCBhcyB1dWlkdjQgfSBmcm9tICd1dWlkJztcbmltcG9ydCB7IEV4Y2VwdGlvbkV2ZW50TmFtZSB9IGZyb20gJy4uL0V2ZW50cy9FeGNlcHRpb25FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vVXRpbHMvUGxhdGZvcm0nO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG4vKlxuICogVGFibGUgb2Ygc2VuZGVyIHZpZGVvIGVuY29kaW5ncyBmb3Igc2ltdWxjYXN0LlxuICogTm90ZSB0aGF0IHRoaXMgaXMganVzdCBhIHBvbGl0ZSByZXF1ZXN0LCBidXQgdGhlIGJyb3dzZXIgaXMgZnJlZSB0byBob25vciBpdFxuICogb3IganVzdCBwbGF5IGJ5IGl0cyBvd24gcnVsZXMuXG4gKlxuICogQ2hyb21lIGltcG9zZXMgc29tZSByZXN0cmljdGlvbnMgYmFzZWQgb24gdGhlIHNpemUgb2YgdGhlIHZpZGVvLCBtYXggYml0cmF0ZSxcbiAqIGFuZCBhdmFpbGFibGUgYmFuZHdpZHRoLiBDaGVjayBoZXJlIGZvciB0aGUgdmlkZW8gc2l6ZSB0YWJsZTpcbiAqIGh0dHBzOi8vY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9leHRlcm5hbC93ZWJydGMvKy9tYXN0ZXIvbWVkaWEvZW5naW5lL3NpbXVsY2FzdC5jYyM5MFxuICpcbiAqIHwgU2l6ZSAocHgpIHwgQml0cmF0ZSAoa2JwcykgfCBNYXggTGF5ZXJzIHxcbiAqIHwtLS0tLS0tLS0tOnwtLS0tLS0tLS0tLS0tLS06fC0tLS0tLS0tLS0tOnxcbiAqIHwgMTkyMHgxMDgwIHwgICAgICAgICAgIDUwMDAgfCAgICAgICAgICAzIHxcbiAqIHwgIDEyODB4NzIwIHwgICAgICAgICAgIDI1MDAgfCAgICAgICAgICAzIHxcbiAqIHwgICA5NjB4NTQwIHwgICAgICAgICAgIDEyMDAgfCAgICAgICAgICAzIHxcbiAqIHwgICA2NDB4MzYwIHwgICAgICAgICAgICA3MDAgfCAgICAgICAgICAyIHxcbiAqIHwgICA0ODB4MjcwIHwgICAgICAgICAgICA0NTAgfCAgICAgICAgICAyIHxcbiAqIHwgICAzMjB4MTgwIHwgICAgICAgICAgICAyMDAgfCAgICAgICAgICAxIHxcbiAqXG4gKiBGaXJlZm94IHdpbGwgc2VuZCBhcyBtYW55IGxheWVycyBhcyB3ZSByZXF1ZXN0LCBidXQgdGhlcmUgYXJlIHNvbWUgbGltaXRzIG9uXG4gKiB0aGVpciBiaXRyYXRlOlxuICpcbiAqIHwgU2l6ZSAocHgpIHwgTWluIGJpdHJhdGUgKGJwcykgfCBTdGFydCBiaXRyYXRlIChicHMpIHwgTWF4IGJpdHJhdGUgKGJwcykgfCAgICAgICBDb21tZW50cyB8XG4gKiB8LS0tLS0tLS0tLTp8LS0tLS0tLS0tLS0tLS0tLS0tOnwtLS0tLS0tLS0tLS0tLS0tLS0tLTp8LS0tLS0tLS0tLS0tLS0tLS0tOnwtLS0tLS0tLS0tLS0tLS06fFxuICogfCAxOTIweDEyMDAgfCAgICAgICAgICAgICAgMTUwMCB8ICAgICAgICAgICAgICAgIDIwMDAgfCAgICAgICAgICAgICAxMDAwMCB8ICAgPkhEICgzSywgNEspIHxcbiAqIHwgIDEyODB4NzIwIHwgICAgICAgICAgICAgIDEyMDAgfCAgICAgICAgICAgICAgICAxNTAwIHwgICAgICAgICAgICAgIDUwMDAgfCAgSEQgfjEwODAtMTIwMCB8XG4gKiB8ICAgODAweDQ4MCB8ICAgICAgICAgICAgICAgMjAwIHwgICAgICAgICAgICAgICAgIDgwMCB8ICAgICAgICAgICAgICAyNTAwIHwgICAgICAgIEhEIH43MjAgfFxuICogfCAgIDQ4MHgyNzAgfCAgICAgICAgICAgICAgIDE1MCB8ICAgICAgICAgICAgICAgICA1MDAgfCAgICAgICAgICAgICAgMjAwMCB8ICAgICAgICAgICBXVkdBIHxcbiAqIHwgICA0MDB4MjQwIHwgICAgICAgICAgICAgICAxMjUgfCAgICAgICAgICAgICAgICAgMzAwIHwgICAgICAgICAgICAgIDEzMDAgfCAgICAgICAgICAgIFZHQSB8XG4gKiB8ICAgMTc2eDE0NCB8ICAgICAgICAgICAgICAgMTAwIHwgICAgICAgICAgICAgICAgIDE1MCB8ICAgICAgICAgICAgICAgNTAwIHwgICAgIFdRVkdBLCBDSUYgfFxuICogfCAgICAgICAgIDAgfCAgICAgICAgICAgICAgICA0MCB8ICAgICAgICAgICAgICAgICAgODAgfCAgICAgICAgICAgICAgIDI1MCB8IFFDSUYgYW5kIGJlbG93IHxcbiAqXG4gKiBEb2NzIGZvciBgUlRDUnRwRW5jb2RpbmdQYXJhbWV0ZXJzYDogaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYnJ0Yy8jZG9tLXJ0Y3J0cGVuY29kaW5ncGFyYW1ldGVyc1xuICogTW9zdCBpbnRlcmVzdGluZyBtZW1iZXJzIGFyZSBgbWF4Qml0cmF0ZWAgYW5kIGBzY2FsZVJlc29sdXRpb25Eb3duQnlgLlxuICpcbiAqIGBzY2FsZVJlc29sdXRpb25Eb3duQnlgIGlzIHNwZWNpZmllZCBhcyA0OjI6MSB3aGljaCBpcyB0aGUgc2FtZSB0aGF0IHRoZSBkZWZhdWx0LlxuICogVGhlIFdlYlJUQyBzcGVjIHNheXMgdGhpcyAoaHR0cHM6Ly93d3cudzMub3JnL1RSL3dlYnJ0Yy8jZG9tLXJ0Y3BlZXJjb25uZWN0aW9uLWFkZHRyYW5zY2VpdmVyKTpcbiAqICAgICA+IElmIHRoZSBzY2FsZVJlc29sdXRpb25Eb3duQnkgYXR0cmlidXRlcyBvZiBzZW5kRW5jb2RpbmdzIGFyZSBzdGlsbCB1bmRlZmluZWQsIGluaXRpYWxpemVcbiAqICAgICA+IGVhY2ggZW5jb2RpbmcncyBzY2FsZVJlc29sdXRpb25Eb3duQnkgdG8gMl4obGVuZ3RoIG9mIHNlbmRFbmNvZGluZ3MgLSBlbmNvZGluZyBpbmRleFxuICogICAgID4gLSAxKS4gVGhpcyByZXN1bHRzIGluIHNtYWxsZXItdG8tbGFyZ2VyIHJlc29sdXRpb25zIHdoZXJlIHRoZSBsYXN0IGVuY29kaW5nIGhhcyBubyBzY2FsaW5nXG4gKiAgICAgPiBhcHBsaWVkIHRvIGl0LCBlLmcuIDQ6MjoxIGlmIHRoZSBsZW5ndGggaXMgMy5cbiAqIEhvd2V2ZXIsIEZpcmVmb3ggZG9lc24ndCBzZWVtIHRvIGltcGxlbWVudCB0aGlzIGRlZmF1bHQgeWV0LiBNZWRpYXNvdXAgbmV2ZXIgZ2V0cyB0byBzZWxlY3RcbiAqIGFuIG91dHB1dCBsYXllci5cbiAqXG4gKiBgbWF4Qml0cmF0ZWAgaXMgbGVmdCB1bnNwZWNpZmllZCwgdG8gbGV0IHRoZSBjbGllbnQgZGVjaWRlIGJhc2VkIG9uIGl0cyBvd25cbiAqIGJhbmR3aWR0aCBsaW1pdCBkZXRlY3Rpb24uXG4gKi9cbmNvbnN0IHNpbXVsY2FzdFZpZGVvRW5jb2RpbmdzOiBSVENSdHBFbmNvZGluZ1BhcmFtZXRlcnNbXSA9IFtcbiAgICB7XG4gICAgICAgIHJpZDogXCJyMFwiLFxuICAgICAgICBzY2FsZVJlc29sdXRpb25Eb3duQnk6IDQsXG4gICAgfSxcbiAgICB7XG4gICAgICAgIHJpZDogXCJyMVwiLFxuICAgICAgICBzY2FsZVJlc29sdXRpb25Eb3duQnk6IDIsXG4gICAgfSxcbiAgICB7XG4gICAgICAgIHJpZDogXCJyMlwiLFxuICAgICAgICBzY2FsZVJlc29sdXRpb25Eb3duQnk6IDEsXG4gICAgfSxcbl07XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24ge1xuICAgIG1lZGlhQ29uc3RyYWludHM6IHtcbiAgICAgICAgYXVkaW86IGJvb2xlYW4sXG4gICAgICAgIHZpZGVvOiBib29sZWFuXG4gICAgfTtcbiAgICBzaW11bGNhc3Q6IGJvb2xlYW47XG4gICAgbWVkaWFTZXJ2ZXI6IHN0cmluZztcbiAgICBvbkljZUNhbmRpZGF0ZTogKGV2ZW50OiBSVENJY2VDYW5kaWRhdGUpID0+IHZvaWQ7XG4gICAgb25JY2VDb25uZWN0aW9uU3RhdGVFeGNlcHRpb246IChleGNlcHRpb25OYW1lOiBFeGNlcHRpb25FdmVudE5hbWUsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IGFueSkgPT4gdm9pZDtcbiAgICBpY2VTZXJ2ZXJzPzogUlRDSWNlU2VydmVyW107XG4gICAgbWVkaWFTdHJlYW0/OiBNZWRpYVN0cmVhbSB8IG51bGw7XG4gICAgbW9kZT86ICdzZW5kb25seScgfCAncmVjdm9ubHknIHwgJ3NlbmRyZWN2JztcbiAgICBpZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuICAgIHBjOiBSVENQZWVyQ29ubmVjdGlvbjtcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICAvLyBTYW1lIGFzIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIGJ1dCB3aXRob3V0IG9wdGlvbmFsIGZpZWxkcy5cbiAgICBwcm90ZWN0ZWQgY29uZmlndXJhdGlvbjogUmVxdWlyZWQ8V2ViUnRjUGVlckNvbmZpZ3VyYXRpb24+O1xuXG4gICAgcHJpdmF0ZSBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uID0ge1xuICAgICAgICAgICAgLi4uY29uZmlndXJhdGlvbixcbiAgICAgICAgICAgIGljZVNlcnZlcnM6XG4gICAgICAgICAgICAgICAgISFjb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiZcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICAgICAgPyBjb25maWd1cmF0aW9uLmljZVNlcnZlcnNcbiAgICAgICAgICAgICAgICAgICAgOiBmcmVlaWNlKCksXG4gICAgICAgICAgICBtZWRpYVN0cmVhbTpcbiAgICAgICAgICAgICAgICBjb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgPyBjb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICAgIG1vZGU6ICEhY29uZmlndXJhdGlvbi5tb2RlID8gY29uZmlndXJhdGlvbi5tb2RlIDogXCJzZW5kcmVjdlwiLFxuICAgICAgICAgICAgaWQ6ICEhY29uZmlndXJhdGlvbi5pZCA/IGNvbmZpZ3VyYXRpb24uaWQgOiB0aGlzLmdlbmVyYXRlVW5pcXVlSWQoKSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnBjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHsgaWNlU2VydmVyczogdGhpcy5jb25maWd1cmF0aW9uLmljZVNlcnZlcnMgfSk7XG5cbiAgICAgICAgdGhpcy5wYy5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCAoZXZlbnQ6IFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudC5jYW5kaWRhdGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlID0gZXZlbnQuY2FuZGlkYXRlO1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5vbkljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIGlmIChjYW5kaWRhdGUuY2FuZGlkYXRlICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlLnB1c2goPFJUQ0ljZUNhbmRpZGF0ZT57IGNhbmRpZGF0ZTogY2FuZGlkYXRlLmNhbmRpZGF0ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucGMuYWRkRXZlbnRMaXN0ZW5lcignc2lnbmFsaW5nc3RhdGVjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAodGhpcy5pY2VDYW5kaWRhdGVMaXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNhbmRpZGF0ZSA9IHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjLmFkZEljZUNhbmRpZGF0ZSg8UlRDSWNlQ2FuZGlkYXRlPmNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRJZCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWd1cmF0aW9uLmlkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGZyZWVzIHRoZSByZXNvdXJjZXMgdXNlZCBieSBXZWJSdGNQZWVyXG4gICAgICovXG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdEaXNwb3NpbmcgV2ViUnRjUGVlcicpO1xuICAgICAgICBpZiAodGhpcy5wYykge1xuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5wYy5jbG9zZSgpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUgPSBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gU0RQIG9mZmVyIGZyb20gdGhlIGxvY2FsIFJUQ1BlZXJDb25uZWN0aW9uIHRvIHNlbmQgdG8gdGhlIG90aGVyIHBlZXJcbiAgICAgKiBPbmx5IGlmIHRoZSBuZWdvdGlhdGlvbiB3YXMgaW5pdGlhdGVkIGJ5IHRoaXMgcGVlclxuICAgICAqL1xuICAgIGNyZWF0ZU9mZmVyKCk6IFByb21pc2U8UlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgLy8gVE9ETzogRGVsZXRlIHRoaXMgY29uZGl0aW9uYWwgd2hlbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzIGFyZVxuICAgICAgICAgICAgLy8gbW9kZXJuIGVub3VnaCB0byBpbXBsZW1lbnQgdGhlIFRyYW5zY2VpdmVyIG1ldGhvZHMuXG4gICAgICAgICAgICBpZiAoXCJhZGRUcmFuc2NlaXZlclwiIGluIHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoXCJbY3JlYXRlT2ZmZXJdIE1ldGhvZCBSVENQZWVyQ29ubmVjdGlvbi5hZGRUcmFuc2NlaXZlcigpIGlzIGF2YWlsYWJsZTsgdXNpbmcgaXRcIik7XG5cbiAgICAgICAgICAgICAgICAvLyBTcGVjIGRvYzogaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jZG9tLXJ0Y3BlZXJjb25uZWN0aW9uLWFkZHRyYW5zY2VpdmVyXG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09IFwicmVjdm9ubHlcIikge1xuICAgICAgICAgICAgICAgICAgICAvLyBUbyBzZW5kIG1lZGlhLCBhc3N1bWUgdGhhdCBhbGwgZGVzaXJlZCBtZWRpYSB0cmFja3NcbiAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBiZWVuIGFscmVhZHkgYWRkZWQgYnkgaGlnaGVyIGxldmVsIGNvZGUgdG8gb3VyXG4gICAgICAgICAgICAgICAgICAgIC8vIE1lZGlhU3RyZWFtLlxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGAke3RoaXMuY29uZmlndXJhdGlvbi5tb2RlfSBkaXJlY3Rpb24gcmVxdWVzdGVkLCBidXQgbm8gc3RyZWFtIHdhcyBjb25maWd1cmVkIHRvIGJlIHNlbnRgKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHRyYWNrIG9mIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbS5nZXRUcmFja3MoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGNJbml0OiBSVENSdHBUcmFuc2NlaXZlckluaXQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBbdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLnNpbXVsY2FzdCAmJiB0cmFjay5raW5kID09PSBcInZpZGVvXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0Y0luaXQuc2VuZEVuY29kaW5ncyA9IHNpbXVsY2FzdFZpZGVvRW5jb2RpbmdzO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGMgPSB0aGlzLnBjLmFkZFRyYW5zY2VpdmVyKHRyYWNrLCB0Y0luaXQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGSVhNRTogQ2hlY2sgdGhhdCB0aGUgc2ltdWxjYXN0IGVuY29kaW5ncyB3ZXJlIGFwcGxpZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGRvZXNuJ3QgaW1wbGVtZW50IGBSVENSdHBUcmFuc2NlaXZlckluaXQuc2VuZEVuY29kaW5nc2BcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNvIHRoZSBvbmx5IHdheSB0byBlbmFibGUgc2ltdWxjYXN0IGlzIHdpdGggYFJUQ1J0cFNlbmRlci5zZXRQYXJhbWV0ZXJzKClgLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgbmV4dCBibG9jayBjYW4gYmUgZGVsZXRlZCB3aGVuIEZpcmVmb3ggZml4ZXMgYnVnICMxMzk2OTE4OlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTM5NjkxOFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVEU6IFRoaXMgaXMgZG9uZSBpbiBhIHdheSB0aGF0IGlzIGNvbXBhdGlibGUgd2l0aCBhbGwgYnJvd3NlcnMsIHRvIHNhdmUgb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJyb3dzZXItY29uZGl0aW9uYWwgY29kZS4gVGhlIGlkZWEgY29tZXMgZnJvbSBXZWJSVEMgQWRhcHRlci5qczpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICogaHR0cHM6Ly9naXRodWIuY29tL3dlYnJ0Y0hhY2tzL2FkYXB0ZXIvaXNzdWVzLzk5OFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKiBodHRwczovL2dpdGh1Yi5jb20vd2VicnRjSGFja3MvYWRhcHRlci9ibG9iLzg0NWEzYjQ4NzRmMTg5MmE3NmYwNGMzY2M1MjBlODBiNTA0MWMzMDMvc3JjL2pzL2ZpcmVmb3gvZmlyZWZveF9zaGltLmpzI0wyMTdcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24uc2ltdWxjYXN0ICYmIHRyYWNrLmtpbmQgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRQYXJhbXMgPSB0Yy5zZW5kZXIuZ2V0UGFyYW1ldGVycygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIShcImVuY29kaW5nc1wiIGluIHNlbmRQYXJhbXMpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQYXJhbXMuZW5jb2RpbmdzLmxlbmd0aCAhPT0gdGNJbml0LnNlbmRFbmNvZGluZ3MhLmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUGFyYW1zLmVuY29kaW5ncyA9IHRjSW5pdC5zZW5kRW5jb2RpbmdzITtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGMuc2VuZGVyLnNldFBhcmFtZXRlcnMoc2VuZFBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVG8ganVzdCByZWNlaXZlIG1lZGlhLCBjcmVhdGUgbmV3IHJlY3Zvbmx5IHRyYW5zY2VpdmVycy5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBraW5kIG9mIFtcImF1ZGlvXCIsIFwidmlkZW9cIl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBtZWRpYSBraW5kIHNob3VsZCBiZSB1c2VkLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50c1traW5kXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFTdHJlYW0gPSBuZXcgTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkVHJhbnNjZWl2ZXIoa2luZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLm1vZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogW3RoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbV0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucGNcbiAgICAgICAgICAgICAgICAgICAgLmNyZWF0ZU9mZmVyKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHNkcE9mZmVyKSA9PiByZXNvbHZlKHNkcE9mZmVyKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIltjcmVhdGVPZmZlcl0gTWV0aG9kIFJUQ1BlZXJDb25uZWN0aW9uLmFkZFRyYW5zY2VpdmVyKCkgaXMgTk9UIGF2YWlsYWJsZTsgdXNpbmcgTEVHQUNZIG9mZmVyVG9SZWNlaXZle0F1ZGlvLFZpZGVvfVwiKTtcblxuICAgICAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgTEVHQUNZIE1FVEhPRDogT2xkIFdlYlJUQyB2ZXJzaW9ucyBkb24ndCBpbXBsZW1lbnRcbiAgICAgICAgICAgICAgICAvLyBUcmFuc2NlaXZlcnMsIGFuZCBpbnN0ZWFkIGRlcGVuZCBvbiB0aGUgZGVwcmVjYXRlZFxuICAgICAgICAgICAgICAgIC8vIFwib2ZmZXJUb1JlY2VpdmVBdWRpb1wiIGFuZCBcIm9mZmVyVG9SZWNlaXZlVmlkZW9cIi5cblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlcHJlY2F0ZWRQZWVyQ29ubmVjdGlvblRyYWNrQXBpKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgaGFzQXVkaW8gPSB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbztcbiAgICAgICAgICAgICAgICBjb25zdCBoYXNWaWRlbyA9IHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvO1xuXG4gICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9uczogUlRDT2ZmZXJPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09IFwic2VuZG9ubHlcIiAmJiBoYXNBdWRpbyxcbiAgICAgICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tb2RlICE9PSBcInNlbmRvbmx5XCIgJiYgaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIlJUQ1BlZXJDb25uZWN0aW9uLmNyZWF0ZU9mZmVyKCkgb3B0aW9uczpcIiwgSlNPTi5zdHJpbmdpZnkob3B0aW9ucykpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5wY1xuICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlIC0gQ29tcGlsZXIgaXMgdG9vIGNsZXZlciBhbmQgdGhpbmtzIHRoaXMgYnJhbmNoIHdpbGwgbmV2ZXIgZXhlY3V0ZS5cbiAgICAgICAgICAgICAgICAgICAgLmNyZWF0ZU9mZmVyKG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKChzZHBPZmZlcikgPT4gcmVzb2x2ZShzZHBPZmZlcikpXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBkZXByZWNhdGVkUGVlckNvbm5lY3Rpb25UcmFja0FwaSgpIHtcbiAgICAgICAgZm9yIChjb25zdCB0cmFjayBvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFTdHJlYW0hLmdldFRyYWNrcygpKSB7XG4gICAgICAgICAgICB0aGlzLnBjLmFkZFRyYWNrKHRyYWNrLCB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFTdHJlYW0hKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gU0RQIGFuc3dlciBmcm9tIHRoZSBsb2NhbCBSVENQZWVyQ29ubmVjdGlvbiB0byBzZW5kIHRvIHRoZSBvdGhlciBwZWVyXG4gICAgICogT25seSBpZiB0aGUgbmVnb3RpYXRpb24gd2FzIGluaXRpYXRlZCBieSB0aGUgb3RoZXIgcGVlclxuICAgICAqL1xuICAgIGNyZWF0ZUFuc3dlcigpOiBQcm9taXNlPFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIC8vIFRPRE86IERlbGV0ZSB0aGlzIGNvbmRpdGlvbmFsIHdoZW4gYWxsIHN1cHBvcnRlZCBicm93c2VycyBhcmVcbiAgICAgICAgICAgIC8vIG1vZGVybiBlbm91Z2ggdG8gaW1wbGVtZW50IHRoZSBUcmFuc2NlaXZlciBtZXRob2RzLlxuICAgICAgICAgICAgaWYgKFwiZ2V0VHJhbnNjZWl2ZXJzXCIgaW4gdGhpcy5wYykge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIltjcmVhdGVBbnN3ZXJdIE1ldGhvZCBSVENQZWVyQ29ubmVjdGlvbi5nZXRUcmFuc2NlaXZlcnMoKSBpcyBhdmFpbGFibGU7IHVzaW5nIGl0XCIpO1xuXG4gICAgICAgICAgICAgICAgLy8gRW5zdXJlIHRoYXQgdGhlIFBlZXJDb25uZWN0aW9uIGFscmVhZHkgY29udGFpbnMgb25lIFRyYW5zY2VpdmVyXG4gICAgICAgICAgICAgICAgLy8gZm9yIGVhY2gga2luZCBvZiBtZWRpYS5cbiAgICAgICAgICAgICAgICAvLyBUaGUgVHJhbnNjZWl2ZXJzIHNob3VsZCBoYXZlIGJlZW4gYWxyZWFkeSBjcmVhdGVkIGludGVybmFsbHkgYnlcbiAgICAgICAgICAgICAgICAvLyB0aGUgUEMgaXRzZWxmLCB3aGVuIGBwYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihzZHBPZmZlcilgIHdhcyBjYWxsZWQuXG5cbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtpbmQgb2YgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgbWVkaWEga2luZCBzaG91bGQgYmUgdXNlZC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50c1traW5kXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBsZXQgdGMgPSB0aGlzLnBjXG4gICAgICAgICAgICAgICAgICAgICAgICAuZ2V0VHJhbnNjZWl2ZXJzKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5maW5kKCh0YykgPT4gdGMucmVjZWl2ZXIudHJhY2sua2luZCA9PT0ga2luZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFbmZvcmNlIG91ciBkZXNpcmVkIGRpcmVjdGlvbi5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRjLmRpcmVjdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5tb2RlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgJHtraW5kfSByZXF1ZXN0ZWQsIGJ1dCBubyB0cmFuc2NlaXZlciB3YXMgY3JlYXRlZCBmcm9tIHJlbW90ZSBkZXNjcmlwdGlvbmApKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucGNcbiAgICAgICAgICAgICAgICAgICAgLmNyZWF0ZUFuc3dlcigpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKChzZHBBbnN3ZXIpID0+IHJlc29sdmUoc2RwQW5zd2VyKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4gcmVqZWN0KGVycm9yKSk7XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBEZWxldGUgZWxzZSBicmFuY2ggd2hlbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzIGFyZVxuICAgICAgICAgICAgICAgIC8vIG1vZGVybiBlbm91Z2ggdG8gaW1wbGVtZW50IHRoZSBUcmFuc2NlaXZlciBtZXRob2RzXG5cbiAgICAgICAgICAgICAgICBsZXQgb2ZmZXJBdWRpbywgb2ZmZXJWaWRlbyA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICAgICAgb2ZmZXJBdWRpbyA9ICh0eXBlb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gPT09ICdib29sZWFuJykgP1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHMuYXVkaW8gOiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBvZmZlclZpZGVvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy52aWRlbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBSVENPZmZlck9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiBvZmZlckF1ZGlvLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogb2ZmZXJWaWRlb1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBjIS5jcmVhdGVBbnN3ZXIoY29uc3RyYWludHMpLnRoZW4oc2RwQW5zd2VyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc2RwQW5zd2VyKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGVsc2UsIHRoZXJlIGlzIG5vdGhpbmcgdG8gZG87IHRoZSBsZWdhY3kgY3JlYXRlQW5zd2VyKCkgb3B0aW9ucyBkb1xuICAgICAgICAgICAgLy8gbm90IG9mZmVyIGFueSBjb250cm9sIG92ZXIgd2hpY2ggdHJhY2tzIGFyZSBpbmNsdWRlZCBpbiB0aGUgYW5zd2VyLlxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIHBlZXIgaW5pdGlhdGVkIG5lZ290aWF0aW9uLiBTdGVwIDEvNCBvZiBTRFAgb2ZmZXItYW5zd2VyIHByb3RvY29sXG4gICAgICovXG4gICAgcHJvY2Vzc0xvY2FsT2ZmZXIob2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgICAgIGlmICghIWxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCdMb2NhbCBkZXNjcmlwdGlvbiBpcyBub3QgZGVmaW5lZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPdGhlciBwZWVyIGluaXRpYXRlZCBuZWdvdGlhdGlvbi4gU3RlcCAyLzQgb2YgU0RQIG9mZmVyLWFuc3dlciBwcm90b2NvbFxuICAgICAqL1xuICAgIHByb2Nlc3NSZW1vdGVPZmZlcihzZHBPZmZlcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnb2ZmZXInLFxuICAgICAgICAgICAgICAgIHNkcDogc2RwT2ZmZXJcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ1NEUCBvZmZlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nLCBvZmZlcik7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJlamVjdCgnUlRDUGVlckNvbm5lY3Rpb24gaXMgY2xvc2VkIHdoZW4gdHJ5aW5nIHRvIHNldCByZW1vdGUgZGVzY3JpcHRpb24nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPdGhlciBwZWVyIGluaXRpYXRlZCBuZWdvdGlhdGlvbi4gU3RlcCAzLzQgb2YgU0RQIG9mZmVyLWFuc3dlciBwcm90b2NvbFxuICAgICAqL1xuICAgIHByb2Nlc3NMb2NhbEFuc3dlcihhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnU0RQIGFuc3dlciBjcmVhdGVkLCBzZXR0aW5nIGxvY2FsIGRlc2NyaXB0aW9uJyk7XG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCB3aGVuIHRyeWluZyB0byBzZXQgbG9jYWwgZGVzY3JpcHRpb24nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBwZWVyIGluaXRpYXRlZCBuZWdvdGlhdGlvbi4gU3RlcCA0LzQgb2YgU0RQIG9mZmVyLWFuc3dlciBwcm90b2NvbFxuICAgICAqL1xuICAgIHByb2Nlc3NSZW1vdGVBbnN3ZXIoc2RwQW5zd2VyOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFuc3dlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnYW5zd2VyJyxcbiAgICAgICAgICAgICAgICBzZHA6IHNkcEFuc3dlclxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnU0RQIGFuc3dlciByZWNlaXZlZCwgc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24nKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMucGMuc2lnbmFsaW5nU3RhdGUgPT09ICdjbG9zZWQnKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KCdSVENQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQgd2hlbiB0cnlpbmcgdG8gc2V0IHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFzeW5jIHNldFJlbW90ZURlc2NyaXB0aW9uKHNkcDogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihzZHApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBJQ0UgY2FuZGlkYXRlIHJlY2VpdmVkJywgaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlLnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3N0YWJsZSc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMucGMucmVtb3RlRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSkudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFkZEljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZUxpc3RlbmVyKG90aGVySWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLnBjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGljZUNvbm5lY3Rpb25TdGF0ZTogUlRDSWNlQ29ubmVjdGlvblN0YXRlID0gdGhpcy5wYy5pY2VDb25uZWN0aW9uU3RhdGU7XG4gICAgICAgICAgICBzd2l0Y2ggKGljZUNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Rpc2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFBvc3NpYmxlIG5ldHdvcmsgZGlzY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtc2cxID0gJ0ljZUNvbm5lY3Rpb25TdGF0ZSBvZiBSVENQZWVyQ29ubmVjdGlvbiAnICsgdGhpcy5jb25maWd1cmF0aW9uLmlkICsgJyAoJyArIG90aGVySWQgKyAnKSBjaGFuZ2UgdG8gXCJkaXNjb25uZWN0ZWRcIi4gUG9zc2libGUgbmV0d29yayBkaXNjb25uZWN0aW9uJztcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4obXNnMSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5vbkljZUNvbm5lY3Rpb25TdGF0ZUV4Y2VwdGlvbihFeGNlcHRpb25FdmVudE5hbWUuSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVELCBtc2cxKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZmFpbGVkJzpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbXNnMiA9ICdJY2VDb25uZWN0aW9uU3RhdGUgb2YgUlRDUGVlckNvbm5lY3Rpb24gJyArIHRoaXMuY29uZmlndXJhdGlvbi5pZCArICcgKCcgKyBvdGhlcklkICsgJykgdG8gXCJmYWlsZWRcIic7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihtc2cyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uSWNlQ29ubmVjdGlvblN0YXRlRXhjZXB0aW9uKEV4Y2VwdGlvbkV2ZW50TmFtZS5JQ0VfQ09OTkVDVElPTl9GQUlMRUQsIG1zZzIpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdJY2VDb25uZWN0aW9uU3RhdGUgb2YgUlRDUGVlckNvbm5lY3Rpb24gJyArIHRoaXMuY29uZmlndXJhdGlvbi5pZCArICcgKCcgKyBvdGhlcklkICsgJykgY2hhbmdlIHRvIFwiY2xvc2VkXCInKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbmV3JzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcIm5ld1wiJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNraW5nJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcImNoZWNraW5nXCInKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY29ubmVjdGVkJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcImNvbm5lY3RlZFwiJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ0ljZUNvbm5lY3Rpb25TdGF0ZSBvZiBSVENQZWVyQ29ubmVjdGlvbiAnICsgdGhpcy5jb25maWd1cmF0aW9uLmlkICsgJyAoJyArIG90aGVySWQgKyAnKSBjaGFuZ2UgdG8gXCJjb21wbGV0ZWRcIicpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdlbmVyYXRlVW5pcXVlSWQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHV1aWR2NCgpO1xuICAgIH1cblxufVxuXG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyUmVjdm9ubHkgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAncmVjdm9ubHknO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyU2VuZG9ubHkgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZG9ubHknO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyU2VuZHJlY3YgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjAgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IFBsYXRmb3JtVXRpbHMgfSBmcm9tICcuLi9VdGlscy9QbGF0Zm9ybSc7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG5pbnRlcmZhY2UgV2VicnRjU3RhdHNDb25maWcge1xuICAgIGludGVydmFsOiBudW1iZXIsXG4gICAgaHR0cEVuZHBvaW50OiBzdHJpbmdcbn1cblxuaW50ZXJmYWNlIEpTT05TdGF0c1Jlc3BvbnNlIHtcbiAgICAnQHRpbWVzdGFtcCc6IHN0cmluZyxcbiAgICBwYXJ0aWNpcGFudF9pZDogc3RyaW5nLFxuICAgIHNlc3Npb25faWQ6IHN0cmluZyxcbiAgICBwbGF0Zm9ybTogc3RyaW5nLFxuICAgIHBsYXRmb3JtX2Rlc2NyaXB0aW9uOiBzdHJpbmcsXG4gICAgc3RyZWFtOiBzdHJpbmcsXG4gICAgd2VicnRjX3N0YXRzOiBJV2VicnRjU3RhdHNcbn1cblxuLyoqXG4gKiBDb21tb24gV2ViUnRjU1RhdHMgZm9yIGxhdGVzdCBDaHJvbWl1bSBhbmQgRmlyZWZveCB2ZXJzaW9uc1xuICovXG5pbnRlcmZhY2UgSVdlYnJ0Y1N0YXRzIHtcbiAgICBpbmJvdW5kPzoge1xuICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyLFxuICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzTG9zdDogbnVtYmVyLFxuICAgICAgICAgICAgaml0dGVyOiBudW1iZXJcbiAgICAgICAgfSB8IHt9LFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyLFxuICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzTG9zdDogbnVtYmVyLFxuICAgICAgICAgICAgaml0dGVyPzogbnVtYmVyLCAvLyBGaXJlZm94XG4gICAgICAgICAgICBqaXR0ZXJCdWZmZXJEZWxheT86IG51bWJlciwgLy8gQ2hyb21lXG4gICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiBudW1iZXIsXG4gICAgICAgICAgICBmaXJDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgbmFja0NvdW50OiBudW1iZXIsXG4gICAgICAgICAgICBwbGlDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgZnJhbWVIZWlnaHQ/OiBudW1iZXIsIC8vIENocm9tZVxuICAgICAgICAgICAgZnJhbWVXaWR0aD86IG51bWJlciwgLy8gQ2hyb21lXG4gICAgICAgICAgICBmcmFtZXNEcm9wcGVkPzogbnVtYmVyLCAvLyBDaHJvbWVcbiAgICAgICAgICAgIGZyYW1lc1JlY2VpdmVkPzogbnVtYmVyIC8vIENocm9tZVxuICAgICAgICB9IHwge31cbiAgICB9LFxuICAgIG91dGJvdW5kPzoge1xuICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgYnl0ZXNTZW50OiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzU2VudDogbnVtYmVyLFxuICAgICAgICB9IHwge30sXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBieXRlc1NlbnQ6IG51bWJlcixcbiAgICAgICAgICAgIHBhY2tldHNTZW50OiBudW1iZXIsXG4gICAgICAgICAgICBmaXJDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogbnVtYmVyLFxuICAgICAgICAgICAgbmFja0NvdW50OiBudW1iZXIsXG4gICAgICAgICAgICBwbGlDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgcXBTdW06IG51bWJlcixcbiAgICAgICAgICAgIGZyYW1lSGVpZ2h0PzogbnVtYmVyLCAvLyBDaHJvbWVcbiAgICAgICAgICAgIGZyYW1lV2lkdGg/OiBudW1iZXIsIC8vIENocm9tZVxuICAgICAgICAgICAgZnJhbWVzU2VudD86IG51bWJlciAvLyBDaHJvbWVcbiAgICAgICAgfSB8IHt9XG4gICAgfSxcbiAgICBjYW5kaWRhdGVwYWlyPzoge1xuICAgICAgICBjdXJyZW50Um91bmRUcmlwVGltZT86IG51bWJlciAvLyBDaHJvbWVcbiAgICAgICAgYXZhaWxhYmxlT3V0Z29pbmdCaXRyYXRlPzogbnVtYmVyIC8vQ2hyb21lXG4gICAgICAgIC8vIGF2YWlsYWJsZUluY29taW5nQml0cmF0ZT86IG51bWJlciAvLyBObyBzdXBwb3J0IGZvciBhbnkgYnJvd3NlcnMgKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SVENJY2VDYW5kaWRhdGVQYWlyU3RhdHMvYXZhaWxhYmxlSW5jb21pbmdCaXRyYXRlKVxuICAgIH1cbn07XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IFNUQVRTX0lURU1fTkFNRSA9ICd3ZWJydGMtc3RhdHMtY29uZmlnJztcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNFbmFibGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0ludGVydmFsSWQ6IE5vZGVKUy5UaW1lcjtcbiAgICBwcml2YXRlIHN0YXRzSW50ZXJ2YWwgPSAxO1xuICAgIHByaXZhdGUgUE9TVF9VUkw6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgd2VicnRjT2JqID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5TVEFUU19JVEVNX05BTUUpO1xuXG4gICAgICAgIGlmICghIXdlYnJ0Y09iaikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3Qgd2VicnRjU3RhdHNDb25maWc6IFdlYnJ0Y1N0YXRzQ29uZmlnID0gSlNPTi5wYXJzZSh3ZWJydGNPYmopO1xuICAgICAgICAgICAgLy8gd2VicnRjIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG4gICAgICAgICAgICBsb2dnZXIud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KHdlYnJ0Y1N0YXRzQ29uZmlnKSk7XG5cbiAgICAgICAgICAgIHRoaXMuUE9TVF9VUkwgPSB3ZWJydGNTdGF0c0NvbmZpZy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWwgPSB3ZWJydGNTdGF0c0NvbmZpZy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludCgpO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB7XG4gICAgLy8gXCJsb2NhbENhbmRpZGF0ZVwiOiB7XG4gICAgLy8gICAgIFwiaWRcIjogXCJSVENJY2VDYW5kaWRhdGVfL3I0UDF5MlFcIixcbiAgICAvLyAgICAgXCJ0aW1lc3RhbXBcIjogMTYxNjA4MDE1NTYxNyxcbiAgICAvLyAgICAgXCJ0eXBlXCI6IFwibG9jYWwtY2FuZGlkYXRlXCIsXG4gICAgLy8gICAgIFwidHJhbnNwb3J0SWRcIjogXCJSVENUcmFuc3BvcnRfMF8xXCIsXG4gICAgLy8gICAgIFwiaXNSZW1vdGVcIjogZmFsc2UsXG4gICAgLy8gICAgIFwibmV0d29ya1R5cGVcIjogXCJ3aWZpXCIsXG4gICAgLy8gICAgIFwiaXBcIjogXCIxMjMuNDUuNjcuODlcIixcbiAgICAvLyAgICAgXCJwb3J0XCI6IDYzMzQwLFxuICAgIC8vICAgICBcInByb3RvY29sXCI6IFwidWRwXCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlVHlwZVwiOiBcInNyZmx4XCIsXG4gICAgLy8gICAgIFwicHJpb3JpdHlcIjogMTY4NjA1MjYwNyxcbiAgICAvLyAgICAgXCJkZWxldGVkXCI6IGZhbHNlLFxuICAgIC8vICAgICBcInJhd1wiOiBbXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjMzNDU0MTI5MjEgMSB1ZHAgMTY4NjA1MjYwNyAxMjMuNDUuNjcuODkgNjMzNDAgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMS4zMSBycG9ydCA2MzM0MCBnZW5lcmF0aW9uIDAgdWZyYWcgMFp0VCBuZXR3b3JrLWlkIDEgbmV0d29yay1jb3N0IDEwXCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjU4MDk0NDgyIDEgdWRwIDQxODg1Njk1IDk4Ljc2LjU0LjMyIDQ0NDMxIHR5cCByZWxheSByYWRkciAxMjMuNDUuNjcuODkgcnBvcnQgNjMzNDAgZ2VuZXJhdGlvbiAwIHVmcmFnIDBadFQgbmV0d29yay1pZCAxIG5ldHdvcmstY29zdCAxMFwiXG4gICAgLy8gICAgIF1cbiAgICAvLyB9LFxuICAgIC8vIFwicmVtb3RlQ2FuZGlkYXRlXCI6IHtcbiAgICAvLyAgICAgXCJpZFwiOiBcIlJUQ0ljZUNhbmRpZGF0ZV8xWU8xOGdwaFwiLFxuICAgIC8vICAgICBcInRpbWVzdGFtcFwiOiAxNjE2MDgwMTU1NjE3LFxuICAgIC8vICAgICBcInR5cGVcIjogXCJyZW1vdGUtY2FuZGlkYXRlXCIsXG4gICAgLy8gICAgIFwidHJhbnNwb3J0SWRcIjogXCJSVENUcmFuc3BvcnRfMF8xXCIsXG4gICAgLy8gICAgIFwiaXNSZW1vdGVcIjogdHJ1ZSxcbiAgICAvLyAgICAgXCJpcFwiOiBcIjEyLjM0LjU2Ljc4XCIsXG4gICAgLy8gICAgIFwicG9ydFwiOiA2NDk4OSxcbiAgICAvLyAgICAgXCJwcm90b2NvbFwiOiBcInVkcFwiLFxuICAgIC8vICAgICBcImNhbmRpZGF0ZVR5cGVcIjogXCJzcmZseFwiLFxuICAgIC8vICAgICBcInByaW9yaXR5XCI6IDE2Nzk4MTkyNjMsXG4gICAgLy8gICAgIFwiZGVsZXRlZFwiOiBmYWxzZSxcbiAgICAvLyAgICAgXCJyYXdcIjogW1xuICAgIC8vICAgICBcImNhbmRpZGF0ZToxNiAxIFVEUCAxNjc5ODE5MjYzIDEyLjM0LjU2Ljc4IDY0OTg5IHR5cCBzcmZseCByYWRkciAxNzIuMTkuMC4xIHJwb3J0IDY0OTg5XCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjE2IDEgVURQIDE2Nzk4MTkyNjMgMTIuMzQuNTYuNzggNjQ5ODkgdHlwIHNyZmx4IHJhZGRyIDE3Mi4xOS4wLjEgcnBvcnQgNjQ5ODlcIlxuICAgIC8vICAgICBdXG4gICAgLy8gfVxuICAgIC8vIH1cbiAgICAvLyBIYXZlIGJlZW4gdGVzdGVkIGluOlxuICAgIC8vICAgLSBMaW51eCBEZXNrdG9wOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIDg5LjAuNDM4OS45MFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzQuMC4zOTExLjIxOFxuICAgIC8vICAgICAgIC0gRmlyZWZveCA4NlxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgOTEuMC44MjUuMFxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBXaW5kb3dzIERlc2t0b3A6XG4gICAgLy8gICAgICAgLSBDaHJvbWUgODkuMC40Mzg5LjkwXG4gICAgLy8gICAgICAgLSBPcGVyYSA3NC4wLjM5MTEuMjMyXG4gICAgLy8gICAgICAgLSBGaXJlZm94IDg2LjAuMVxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgODkuMC43NzQuNTRcbiAgICAvLyAgICAgICAtIEVsZWN0cm9uIDExLjMuMCAoQ2hyb21pdW0gODcuMC40MjgwLjE0MSlcbiAgICAvLyAgIC0gTWFjT1MgRGVza3RvcDpcbiAgICAvLyAgICAgICAtIENocm9tZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIEZpcmVmb3ggODcuMFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzUuMC4zOTY5LjkzXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSA4OS4wLjc3NC41N1xuICAgIC8vICAgICAgIC0gU2FmYXJpIDE0LjAgKDE0NjEwLjEuMjguMS45KVxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBBbmRyb2lkOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIE1vYmlsZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIE9wZXJhIDYyLjMuMzE0Ni41Nzc2M1xuICAgIC8vICAgICAgIC0gRmlyZWZveCBNb2JpbGUgODYuNi4xXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSBNb2JpbGUgNDYuMDIuNC41MTQ3XG4gICAgLy8gICAgICAgLSBJb25pYyA1XG4gICAgLy8gICAgICAgLSBSZWFjdCBOYXRpdmUgMC42NFxuICAgIC8vICAgLSBpT1M6XG4gICAgLy8gICAgICAgLSBTYWZhcmkgTW9iaWxlXG4gICAgLy8gICAgICAgLSDCv0lvbmljP1xuICAgIC8vICAgICAgIC0gwr9SZWFjdCBOYXRpdmU/XG4gICAgcHVibGljIGdldFNlbGVjdGVkSWNlQ2FuZGlkYXRlSW5mbygpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzdGF0c1JlcG9ydDogYW55ID0gYXdhaXQgdGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5nZXRTdGF0cygpO1xuICAgICAgICAgICAgbGV0IHRyYW5zcG9ydFN0YXQ7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXM6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBzdGF0c1JlcG9ydC5mb3JFYWNoKChzdGF0OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAndHJhbnNwb3J0JyAmJiAocGxhdGZvcm0uaXNDaHJvbWl1bSgpIHx8IHBsYXRmb3JtLmlzU2FmYXJpQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzUmVhY3ROYXRpdmUoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNwb3J0U3RhdCA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCAoc3RhdC50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NhbmRpZGF0ZS1wYWlyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZVBhaXJzLnNldChzdGF0LmlkLCBzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdsb2NhbC1jYW5kaWRhdGUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVzLnNldChzdGF0LmlkLCBzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZW1vdGUtY2FuZGlkYXRlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXMuc2V0KHN0YXQuaWQsIHN0YXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBsZXQgc2VsZWN0ZWRDYW5kaWRhdGVQYWlyO1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydFN0YXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkQ2FuZGlkYXRlUGFpcklkID0gdHJhbnNwb3J0U3RhdC5zZWxlY3RlZENhbmRpZGF0ZVBhaXJJZFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkQ2FuZGlkYXRlUGFpciA9IGNhbmRpZGF0ZVBhaXJzLmdldChzZWxlY3RlZENhbmRpZGF0ZVBhaXJJZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYmFzaWNhbGx5IEZpcmVmb3hcbiAgICAgICAgICAgICAgICBjb25zdCBsZW5ndGggPSBjYW5kaWRhdGVQYWlycy5zaXplO1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZXJhdG9yID0gY2FuZGlkYXRlUGFpcnMudmFsdWVzKCk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyID0gaXRlcmF0b3IubmV4dCgpLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FuZGlkYXRlUGFpclsnc2VsZWN0ZWQnXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRDYW5kaWRhdGVQYWlyID0gY2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbG9jYWxDYW5kaWRhdGVJZCA9IHNlbGVjdGVkQ2FuZGlkYXRlUGFpci5sb2NhbENhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzZWxlY3RlZENhbmRpZGF0ZVBhaXIucmVtb3RlQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlcy5nZXQobG9jYWxDYW5kaWRhdGVJZCk7XG4gICAgICAgICAgICBpZiAoISFmaW5hbExvY2FsQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjYW5kID0gY2FuZExpc3QuZmlsdGVyKChjOiBSVENJY2VDYW5kaWRhdGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICghIWMuY2FuZGlkYXRlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwKSA+PSAwIHx8IGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5hZGRyZXNzKSA+PSAwKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnQpID49IDApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgYyBvZiBjYW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3LnB1c2goYy5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIGxvY2FsIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9IHJlbW90ZUNhbmRpZGF0ZXMuZ2V0KHJlbW90ZUNhbmRpZGF0ZUlkKTtcbiAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXApID49IDAgfHwgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5hZGRyZXNzKSA+PSAwKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wb3J0KSA+PSAwKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZS5yYXcgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjIG9mIGNhbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3LnB1c2goYy5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSByZW1vdGUgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGU6IGZpbmFsTG9jYWxDYW5kaWRhdGUsXG4gICAgICAgICAgICAgICAgcmVtb3RlQ2FuZGlkYXRlOiBmaW5hbFJlbW90ZUNhbmRpZGF0ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBzdG9wV2ViUnRjU3RhdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLndlYlJ0Y1N0YXRzRW5hYmxlZCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLndlYlJ0Y1N0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICBsb2dnZXIud2FybignV2ViUnRjIHN0YXRzIHN0b3BwZWQgZm9yIGRpc3Bvc2VkIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgc2VuZFN0YXRzKHVybDogc3RyaW5nLCByZXNwb25zZTogSlNPTlN0YXRzUmVzcG9uc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZ3VyYXRpb246IFJlcXVlc3RJbml0ID0ge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgJ0NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJ1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGF3YWl0IGZldGNoKHVybCwgY29uZmlndXJhdGlvbik7XG5cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgc2VuZFN0YXRzIGVycm9yOiAke0pTT04uc3RyaW5naWZ5KGVycm9yKX1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgc2VuZFN0YXRzVG9IdHRwRW5kcG9pbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB3ZWJydGNTdGF0czogSVdlYnJ0Y1N0YXRzID0gYXdhaXQgdGhpcy5nZXRDb21tb25TdGF0cygpO1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSB0aGlzLmdlbmVyYXRlSlNPTlN0YXRzUmVzcG9uc2Uod2VicnRjU3RhdHMpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kU3RhdHModGhpcy5QT1NUX1VSTCwgcmVzcG9uc2UpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZyhlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBIYXZlIGJlZW4gdGVzdGVkIGluOlxuICAgIC8vICAgLSBMaW51eCBEZXNrdG9wOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIDg5LjAuNDM4OS45MFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzQuMC4zOTExLjIxOFxuICAgIC8vICAgICAgIC0gRmlyZWZveCA4NlxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgOTEuMC44MjUuMFxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBXaW5kb3dzIERlc2t0b3A6XG4gICAgLy8gICAgICAgLSBDaHJvbWUgODkuMC40Mzg5LjkwXG4gICAgLy8gICAgICAgLSBPcGVyYSA3NC4wLjM5MTEuMjMyXG4gICAgLy8gICAgICAgLSBGaXJlZm94IDg2LjAuMVxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgODkuMC43NzQuNTRcbiAgICAvLyAgICAgICAtIEVsZWN0cm9uIDExLjMuMCAoQ2hyb21pdW0gODcuMC40MjgwLjE0MSlcbiAgICAvLyAgIC0gTWFjT1MgRGVza3RvcDpcbiAgICAvLyAgICAgICAtIENocm9tZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIE9wZXJhIDc1LjAuMzk2OS45M1xuICAgIC8vICAgICAgIC0gRmlyZWZveCA4Ny4wXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSA4OS4wLjc3NC41N1xuICAgIC8vICAgICAgIC0gU2FmYXJpIDE0LjAgKDE0NjEwLjEuMjguMS45KVxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBBbmRyb2lkOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIE1vYmlsZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIE9wZXJhIDYyLjMuMzE0Ni41Nzc2M1xuICAgIC8vICAgICAgIC0gRmlyZWZveCBNb2JpbGUgODYuNi4xXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSBNb2JpbGUgNDYuMDIuNC41MTQ3XG4gICAgLy8gICAgICAgLSBJb25pYyA1XG4gICAgLy8gICAgICAgLSBSZWFjdCBOYXRpdmUgMC42NFxuICAgIC8vICAgLSBpT1M6XG4gICAgLy8gICAgICAgLSBTYWZhcmkgTW9iaWxlXG4gICAgLy8gICAgICAgLSDCv0lvbmljP1xuICAgIC8vICAgICAgIC0gwr9SZWFjdCBOYXRpdmU/XG4gICAgcHVibGljIGFzeW5jIGdldENvbW1vblN0YXRzKCk6IFByb21pc2U8SVdlYnJ0Y1N0YXRzPiB7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgY29uc3Qgc3RhdHNSZXBvcnQ6IGFueSA9IGF3YWl0IHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuZ2V0U3RhdHMoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlOiBJV2VicnRjU3RhdHMgPSB0aGlzLmdldFdlYlJ0Y1N0YXRzUmVzcG9uc2VPdXRsaW5lKCk7XG4gICAgICAgICAgICBjb25zdCB2aWRlb1RyYWNrU3RhdHMgPSBbJ2ZyYW1lc1JlY2VpdmVkJywgJ2ZyYW1lc0Ryb3BwZWQnLCAnZnJhbWVzU2VudCcsICdmcmFtZUhlaWdodCcsICdmcmFtZVdpZHRoJ107XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyU3RhdHMgPSBbJ2F2YWlsYWJsZU91dGdvaW5nQml0cmF0ZScsICdjdXJyZW50Um91bmRUcmlwVGltZSddO1xuXG4gICAgICAgICAgICBzdGF0c1JlcG9ydC5mb3JFYWNoKChzdGF0OiBhbnkpID0+IHtcblxuICAgICAgICAgICAgICAgIGxldCBtZWRpYVR5cGUgPSBzdGF0Lm1lZGlhVHlwZSAhPSBudWxsID8gc3RhdC5tZWRpYVR5cGUgOiBzdGF0LmtpbmQ7XG4gICAgICAgICAgICAgICAgY29uc3QgYWRkU3RhdCA9IChkaXJlY3Rpb246IHN0cmluZywga2V5OiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRba2V5XSAhPSBudWxsICYmIHJlc3BvbnNlW2RpcmVjdGlvbl0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtZWRpYVR5cGUgJiYgKHZpZGVvVHJhY2tTdGF0cy5pbmRleE9mKGtleSkgPiAtMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVR5cGUgPSAndmlkZW8nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpcmVjdGlvbiAhPSBudWxsICYmIG1lZGlhVHlwZSAhPSBudWxsICYmIGtleSAhPSBudWxsICYmIHJlc3BvbnNlW2RpcmVjdGlvbl1bbWVkaWFUeXBlXSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VbZGlyZWN0aW9uXVttZWRpYVR5cGVdW2tleV0gPSBOdW1iZXIoc3RhdFtrZXldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihkaXJlY3Rpb24gIT0gbnVsbCAmJiBrZXkgIT0gbnVsbCAmJiBjYW5kaWRhdGVQYWlyU3RhdHMuaW5jbHVkZXMoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbmRpZGF0ZS1wYWlyLXN0YXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VbZGlyZWN0aW9uXVtrZXldID0gTnVtYmVyKHN0YXRba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHN0YXQudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3V0Ym91bmQtcnRwXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdieXRlc1NlbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ291dGJvdW5kJywgJ3BhY2tldHNTZW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdmcmFtZXNFbmNvZGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICduYWNrQ291bnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ291dGJvdW5kJywgJ2ZpckNvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdwbGlDb3VudCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnb3V0Ym91bmQnLCAncXBTdW0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW5ib3VuZC1ydHBcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnYnl0ZXNSZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdwYWNrZXRzUmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAncGFja2V0c0xvc3QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnaml0dGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdpbmJvdW5kJywgJ2ZyYW1lc0RlY29kZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnbmFja0NvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdpbmJvdW5kJywgJ2ZpckNvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdpbmJvdW5kJywgJ3BsaUNvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndHJhY2snOlxuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdqaXR0ZXJCdWZmZXJEZWxheScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdmcmFtZXNSZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnb3V0Ym91bmQnLCAnZnJhbWVzRHJvcHBlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnb3V0Ym91bmQnLCAnZnJhbWVzU2VudCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCh0aGlzLnN0cmVhbS5pc0xvY2FsKCkgPyAnb3V0Ym91bmQnIDogJ2luYm91bmQnLCAnZnJhbWVIZWlnaHQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQodGhpcy5zdHJlYW0uaXNMb2NhbCgpID8gJ291dGJvdW5kJyA6ICdpbmJvdW5kJywgJ2ZyYW1lV2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdjYW5kaWRhdGUtcGFpcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdjYW5kaWRhdGVwYWlyJywgJ2N1cnJlbnRSb3VuZFRyaXBUaW1lJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdjYW5kaWRhdGVwYWlyJywgJ2F2YWlsYWJsZU91dGdvaW5nQml0cmF0ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBjYW5kaWRhdGVwYWlyIGZyb20gcmVzcG9uc2UgaWYgbnVsbFxuICAgICAgICAgICAgaWYoIXJlc3BvbnNlPy5jYW5kaWRhdGVwYWlyIHx8IE9iamVjdC5rZXlzKDxPYmplY3Q+cmVzcG9uc2UuY2FuZGlkYXRlcGFpcikubGVuZ3RoID09PSAwKXtcbiAgICAgICAgICAgICAgICBkZWxldGUgcmVzcG9uc2UuY2FuZGlkYXRlcGFpcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlSlNPTlN0YXRzUmVzcG9uc2Uoc3RhdHM6IElXZWJydGNTdGF0cyk6IEpTT05TdGF0c1Jlc3BvbnNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICdAdGltZXN0YW1wJzogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgICAgcGFydGljaXBhbnRfaWQ6IHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uZGF0YSxcbiAgICAgICAgICAgIHNlc3Npb25faWQ6IHRoaXMuc3RyZWFtLnNlc3Npb24uc2Vzc2lvbklkLFxuICAgICAgICAgICAgcGxhdGZvcm06IHBsYXRmb3JtLmdldE5hbWUoKSxcbiAgICAgICAgICAgIHBsYXRmb3JtX2Rlc2NyaXB0aW9uOiBwbGF0Zm9ybS5nZXREZXNjcmlwdGlvbigpLFxuICAgICAgICAgICAgc3RyZWFtOiAnd2ViUlRDJyxcbiAgICAgICAgICAgIHdlYnJ0Y19zdGF0czogc3RhdHNcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFdlYlJ0Y1N0YXRzUmVzcG9uc2VPdXRsaW5lKCk6IElXZWJydGNTdGF0cyB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgb3V0Ym91bmQ6IHtcbiAgICAgICAgICAgICAgICAgICAgYXVkaW86IHt9LFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzoge31cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZXBhaXI6IHt9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBpbmJvdW5kOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHt9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxufSJdfQ==
|