require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice var len = b64.length placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 // base64 is 4/3 + up to two characters of the original data arr = new Arr(b64.length * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? b64.length - 4 : b64.length var L = 0 function push (v) { arr[L++] = v } for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) push((tmp & 0xFF0000) >> 16) push((tmp & 0xFF00) >> 8) push(tmp & 0xFF) } if (placeHolders === 2) { tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) push(tmp & 0xFF) } else if (placeHolders === 1) { tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) push((tmp >> 8) & 0xFF) push(tmp & 0xFF) } return arr } function uint8ToBase64 (uint8) { var i, extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes output = "", temp, length function encode (num) { return lookup.charAt(num) } function tripletToBase64 (num) { return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) } // go through the array every three bytes, we'll deal with trailing stuff later for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) output += tripletToBase64(temp) } // pad the end with zeros, but make sure to not forget the extra bytes switch (extraBytes) { case 1: temp = uint8[uint8.length - 1] output += encode(temp >> 2) output += encode((temp << 4) & 0x3F) output += '==' break case 2: temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) output += encode(temp >> 10) output += encode((temp >> 4) & 0x3F) output += encode((temp << 2) & 0x3F) output += '=' break } return output } exports.toByteArray = b64ToByteArray exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) },{}],2:[function(require,module,exports){ },{}],3:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],4:[function(require,module,exports){ (function (global){ /*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ /* eslint-disable no-proto */ 'use strict' var base64 = require('base64-js') var ieee754 = require('ieee754') var isArray = require('isarray') exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 // not used by this implementation var rootParent = {} /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property * on objects. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() function typedArraySupport () { function Bar () {} try { var arr = new Uint8Array(1) arr.foo = function () { return 42 } arr.constructor = Bar return arr.foo() === 42 && // typed array instances can be augmented arr.constructor === Bar && // constructor can be set typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } /** * Class: Buffer * ============= * * The Buffer constructor returns instances of `Uint8Array` that are augmented * with function properties for all the node `Buffer` API functions. We use * `Uint8Array` so that square bracket notation works as expected -- it returns * a single octet. * * By augmenting the instances, we can avoid modifying the `Uint8Array` * prototype. */ function Buffer (arg) { if (!(this instanceof Buffer)) { // Avoid going through an ArgumentsAdaptorTrampoline in the common case. if (arguments.length > 1) return new Buffer(arg, arguments[1]) return new Buffer(arg) } if (!Buffer.TYPED_ARRAY_SUPPORT) { this.length = 0 this.parent = undefined } // Common case. if (typeof arg === 'number') { return fromNumber(this, arg) } // Slightly less common case. if (typeof arg === 'string') { return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') } // Unusual. return fromObject(this, arg) } function fromNumber (that, length) { that = allocate(that, length < 0 ? 0 : checked(length) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < length; i++) { that[i] = 0 } } return that } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' // Assumption: byteLength() return value is always < kMaxLength. var length = byteLength(string, encoding) | 0 that = allocate(that, length) that.write(string, encoding) return that } function fromObject (that, object) { if (Buffer.isBuffer(object)) return fromBuffer(that, object) if (isArray(object)) return fromArray(that, object) if (object == null) { throw new TypeError('must start with number, buffer, array or string') } if (typeof ArrayBuffer !== 'undefined') { if (object.buffer instanceof ArrayBuffer) { return fromTypedArray(that, object) } if (object instanceof ArrayBuffer) { return fromArrayBuffer(that, object) } } if (object.length) return fromArrayLike(that, object) return fromJsonObject(that, object) } function fromBuffer (that, buffer) { var length = checked(buffer.length) | 0 that = allocate(that, length) buffer.copy(that, 0, 0, length) return that } function fromArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Duplicate of fromArray() to keep fromArray() monomorphic. function fromTypedArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) // Truncating the elements is probably not what people expect from typed // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior // of the old Buffer constructor. for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayBuffer (that, array) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance array.byteLength that = Buffer._augment(new Uint8Array(array)) } else { // Fallback: Return an object instance of the Buffer class that = fromTypedArray(that, new Uint8Array(array)) } return that } function fromArrayLike (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. // Returns a zero-length buffer for inputs that don't conform to the spec. function fromJsonObject (that, object) { var array var length = 0 if (object.type === 'Buffer' && isArray(object.data)) { array = object.data length = checked(array.length) | 0 } that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array } else { // pre-set for values that may exist in the future Buffer.prototype.length = undefined Buffer.prototype.parent = undefined } function allocate (that, length) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = Buffer._augment(new Uint8Array(length)) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that.length = length that._isBuffer = true } var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 if (fromPool) that.parent = rootParent return that } function checked (length) { // Note: cannot use `length < kMaxLength` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength()) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength().toString(16) + ' bytes') } return length | 0 } function SlowBuffer (subject, encoding) { if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) var buf = new Buffer(subject, encoding) delete buf.parent return buf } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length var i = 0 var len = Math.min(x, y) while (i < len) { if (a[i] !== b[i]) break ++i } if (i !== len) { x = a[i] y = b[i] } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'raw': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } } Buffer.concat = function concat (list, length) { if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') if (list.length === 0) { return new Buffer(0) } var i if (length === undefined) { length = 0 for (i = 0; i < list.length; i++) { length += list[i].length } } var buf = new Buffer(length) var pos = 0 for (i = 0; i < list.length; i++) { var item = list[i] item.copy(buf, pos) pos += item.length } return buf } function byteLength (string, encoding) { if (typeof string !== 'string') string = '' + string var len = string.length if (len === 0) return 0 // Use a for loop to avoid recursion var loweredCase = false for (;;) { switch (encoding) { case 'ascii': case 'binary': // Deprecated case 'raw': case 'raws': return len case 'utf8': case 'utf-8': return utf8ToBytes(string).length case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return len * 2 case 'hex': return len >>> 1 case 'base64': return base64ToBytes(string).length default: if (loweredCase) return utf8ToBytes(string).length // assume utf8 encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.byteLength = byteLength function slowToString (encoding, start, end) { var loweredCase = false start = start | 0 end = end === undefined || end === Infinity ? this.length : end | 0 if (!encoding) encoding = 'utf8' if (start < 0) start = 0 if (end > this.length) end = this.length if (end <= start) return '' while (true) { switch (encoding) { case 'hex': return hexSlice(this, start, end) case 'utf8': case 'utf-8': return utf8Slice(this, start, end) case 'ascii': return asciiSlice(this, start, end) case 'binary': return binarySlice(this, start, end) case 'base64': return base64Slice(this, start, end) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return utf16leSlice(this, start, end) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase() loweredCase = true } } } Buffer.prototype.toString = function toString () { var length = this.length | 0 if (length === 0) return '' if (arguments.length === 0) return utf8Slice(this, 0, length) return slowToString.apply(this, arguments) } Buffer.prototype.equals = function equals (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return true return Buffer.compare(this, b) === 0 } Buffer.prototype.inspect = function inspect () { var str = '' var max = exports.INSPECT_MAX_BYTES if (this.length > 0) { str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') if (this.length > max) str += ' ... ' } return '' } Buffer.prototype.compare = function compare (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return 0 return Buffer.compare(this, b) } Buffer.prototype.indexOf = function indexOf (val, byteOffset) { if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff else if (byteOffset < -0x80000000) byteOffset = -0x80000000 byteOffset >>= 0 if (this.length === 0) return -1 if (byteOffset >= this.length) return -1 // Negative offsets start from the end of the buffer if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) if (typeof val === 'string') { if (val.length === 0) return -1 // special case: looking for empty string always fails return String.prototype.indexOf.call(this, val, byteOffset) } if (Buffer.isBuffer(val)) { return arrayIndexOf(this, val, byteOffset) } if (typeof val === 'number') { if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { return Uint8Array.prototype.indexOf.call(this, val, byteOffset) } return arrayIndexOf(this, [ val ], byteOffset) } function arrayIndexOf (arr, val, byteOffset) { var foundIndex = -1 for (var i = 0; byteOffset + i < arr.length; i++) { if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { if (foundIndex === -1) foundIndex = i if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex } else { foundIndex = -1 } } return -1 } throw new TypeError('val must be string, number or Buffer') } // `get` is deprecated Buffer.prototype.get = function get (offset) { console.log('.get() is deprecated. Access using array indexes instead.') return this.readUInt8(offset) } // `set` is deprecated Buffer.prototype.set = function set (v, offset) { console.log('.set() is deprecated. Access using array indexes instead.') return this.writeUInt8(v, offset) } function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 var remaining = buf.length - offset if (!length) { length = remaining } else { length = Number(length) if (length > remaining) { length = remaining } } // must be an even number of digits var strLen = string.length if (strLen % 2 !== 0) throw new Error('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var parsed = parseInt(string.substr(i * 2, 2), 16) if (isNaN(parsed)) throw new Error('Invalid hex string') buf[offset + i] = parsed } return i } function utf8Write (buf, string, offset, length) { return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) } function asciiWrite (buf, string, offset, length) { return blitBuffer(asciiToBytes(string), buf, offset, length) } function binaryWrite (buf, string, offset, length) { return asciiWrite(buf, string, offset, length) } function base64Write (buf, string, offset, length) { return blitBuffer(base64ToBytes(string), buf, offset, length) } function ucs2Write (buf, string, offset, length) { return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { encoding = 'utf8' length = this.length offset = 0 // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { encoding = offset length = this.length offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { offset = offset | 0 if (isFinite(length)) { length = length | 0 if (encoding === undefined) encoding = 'utf8' } else { encoding = length length = undefined } // legacy write(string, encoding, offset, length) - remove in v0.13 } else { var swap = encoding encoding = offset offset = length | 0 length = swap } var remaining = this.length - offset if (length === undefined || length > remaining) length = remaining if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('attempt to write outside buffer bounds') } if (!encoding) encoding = 'utf8' var loweredCase = false for (;;) { switch (encoding) { case 'hex': return hexWrite(this, string, offset, length) case 'utf8': case 'utf-8': return utf8Write(this, string, offset, length) case 'ascii': return asciiWrite(this, string, offset, length) case 'binary': return binaryWrite(this, string, offset, length) case 'base64': // Warning: maxLength not taken into account in base64Write return base64Write(this, string, offset, length) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return ucs2Write(this, string, offset, length) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } } function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) } else { return base64.fromByteArray(buf.slice(start, end)) } } function utf8Slice (buf, start, end) { end = Math.min(buf.length, end) var res = [] var i = start while (i < end) { var firstByte = buf[i] var codePoint = null var bytesPerSequence = (firstByte > 0xEF) ? 4 : (firstByte > 0xDF) ? 3 : (firstByte > 0xBF) ? 2 : 1 if (i + bytesPerSequence <= end) { var secondByte, thirdByte, fourthByte, tempCodePoint switch (bytesPerSequence) { case 1: if (firstByte < 0x80) { codePoint = firstByte } break case 2: secondByte = buf[i + 1] if ((secondByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) if (tempCodePoint > 0x7F) { codePoint = tempCodePoint } } break case 3: secondByte = buf[i + 1] thirdByte = buf[i + 2] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { codePoint = tempCodePoint } } break case 4: secondByte = buf[i + 1] thirdByte = buf[i + 2] fourthByte = buf[i + 3] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { codePoint = tempCodePoint } } } } if (codePoint === null) { // we did not generate a valid codePoint so insert a // replacement char (U+FFFD) and advance only 1 byte codePoint = 0xFFFD bytesPerSequence = 1 } else if (codePoint > 0xFFFF) { // encode to utf16 (surrogate pair dance) codePoint -= 0x10000 res.push(codePoint >>> 10 & 0x3FF | 0xD800) codePoint = 0xDC00 | codePoint & 0x3FF } res.push(codePoint) i += bytesPerSequence } return decodeCodePointsArray(res) } // Based on http://stackoverflow.com/a/22747272/680742, the browser with // the lowest limit is Chrome, with 0x10000 args. // We go 1 magnitude less, for safety var MAX_ARGUMENTS_LENGTH = 0x1000 function decodeCodePointsArray (codePoints) { var len = codePoints.length if (len <= MAX_ARGUMENTS_LENGTH) { return String.fromCharCode.apply(String, codePoints) // avoid extra slice() } // Decode in chunks to avoid "call stack size exceeded". var res = '' var i = 0 while (i < len) { res += String.fromCharCode.apply( String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) ) } return res } function asciiSlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { ret += String.fromCharCode(buf[i] & 0x7F) } return ret } function binarySlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; i++) { ret += String.fromCharCode(buf[i]) } return ret } function hexSlice (buf, start, end) { var len = buf.length if (!start || start < 0) start = 0 if (!end || end < 0 || end > len) end = len var out = '' for (var i = start; i < end; i++) { out += toHex(buf[i]) } return out } function utf16leSlice (buf, start, end) { var bytes = buf.slice(start, end) var res = '' for (var i = 0; i < bytes.length; i += 2) { res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) } return res } Buffer.prototype.slice = function slice (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { start += len if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len if (end < 0) end = 0 } else if (end > len) { end = len } if (end < start) end = start var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { newBuf = Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) for (var i = 0; i < sliceLen; i++) { newBuf[i] = this[i + start] } } if (newBuf.length) newBuf.parent = this.parent || this return newBuf } /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } return val } Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { checkOffset(offset, byteLength, this.length) } var val = this[offset + --byteLength] var mul = 1 while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul } return val } Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) } Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) } Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var i = byteLength var mul = 1 var val = this[offset + --i] while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset] | (this[offset + 1] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset + 1] | (this[offset] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) } Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) } Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } function checkInt (buf, value, offset, ext, max, min) { if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') if (value > max || value < min) throw new RangeError('value is out of bounds') if (offset + ext > buf.length) throw new RangeError('index out of range') } Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) var mul = 1 var i = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) var i = byteLength - 1 var mul = 1 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = (value & 0xff) return offset + 1 } function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } } Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset + 3] = (value >>> 24) this[offset + 2] = (value >>> 16) this[offset + 1] = (value >>> 8) this[offset] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = 0 var mul = 1 var sub = value < 0 ? 1 : 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = byteLength - 1 var mul = 1 var sub = value < 0 ? 1 : 0 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) if (value < 0) value = 0xff + value + 1 this[offset] = (value & 0xff) return offset + 1 } Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) this[offset + 2] = (value >>> 16) this[offset + 3] = (value >>> 24) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (value < 0) value = 0xffffffff + value + 1 if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } function checkIEEE754 (buf, value, offset, ext, max, min) { if (value > max || value < min) throw new RangeError('value is out of bounds') if (offset + ext > buf.length) throw new RangeError('index out of range') if (offset < 0) throw new RangeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (!start) start = 0 if (!end && end !== 0) end = this.length if (targetStart >= target.length) targetStart = target.length if (!targetStart) targetStart = 0 if (end > 0 && end < start) end = start // Copy 0 bytes; we're done if (end === start) return 0 if (target.length === 0 || this.length === 0) return 0 // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length if (target.length - targetStart < end - start) { end = target.length - targetStart + start } var len = end - start var i if (this === target && start < targetStart && targetStart < end) { // descending copy from end for (i = len - 1; i >= 0; i--) { target[i + targetStart] = this[i + start] } } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { // ascending copy from start for (i = 0; i < len; i++) { target[i + targetStart] = this[i + start] } } else { target._set(this.subarray(start, start + len), targetStart) } return len } // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length if (end < start) throw new RangeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') if (end < 0 || end > this.length) throw new RangeError('end out of bounds') var i if (typeof value === 'number') { for (i = start; i < end; i++) { this[i] = value } } else { var bytes = utf8ToBytes(value.toString()) var len = bytes.length for (i = start; i < end; i++) { this[i] = bytes[i % len] } } return this } /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. */ Buffer.prototype.toArrayBuffer = function toArrayBuffer () { if (typeof Uint8Array !== 'undefined') { if (Buffer.TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer } else { var buf = new Uint8Array(this.length) for (var i = 0, len = buf.length; i < len; i += 1) { buf[i] = this[i] } return buf.buffer } } else { throw new TypeError('Buffer.toArrayBuffer not supported in this browser') } } // HELPER FUNCTIONS // ================ var BP = Buffer.prototype /** * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ Buffer._augment = function _augment (arr) { arr.constructor = Buffer arr._isBuffer = true // save reference to original Uint8Array set method before overwriting arr._set = arr.set // deprecated arr.get = BP.get arr.set = BP.set arr.write = BP.write arr.toString = BP.toString arr.toLocaleString = BP.toString arr.toJSON = BP.toJSON arr.equals = BP.equals arr.compare = BP.compare arr.indexOf = BP.indexOf arr.copy = BP.copy arr.slice = BP.slice arr.readUIntLE = BP.readUIntLE arr.readUIntBE = BP.readUIntBE arr.readUInt8 = BP.readUInt8 arr.readUInt16LE = BP.readUInt16LE arr.readUInt16BE = BP.readUInt16BE arr.readUInt32LE = BP.readUInt32LE arr.readUInt32BE = BP.readUInt32BE arr.readIntLE = BP.readIntLE arr.readIntBE = BP.readIntBE arr.readInt8 = BP.readInt8 arr.readInt16LE = BP.readInt16LE arr.readInt16BE = BP.readInt16BE arr.readInt32LE = BP.readInt32LE arr.readInt32BE = BP.readInt32BE arr.readFloatLE = BP.readFloatLE arr.readFloatBE = BP.readFloatBE arr.readDoubleLE = BP.readDoubleLE arr.readDoubleBE = BP.readDoubleBE arr.writeUInt8 = BP.writeUInt8 arr.writeUIntLE = BP.writeUIntLE arr.writeUIntBE = BP.writeUIntBE arr.writeUInt16LE = BP.writeUInt16LE arr.writeUInt16BE = BP.writeUInt16BE arr.writeUInt32LE = BP.writeUInt32LE arr.writeUInt32BE = BP.writeUInt32BE arr.writeIntLE = BP.writeIntLE arr.writeIntBE = BP.writeIntBE arr.writeInt8 = BP.writeInt8 arr.writeInt16LE = BP.writeInt16LE arr.writeInt16BE = BP.writeInt16BE arr.writeInt32LE = BP.writeInt32LE arr.writeInt32BE = BP.writeInt32BE arr.writeFloatLE = BP.writeFloatLE arr.writeFloatBE = BP.writeFloatBE arr.writeDoubleLE = BP.writeDoubleLE arr.writeDoubleBE = BP.writeDoubleBE arr.fill = BP.fill arr.inspect = BP.inspect arr.toArrayBuffer = BP.toArrayBuffer return arr } var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') // Node converts strings with length < 2 to '' if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' } return str } function stringtrim (str) { if (str.trim) return str.trim() return str.replace(/^\s+|\s+$/g, '') } function toHex (n) { if (n < 16) return '0' + n.toString(16) return n.toString(16) } function utf8ToBytes (string, units) { units = units || Infinity var codePoint var length = string.length var leadSurrogate = null var bytes = [] for (var i = 0; i < length; i++) { codePoint = string.charCodeAt(i) // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (!leadSurrogate) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } // valid lead leadSurrogate = codePoint continue } // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) leadSurrogate = codePoint continue } // valid surrogate pair codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) } leadSurrogate = null // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break bytes.push(codePoint) } else if (codePoint < 0x800) { if ((units -= 2) < 0) break bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x110000) { if ((units -= 4) < 0) break bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else { throw new Error('Invalid code point') } } return bytes } function asciiToBytes (str) { var byteArray = [] for (var i = 0; i < str.length; i++) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) } return byteArray } function utf16leToBytes (str, units) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; i++) { if ((units -= 2) < 0) break c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 byteArray.push(lo) byteArray.push(hi) } return byteArray } function base64ToBytes (str) { return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; i++) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"base64-js":1,"ieee754":6,"isarray":5}],5:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; },{}],6:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = (nBytes * 8) - mLen - 1 var eMax = (1 << eLen) - 1 var eBias = eMax >> 1 var nBits = -7 var i = isLE ? (nBytes - 1) : 0 var d = isLE ? -1 : 1 var s = buffer[offset + i] i += d e = s & ((1 << (-nBits)) - 1) s >>= (-nBits) nBits += eLen for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} m = e & ((1 << (-nBits)) - 1) e >>= (-nBits) nBits += mLen for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { e = 1 - eBias } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { m = m + Math.pow(2, mLen) e = e - eBias } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) } exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { var e, m, c var eLen = (nBytes * 8) - mLen - 1 var eMax = (1 << eLen) - 1 var eBias = eMax >> 1 var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) var i = isLE ? 0 : (nBytes - 1) var d = isLE ? 1 : -1 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 value = Math.abs(value) if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0 e = eMax } else { e = Math.floor(Math.log(value) / Math.LN2) if (value * (c = Math.pow(2, -e)) < 1) { e-- c *= 2 } if (e + eBias >= 1) { value += rt / c } else { value += rt * Math.pow(2, 1 - eBias) } if (value * c >= 2) { e++ c /= 2 } if (e + eBias >= eMax) { m = 0 e = eMax } else if (e + eBias >= 1) { m = ((value * c) - 1) * Math.pow(2, mLen) e = e + eBias } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) e = 0 } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} e = (e << mLen) | m eLen += mLen for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128 } },{}],7:[function(require,module,exports){ (function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename){ /* * SystemJS v0.20.19 Dev */ (function () { 'use strict'; /* * Environment */ var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; var isNode = typeof process !== 'undefined' && process.versions && process.versions.node; var isWindows = typeof process !== 'undefined' && typeof process.platform === 'string' && process.platform.match(/^win/); var envGlobal = typeof self !== 'undefined' ? self : global; /* * Simple Symbol() shim */ var hasSymbol = typeof Symbol !== 'undefined'; function createSymbol (name) { return hasSymbol ? Symbol() : '@@' + name; } /* * Environment baseURI */ var baseURI; // environent baseURI detection if (typeof document != 'undefined' && document.getElementsByTagName) { baseURI = document.baseURI; if (!baseURI) { var bases = document.getElementsByTagName('base'); baseURI = bases[0] && bases[0].href || window.location.href; } } else if (typeof location != 'undefined') { baseURI = location.href; } // sanitize out the hash and querystring if (baseURI) { baseURI = baseURI.split('#')[0].split('?')[0]; var slashIndex = baseURI.lastIndexOf('/'); if (slashIndex !== -1) baseURI = baseURI.substr(0, slashIndex + 1); } else if (typeof process !== 'undefined' && process.cwd) { baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd(); if (isWindows) baseURI = baseURI.replace(/\\/g, '/'); } else { throw new TypeError('No environment baseURI'); } // ensure baseURI has trailing "/" if (baseURI[baseURI.length - 1] !== '/') baseURI += '/'; /* * LoaderError with chaining for loader stacks */ var errArgs = new Error(0, '_').fileName == '_'; function LoaderError__Check_error_message_for_loader_stack (childErr, newMessage) { // Convert file:/// URLs to paths in Node if (!isBrowser) newMessage = newMessage.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, ''); var message = (childErr.message || childErr) + '\n ' + newMessage; var err; if (errArgs && childErr.fileName) err = new Error(message, childErr.fileName, childErr.lineNumber); else err = new Error(message); var stack = childErr.originalErr ? childErr.originalErr.stack : childErr.stack; if (isNode) // node doesn't show the message otherwise err.stack = message + '\n ' + stack; else err.stack = stack; err.originalErr = childErr.originalErr || childErr; return err; } /* * Optimized URL normalization assuming a syntax-valid URL parent */ function throwResolveError (relUrl, parentUrl) { throw new RangeError('Unable to resolve "' + relUrl + '" to ' + parentUrl); } function resolveIfNotPlain (relUrl, parentUrl) { relUrl = relUrl.trim(); var parentProtocol = parentUrl && parentUrl.substr(0, parentUrl.indexOf(':') + 1); var firstChar = relUrl[0]; var secondChar = relUrl[1]; // protocol-relative if (firstChar === '/' && secondChar === '/') { if (!parentProtocol) throwResolveError(relUrl, parentUrl); return parentProtocol + relUrl; } // relative-url else if (firstChar === '.' && (secondChar === '/' || secondChar === '.' && (relUrl[2] === '/' || relUrl.length === 2 && (relUrl += '/')) || relUrl.length === 1 && (relUrl += '/')) || firstChar === '/') { var parentIsPlain = !parentProtocol || parentUrl[parentProtocol.length] !== '/'; // read pathname from parent if a URL // pathname taken to be part after leading "/" var pathname; if (parentIsPlain) { // resolving to a plain parent -> skip standard URL prefix, and treat entire parent as pathname if (parentUrl === undefined) throwResolveError(relUrl, parentUrl); pathname = parentUrl; } else if (parentUrl[parentProtocol.length + 1] === '/') { // resolving to a :// so we need to read out the auth and host if (parentProtocol !== 'file:') { pathname = parentUrl.substr(parentProtocol.length + 2); pathname = pathname.substr(pathname.indexOf('/') + 1); } else { pathname = parentUrl.substr(8); } } else { // resolving to :/ so pathname is the /... part pathname = parentUrl.substr(parentProtocol.length + 1); } if (firstChar === '/') { if (parentIsPlain) throwResolveError(relUrl, parentUrl); else return parentUrl.substr(0, parentUrl.length - pathname.length - 1) + relUrl; } // join together and split for removal of .. and . segments // looping the string instead of anything fancy for perf reasons // '../../../../../z' resolved to 'x/y' is just 'z' regardless of parentIsPlain var segmented = pathname.substr(0, pathname.lastIndexOf('/') + 1) + relUrl; var output = []; var segmentIndex = -1; for (var i = 0; i < segmented.length; i++) { // busy reading a segment - only terminate on '/' if (segmentIndex !== -1) { if (segmented[i] === '/') { output.push(segmented.substring(segmentIndex, i + 1)); segmentIndex = -1; } continue; } // new segment - check if it is relative if (segmented[i] === '.') { // ../ segment if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i + 2 === segmented.length)) { output.pop(); i += 2; } // ./ segment else if (segmented[i + 1] === '/' || i + 1 === segmented.length) { i += 1; } else { // the start of a new segment as below segmentIndex = i; continue; } // this is the plain URI backtracking error (../, package:x -> error) if (parentIsPlain && output.length === 0) throwResolveError(relUrl, parentUrl); continue; } // it is the start of a new segment segmentIndex = i; } // finish reading out the last segment if (segmentIndex !== -1) output.push(segmented.substr(segmentIndex)); return parentUrl.substr(0, parentUrl.length - pathname.length) + output.join(''); } // sanitizes and verifies (by returning undefined if not a valid URL-like form) // Windows filepath compatibility is an added convenience here var protocolIndex = relUrl.indexOf(':'); if (protocolIndex !== -1) { if (isNode) { // C:\x becomes file:///c:/x (we don't support C|\x) if (relUrl[1] === ':' && relUrl[2] === '\\' && relUrl[0].match(/[a-z]/i)) return 'file:///' + relUrl.replace(/\\/g, '/'); } return relUrl; } } var resolvedPromise$1 = Promise.resolve(); /* * Simple Array values shim */ function arrayValues (arr) { if (arr.values) return arr.values(); if (typeof Symbol === 'undefined' || !Symbol.iterator) throw new Error('Symbol.iterator not supported in this browser'); var iterable = {}; iterable[Symbol.iterator] = function () { var keys = Object.keys(arr); var keyIndex = 0; return { next: function () { if (keyIndex < keys.length) return { value: arr[keys[keyIndex++]], done: false }; else return { value: undefined, done: true }; } }; }; return iterable; } /* * 3. Reflect.Loader * * We skip the entire native internal pipeline, just providing the bare API */ // 3.1.1 function Loader () { this.registry = new Registry(); } // 3.3.1 Loader.prototype.constructor = Loader; function ensureInstantiated (module) { if (!(module instanceof ModuleNamespace)) throw new TypeError('Module instantiation did not return a valid namespace object.'); return module; } // 3.3.2 Loader.prototype.import = function (key, parent) { if (typeof key !== 'string') throw new TypeError('Loader import method must be passed a module key string'); // custom resolveInstantiate combined hook for better perf var loader = this; return resolvedPromise$1 .then(function () { return loader[RESOLVE_INSTANTIATE](key, parent); }) .then(ensureInstantiated) //.then(Module.evaluate) .catch(function (err) { throw LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); }); }; // 3.3.3 var RESOLVE = Loader.resolve = createSymbol('resolve'); /* * Combined resolve / instantiate hook * * Not in current reduced spec, but necessary to separate RESOLVE from RESOLVE + INSTANTIATE as described * in the spec notes of this repo to ensure that loader.resolve doesn't instantiate when not wanted. * * We implement RESOLVE_INSTANTIATE as a single hook instead of a separate INSTANTIATE in order to avoid * the need for double registry lookups as a performance optimization. */ var RESOLVE_INSTANTIATE = Loader.resolveInstantiate = createSymbol('resolveInstantiate'); // default resolveInstantiate is just to call resolve and then get from the registry // this provides compatibility for the resolveInstantiate optimization Loader.prototype[RESOLVE_INSTANTIATE] = function (key, parent) { var loader = this; return loader.resolve(key, parent) .then(function (resolved) { return loader.registry.get(resolved); }); }; function ensureResolution (resolvedKey) { if (resolvedKey === undefined) throw new RangeError('No resolution found.'); return resolvedKey; } Loader.prototype.resolve = function (key, parent) { var loader = this; return resolvedPromise$1 .then(function() { return loader[RESOLVE](key, parent); }) .then(ensureResolution) .catch(function (err) { throw LoaderError__Check_error_message_for_loader_stack(err, 'Resolving ' + key + (parent ? ' to ' + parent : '')); }); }; // 3.3.4 (import without evaluate) // this is not documented because the use of deferred evaluation as in Module.evaluate is not // documented, as it is not considered a stable feature to be encouraged // Loader.prototype.load may well be deprecated if this stays disabled /* Loader.prototype.load = function (key, parent) { return Promise.resolve(this[RESOLVE_INSTANTIATE](key, parent || this.key)) .catch(function (err) { throw addToError(err, 'Loading ' + key + (parent ? ' from ' + parent : '')); }); }; */ /* * 4. Registry * * Instead of structuring through a Map, just use a dictionary object * We throw for construction attempts so this doesn't affect the public API * * Registry has been adjusted to use Namespace objects over ModuleStatus objects * as part of simplifying loader API implementation */ var iteratorSupport = typeof Symbol !== 'undefined' && Symbol.iterator; var REGISTRY = createSymbol('registry'); function Registry() { this[REGISTRY] = {}; } // 4.4.1 if (iteratorSupport) { // 4.4.2 Registry.prototype[Symbol.iterator] = function () { return this.entries()[Symbol.iterator](); }; // 4.4.3 Registry.prototype.entries = function () { var registry = this[REGISTRY]; return arrayValues(Object.keys(registry).map(function (key) { return [key, registry[key]]; })); }; } // 4.4.4 Registry.prototype.keys = function () { return arrayValues(Object.keys(this[REGISTRY])); }; // 4.4.5 Registry.prototype.values = function () { var registry = this[REGISTRY]; return arrayValues(Object.keys(registry).map(function (key) { return registry[key]; })); }; // 4.4.6 Registry.prototype.get = function (key) { return this[REGISTRY][key]; }; // 4.4.7 Registry.prototype.set = function (key, namespace) { if (!(namespace instanceof ModuleNamespace)) throw new Error('Registry must be set with an instance of Module Namespace'); this[REGISTRY][key] = namespace; return this; }; // 4.4.8 Registry.prototype.has = function (key) { return Object.hasOwnProperty.call(this[REGISTRY], key); }; // 4.4.9 Registry.prototype.delete = function (key) { if (Object.hasOwnProperty.call(this[REGISTRY], key)) { delete this[REGISTRY][key]; return true; } return false; }; /* * Simple ModuleNamespace Exotic object based on a baseObject * We export this for allowing a fast-path for module namespace creation over Module descriptors */ // var EVALUATE = createSymbol('evaluate'); var BASE_OBJECT = createSymbol('baseObject'); // 8.3.1 Reflect.Module /* * Best-effort simplified non-spec implementation based on * a baseObject referenced via getters. * * Allows: * * loader.registry.set('x', new Module({ default: 'x' })); * * Optional evaluation function provides experimental Module.evaluate * support for non-executed modules in registry. */ function ModuleNamespace (baseObject/*, evaluate*/) { Object.defineProperty(this, BASE_OBJECT, { value: baseObject }); // evaluate defers namespace population /* if (evaluate) { Object.defineProperty(this, EVALUATE, { value: evaluate, configurable: true, writable: true }); } else { */ Object.keys(baseObject).forEach(extendNamespace, this); //} } // 8.4.2 ModuleNamespace.prototype = Object.create(null); if (typeof Symbol !== 'undefined' && Symbol.toStringTag) Object.defineProperty(ModuleNamespace.prototype, Symbol.toStringTag, { value: 'Module' }); function extendNamespace (key) { Object.defineProperty(this, key, { enumerable: true, get: function () { return this[BASE_OBJECT][key]; } }); } /* function doEvaluate (evaluate, context) { try { evaluate.call(context); } catch (e) { return e; } } // 8.4.1 Module.evaluate... not documented or used because this is potentially unstable Module.evaluate = function (ns) { var evaluate = ns[EVALUATE]; if (evaluate) { ns[EVALUATE] = undefined; var err = doEvaluate(evaluate); if (err) { // cache the error ns[EVALUATE] = function () { throw err; }; throw err; } Object.keys(ns[BASE_OBJECT]).forEach(extendNamespace, ns); } // make chainable return ns; }; */ /* * Register Loader * * Builds directly on top of loader polyfill to provide: * - loader.register support * - hookable higher-level resolve * - instantiate hook returning a ModuleNamespace or undefined for es module loading * - loader error behaviour as in HTML and loader specs, caching load and eval errors separately * - build tracing support by providing a .trace=true and .loads object format */ var REGISTER_INTERNAL = createSymbol('register-internal'); function RegisterLoader$1 () { Loader.call(this); var registryDelete = this.registry.delete; this.registry.delete = function (key) { var deleted = registryDelete.call(this, key); // also delete from register registry if linked if (records.hasOwnProperty(key) && !records[key].linkRecord) { delete records[key]; deleted = true; } return deleted; }; var records = {}; this[REGISTER_INTERNAL] = { // last anonymous System.register call lastRegister: undefined, // in-flight es module load records records: records }; // tracing this.trace = false; } RegisterLoader$1.prototype = Object.create(Loader.prototype); RegisterLoader$1.prototype.constructor = RegisterLoader$1; var INSTANTIATE = RegisterLoader$1.instantiate = createSymbol('instantiate'); // default normalize is the WhatWG style normalizer RegisterLoader$1.prototype[RegisterLoader$1.resolve = Loader.resolve] = function (key, parentKey) { return resolveIfNotPlain(key, parentKey || baseURI); }; RegisterLoader$1.prototype[INSTANTIATE] = function (key, processAnonRegister) {}; // once evaluated, the linkRecord is set to undefined leaving just the other load record properties // this allows tracking new binding listeners for es modules through importerSetters // for dynamic modules, the load record is removed entirely. function createLoadRecord (state, key, registration) { return state.records[key] = { key: key, // defined System.register cache registration: registration, // module namespace object module: undefined, // es-only // this sticks around so new module loads can listen to binding changes // for already-loaded modules by adding themselves to their importerSetters importerSetters: undefined, loadError: undefined, evalError: undefined, // in-flight linking record linkRecord: { // promise for instantiated instantiatePromise: undefined, dependencies: undefined, execute: undefined, executingRequire: false, // underlying module object bindings moduleObj: undefined, // es only, also indicates if es or not setters: undefined, // promise for instantiated dependencies (dependencyInstantiations populated) depsInstantiatePromise: undefined, // will be the array of dependency load record or a module namespace dependencyInstantiations: undefined, // NB optimization and way of ensuring module objects in setters // indicates setters which should run pre-execution of that dependency // setters is then just for completely executed module objects // alternatively we just pass the partially filled module objects as // arguments into the execute function // hoisted: undefined } }; } RegisterLoader$1.prototype[Loader.resolveInstantiate] = function (key, parentKey) { var loader = this; var state = this[REGISTER_INTERNAL]; var registry = this.registry[REGISTRY]; return resolveInstantiate(loader, key, parentKey, registry, state) .then(function (instantiated) { if (instantiated instanceof ModuleNamespace) return instantiated; // resolveInstantiate always returns a load record with a link record and no module value var link = instantiated.linkRecord; // if already beaten to done, return if (!link) { if (instantiated.module) return instantiated.module; throw instantiated.evalError; } return deepInstantiateDeps(loader, instantiated, link, registry, state) .then(function () { return ensureEvaluate(loader, instantiated, link, registry, state, undefined); }); }); }; function resolveInstantiate (loader, key, parentKey, registry, state) { // normalization shortpath for already-normalized key // could add a plain name filter, but doesn't yet seem necessary for perf var module = registry[key]; if (module) return Promise.resolve(module); var load = state.records[key]; // already linked but not in main registry is ignored if (load && !load.module) { if (load.loadError) return Promise.reject(load.loadError); return instantiate(loader, load, load.linkRecord, registry, state); } return loader.resolve(key, parentKey) .then(function (resolvedKey) { // main loader registry always takes preference module = registry[resolvedKey]; if (module) return module; load = state.records[resolvedKey]; // already has a module value but not already in the registry (load.module) // means it was removed by registry.delete, so we should // disgard the current load record creating a new one over it // but keep any existing registration if (!load || load.module) load = createLoadRecord(state, resolvedKey, load && load.registration); if (load.loadError) return Promise.reject(load.loadError); var link = load.linkRecord; if (!link) return load; return instantiate(loader, load, link, registry, state); }); } function createProcessAnonRegister (loader, load, state) { return function () { var lastRegister = state.lastRegister; if (!lastRegister) return !!load.registration; state.lastRegister = undefined; load.registration = lastRegister; return true; }; } function instantiate (loader, load, link, registry, state) { return link.instantiatePromise || (link.instantiatePromise = // if there is already an existing registration, skip running instantiate (load.registration ? Promise.resolve() : Promise.resolve().then(function () { state.lastRegister = undefined; return loader[INSTANTIATE](load.key, loader[INSTANTIATE].length > 1 && createProcessAnonRegister(loader, load, state)); })) .then(function (instantiation) { // direct module return from instantiate -> we're done if (instantiation !== undefined) { if (!(instantiation instanceof ModuleNamespace)) throw new TypeError('Instantiate did not return a valid Module object.'); delete state.records[load.key]; if (loader.trace) traceLoad(loader, load, link); return registry[load.key] = instantiation; } // run the cached loader.register declaration if there is one var registration = load.registration; // clear to allow new registrations for future loads (combined with registry delete) load.registration = undefined; if (!registration) throw new TypeError('Module instantiation did not call an anonymous or correctly named System.register.'); link.dependencies = registration[0]; load.importerSetters = []; link.moduleObj = {}; // process System.registerDynamic declaration if (registration[2]) { link.moduleObj.default = link.moduleObj.__useDefault = {}; link.executingRequire = registration[1]; link.execute = registration[2]; } // process System.register declaration else { registerDeclarative(loader, load, link, registration[1]); } return load; }) .catch(function (err) { load.linkRecord = undefined; throw load.loadError = load.loadError || LoaderError__Check_error_message_for_loader_stack(err, 'Instantiating ' + load.key); })); } // like resolveInstantiate, but returning load records for linking function resolveInstantiateDep (loader, key, parentKey, registry, state, traceDepMap) { // normalization shortpaths for already-normalized key // DISABLED to prioritise consistent resolver calls // could add a plain name filter, but doesn't yet seem necessary for perf /* var load = state.records[key]; var module = registry[key]; if (module) { if (traceDepMap) traceDepMap[key] = key; // registry authority check in case module was deleted or replaced in main registry if (load && load.module && load.module === module) return load; else return module; } // already linked but not in main registry is ignored if (load && !load.module) { if (traceDepMap) traceDepMap[key] = key; return instantiate(loader, load, load.linkRecord, registry, state); } */ return loader.resolve(key, parentKey) .then(function (resolvedKey) { if (traceDepMap) traceDepMap[key] = resolvedKey; // normalization shortpaths for already-normalized key var load = state.records[resolvedKey]; var module = registry[resolvedKey]; // main loader registry always takes preference if (module && (!load || load.module && module !== load.module)) return module; if (load && load.loadError) throw load.loadError; // already has a module value but not already in the registry (load.module) // means it was removed by registry.delete, so we should // disgard the current load record creating a new one over it // but keep any existing registration if (!load || !module && load.module) load = createLoadRecord(state, resolvedKey, load && load.registration); var link = load.linkRecord; if (!link) return load; return instantiate(loader, load, link, registry, state); }); } function traceLoad (loader, load, link) { loader.loads = loader.loads || {}; loader.loads[load.key] = { key: load.key, deps: link.dependencies, dynamicDeps: [], depMap: link.depMap || {} }; } /* * Convert a CJS module.exports into a valid object for new Module: * * new Module(getEsModule(module.exports)) * * Sets the default value to the module, while also reading off named exports carefully. */ function registerDeclarative (loader, load, link, declare) { var moduleObj = link.moduleObj; var importerSetters = load.importerSetters; var definedExports = false; // closure especially not based on link to allow link record disposal var declared = declare.call(envGlobal, function (name, value) { if (typeof name === 'object') { var changed = false; for (var p in name) { value = name[p]; if (p !== '__useDefault' && (!(p in moduleObj) || moduleObj[p] !== value)) { changed = true; moduleObj[p] = value; } } if (changed === false) return value; } else { if ((definedExports || name in moduleObj) && moduleObj[name] === value) return value; moduleObj[name] = value; } for (var i = 0; i < importerSetters.length; i++) importerSetters[i](moduleObj); return value; }, new ContextualLoader(loader, load.key)); link.setters = declared.setters; link.execute = declared.execute; if (declared.exports) { link.moduleObj = moduleObj = declared.exports; definedExports = true; } } function instantiateDeps (loader, load, link, registry, state) { if (link.depsInstantiatePromise) return link.depsInstantiatePromise; var depsInstantiatePromises = Array(link.dependencies.length); for (var i = 0; i < link.dependencies.length; i++) depsInstantiatePromises[i] = resolveInstantiateDep(loader, link.dependencies[i], load.key, registry, state, loader.trace && link.depMap || (link.depMap = {})); var depsInstantiatePromise = Promise.all(depsInstantiatePromises) .then(function (dependencyInstantiations) { link.dependencyInstantiations = dependencyInstantiations; // run setters to set up bindings to instantiated dependencies if (link.setters) { for (var i = 0; i < dependencyInstantiations.length; i++) { var setter = link.setters[i]; if (setter) { var instantiation = dependencyInstantiations[i]; if (instantiation instanceof ModuleNamespace) { setter(instantiation); } else { if (instantiation.loadError) throw instantiation.loadError; setter(instantiation.module || instantiation.linkRecord.moduleObj); // this applies to both es and dynamic registrations if (instantiation.importerSetters) instantiation.importerSetters.push(setter); } } } } return load; }); if (loader.trace) depsInstantiatePromise = depsInstantiatePromise.then(function () { traceLoad(loader, load, link); return load; }); depsInstantiatePromise = depsInstantiatePromise.catch(function (err) { // throw up the instantiateDeps stack link.depsInstantiatePromise = undefined; throw LoaderError__Check_error_message_for_loader_stack(err, 'Loading ' + load.key); }); depsInstantiatePromise.catch(function () {}); return link.depsInstantiatePromise = depsInstantiatePromise; } function deepInstantiateDeps (loader, load, link, registry, state) { return new Promise(function (resolve, reject) { var seen = []; var loadCnt = 0; function queueLoad (load) { var link = load.linkRecord; if (!link) return; if (seen.indexOf(load) !== -1) return; seen.push(load); loadCnt++; instantiateDeps(loader, load, link, registry, state) .then(processLoad, reject); } function processLoad (load) { loadCnt--; var link = load.linkRecord; if (link) { for (var i = 0; i < link.dependencies.length; i++) { var depLoad = link.dependencyInstantiations[i]; if (!(depLoad instanceof ModuleNamespace)) queueLoad(depLoad); } } if (loadCnt === 0) resolve(); } queueLoad(load); }); } /* * System.register */ RegisterLoader$1.prototype.register = function (key, deps, declare) { var state = this[REGISTER_INTERNAL]; // anonymous modules get stored as lastAnon if (declare === undefined) { state.lastRegister = [key, deps, undefined]; } // everything else registers into the register cache else { var load = state.records[key] || createLoadRecord(state, key, undefined); load.registration = [deps, declare, undefined]; } }; /* * System.registerDyanmic */ RegisterLoader$1.prototype.registerDynamic = function (key, deps, executingRequire, execute) { var state = this[REGISTER_INTERNAL]; // anonymous modules get stored as lastAnon if (typeof key !== 'string') { state.lastRegister = [key, deps, executingRequire]; } // everything else registers into the register cache else { var load = state.records[key] || createLoadRecord(state, key, undefined); load.registration = [deps, executingRequire, execute]; } }; // ContextualLoader class // backwards-compatible with previous System.register context argument by exposing .id, .key function ContextualLoader (loader, key) { this.loader = loader; this.key = this.id = key; this.meta = { url: key // scriptElement: null }; } /*ContextualLoader.prototype.constructor = function () { throw new TypeError('Cannot subclass the contextual loader only Reflect.Loader.'); };*/ ContextualLoader.prototype.import = function (key) { if (this.loader.trace) this.loader.loads[this.key].dynamicDeps.push(key); return this.loader.import(key, this.key); }; /*ContextualLoader.prototype.resolve = function (key) { return this.loader.resolve(key, this.key); };*/ // this is the execution function bound to the Module namespace record function ensureEvaluate (loader, load, link, registry, state, seen) { if (load.module) return load.module; if (load.evalError) throw load.evalError; if (seen && seen.indexOf(load) !== -1) return load.linkRecord.moduleObj; // for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless // for dynamic loads, we pass seen if also dynamic var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []); if (err) throw err; return load.module; } function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations, registry, state, seen) { // we can only require from already-known dependencies return function (name) { for (var i = 0; i < dependencies.length; i++) { if (dependencies[i] === name) { var depLoad = dependencyInstantiations[i]; var module; if (depLoad instanceof ModuleNamespace) module = depLoad; else module = ensureEvaluate(loader, depLoad, depLoad.linkRecord, registry, state, seen); return '__useDefault' in module ? module.__useDefault : module; } } throw new Error('Module ' + name + ' not declared as a System.registerDynamic dependency of ' + key); }; } // ensures the given es load is evaluated // returns the error if any function doEvaluate (loader, load, link, registry, state, seen) { seen.push(load); var err; // es modules evaluate dependencies first // non es modules explicitly call moduleEvaluate through require if (link.setters) { var depLoad, depLink; for (var i = 0; i < link.dependencies.length; i++) { depLoad = link.dependencyInstantiations[i]; if (depLoad instanceof ModuleNamespace) continue; // custom Module returned from instantiate depLink = depLoad.linkRecord; if (depLink && seen.indexOf(depLoad) === -1) { if (depLoad.evalError) err = depLoad.evalError; else // dynamic / declarative boundaries clear the "seen" list // we just let cross format circular throw as would happen in real implementations err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []); } if (err) { load.linkRecord = undefined; load.evalError = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); return load.evalError; } } } // link.execute won't exist for Module returns from instantiate on top-level load if (link.execute) { // ES System.register execute // "this" is null in ES if (link.setters) { err = declarativeExecute(link.execute); } // System.registerDynamic execute // "this" is "exports" in CJS else { var module = { id: load.key }; var moduleObj = link.moduleObj; Object.defineProperty(module, 'exports', { configurable: true, set: function (exports) { moduleObj.default = moduleObj.__useDefault = exports; }, get: function () { return moduleObj.__useDefault; } }); var require = makeDynamicRequire(loader, load.key, link.dependencies, link.dependencyInstantiations, registry, state, seen); // evaluate deps first if (!link.executingRequire) for (var i = 0; i < link.dependencies.length; i++) require(link.dependencies[i]); err = dynamicExecute(link.execute, require, moduleObj.default, module); // pick up defineProperty calls to module.exports when we can if (module.exports !== moduleObj.__useDefault) moduleObj.default = moduleObj.__useDefault = module.exports; var moduleDefault = moduleObj.default; // __esModule flag extension support via lifting if (moduleDefault && moduleDefault.__esModule) { for (var p in moduleDefault) { if (Object.hasOwnProperty.call(moduleDefault, p)) moduleObj[p] = moduleDefault[p]; } } } } // dispose link record load.linkRecord = undefined; if (err) return load.evalError = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key); registry[load.key] = load.module = new ModuleNamespace(link.moduleObj); // if not an esm module, run importer setters and clear them // this allows dynamic modules to update themselves into es modules // as soon as execution has completed if (!link.setters) { if (load.importerSetters) for (var i = 0; i < load.importerSetters.length; i++) load.importerSetters[i](load.module); load.importerSetters = undefined; } } // {} is the closest we can get to call(undefined) var nullContext = {}; if (Object.freeze) Object.freeze(nullContext); function declarativeExecute (execute) { try { execute.call(nullContext); } catch (e) { return e; } } function dynamicExecute (execute, require, exports, module) { try { var output = execute.call(envGlobal, require, exports, module); if (output !== undefined) module.exports = output; } catch (e) { return e; } } var resolvedPromise = Promise.resolve(); function noop () {} var emptyModule = new ModuleNamespace({}); function protectedCreateNamespace (bindings) { if (bindings instanceof ModuleNamespace) return bindings; if (bindings && bindings.__esModule) return new ModuleNamespace(bindings); return new ModuleNamespace({ default: bindings, __useDefault: bindings }); } var hasStringTag; function isModule (m) { if (hasStringTag === undefined) hasStringTag = typeof Symbol !== 'undefined' && !!Symbol.toStringTag; return m instanceof ModuleNamespace || hasStringTag && Object.prototype.toString.call(m) == '[object Module]'; } var CONFIG = createSymbol('loader-config'); var METADATA = createSymbol('metadata'); var isWorker = typeof window === 'undefined' && typeof self !== 'undefined' && typeof importScripts !== 'undefined'; function warn (msg, force) { if (force || this.warnings && typeof console !== 'undefined' && console.warn) console.warn(msg); } function checkInstantiateWasm (loader, wasmBuffer, processAnonRegister) { var bytes = new Uint8Array(wasmBuffer); // detect by leading bytes // Can be (new Uint32Array(fetched))[0] === 0x6D736100 when working in Node if (bytes[0] === 0 && bytes[1] === 97 && bytes[2] === 115) { return WebAssembly.compile(wasmBuffer).then(function (m) { var deps = []; var setters = []; var importObj = {}; // we can only set imports if supported (eg Safari doesnt support) if (WebAssembly.Module.imports) WebAssembly.Module.imports(m).forEach(function (i) { var key = i.module; setters.push(function (m) { importObj[key] = m; }); if (deps.indexOf(key) === -1) deps.push(key); }); loader.register(deps, function (_export) { return { setters: setters, execute: function () { _export(new WebAssembly.Instance(m, importObj).exports); } }; }); processAnonRegister(); return true; }); } return Promise.resolve(false); } var parentModuleContext; function loadNodeModule (key, baseURL) { if (key[0] === '.') throw new Error('Node module ' + key + ' can\'t be loaded as it is not a package require.'); if (!parentModuleContext) { var Module = this._nodeRequire('module'); var base = decodeURI(baseURL.substr(isWindows ? 8 : 7)); parentModuleContext = new Module(base); parentModuleContext.paths = Module._nodeModulePaths(base); } return parentModuleContext.require(key); } function extend (a, b) { for (var p in b) { if (!Object.hasOwnProperty.call(b, p)) continue; a[p] = b[p]; } return a; } function prepend (a, b) { for (var p in b) { if (!Object.hasOwnProperty.call(b, p)) continue; if (a[p] === undefined) a[p] = b[p]; } return a; } // meta first-level extends where: // array + array appends // object + object extends // other properties replace function extendMeta (a, b, _prepend) { for (var p in b) { if (!Object.hasOwnProperty.call(b, p)) continue; var val = b[p]; if (a[p] === undefined) a[p] = val; else if (val instanceof Array && a[p] instanceof Array) a[p] = [].concat(_prepend ? val : a[p]).concat(_prepend ? a[p] : val); else if (typeof val == 'object' && val !== null && typeof a[p] == 'object') a[p] = (_prepend ? prepend : extend)(extend({}, a[p]), val); else if (!_prepend) a[p] = val; } } var supportsPreload = false; var supportsPrefetch = false; if (isBrowser) (function () { var relList = document.createElement('link').relList; if (relList && relList.supports) { supportsPrefetch = true; try { supportsPreload = relList.supports('preload'); } catch (e) {} } })(); function preloadScript (url) { // fallback to old fashioned image technique which still works in safari if (!supportsPreload && !supportsPrefetch) { var preloadImage = new Image(); preloadImage.src = url; return; } var link = document.createElement('link'); if (supportsPreload) { link.rel = 'preload'; link.as = 'script'; } else { // this works for all except Safari (detected by relList.supports lacking) link.rel = 'prefetch'; } link.href = url; document.head.appendChild(link); } function workerImport (src, resolve, reject) { try { importScripts(src); } catch (e) { reject(e); } resolve(); } if (isBrowser) { var loadingScripts = []; var onerror = window.onerror; window.onerror = function globalOnerror (msg, src) { for (var i = 0; i < loadingScripts.length; i++) { if (loadingScripts[i].src !== src) continue; loadingScripts[i].err(msg); return; } if (onerror) onerror.apply(this, arguments); }; } function scriptLoad (src, crossOrigin, integrity, resolve, reject) { // percent encode just "#" for HTTP requests src = src.replace(/#/g, '%23'); // subresource integrity is not supported in web workers if (isWorker) return workerImport(src, resolve, reject); var script = document.createElement('script'); script.type = 'text/javascript'; script.charset = 'utf-8'; script.async = true; if (crossOrigin) script.crossOrigin = crossOrigin; if (integrity) script.integrity = integrity; script.addEventListener('load', load, false); script.addEventListener('error', error, false); script.src = src; document.head.appendChild(script); function load () { resolve(); cleanup(); } // note this does not catch execution errors function error (err) { cleanup(); reject(new Error('Fetching ' + src)); } function cleanup () { for (var i = 0; i < loadingScripts.length; i++) { if (loadingScripts[i].err === error) { loadingScripts.splice(i, 1); break; } } script.removeEventListener('load', load, false); script.removeEventListener('error', error, false); document.head.removeChild(script); } } function readMemberExpression (p, value) { var pParts = p.split('.'); while (pParts.length) value = value[pParts.shift()]; return value; } // separate out paths cache as a baseURL lock process function applyPaths (baseURL, paths, key) { var mapMatch = getMapMatch(paths, key); if (mapMatch) { var target = paths[mapMatch] + key.substr(mapMatch.length); var resolved = resolveIfNotPlain(target, baseURI); if (resolved !== undefined) return resolved; return baseURL + target; } else if (key.indexOf(':') !== -1) { return key; } else { return baseURL + key; } } function checkMap (p) { var name = this.name; // can add ':' here if we want paths to match the behaviour of map if (name.substr(0, p.length) === p && (name.length === p.length || name[p.length] === '/' || p[p.length - 1] === '/' || p[p.length - 1] === ':')) { var curLen = p.split('/').length; if (curLen > this.len) { this.match = p; this.len = curLen; } } } function getMapMatch (map, name) { if (Object.hasOwnProperty.call(map, name)) return name; var bestMatch = { name: name, match: undefined, len: 0 }; Object.keys(map).forEach(checkMap, bestMatch); return bestMatch.match; } // RegEx adjusted from https://github.com/jbrantly/yabble/blob/master/lib/yabble.js#L339 var cjsRequireRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF."'])require\s*\(\s*("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*'|`[^`\\]*(?:\\.[^`\\]*)*`)\s*\)/g; /* * Source loading */ function fetchFetch (url, authorization, integrity, asBuffer) { // fetch doesn't support file:/// urls if (url.substr(0, 8) === 'file:///') { if (hasXhr) return xhrFetch(url, authorization, integrity, asBuffer); else throw new Error('Unable to fetch file URLs in this environment.'); } // percent encode just "#" for HTTP requests url = url.replace(/#/g, '%23'); var opts = { // NB deprecate headers: { Accept: 'application/x-es-module, */*' } }; if (integrity) opts.integrity = integrity; if (authorization) { if (typeof authorization == 'string') opts.headers['Authorization'] = authorization; opts.credentials = 'include'; } return fetch(url, opts) .then(function(res) { if (res.ok) return asBuffer ? res.arrayBuffer() : res.text(); else throw new Error('Fetch error: ' + res.status + ' ' + res.statusText); }); } function xhrFetch (url, authorization, integrity, asBuffer) { return new Promise(function (resolve, reject) { // percent encode just "#" for HTTP requests url = url.replace(/#/g, '%23'); var xhr = new XMLHttpRequest(); if (asBuffer) xhr.responseType = 'arraybuffer'; function load() { resolve(asBuffer ? xhr.response : xhr.responseText); } function error() { reject(new Error('XHR error: ' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url)); } xhr.onreadystatechange = function () { if (xhr.readyState === 4) { // in Chrome on file:/// URLs, status is 0 if (xhr.status == 0) { if (xhr.response) { load(); } else { // when responseText is empty, wait for load or error event // to inform if it is a 404 or empty file xhr.addEventListener('error', error); xhr.addEventListener('load', load); } } else if (xhr.status === 200) { load(); } else { error(); } } }; xhr.open("GET", url, true); if (xhr.setRequestHeader) { xhr.setRequestHeader('Accept', 'application/x-es-module, */*'); // can set "authorization: true" to enable withCredentials only if (authorization) { if (typeof authorization == 'string') xhr.setRequestHeader('Authorization', authorization); xhr.withCredentials = true; } } xhr.send(null); }); } var fs; function nodeFetch (url, authorization, integrity, asBuffer) { if (url.substr(0, 8) != 'file:///') return Promise.reject(new Error('Unable to fetch "' + url + '". Only file URLs of the form file:/// supported running in Node.')); fs = fs || require('fs'); if (isWindows) url = url.replace(/\//g, '\\').substr(8); else url = url.substr(7); return new Promise(function (resolve, reject) { fs.readFile(url, function(err, data) { if (err) { return reject(err); } else { if (asBuffer) { resolve(data); } else { // Strip Byte Order Mark out if it's the leading char var dataString = data + ''; if (dataString[0] === '\ufeff') dataString = dataString.substr(1); resolve(dataString); } } }); }); } function noFetch () { throw new Error('No fetch method is defined for this environment.'); } var fetchFunction; var hasXhr = typeof XMLHttpRequest !== 'undefined'; if (typeof self !== 'undefined' && typeof self.fetch !== 'undefined') fetchFunction = fetchFetch; else if (hasXhr) fetchFunction = xhrFetch; else if (typeof require !== 'undefined' && typeof process !== 'undefined') fetchFunction = nodeFetch; else fetchFunction = noFetch; var fetch$1 = fetchFunction; function createMetadata () { return { pluginKey: undefined, pluginArgument: undefined, pluginModule: undefined, packageKey: undefined, packageConfig: undefined, load: undefined }; } function getParentMetadata (loader, config, parentKey) { var parentMetadata = createMetadata(); if (parentKey) { // detect parent plugin // we just need pluginKey to be truthy for package configurations // so we duplicate it as pluginArgument - although not correct its not used var parentPluginIndex; if (config.pluginFirst) { if ((parentPluginIndex = parentKey.lastIndexOf('!')) !== -1) parentMetadata.pluginArgument = parentMetadata.pluginKey = parentKey.substr(0, parentPluginIndex); } else { if ((parentPluginIndex = parentKey.indexOf('!')) !== -1) parentMetadata.pluginArgument = parentMetadata.pluginKey = parentKey.substr(parentPluginIndex + 1); } // detect parent package parentMetadata.packageKey = getMapMatch(config.packages, parentKey); if (parentMetadata.packageKey) parentMetadata.packageConfig = config.packages[parentMetadata.packageKey]; } return parentMetadata; } function normalize (key, parentKey) { var config = this[CONFIG]; var metadata = createMetadata(); var parentMetadata = getParentMetadata(this, config, parentKey); var loader = this; return Promise.resolve() // boolean conditional .then(function () { // first we normalize the conditional var booleanIndex = key.lastIndexOf('#?'); if (booleanIndex === -1) return Promise.resolve(key); var conditionObj = parseCondition.call(loader, key.substr(booleanIndex + 2)); // in builds, return normalized conditional /*if (this.builder) return this.resolve(conditionObj.module, parentKey) .then(function (conditionModule) { conditionObj.module = conditionModule; return key.substr(0, booleanIndex) + '#?' + serializeCondition(conditionObj); });*/ return resolveCondition.call(loader, conditionObj, parentKey, true) .then(function (conditionValue) { return conditionValue ? key.substr(0, booleanIndex) : '@empty'; }); }) // plugin .then(function (key) { var parsed = parsePlugin(config.pluginFirst, key); if (!parsed) return packageResolve.call(loader, config, key, parentMetadata && parentMetadata.pluginArgument || parentKey, metadata, parentMetadata, false); metadata.pluginKey = parsed.plugin; return Promise.all([ packageResolve.call(loader, config, parsed.argument, parentMetadata && parentMetadata.pluginArgument || parentKey, metadata, parentMetadata, true), loader.resolve(parsed.plugin, parentKey) ]) .then(function (normalized) { metadata.pluginArgument = normalized[0]; metadata.pluginKey = normalized[1]; // don't allow a plugin to load itself if (metadata.pluginArgument === metadata.pluginKey) throw new Error('Plugin ' + metadata.pluginArgument + ' cannot load itself, make sure it is excluded from any wildcard meta configuration via a custom loader: false rule.'); return combinePluginParts(config.pluginFirst, normalized[0], normalized[1]); }); }) .then(function (normalized) { return interpolateConditional.call(loader, normalized, parentKey, parentMetadata); }) .then(function (normalized) { setMeta.call(loader, config, normalized, metadata); if (metadata.pluginKey || !metadata.load.loader) return normalized; // loader by configuration // normalizes to parent to support package loaders return loader.resolve(metadata.load.loader, normalized) .then(function (pluginKey) { metadata.pluginKey = pluginKey; metadata.pluginArgument = normalized; return normalized; }); }) .then(function (normalized) { loader[METADATA][normalized] = metadata; return normalized; }); } // normalization function used for registry keys // just does coreResolve without map function decanonicalize (config, key) { var parsed = parsePlugin(config.pluginFirst, key); // plugin if (parsed) { var pluginKey = decanonicalize.call(this, config, parsed.plugin); return combinePluginParts(config.pluginFirst, coreResolve.call(this, config, parsed.argument, undefined, false, false), pluginKey); } return coreResolve.call(this, config, key, undefined, false, false); } function normalizeSync (key, parentKey) { var config = this[CONFIG]; // normalizeSync is metadataless, so create metadata var metadata = createMetadata(); var parentMetadata = parentMetadata || getParentMetadata(this, config, parentKey); var parsed = parsePlugin(config.pluginFirst, key); // plugin if (parsed) { metadata.pluginKey = normalizeSync.call(this, parsed.plugin, parentKey); return combinePluginParts(config.pluginFirst, packageResolveSync.call(this, config, parsed.argument, parentMetadata.pluginArgument || parentKey, metadata, parentMetadata, !!metadata.pluginKey), metadata.pluginKey); } return packageResolveSync.call(this, config, key, parentMetadata.pluginArgument || parentKey, metadata, parentMetadata, !!metadata.pluginKey); } function coreResolve (config, key, parentKey, doMap, packageName) { var relativeResolved = resolveIfNotPlain(key, parentKey || baseURI); // standard URL resolution if (relativeResolved) return applyPaths(config.baseURL, config.paths, relativeResolved); // plain keys not starting with './', 'x://' and '/' go through custom resolution if (doMap) { var mapMatch = getMapMatch(config.map, key); if (mapMatch) { key = config.map[mapMatch] + key.substr(mapMatch.length); relativeResolved = resolveIfNotPlain(key, baseURI); if (relativeResolved) return applyPaths(config.baseURL, config.paths, relativeResolved); } } if (this.registry.has(key)) return key; if (key.substr(0, 6) === '@node/') return key; var trailingSlash = packageName && key[key.length - 1] !== '/'; var resolved = applyPaths(config.baseURL, config.paths, trailingSlash ? key + '/' : key); if (trailingSlash) return resolved.substr(0, resolved.length - 1); return resolved; } function packageResolveSync (config, key, parentKey, metadata, parentMetadata, skipExtensions) { // ignore . since internal maps handled by standard package resolution if (parentMetadata && parentMetadata.packageConfig && key[0] !== '.') { var parentMap = parentMetadata.packageConfig.map; var parentMapMatch = parentMap && getMapMatch(parentMap, key); if (parentMapMatch && typeof parentMap[parentMapMatch] === 'string') { var mapped = doMapSync(this, config, parentMetadata.packageConfig, parentMetadata.packageKey, parentMapMatch, key, metadata, skipExtensions); if (mapped) return mapped; } } var normalized = coreResolve.call(this, config, key, parentKey, true, true); var pkgConfigMatch = getPackageConfigMatch(config, normalized); metadata.packageKey = pkgConfigMatch && pkgConfigMatch.packageKey || getMapMatch(config.packages, normalized); if (!metadata.packageKey) return normalized; if (config.packageConfigKeys.indexOf(normalized) !== -1) { metadata.packageKey = undefined; return normalized; } metadata.packageConfig = config.packages[metadata.packageKey] || (config.packages[metadata.packageKey] = createPackage()); var subPath = normalized.substr(metadata.packageKey.length + 1); return applyPackageConfigSync(this, config, metadata.packageConfig, metadata.packageKey, subPath, metadata, skipExtensions); } function packageResolve (config, key, parentKey, metadata, parentMetadata, skipExtensions) { var loader = this; return resolvedPromise .then(function () { // ignore . since internal maps handled by standard package resolution if (parentMetadata && parentMetadata.packageConfig && key.substr(0, 2) !== './') { var parentMap = parentMetadata.packageConfig.map; var parentMapMatch = parentMap && getMapMatch(parentMap, key); if (parentMapMatch) return doMap(loader, config, parentMetadata.packageConfig, parentMetadata.packageKey, parentMapMatch, key, metadata, skipExtensions); } return resolvedPromise; }) .then(function (mapped) { if (mapped) return mapped; // apply map, core, paths, contextual package map var normalized = coreResolve.call(loader, config, key, parentKey, true, true); var pkgConfigMatch = getPackageConfigMatch(config, normalized); metadata.packageKey = pkgConfigMatch && pkgConfigMatch.packageKey || getMapMatch(config.packages, normalized); if (!metadata.packageKey) return Promise.resolve(normalized); if (config.packageConfigKeys.indexOf(normalized) !== -1) { metadata.packageKey = undefined; metadata.load = createMeta(); metadata.load.format = 'json'; // ensure no loader metadata.load.loader = ''; return Promise.resolve(normalized); } metadata.packageConfig = config.packages[metadata.packageKey] || (config.packages[metadata.packageKey] = createPackage()); // load configuration when it matches packageConfigPaths, not already configured, and not the config itself var loadConfig = pkgConfigMatch && !metadata.packageConfig.configured; return (loadConfig ? loadPackageConfigPath(loader, config, pkgConfigMatch.configPath, metadata) : resolvedPromise) .then(function () { var subPath = normalized.substr(metadata.packageKey.length + 1); return applyPackageConfig(loader, config, metadata.packageConfig, metadata.packageKey, subPath, metadata, skipExtensions); }); }); } function createMeta () { return { extension: '', deps: undefined, format: undefined, loader: undefined, scriptLoad: undefined, globals: undefined, nonce: undefined, integrity: undefined, sourceMap: undefined, exports: undefined, encapsulateGlobal: false, crossOrigin: undefined, cjsRequireDetection: true, cjsDeferDepsExecute: false, esModule: false }; } function setMeta (config, key, metadata) { metadata.load = metadata.load || createMeta(); // apply wildcard metas var bestDepth = 0; var wildcardIndex; for (var module in config.meta) { wildcardIndex = module.indexOf('*'); if (wildcardIndex === -1) continue; if (module.substr(0, wildcardIndex) === key.substr(0, wildcardIndex) && module.substr(wildcardIndex + 1) === key.substr(key.length - module.length + wildcardIndex + 1)) { var depth = module.split('/').length; if (depth > bestDepth) bestDepth = depth; extendMeta(metadata.load, config.meta[module], bestDepth !== depth); } } // apply exact meta if (config.meta[key]) extendMeta(metadata.load, config.meta[key], false); // apply package meta if (metadata.packageKey) { var subPath = key.substr(metadata.packageKey.length + 1); var meta = {}; if (metadata.packageConfig.meta) { var bestDepth = 0; getMetaMatches(metadata.packageConfig.meta, subPath, function (metaPattern, matchMeta, matchDepth) { if (matchDepth > bestDepth) bestDepth = matchDepth; extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth); }); extendMeta(metadata.load, meta, false); } // format if (metadata.packageConfig.format && !metadata.pluginKey && !metadata.load.loader) metadata.load.format = metadata.load.format || metadata.packageConfig.format; } } function parsePlugin (pluginFirst, key) { var argumentKey; var pluginKey; var pluginIndex = pluginFirst ? key.indexOf('!') : key.lastIndexOf('!'); if (pluginIndex === -1) return; if (pluginFirst) { argumentKey = key.substr(pluginIndex + 1); pluginKey = key.substr(0, pluginIndex); } else { argumentKey = key.substr(0, pluginIndex); pluginKey = key.substr(pluginIndex + 1) || argumentKey.substr(argumentKey.lastIndexOf('.') + 1); } return { argument: argumentKey, plugin: pluginKey }; } // put key back together after parts have been normalized function combinePluginParts (pluginFirst, argumentKey, pluginKey) { if (pluginFirst) return pluginKey + '!' + argumentKey; else return argumentKey + '!' + pluginKey; } /* * Package Configuration Extension * * Example: * * SystemJS.packages = { * jquery: { * main: 'index.js', // when not set, package key is requested directly * format: 'amd', * defaultExtension: 'ts', // defaults to 'js', can be set to false * modules: { * '*.ts': { * loader: 'typescript' * }, * 'vendor/sizzle.js': { * format: 'global' * } * }, * map: { * // map internal require('sizzle') to local require('./vendor/sizzle') * sizzle: './vendor/sizzle.js', * // map any internal or external require of 'jquery/vendor/another' to 'another/index.js' * './vendor/another.js': './another/index.js', * // test.js / test -> lib/test.js * './test.js': './lib/test.js', * * // environment-specific map configurations * './index.js': { * '~browser': './index-node.js', * './custom-condition.js|~export': './index-custom.js' * } * }, * // allows for setting package-prefixed depCache * // keys are normalized module keys relative to the package itself * depCache: { * // import 'package/index.js' loads in parallel package/lib/test.js,package/vendor/sizzle.js * './index.js': ['./test'], * './test.js': ['external-dep'], * 'external-dep/path.js': ['./another.js'] * } * } * }; * * Then: * import 'jquery' -> jquery/index.js * import 'jquery/submodule' -> jquery/submodule.js * import 'jquery/submodule.ts' -> jquery/submodule.ts loaded as typescript * import 'jquery/vendor/another' -> another/index.js * * Detailed Behaviours * - main can have a leading "./" can be added optionally * - map and defaultExtension are applied to the main * - defaultExtension adds the extension only if the exact extension is not present * - if a meta value is available for a module, map and defaultExtension are skipped * - like global map, package map also applies to subpaths (sizzle/x, ./vendor/another/sub) * - condition module map is '@env' module in package or '@system-env' globally * - map targets support conditional interpolation ('./x': './x.#{|env}.js') * - internal package map targets cannot use boolean conditionals * * Package Configuration Loading * * Not all packages may already have their configuration present in the System config * For these cases, a list of packageConfigPaths can be provided, which when matched against * a request, will first request a ".json" file by the package key to derive the package * configuration from. This allows dynamic loading of non-predetermined code, a key use * case in SystemJS. * * Example: * * SystemJS.packageConfigPaths = ['packages/test/package.json', 'packages/*.json']; * * // will first request 'packages/new-package/package.json' for the package config * // before completing the package request to 'packages/new-package/path' * SystemJS.import('packages/new-package/path'); * * // will first request 'packages/test/package.json' before the main * SystemJS.import('packages/test'); * * When a package matches packageConfigPaths, it will always send a config request for * the package configuration. * The package key itself is taken to be the match up to and including the last wildcard * or trailing slash. * The most specific package config path will be used. * Any existing package configurations for the package will deeply merge with the * package config, with the existing package configurations taking preference. * To opt-out of the package configuration request for a package that matches * packageConfigPaths, use the { configured: true } package config option. * */ function addDefaultExtension (config, pkg, pkgKey, subPath, skipExtensions) { // don't apply extensions to folders or if defaultExtension = false if (!subPath || !pkg.defaultExtension || subPath[subPath.length - 1] === '/' || skipExtensions) return subPath; var metaMatch = false; // exact meta or meta with any content after the last wildcard skips extension if (pkg.meta) getMetaMatches(pkg.meta, subPath, function (metaPattern, matchMeta, matchDepth) { if (matchDepth === 0 || metaPattern.lastIndexOf('*') !== metaPattern.length - 1) return metaMatch = true; }); // exact global meta or meta with any content after the last wildcard skips extension if (!metaMatch && config.meta) getMetaMatches(config.meta, pkgKey + '/' + subPath, function (metaPattern, matchMeta, matchDepth) { if (matchDepth === 0 || metaPattern.lastIndexOf('*') !== metaPattern.length - 1) return metaMatch = true; }); if (metaMatch) return subPath; // work out what the defaultExtension is and add if not there already var defaultExtension = '.' + pkg.defaultExtension; if (subPath.substr(subPath.length - defaultExtension.length) !== defaultExtension) return subPath + defaultExtension; else return subPath; } function applyPackageConfigSync (loader, config, pkg, pkgKey, subPath, metadata, skipExtensions) { // main if (!subPath) { if (pkg.main) subPath = pkg.main.substr(0, 2) === './' ? pkg.main.substr(2) : pkg.main; else // also no submap if key is package itself (import 'pkg' -> 'path/to/pkg.js') // NB can add a default package main convention here // if it becomes internal to the package then it would no longer be an exit path return pkgKey; } // map config checking without then with extensions if (pkg.map) { var mapPath = './' + subPath; var mapMatch = getMapMatch(pkg.map, mapPath); // we then check map with the default extension adding if (!mapMatch) { mapPath = './' + addDefaultExtension(config, pkg, pkgKey, subPath, skipExtensions); if (mapPath !== './' + subPath) mapMatch = getMapMatch(pkg.map, mapPath); } if (mapMatch) { var mapped = doMapSync(loader, config, pkg, pkgKey, mapMatch, mapPath, metadata, skipExtensions); if (mapped) return mapped; } } // normal package resolution return pkgKey + '/' + addDefaultExtension(config, pkg, pkgKey, subPath, skipExtensions); } function validMapping (mapMatch, mapped, path) { // allow internal ./x -> ./x/y or ./x/ -> ./x/y recursive maps // but only if the path is exactly ./x and not ./x/z if (mapped.substr(0, mapMatch.length) === mapMatch && path.length > mapMatch.length) return false; return true; } function doMapSync (loader, config, pkg, pkgKey, mapMatch, path, metadata, skipExtensions) { if (path[path.length - 1] === '/') path = path.substr(0, path.length - 1); var mapped = pkg.map[mapMatch]; if (typeof mapped === 'object') throw new Error('Synchronous conditional normalization not supported sync normalizing ' + mapMatch + ' in ' + pkgKey); if (!validMapping(mapMatch, mapped, path) || typeof mapped !== 'string') return; return packageResolveSync.call(loader, config, mapped + path.substr(mapMatch.length), pkgKey + '/', metadata, metadata, skipExtensions); } function applyPackageConfig (loader, config, pkg, pkgKey, subPath, metadata, skipExtensions) { // main if (!subPath) { if (pkg.main) subPath = pkg.main.substr(0, 2) === './' ? pkg.main.substr(2) : pkg.main; // also no submap if key is package itself (import 'pkg' -> 'path/to/pkg.js') else // NB can add a default package main convention here // if it becomes internal to the package then it would no longer be an exit path return Promise.resolve(pkgKey); } // map config checking without then with extensions var mapPath, mapMatch; if (pkg.map) { mapPath = './' + subPath; mapMatch = getMapMatch(pkg.map, mapPath); // we then check map with the default extension adding if (!mapMatch) { mapPath = './' + addDefaultExtension(config, pkg, pkgKey, subPath, skipExtensions); if (mapPath !== './' + subPath) mapMatch = getMapMatch(pkg.map, mapPath); } } return (mapMatch ? doMap(loader, config, pkg, pkgKey, mapMatch, mapPath, metadata, skipExtensions) : resolvedPromise) .then(function (mapped) { if (mapped) return Promise.resolve(mapped); // normal package resolution / fallback resolution for no conditional match return Promise.resolve(pkgKey + '/' + addDefaultExtension(config, pkg, pkgKey, subPath, skipExtensions)); }); } function doMap (loader, config, pkg, pkgKey, mapMatch, path, metadata, skipExtensions) { if (path[path.length - 1] === '/') path = path.substr(0, path.length - 1); var mapped = pkg.map[mapMatch]; if (typeof mapped === 'string') { if (!validMapping(mapMatch, mapped, path)) return resolvedPromise; return packageResolve.call(loader, config, mapped + path.substr(mapMatch.length), pkgKey + '/', metadata, metadata, skipExtensions) .then(function (normalized) { return interpolateConditional.call(loader, normalized, pkgKey + '/', metadata); }); } // we use a special conditional syntax to allow the builder to handle conditional branch points further /*if (loader.builder) return Promise.resolve(pkgKey + '/#:' + path);*/ // we load all conditions upfront var conditionPromises = []; var conditions = []; for (var e in mapped) { var c = parseCondition(e); conditions.push({ condition: c, map: mapped[e] }); conditionPromises.push(RegisterLoader$1.prototype.import.call(loader, c.module, pkgKey)); } // map object -> conditional map return Promise.all(conditionPromises) .then(function (conditionValues) { // first map condition to match is used for (var i = 0; i < conditions.length; i++) { var c = conditions[i].condition; var value = readMemberExpression(c.prop, '__useDefault' in conditionValues[i] ? conditionValues[i].__useDefault : conditionValues[i]); if (!c.negate && value || c.negate && !value) return conditions[i].map; } }) .then(function (mapped) { if (mapped) { if (!validMapping(mapMatch, mapped, path)) return resolvedPromise; return packageResolve.call(loader, config, mapped + path.substr(mapMatch.length), pkgKey + '/', metadata, metadata, skipExtensions) .then(function (normalized) { return interpolateConditional.call(loader, normalized, pkgKey + '/', metadata); }); } // no environment match -> fallback to original subPath by returning undefined }); } // check if the given normalized key matches a packageConfigPath // if so, loads the config var packageConfigPaths = {}; // data object for quick checks against package paths function createPkgConfigPathObj (path) { var lastWildcard = path.lastIndexOf('*'); var length = Math.max(lastWildcard + 1, path.lastIndexOf('/')); return { length: length, regEx: new RegExp('^(' + path.substr(0, length).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^\\/]+') + ')(\\/|$)'), wildcard: lastWildcard !== -1 }; } // most specific match wins function getPackageConfigMatch (config, normalized) { var pkgKey, exactMatch = false, configPath; for (var i = 0; i < config.packageConfigPaths.length; i++) { var packageConfigPath = config.packageConfigPaths[i]; var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath)); if (normalized.length < p.length) continue; var match = normalized.match(p.regEx); if (match && (!pkgKey || (!(exactMatch && p.wildcard) && pkgKey.length < match[1].length))) { pkgKey = match[1]; exactMatch = !p.wildcard; configPath = pkgKey + packageConfigPath.substr(p.length); } } if (!pkgKey) return; return { packageKey: pkgKey, configPath: configPath }; } function loadPackageConfigPath (loader, config, pkgConfigPath, metadata, normalized) { var configLoader = loader.pluginLoader || loader; // ensure we note this is a package config file path // it will then be skipped from getting other normalizations itself to ensure idempotency if (config.packageConfigKeys.indexOf(pkgConfigPath) === -1) config.packageConfigKeys.push(pkgConfigPath); return configLoader.import(pkgConfigPath) .then(function (pkgConfig) { setPkgConfig(metadata.packageConfig, pkgConfig, metadata.packageKey, true, config); metadata.packageConfig.configured = true; }) .catch(function (err) { throw LoaderError__Check_error_message_for_loader_stack(err, 'Unable to fetch package configuration file ' + pkgConfigPath); }); } function getMetaMatches (pkgMeta, subPath, matchFn) { // wildcard meta var wildcardIndex; for (var module in pkgMeta) { // allow meta to start with ./ for flexibility var dotRel = module.substr(0, 2) === './' ? './' : ''; if (dotRel) module = module.substr(2); wildcardIndex = module.indexOf('*'); if (wildcardIndex === -1) continue; if (module.substr(0, wildcardIndex) === subPath.substr(0, wildcardIndex) && module.substr(wildcardIndex + 1) === subPath.substr(subPath.length - module.length + wildcardIndex + 1)) { // alow match function to return true for an exit path if (matchFn(module, pkgMeta[dotRel + module], module.split('/').length)) return; } } // exact meta var exactMeta = pkgMeta[subPath] && Object.hasOwnProperty.call(pkgMeta, subPath) ? pkgMeta[subPath] : pkgMeta['./' + subPath]; if (exactMeta) matchFn(exactMeta, exactMeta, 0); } /* * Conditions Extension * * Allows a condition module to alter the resolution of an import via syntax: * * import $ from 'jquery/#{browser}'; * * Will first load the module 'browser' via `SystemJS.import('browser')` and * take the default export of that module. * If the default export is not a string, an error is thrown. * * We then substitute the string into the require to get the conditional resolution * enabling environment-specific variations like: * * import $ from 'jquery/ie' * import $ from 'jquery/firefox' * import $ from 'jquery/chrome' * import $ from 'jquery/safari' * * It can be useful for a condition module to define multiple conditions. * This can be done via the `|` modifier to specify an export member expression: * * import 'jquery/#{./browser.js|grade.version}' * * Where the `grade` export `version` member in the `browser.js` module is substituted. * * * Boolean Conditionals * * For polyfill modules, that are used as imports but have no module value, * a binary conditional allows a module not to be loaded at all if not needed: * * import 'es5-shim#?./conditions.js|needs-es5shim' * * These conditions can also be negated via: * * import 'es5-shim#?./conditions.js|~es6' * */ var sysConditions = ['browser', 'node', 'dev', 'build', 'production', 'default']; function parseCondition (condition) { var conditionExport, conditionModule, negation; var negation; var conditionExportIndex = condition.lastIndexOf('|'); if (conditionExportIndex !== -1) { conditionExport = condition.substr(conditionExportIndex + 1); conditionModule = condition.substr(0, conditionExportIndex); if (conditionExport[0] === '~') { negation = true; conditionExport = conditionExport.substr(1); } } else { negation = condition[0] === '~'; conditionExport = 'default'; conditionModule = condition.substr(negation); if (sysConditions.indexOf(conditionModule) !== -1) { conditionExport = conditionModule; conditionModule = null; } } return { module: conditionModule || '@system-env', prop: conditionExport, negate: negation }; } function resolveCondition (conditionObj, parentKey, bool) { // import without __useDefault handling here return RegisterLoader$1.prototype.import.call(this, conditionObj.module, parentKey) .then(function (condition) { var m = readMemberExpression(conditionObj.prop, condition); if (bool && typeof m !== 'boolean') throw new TypeError('Condition did not resolve to a boolean.'); return conditionObj.negate ? !m : m; }); } var interpolationRegEx = /#\{[^\}]+\}/; function interpolateConditional (key, parentKey, parentMetadata) { // first we normalize the conditional var conditionalMatch = key.match(interpolationRegEx); if (!conditionalMatch) return Promise.resolve(key); var conditionObj = parseCondition.call(this, conditionalMatch[0].substr(2, conditionalMatch[0].length - 3)); // in builds, return normalized conditional /*if (this.builder) return this.normalize(conditionObj.module, parentKey, createMetadata(), parentMetadata) .then(function (conditionModule) { conditionObj.module = conditionModule; return key.replace(interpolationRegEx, '#{' + serializeCondition(conditionObj) + '}'); });*/ return resolveCondition.call(this, conditionObj, parentKey, false) .then(function (conditionValue) { if (typeof conditionValue !== 'string') throw new TypeError('The condition value for ' + key + ' doesn\'t resolve to a string.'); if (conditionValue.indexOf('/') !== -1) throw new TypeError('Unabled to interpolate conditional ' + key + (parentKey ? ' in ' + parentKey : '') + '\n\tThe condition value ' + conditionValue + ' cannot contain a "/" separator.'); return key.replace(interpolationRegEx, conditionValue); }); } /* Extend config merging one deep only loader.config({ some: 'random', config: 'here', deep: { config: { too: 'too' } } }); <=> loader.some = 'random'; loader.config = 'here' loader.deep = loader.deep || {}; loader.deep.config = { too: 'too' }; Normalizes meta and package configs allowing for: SystemJS.config({ meta: { './index.js': {} } }); To become SystemJS.meta['https://thissite.com/index.js'] = {}; For easy normalization canonicalization with latest URL support. */ var envConfigNames = ['browserConfig', 'nodeConfig', 'devConfig', 'buildConfig', 'productionConfig']; function envSet(loader, cfg, envCallback) { for (var i = 0; i < envConfigNames.length; i++) { var envConfig = envConfigNames[i]; if (cfg[envConfig] && envModule[envConfig.substr(0, envConfig.length - 6)]) envCallback(cfg[envConfig]); } } function cloneObj (obj, maxDepth) { var clone = {}; for (var p in obj) { var prop = obj[p]; if (maxDepth > 1) { if (prop instanceof Array) clone[p] = [].concat(prop); else if (typeof prop === 'object') clone[p] = cloneObj(prop, maxDepth - 1); else if (p !== 'packageConfig') clone[p] = prop; } else { clone[p] = prop; } } return clone; } function getConfigItem (config, p) { var cfgItem = config[p]; // getConfig must return an unmodifiable clone of the configuration if (cfgItem instanceof Array) return config[p].concat([]); else if (typeof cfgItem === 'object') return cloneObj(cfgItem, 3) else return config[p]; } function getConfig (configName) { if (configName) { if (configNames.indexOf(configName) !== -1) return getConfigItem(this[CONFIG], configName); throw new Error('"' + configName + '" is not a valid configuration name. Must be one of ' + configNames.join(', ') + '.'); } var cfg = {}; for (var i = 0; i < configNames.length; i++) { var p = configNames[i]; var configItem = getConfigItem(this[CONFIG], p); if (configItem !== undefined) cfg[p] = configItem; } return cfg; } function setConfig (cfg, isEnvConfig) { var loader = this; var config = this[CONFIG]; if ('warnings' in cfg) config.warnings = cfg.warnings; if ('wasm' in cfg) config.wasm = typeof WebAssembly !== 'undefined' && cfg.wasm; if ('production' in cfg || 'build' in cfg) setProduction.call(loader, !!cfg.production, !!(cfg.build || envModule && envModule.build)); if (!isEnvConfig) { // if using nodeConfig / browserConfig / productionConfig, take baseURL from there // these exceptions will be unnecessary when we can properly implement config queuings var baseURL; envSet(loader, cfg, function(cfg) { baseURL = baseURL || cfg.baseURL; }); baseURL = baseURL || cfg.baseURL; // always configure baseURL first if (baseURL) { config.baseURL = resolveIfNotPlain(baseURL, baseURI) || resolveIfNotPlain('./' + baseURL, baseURI); if (config.baseURL[config.baseURL.length - 1] !== '/') config.baseURL += '/'; } if (cfg.paths) extend(config.paths, cfg.paths); envSet(loader, cfg, function(cfg) { if (cfg.paths) extend(config.paths, cfg.paths); }); for (var p in config.paths) { if (config.paths[p].indexOf('*') === -1) continue; warn.call(config, 'Path config ' + p + ' -> ' + config.paths[p] + ' is no longer supported as wildcards are deprecated.'); delete config.paths[p]; } } if (cfg.defaultJSExtensions) warn.call(config, 'The defaultJSExtensions configuration option is deprecated.\n Use packages defaultExtension instead.', true); if (typeof cfg.pluginFirst === 'boolean') config.pluginFirst = cfg.pluginFirst; if (cfg.map) { for (var p in cfg.map) { var v = cfg.map[p]; if (typeof v === 'string') { var mapped = coreResolve.call(loader, config, v, undefined, false, false); if (mapped[mapped.length -1] === '/' && p[p.length - 1] !== ':' && p[p.length - 1] !== '/') mapped = mapped.substr(0, mapped.length - 1); config.map[p] = mapped; } // object map else { var pkgName = coreResolve.call(loader, config, p[p.length - 1] !== '/' ? p + '/' : p, undefined, true, true); pkgName = pkgName.substr(0, pkgName.length - 1); var pkg = config.packages[pkgName]; if (!pkg) { pkg = config.packages[pkgName] = createPackage(); // use '' instead of false to keep type consistent pkg.defaultExtension = ''; } setPkgConfig(pkg, { map: v }, pkgName, false, config); } } } if (cfg.packageConfigPaths) { var packageConfigPaths = []; for (var i = 0; i < cfg.packageConfigPaths.length; i++) { var path = cfg.packageConfigPaths[i]; var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/')); var normalized = coreResolve.call(loader, config, path.substr(0, packageLength), undefined, false, false); packageConfigPaths[i] = normalized + path.substr(packageLength); } config.packageConfigPaths = packageConfigPaths; } if (cfg.bundles) { for (var p in cfg.bundles) { var bundle = []; for (var i = 0; i < cfg.bundles[p].length; i++) bundle.push(loader.normalizeSync(cfg.bundles[p][i])); config.bundles[p] = bundle; } } if (cfg.packages) { for (var p in cfg.packages) { if (p.match(/^([^\/]+:)?\/\/$/)) throw new TypeError('"' + p + '" is not a valid package name.'); var pkgName = coreResolve.call(loader, config, p[p.length - 1] !== '/' ? p + '/' : p, undefined, true, true); pkgName = pkgName.substr(0, pkgName.length - 1); setPkgConfig(config.packages[pkgName] = config.packages[pkgName] || createPackage(), cfg.packages[p], pkgName, false, config); } } if (cfg.depCache) { for (var p in cfg.depCache) config.depCache[loader.normalizeSync(p)] = [].concat(cfg.depCache[p]); } if (cfg.meta) { for (var p in cfg.meta) { // base wildcard stays base if (p[0] === '*') { extend(config.meta[p] = config.meta[p] || {}, cfg.meta[p]); } else { var resolved = coreResolve.call(loader, config, p, undefined, true, true); extend(config.meta[resolved] = config.meta[resolved] || {}, cfg.meta[p]); } } } if ('transpiler' in cfg) config.transpiler = cfg.transpiler; // copy any remaining non-standard configuration properties for (var c in cfg) { if (configNames.indexOf(c) !== -1) continue; if (envConfigNames.indexOf(c) !== -1) continue; // warn.call(config, 'Setting custom config option `System.config({ ' + c + ': ... })` is deprecated. Avoid custom config options or set SystemJS.' + c + ' = ... directly.'); loader[c] = cfg[c]; } envSet(loader, cfg, function(cfg) { loader.config(cfg, true); }); } function createPackage () { return { defaultExtension: undefined, main: undefined, format: undefined, meta: undefined, map: undefined, packageConfig: undefined, configured: false }; } // deeply-merge (to first level) config with any existing package config function setPkgConfig (pkg, cfg, pkgName, prependConfig, config) { for (var prop in cfg) { if (prop === 'main' || prop === 'format' || prop === 'defaultExtension' || prop === 'configured') { if (!prependConfig || pkg[prop] === undefined) pkg[prop] = cfg[prop]; } else if (prop === 'map') { (prependConfig ? prepend : extend)(pkg.map = pkg.map || {}, cfg.map); } else if (prop === 'meta') { (prependConfig ? prepend : extend)(pkg.meta = pkg.meta || {}, cfg.meta); } else if (Object.hasOwnProperty.call(cfg, prop)) { warn.call(config, '"' + prop + '" is not a valid package configuration option in package ' + pkgName); } } // default defaultExtension for packages only if (pkg.defaultExtension === undefined) pkg.defaultExtension = 'js'; if (pkg.main === undefined && pkg.map && pkg.map['.']) { pkg.main = pkg.map['.']; delete pkg.map['.']; } // main object becomes main map else if (typeof pkg.main === 'object') { pkg.map = pkg.map || {}; pkg.map['./@main'] = pkg.main; pkg.main['default'] = pkg.main['default'] || './'; pkg.main = '@main'; } return pkg; } var hasBuffer = typeof Buffer !== 'undefined'; try { if (hasBuffer && new Buffer('a').toString('base64') !== 'YQ==') hasBuffer = false; } catch (e) { hasBuffer = false; } var sourceMapPrefix = '\n//# sourceMapping' + 'URL=data:application/json;base64,'; function inlineSourceMap (sourceMapString) { if (hasBuffer) return sourceMapPrefix + new Buffer(sourceMapString).toString('base64'); else if (typeof btoa !== 'undefined') return sourceMapPrefix + btoa(unescape(encodeURIComponent(sourceMapString))); else return ''; } function getSource(source, sourceMap, address, wrap) { var lastLineIndex = source.lastIndexOf('\n'); if (sourceMap) { if (typeof sourceMap != 'object') throw new TypeError('load.metadata.sourceMap must be set to an object.'); sourceMap = JSON.stringify(sourceMap); } return (wrap ? '(function(System, SystemJS) {' : '') + source + (wrap ? '\n})(System, System);' : '') // adds the sourceURL comment if not already present + (source.substr(lastLineIndex, 15) != '\n//# sourceURL=' ? '\n//# sourceURL=' + address + (sourceMap ? '!transpiled' : '') : '') // add sourceMappingURL if load.metadata.sourceMap is set + (sourceMap && inlineSourceMap(sourceMap) || ''); } // script execution via injecting a script tag into the page // this allows CSP nonce to be set for CSP environments var head; function scriptExec(loader, source, sourceMap, address, nonce) { if (!head) head = document.head || document.body || document.documentElement; var script = document.createElement('script'); script.text = getSource(source, sourceMap, address, false); var onerror = window.onerror; var e; window.onerror = function(_e) { e = addToError(_e, 'Evaluating ' + address); if (onerror) onerror.apply(this, arguments); }; preExec(loader); if (nonce) script.setAttribute('nonce', nonce); head.appendChild(script); head.removeChild(script); postExec(); window.onerror = onerror; if (e) return e; } var vm; var useVm; var curSystem; var callCounter = 0; function preExec (loader) { if (callCounter++ == 0) curSystem = envGlobal.System; envGlobal.System = envGlobal.SystemJS = loader; } function postExec () { if (--callCounter == 0) envGlobal.System = envGlobal.SystemJS = curSystem; } var supportsScriptExec = false; if (isBrowser && typeof document != 'undefined' && document.getElementsByTagName) { if (!(window.chrome && window.chrome.extension || navigator.userAgent.match(/^Node\.js/))) supportsScriptExec = true; } function evaluate (loader, source, sourceMap, address, integrity, nonce, noWrap) { if (!source) return; if (nonce && supportsScriptExec) return scriptExec(loader, source, sourceMap, address, nonce); try { preExec(loader); // global scoped eval for node (avoids require scope leak) if (!vm && loader._nodeRequire) { vm = loader._nodeRequire('vm'); useVm = vm.runInThisContext("typeof System !== 'undefined' && System") === loader; } if (useVm) vm.runInThisContext(getSource(source, sourceMap, address, !noWrap), { filename: address + (sourceMap ? '!transpiled' : '') }); else (0, eval)(getSource(source, sourceMap, address, !noWrap)); postExec(); } catch (e) { postExec(); return e; } } var formatHelpers = function (loader) { loader.set('@@cjs-helpers', loader.newModule({ requireResolve: requireResolve.bind(loader), getPathVars: getPathVars })); loader.set('@@global-helpers', loader.newModule({ prepareGlobal: prepareGlobal })); /* AMD-compatible require To copy RequireJS, set window.require = window.requirejs = loader.amdRequire */ function require (names, callback, errback, referer) { // in amd, first arg can be a config object... we just ignore if (typeof names === 'object' && !(names instanceof Array)) return require.apply(null, Array.prototype.splice.call(arguments, 1, arguments.length - 1)); // amd require if (typeof names === 'string' && typeof callback === 'function') names = [names]; if (names instanceof Array) { var dynamicRequires = []; for (var i = 0; i < names.length; i++) dynamicRequires.push(loader.import(names[i], referer)); Promise.all(dynamicRequires).then(function (modules) { if (callback) callback.apply(null, modules); }, errback); } // commonjs require else if (typeof names === 'string') { var normalized = loader.decanonicalize(names, referer); var module = loader.get(normalized); if (!module) throw new Error('Module not already loaded loading "' + names + '" as ' + normalized + (referer ? ' from "' + referer + '".' : '.')); return '__useDefault' in module ? module.__useDefault : module; } else throw new TypeError('Invalid require'); } function define (name, deps, factory) { if (typeof name !== 'string') { factory = deps; deps = name; name = null; } if (!(deps instanceof Array)) { factory = deps; deps = ['require', 'exports', 'module'].splice(0, factory.length); } if (typeof factory !== 'function') factory = (function (factory) { return function() { return factory; } })(factory); if (!name) { if (curMetaDeps) { deps = deps.concat(curMetaDeps); curMetaDeps = undefined; } } // remove system dependencies var requireIndex, exportsIndex, moduleIndex; if ((requireIndex = deps.indexOf('require')) !== -1) { deps.splice(requireIndex, 1); // only trace cjs requires for non-named // named defines assume the trace has already been done if (!name) deps = deps.concat(amdGetCJSDeps(factory.toString(), requireIndex)); } if ((exportsIndex = deps.indexOf('exports')) !== -1) deps.splice(exportsIndex, 1); if ((moduleIndex = deps.indexOf('module')) !== -1) deps.splice(moduleIndex, 1); function execute (req, exports, module) { var depValues = []; for (var i = 0; i < deps.length; i++) depValues.push(req(deps[i])); module.uri = module.id; module.config = noop; // add back in system dependencies if (moduleIndex !== -1) depValues.splice(moduleIndex, 0, module); if (exportsIndex !== -1) depValues.splice(exportsIndex, 0, exports); if (requireIndex !== -1) { var contextualRequire = function (names, callback, errback) { if (typeof names === 'string' && typeof callback !== 'function') return req(names); return require.call(loader, names, callback, errback, module.id); }; contextualRequire.toUrl = function (name) { return loader.normalizeSync(name, module.id); }; depValues.splice(requireIndex, 0, contextualRequire); } // set global require to AMD require var curRequire = envGlobal.require; envGlobal.require = require; var output = factory.apply(exportsIndex === -1 ? envGlobal : exports, depValues); envGlobal.require = curRequire; if (typeof output !== 'undefined') module.exports = output; } // anonymous define if (!name) { loader.registerDynamic(deps, false, curEsModule ? wrapEsModuleExecute(execute) : execute); } else { loader.registerDynamic(name, deps, false, execute); // if we don't have any other defines, // then let this be an anonymous define // this is just to support single modules of the form: // define('jquery') // still loading anonymously // because it is done widely enough to be useful // as soon as there is more than one define, this gets removed though if (lastNamedDefine) { lastNamedDefine = undefined; multipleNamedDefines = true; } else if (!multipleNamedDefines) { lastNamedDefine = [deps, execute]; } } } define.amd = {}; loader.amdDefine = define; loader.amdRequire = require; }; // CJS var windowOrigin; if (typeof window !== 'undefined' && typeof document !== 'undefined' && window.location) windowOrigin = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : ''); function stripOrigin(path) { if (path.substr(0, 8) === 'file:///') return path.substr(7 + !!isWindows); if (windowOrigin && path.substr(0, windowOrigin.length) === windowOrigin) return path.substr(windowOrigin.length); return path; } function requireResolve (request, parentId) { return stripOrigin(this.normalizeSync(request, parentId)); } function getPathVars (moduleId) { // remove any plugin syntax var pluginIndex = moduleId.lastIndexOf('!'); var filename; if (pluginIndex !== -1) filename = moduleId.substr(0, pluginIndex); else filename = moduleId; var dirname = filename.split('/'); dirname.pop(); dirname = dirname.join('/'); return { filename: stripOrigin(filename), dirname: stripOrigin(dirname) }; } var commentRegEx$1 = /(^|[^\\])(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg; var stringRegEx$1 = /("[^"\\\n\r]*(\\.[^"\\\n\r]*)*"|'[^'\\\n\r]*(\\.[^'\\\n\r]*)*')/g; // extract CJS dependencies from source text via regex static analysis // read require('x') statements not in comments or strings function getCJSDeps (source) { cjsRequireRegEx.lastIndex = commentRegEx$1.lastIndex = stringRegEx$1.lastIndex = 0; var deps = []; var match; // track string and comment locations for unminified source var stringLocations = [], commentLocations = []; function inLocation (locations, match) { for (var i = 0; i < locations.length; i++) if (locations[i][0] < match.index && locations[i][1] > match.index) return true; return false; } if (source.length / source.split('\n').length < 200) { while (match = stringRegEx$1.exec(source)) stringLocations.push([match.index, match.index + match[0].length]); // TODO: track template literals here before comments while (match = commentRegEx$1.exec(source)) { // only track comments not starting in strings if (!inLocation(stringLocations, match)) commentLocations.push([match.index + match[1].length, match.index + match[0].length - 1]); } } while (match = cjsRequireRegEx.exec(source)) { // ensure we're not within a string or comment location if (!inLocation(stringLocations, match) && !inLocation(commentLocations, match)) { var dep = match[1].substr(1, match[1].length - 2); // skip cases like require('" + file + "') if (dep.match(/"|'/)) continue; deps.push(dep); } } return deps; } // Global // bare minimum ignores var ignoredGlobalProps = ['_g', 'sessionStorage', 'localStorage', 'clipboardData', 'frames', 'frameElement', 'external', 'mozAnimationStartTime', 'webkitStorageInfo', 'webkitIndexedDB', 'mozInnerScreenY', 'mozInnerScreenX']; var globalSnapshot; function globalIterator (globalName) { if (ignoredGlobalProps.indexOf(globalName) !== -1) return; try { var value = envGlobal[globalName]; } catch (e) { ignoredGlobalProps.push(globalName); } this(globalName, value); } function getGlobalValue (exports) { if (typeof exports === 'string') return readMemberExpression(exports, envGlobal); if (!(exports instanceof Array)) throw new Error('Global exports must be a string or array.'); var globalValue = {}; for (var i = 0; i < exports.length; i++) globalValue[exports[i].split('.').pop()] = readMemberExpression(exports[i], envGlobal); return globalValue; } function prepareGlobal (moduleName, exports, globals, encapsulate) { // disable module detection var curDefine = envGlobal.define; envGlobal.define = undefined; // set globals var oldGlobals; if (globals) { oldGlobals = {}; for (var g in globals) { oldGlobals[g] = envGlobal[g]; envGlobal[g] = globals[g]; } } // store a complete copy of the global object in order to detect changes if (!exports) { globalSnapshot = {}; Object.keys(envGlobal).forEach(globalIterator, function (name, value) { globalSnapshot[name] = value; }); } // return function to retrieve global return function () { var globalValue = exports ? getGlobalValue(exports) : {}; var singleGlobal; var multipleExports = !!exports; if (!exports || encapsulate) Object.keys(envGlobal).forEach(globalIterator, function (name, value) { if (globalSnapshot[name] === value) return; if (value === undefined) return; // allow global encapsulation where globals are removed if (encapsulate) envGlobal[name] = undefined; if (!exports) { globalValue[name] = value; if (singleGlobal !== undefined) { if (!multipleExports && singleGlobal !== value) multipleExports = true; } else { singleGlobal = value; } } }); globalValue = multipleExports ? globalValue : singleGlobal; // revert globals if (oldGlobals) { for (var g in oldGlobals) envGlobal[g] = oldGlobals[g]; } envGlobal.define = curDefine; return globalValue; }; } // AMD var cjsRequirePre = "(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])"; var cjsRequirePost = "\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)"; var fnBracketRegEx = /\(([^\)]*)\)/; var wsRegEx = /^\s+|\s+$/g; var requireRegExs = {}; function amdGetCJSDeps(source, requireIndex) { // remove comments source = source.replace(commentRegEx$1, ''); // determine the require alias var params = source.match(fnBracketRegEx); var requireAlias = (params[1].split(',')[requireIndex] || 'require').replace(wsRegEx, ''); // find or generate the regex for this requireAlias var requireRegEx = requireRegExs[requireAlias] || (requireRegExs[requireAlias] = new RegExp(cjsRequirePre + requireAlias + cjsRequirePost, 'g')); requireRegEx.lastIndex = 0; var deps = []; var match; while (match = requireRegEx.exec(source)) deps.push(match[2] || match[3]); return deps; } function wrapEsModuleExecute (execute) { return function (require, exports, module) { execute(require, exports, module); exports = module.exports; if ((typeof exports === 'object' || typeof exports === 'function') && !('__esModule' in exports)) Object.defineProperty(module.exports, '__esModule', { value: true }); }; } // generate anonymous define from singular named define var multipleNamedDefines = false; var lastNamedDefine; var curMetaDeps; var curEsModule = false; function clearLastDefine (metaDeps, esModule) { curMetaDeps = metaDeps; curEsModule = esModule; lastNamedDefine = undefined; multipleNamedDefines = false; } function registerLastDefine (loader) { if (lastNamedDefine) loader.registerDynamic(curMetaDeps ? lastNamedDefine[0].concat(curMetaDeps) : lastNamedDefine[0], false, curEsModule ? wrapEsModuleExecute(lastNamedDefine[1]) : lastNamedDefine[1]); // bundles are an empty module else if (multipleNamedDefines) loader.registerDynamic([], false, noop); } var supportsScriptLoad = (isBrowser || isWorker) && typeof navigator !== 'undefined' && navigator.userAgent && !navigator.userAgent.match(/MSIE (9|10).0/); // include the node require since we're overriding it var nodeRequire; if (typeof require !== 'undefined' && typeof process !== 'undefined' && !process.browser) nodeRequire = require; function setMetaEsModule (metadata, moduleValue) { if (metadata.load.esModule && (typeof moduleValue === 'object' || typeof moduleValue === 'function') && !('__esModule' in moduleValue)) Object.defineProperty(moduleValue, '__esModule', { value: true }); } function instantiate$1 (key, processAnonRegister) { var loader = this; var config = this[CONFIG]; // first do bundles and depCache return (loadBundlesAndDepCache(config, this, key) || resolvedPromise) .then(function () { if (processAnonRegister()) return; var metadata = loader[METADATA][key]; // node module loading if (key.substr(0, 6) === '@node/') { if (!loader._nodeRequire) throw new TypeError('Error loading ' + key + '. Can only load node core modules in Node.'); loader.registerDynamic([], false, function () { return loadNodeModule.call(loader, key.substr(6), loader.baseURL); }); processAnonRegister(); return; } if (metadata.load.scriptLoad ) { if (metadata.load.pluginKey || !supportsScriptLoad) { metadata.load.scriptLoad = false; warn.call(config, 'scriptLoad not supported for "' + key + '"'); } } else if (metadata.load.scriptLoad !== false && !metadata.load.pluginKey && supportsScriptLoad) { // auto script load AMD, global without deps if (!metadata.load.deps && !metadata.load.globals && (metadata.load.format === 'system' || metadata.load.format === 'register' || metadata.load.format === 'global' && metadata.load.exports)) metadata.load.scriptLoad = true; } // fetch / translate / instantiate pipeline if (!metadata.load.scriptLoad) return initializePlugin(loader, key, metadata) .then(function () { return runFetchPipeline(loader, key, metadata, processAnonRegister, config.wasm); }) // just script loading return new Promise(function (resolve, reject) { if (metadata.load.format === 'amd' && envGlobal.define !== loader.amdDefine) throw new Error('Loading AMD with scriptLoad requires setting the global `' + globalName + '.define = SystemJS.amdDefine`'); scriptLoad(key, metadata.load.crossOrigin, metadata.load.integrity, function () { if (!processAnonRegister()) { metadata.load.format = 'global'; var globalValue = metadata.load.exports && getGlobalValue(metadata.load.exports); loader.registerDynamic([], false, function () { setMetaEsModule(metadata, globalValue); return globalValue; }); processAnonRegister(); } resolve(); }, reject); }); }) .then(function (instantiated) { delete loader[METADATA][key]; return instantiated; }); } function initializePlugin (loader, key, metadata) { if (!metadata.pluginKey) return resolvedPromise; return loader.import(metadata.pluginKey).then(function (plugin) { metadata.pluginModule = plugin; metadata.pluginLoad = { name: key, address: metadata.pluginArgument, source: undefined, metadata: metadata.load }; metadata.load.deps = metadata.load.deps || []; }); } function loadBundlesAndDepCache (config, loader, key) { // load direct deps, in turn will pick up their trace trees var deps = config.depCache[key]; if (deps) { for (var i = 0; i < deps.length; i++) loader.normalize(deps[i], key).then(preloadScript); } else { var matched = false; for (var b in config.bundles) { for (var i = 0; i < config.bundles[b].length; i++) { var curModule = config.bundles[b][i]; if (curModule === key) { matched = true; break; } // wildcard in bundles includes / boundaries if (curModule.indexOf('*') !== -1) { var parts = curModule.split('*'); if (parts.length !== 2) { config.bundles[b].splice(i--, 1); continue; } if (key.substr(0, parts[0].length) === parts[0] && key.substr(key.length - parts[1].length, parts[1].length) === parts[1]) { matched = true; break; } } } if (matched) return loader.import(b); } } } function runFetchPipeline (loader, key, metadata, processAnonRegister, wasm) { if (metadata.load.exports && !metadata.load.format) metadata.load.format = 'global'; return resolvedPromise // locate .then(function () { if (!metadata.pluginModule || !metadata.pluginModule.locate) return; return Promise.resolve(metadata.pluginModule.locate.call(loader, metadata.pluginLoad)) .then(function (address) { if (address) metadata.pluginLoad.address = address; }); }) // fetch .then(function () { if (!metadata.pluginModule) return fetch$1(key, metadata.load.authorization, metadata.load.integrity, wasm); wasm = false; if (!metadata.pluginModule.fetch) return fetch$1(metadata.pluginLoad.address, metadata.load.authorization, metadata.load.integrity, false); return metadata.pluginModule.fetch.call(loader, metadata.pluginLoad, function (load) { return fetch$1(load.address, metadata.load.authorization, metadata.load.integrity, false); }); }) .then(function (fetched) { // fetch is already a utf-8 string if not doing wasm detection if (!wasm || typeof fetched === 'string') return translateAndInstantiate(loader, key, fetched, metadata, processAnonRegister); return checkInstantiateWasm(loader, fetched, processAnonRegister) .then(function (wasmInstantiated) { if (wasmInstantiated) return; // not wasm -> convert buffer into utf-8 string to execute as a module // TextDecoder compatibility matches WASM currently. Need to keep checking this. // The TextDecoder interface is documented at http://encoding.spec.whatwg.org/#interface-textdecoder var stringSource = isBrowser ? new TextDecoder('utf-8').decode(new Uint8Array(fetched)) : fetched.toString(); return translateAndInstantiate(loader, key, stringSource, metadata, processAnonRegister); }); }); } function translateAndInstantiate (loader, key, source, metadata, processAnonRegister) { return Promise.resolve(source) // translate .then(function (source) { if (metadata.load.format === 'detect') metadata.load.format = undefined; readMetaSyntax(source, metadata); if (!metadata.pluginModule) return source; metadata.pluginLoad.source = source; if (!metadata.pluginModule.translate) return source; return Promise.resolve(metadata.pluginModule.translate.call(loader, metadata.pluginLoad, metadata.traceOpts)) .then(function (translated) { if (metadata.load.sourceMap) { if (typeof metadata.load.sourceMap !== 'object') throw new Error('metadata.load.sourceMap must be set to an object.'); sanitizeSourceMap(metadata.pluginLoad.address, metadata.load.sourceMap); } if (typeof translated === 'string') return translated; else return metadata.pluginLoad.source; }); }) .then(function (source) { if (!metadata.load.format && source.substring(0, 8) === '"bundle"') { metadata.load.format = 'system'; return source; } if (metadata.load.format === 'register' || !metadata.load.format && detectRegisterFormat(source)) { metadata.load.format = 'register'; return source; } if (metadata.load.format !== 'esm' && (metadata.load.format || !source.match(esmRegEx))) { return source; } metadata.load.format = 'esm'; return transpile(loader, source, key, metadata, processAnonRegister); }) // instantiate .then(function (translated) { if (typeof translated !== 'string' || !metadata.pluginModule || !metadata.pluginModule.instantiate) return translated; var calledInstantiate = false; metadata.pluginLoad.source = translated; return Promise.resolve(metadata.pluginModule.instantiate.call(loader, metadata.pluginLoad, function (load) { translated = load.source; metadata.load = load.metadata; if (calledInstantiate) throw new Error('Instantiate must only be called once.'); calledInstantiate = true; })) .then(function (result) { if (calledInstantiate) return translated; return protectedCreateNamespace(result); }); }) .then(function (source) { // plugin instantiate result case if (typeof source !== 'string') return source; if (!metadata.load.format) metadata.load.format = detectLegacyFormat(source); var registered = false; switch (metadata.load.format) { case 'esm': case 'register': case 'system': var err = evaluate(loader, source, metadata.load.sourceMap, key, metadata.load.integrity, metadata.load.nonce, false); if (err) throw err; if (!processAnonRegister()) return emptyModule; return; break; case 'json': // warn.call(config, '"json" module format is deprecated.'); var parsed = JSON.parse(source); return loader.newModule({ default: parsed, __useDefault: parsed }); case 'amd': var curDefine = envGlobal.define; envGlobal.define = loader.amdDefine; clearLastDefine(metadata.load.deps, metadata.load.esModule); var err = evaluate(loader, source, metadata.load.sourceMap, key, metadata.load.integrity, metadata.load.nonce, false); // if didn't register anonymously, use the last named define if only one registered = processAnonRegister(); if (!registered) { registerLastDefine(loader); registered = processAnonRegister(); } envGlobal.define = curDefine; if (err) throw err; break; case 'cjs': var metaDeps = metadata.load.deps; var deps = (metadata.load.deps || []).concat(metadata.load.cjsRequireDetection ? getCJSDeps(source) : []); for (var g in metadata.load.globals) if (metadata.load.globals[g]) deps.push(metadata.load.globals[g]); loader.registerDynamic(deps, true, function (require, exports, module) { require.resolve = function (key) { return requireResolve.call(loader, key, module.id); }; // support module.paths ish module.paths = []; module.require = require; // ensure meta deps execute first if (!metadata.load.cjsDeferDepsExecute && metaDeps) for (var i = 0; i < metaDeps.length; i++) require(metaDeps[i]); var pathVars = getPathVars(module.id); var __cjsWrapper = { exports: exports, args: [require, exports, module, pathVars.filename, pathVars.dirname, envGlobal, envGlobal] }; var cjsWrapper = "(function (require, exports, module, __filename, __dirname, global, GLOBAL"; // add metadata.globals to the wrapper arguments if (metadata.load.globals) for (var g in metadata.load.globals) { __cjsWrapper.args.push(require(metadata.load.globals[g])); cjsWrapper += ", " + g; } // disable AMD detection var define = envGlobal.define; envGlobal.define = undefined; envGlobal.__cjsWrapper = __cjsWrapper; source = cjsWrapper + ") {" + source.replace(hashBangRegEx, '') + "\n}).apply(__cjsWrapper.exports, __cjsWrapper.args);"; var err = evaluate(loader, source, metadata.load.sourceMap, key, metadata.load.integrity, metadata.load.nonce, false); if (err) throw err; setMetaEsModule(metadata, exports); envGlobal.__cjsWrapper = undefined; envGlobal.define = define; }); registered = processAnonRegister(); break; case 'global': var deps = metadata.load.deps || []; for (var g in metadata.load.globals) { var gl = metadata.load.globals[g]; if (gl) deps.push(gl); } loader.registerDynamic(deps, false, function (require, exports, module) { var globals; if (metadata.load.globals) { globals = {}; for (var g in metadata.load.globals) if (metadata.load.globals[g]) globals[g] = require(metadata.load.globals[g]); } var exportName = metadata.load.exports; if (exportName) source += '\n' + globalName + '["' + exportName + '"] = ' + exportName + ';'; var retrieveGlobal = prepareGlobal(module.id, exportName, globals, metadata.load.encapsulateGlobal); var err = evaluate(loader, source, metadata.load.sourceMap, key, metadata.load.integrity, metadata.load.nonce, true); if (err) throw err; var output = retrieveGlobal(); setMetaEsModule(metadata, output); return output; }); registered = processAnonRegister(); break; default: throw new TypeError('Unknown module format "' + metadata.load.format + '" for "' + key + '".' + (metadata.load.format === 'es6' ? ' Use "esm" instead here.' : '')); } if (!registered) throw new Error('Module ' + key + ' detected as ' + metadata.load.format + ' but didn\'t execute correctly.'); }); } var globalName = typeof self != 'undefined' ? 'self' : 'global'; // good enough ES6 module detection regex - format detections not designed to be accurate, but to handle the 99% use case var esmRegEx = /(^\s*|[}\);\n]\s*)(import\s*(['"]|(\*\s+as\s+)?(?!type)([^"'\(\)\n; ]+)\s*from\s*['"]|\{)|export\s+\*\s+from\s+["']|export\s*(\{|default|function|class|var|const|let|async\s+function))/; var leadingCommentAndMetaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)*\s*/; function detectRegisterFormat(source) { var leadingCommentAndMeta = source.match(leadingCommentAndMetaRegEx); return leadingCommentAndMeta && source.substr(leadingCommentAndMeta[0].length, 15) === 'System.register'; } // AMD Module Format Detection RegEx // define([.., .., ..], ...) // define(varName); || define(function(require, exports) {}); || define({}) var amdRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])define\s*\(\s*("[^"]+"\s*,\s*|'[^']+'\s*,\s*)?\s*(\[(\s*(("[^"]+"|'[^']+')\s*,|\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*(\s*("[^"]+"|'[^']+')\s*,?)?(\s*(\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*\s*\]|function\s*|{|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*\))/; /// require('...') || exports[''] = ... || exports.asd = ... || module.exports = ... var cjsExportsRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])(exports\s*(\[['"]|\.)|module(\.exports|\['exports'\]|\["exports"\])\s*(\[['"]|[=,\.]))/; // used to support leading #!/usr/bin/env in scripts as supported in Node var hashBangRegEx = /^\#\!.*/; function detectLegacyFormat (source) { if (source.match(amdRegEx)) return 'amd'; cjsExportsRegEx.lastIndex = 0; cjsRequireRegEx.lastIndex = 0; if (cjsRequireRegEx.exec(source) || cjsExportsRegEx.exec(source)) return 'cjs'; // global is the fallback format return 'global'; } function sanitizeSourceMap (address, sourceMap) { var originalName = address.split('!')[0]; // force set the filename of the original file if (!sourceMap.file || sourceMap.file == address) sourceMap.file = originalName + '!transpiled'; // force set the sources list if only one source if (!sourceMap.sources || sourceMap.sources.length <= 1 && (!sourceMap.sources[0] || sourceMap.sources[0] === address)) sourceMap.sources = [originalName]; } function transpile (loader, source, key, metadata, processAnonRegister) { if (!loader.transpiler) throw new TypeError('Unable to dynamically transpile ES module\n A loader plugin needs to be configured via `SystemJS.config({ transpiler: \'transpiler-module\' })`.'); // deps support for es transpile if (metadata.load.deps) { var depsPrefix = ''; for (var i = 0; i < metadata.load.deps.length; i++) depsPrefix += 'import "' + metadata.load.deps[i] + '"; '; source = depsPrefix + source; } // do transpilation return loader.import.call(loader, loader.transpiler) .then(function (transpiler) { transpiler = transpiler.__useDefault || transpiler; // translate hooks means this is a transpiler plugin instead of a raw implementation if (!transpiler.translate) throw new Error(loader.transpiler + ' is not a valid transpiler plugin.'); // if transpiler is the same as the plugin loader, then don't run twice if (transpiler === metadata.pluginModule) return source; // convert the source map into an object for transpilation chaining if (typeof metadata.load.sourceMap === 'string') metadata.load.sourceMap = JSON.parse(metadata.load.sourceMap); metadata.pluginLoad = metadata.pluginLoad || { name: key, address: key, source: source, metadata: metadata.load }; metadata.load.deps = metadata.load.deps || []; return Promise.resolve(transpiler.translate.call(loader, metadata.pluginLoad, metadata.traceOpts)) .then(function (source) { // sanitize sourceMap if an object not a JSON string var sourceMap = metadata.load.sourceMap; if (sourceMap && typeof sourceMap === 'object') sanitizeSourceMap(key, sourceMap); if (metadata.load.format === 'esm' && detectRegisterFormat(source)) metadata.load.format = 'register'; return source; }); }, function (err) { throw LoaderError__Check_error_message_for_loader_stack(err, 'Unable to load transpiler to transpile ' + key); }); } // detect any meta header syntax // only set if not already set var metaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/; var metaPartRegEx = /\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g; function setMetaProperty(target, p, value) { var pParts = p.split('.'); var curPart; while (pParts.length > 1) { curPart = pParts.shift(); target = target[curPart] = target[curPart] || {}; } curPart = pParts.shift(); if (target[curPart] === undefined) target[curPart] = value; } function readMetaSyntax (source, metadata) { var meta = source.match(metaRegEx); if (!meta) return; var metaParts = meta[0].match(metaPartRegEx); for (var i = 0; i < metaParts.length; i++) { var curPart = metaParts[i]; var len = curPart.length; var firstChar = curPart.substr(0, 1); if (curPart.substr(len - 1, 1) == ';') len--; if (firstChar != '"' && firstChar != "'") continue; var metaString = curPart.substr(1, curPart.length - 3); var metaName = metaString.substr(0, metaString.indexOf(' ')); if (metaName) { var metaValue = metaString.substr(metaName.length + 1, metaString.length - metaName.length - 1); if (metaName === 'deps') metaName = 'deps[]'; if (metaName.substr(metaName.length - 2, 2) === '[]') { metaName = metaName.substr(0, metaName.length - 2); metadata.load[metaName] = metadata.load[metaName] || []; metadata.load[metaName].push(metaValue); } // "use strict" is not meta else if (metaName !== 'use') { setMetaProperty(metadata.load, metaName, metaValue); } } else { metadata.load[metaString] = true; } } } var scriptSrc; // Promise detection and error message if (typeof Promise === 'undefined') throw new Error('SystemJS needs a Promise polyfill.'); if (typeof document !== 'undefined') { var scripts = document.getElementsByTagName('script'); var curScript = scripts[scripts.length - 1]; if (document.currentScript && (curScript.defer || curScript.async)) curScript = document.currentScript; scriptSrc = curScript && curScript.src; } // worker else if (typeof importScripts !== 'undefined') { try { throw new Error('_'); } catch (e) { e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/, function(m, url) { scriptSrc = url; }); } } // node else if (typeof __filename !== 'undefined') { scriptSrc = __filename; } function SystemJSLoader$1 () { RegisterLoader$1.call(this); // NB deprecate this._loader = {}; // internal metadata store this[METADATA] = {}; // internal configuration this[CONFIG] = { baseURL: baseURI, paths: {}, packageConfigPaths: [], packageConfigKeys: [], map: {}, packages: {}, depCache: {}, meta: {}, bundles: {}, production: false, transpiler: undefined, loadedBundles: {}, // global behaviour flags warnings: false, pluginFirst: false, // enable wasm loading and detection when supported wasm: false }; // make the location of the system.js script accessible (if any) this.scriptSrc = scriptSrc; this._nodeRequire = nodeRequire; // support the empty module, as a concept this.registry.set('@empty', emptyModule); setProduction.call(this, false, false); // add module format helpers formatHelpers(this); } var envModule; function setProduction (isProduction, isBuilder) { this[CONFIG].production = isProduction; this.registry.set('@system-env', envModule = this.newModule({ browser: isBrowser, node: !!this._nodeRequire, production: !isBuilder && isProduction, dev: isBuilder || !isProduction, build: isBuilder, 'default': true })); } SystemJSLoader$1.prototype = Object.create(RegisterLoader$1.prototype); SystemJSLoader$1.prototype.constructor = SystemJSLoader$1; // NB deprecate normalize SystemJSLoader$1.prototype[SystemJSLoader$1.resolve = RegisterLoader$1.resolve] = SystemJSLoader$1.prototype.normalize = normalize; SystemJSLoader$1.prototype.load = function (key, parentKey) { warn.call(this[CONFIG], 'System.load is deprecated.'); return this.import(key, parentKey); }; // NB deprecate decanonicalize, normalizeSync SystemJSLoader$1.prototype.decanonicalize = SystemJSLoader$1.prototype.normalizeSync = SystemJSLoader$1.prototype.resolveSync = normalizeSync; SystemJSLoader$1.prototype[SystemJSLoader$1.instantiate = RegisterLoader$1.instantiate] = instantiate$1; SystemJSLoader$1.prototype.config = setConfig; SystemJSLoader$1.prototype.getConfig = getConfig; SystemJSLoader$1.prototype.global = envGlobal; SystemJSLoader$1.prototype.import = function () { return RegisterLoader$1.prototype.import.apply(this, arguments) .then(function (m) { return '__useDefault' in m ? m.__useDefault : m; }); }; var configNames = ['baseURL', 'map', 'paths', 'packages', 'packageConfigPaths', 'depCache', 'meta', 'bundles', 'transpiler', 'warnings', 'pluginFirst', 'production', 'wasm']; var hasProxy = typeof Proxy !== 'undefined'; for (var i = 0; i < configNames.length; i++) (function (configName) { Object.defineProperty(SystemJSLoader$1.prototype, configName, { get: function () { var cfg = getConfigItem(this[CONFIG], configName); if (hasProxy && typeof cfg === 'object') cfg = new Proxy(cfg, { set: function (target, option) { throw new Error('Cannot set SystemJS.' + configName + '["' + option + '"] directly. Use SystemJS.config({ ' + configName + ': { "' + option + '": ... } }) rather.'); } }); //if (typeof cfg === 'object') // warn.call(this[CONFIG], 'Referencing `SystemJS.' + configName + '` is deprecated. Use the config getter `SystemJS.getConfig(\'' + configName + '\')`'); return cfg; }, set: function (name) { throw new Error('Setting `SystemJS.' + configName + '` directly is no longer supported. Use `SystemJS.config({ ' + configName + ': ... })`.'); } }); })(configNames[i]); /* * Backwards-compatible registry API, to be deprecated */ function registryWarn(loader, method) { warn.call(loader[CONFIG], 'SystemJS.' + method + ' is deprecated for SystemJS.registry.' + method); } SystemJSLoader$1.prototype.delete = function (key) { registryWarn(this, 'delete'); return this.registry.delete(key); }; SystemJSLoader$1.prototype.get = function (key) { registryWarn(this, 'get'); return this.registry.get(key); }; SystemJSLoader$1.prototype.has = function (key) { registryWarn(this, 'has'); return this.registry.has(key); }; SystemJSLoader$1.prototype.set = function (key, module) { registryWarn(this, 'set'); return this.registry.set(key, module); }; SystemJSLoader$1.prototype.newModule = function (bindings) { return new ModuleNamespace(bindings); }; SystemJSLoader$1.prototype.isModule = isModule; // ensure System.register and System.registerDynamic decanonicalize SystemJSLoader$1.prototype.register = function (key, deps, declare) { if (typeof key === 'string') key = decanonicalize.call(this, this[CONFIG], key); return RegisterLoader$1.prototype.register.call(this, key, deps, declare); }; SystemJSLoader$1.prototype.registerDynamic = function (key, deps, executingRequire, execute) { if (typeof key === 'string') key = decanonicalize.call(this, this[CONFIG], key); return RegisterLoader$1.prototype.registerDynamic.call(this, key, deps, executingRequire, execute); }; SystemJSLoader$1.prototype.version = "0.20.19 Dev"; var System = new SystemJSLoader$1(); // only set the global System on the global in browsers if (isBrowser || isWorker) envGlobal.SystemJS = envGlobal.System = System; if (typeof module !== 'undefined' && module.exports) module.exports = System; }()); }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/systemjs/dist/system.src.js") },{"_process":3,"buffer":4,"fs":2}],8:[function(require,module,exports){ (function(self) { 'use strict'; if (self.fetch) { return } var support = { searchParams: 'URLSearchParams' in self, iterable: 'Symbol' in self && 'iterator' in Symbol, blob: 'FileReader' in self && 'Blob' in self && (function() { try { new Blob() return true } catch(e) { return false } })(), formData: 'FormData' in self, arrayBuffer: 'ArrayBuffer' in self } if (support.arrayBuffer) { var viewClasses = [ '[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]' ] var isDataView = function(obj) { return obj && DataView.prototype.isPrototypeOf(obj) } var isArrayBufferView = ArrayBuffer.isView || function(obj) { return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 } } function normalizeName(name) { if (typeof name !== 'string') { name = String(name) } if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name') } return name.toLowerCase() } function normalizeValue(value) { if (typeof value !== 'string') { value = String(value) } return value } // Build a destructive iterator for the value list function iteratorFor(items) { var iterator = { next: function() { var value = items.shift() return {done: value === undefined, value: value} } } if (support.iterable) { iterator[Symbol.iterator] = function() { return iterator } } return iterator } function Headers(headers) { this.map = {} if (headers instanceof Headers) { headers.forEach(function(value, name) { this.append(name, value) }, this) } else if (Array.isArray(headers)) { headers.forEach(function(header) { this.append(header[0], header[1]) }, this) } else if (headers) { Object.getOwnPropertyNames(headers).forEach(function(name) { this.append(name, headers[name]) }, this) } } Headers.prototype.append = function(name, value) { name = normalizeName(name) value = normalizeValue(value) var oldValue = this.map[name] this.map[name] = oldValue ? oldValue+','+value : value } Headers.prototype['delete'] = function(name) { delete this.map[normalizeName(name)] } Headers.prototype.get = function(name) { name = normalizeName(name) return this.has(name) ? this.map[name] : null } Headers.prototype.has = function(name) { return this.map.hasOwnProperty(normalizeName(name)) } Headers.prototype.set = function(name, value) { this.map[normalizeName(name)] = normalizeValue(value) } Headers.prototype.forEach = function(callback, thisArg) { for (var name in this.map) { if (this.map.hasOwnProperty(name)) { callback.call(thisArg, this.map[name], name, this) } } } Headers.prototype.keys = function() { var items = [] this.forEach(function(value, name) { items.push(name) }) return iteratorFor(items) } Headers.prototype.values = function() { var items = [] this.forEach(function(value) { items.push(value) }) return iteratorFor(items) } Headers.prototype.entries = function() { var items = [] this.forEach(function(value, name) { items.push([name, value]) }) return iteratorFor(items) } if (support.iterable) { Headers.prototype[Symbol.iterator] = Headers.prototype.entries } function consumed(body) { if (body.bodyUsed) { return Promise.reject(new TypeError('Already read')) } body.bodyUsed = true } function fileReaderReady(reader) { return new Promise(function(resolve, reject) { reader.onload = function() { resolve(reader.result) } reader.onerror = function() { reject(reader.error) } }) } function readBlobAsArrayBuffer(blob) { var reader = new FileReader() var promise = fileReaderReady(reader) reader.readAsArrayBuffer(blob) return promise } function readBlobAsText(blob) { var reader = new FileReader() var promise = fileReaderReady(reader) reader.readAsText(blob) return promise } function readArrayBufferAsText(buf) { var view = new Uint8Array(buf) var chars = new Array(view.length) for (var i = 0; i < view.length; i++) { chars[i] = String.fromCharCode(view[i]) } return chars.join('') } function bufferClone(buf) { if (buf.slice) { return buf.slice(0) } else { var view = new Uint8Array(buf.byteLength) view.set(new Uint8Array(buf)) return view.buffer } } function Body() { this.bodyUsed = false this._initBody = function(body) { this._bodyInit = body if (!body) { this._bodyText = '' } else if (typeof body === 'string') { this._bodyText = body } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { this._bodyBlob = body } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { this._bodyFormData = body } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this._bodyText = body.toString() } else if (support.arrayBuffer && support.blob && isDataView(body)) { this._bodyArrayBuffer = bufferClone(body.buffer) // IE 10-11 can't handle a DataView body. this._bodyInit = new Blob([this._bodyArrayBuffer]) } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { this._bodyArrayBuffer = bufferClone(body) } else { throw new Error('unsupported BodyInit type') } if (!this.headers.get('content-type')) { if (typeof body === 'string') { this.headers.set('content-type', 'text/plain;charset=UTF-8') } else if (this._bodyBlob && this._bodyBlob.type) { this.headers.set('content-type', this._bodyBlob.type) } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8') } } } if (support.blob) { this.blob = function() { var rejected = consumed(this) if (rejected) { return rejected } if (this._bodyBlob) { return Promise.resolve(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(new Blob([this._bodyArrayBuffer])) } else if (this._bodyFormData) { throw new Error('could not read FormData body as blob') } else { return Promise.resolve(new Blob([this._bodyText])) } } this.arrayBuffer = function() { if (this._bodyArrayBuffer) { return consumed(this) || Promise.resolve(this._bodyArrayBuffer) } else { return this.blob().then(readBlobAsArrayBuffer) } } } this.text = function() { var rejected = consumed(this) if (rejected) { return rejected } if (this._bodyBlob) { return readBlobAsText(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) } else if (this._bodyFormData) { throw new Error('could not read FormData body as text') } else { return Promise.resolve(this._bodyText) } } if (support.formData) { this.formData = function() { return this.text().then(decode) } } this.json = function() { return this.text().then(JSON.parse) } return this } // HTTP methods whose capitalization should be normalized var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] function normalizeMethod(method) { var upcased = method.toUpperCase() return (methods.indexOf(upcased) > -1) ? upcased : method } function Request(input, options) { options = options || {} var body = options.body if (input instanceof Request) { if (input.bodyUsed) { throw new TypeError('Already read') } this.url = input.url this.credentials = input.credentials if (!options.headers) { this.headers = new Headers(input.headers) } this.method = input.method this.mode = input.mode if (!body && input._bodyInit != null) { body = input._bodyInit input.bodyUsed = true } } else { this.url = String(input) } this.credentials = options.credentials || this.credentials || 'omit' if (options.headers || !this.headers) { this.headers = new Headers(options.headers) } this.method = normalizeMethod(options.method || this.method || 'GET') this.mode = options.mode || this.mode || null this.referrer = null if ((this.method === 'GET' || this.method === 'HEAD') && body) { throw new TypeError('Body not allowed for GET or HEAD requests') } this._initBody(body) } Request.prototype.clone = function() { return new Request(this, { body: this._bodyInit }) } function decode(body) { var form = new FormData() body.trim().split('&').forEach(function(bytes) { if (bytes) { var split = bytes.split('=') var name = split.shift().replace(/\+/g, ' ') var value = split.join('=').replace(/\+/g, ' ') form.append(decodeURIComponent(name), decodeURIComponent(value)) } }) return form } function parseHeaders(rawHeaders) { var headers = new Headers() // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space // https://tools.ietf.org/html/rfc7230#section-3.2 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ') preProcessedHeaders.split(/\r?\n/).forEach(function(line) { var parts = line.split(':') var key = parts.shift().trim() if (key) { var value = parts.join(':').trim() headers.append(key, value) } }) return headers } Body.call(Request.prototype) function Response(bodyInit, options) { if (!options) { options = {} } this.type = 'default' this.status = options.status === undefined ? 200 : options.status this.ok = this.status >= 200 && this.status < 300 this.statusText = 'statusText' in options ? options.statusText : 'OK' this.headers = new Headers(options.headers) this.url = options.url || '' this._initBody(bodyInit) } Body.call(Response.prototype) Response.prototype.clone = function() { return new Response(this._bodyInit, { status: this.status, statusText: this.statusText, headers: new Headers(this.headers), url: this.url }) } Response.error = function() { var response = new Response(null, {status: 0, statusText: ''}) response.type = 'error' return response } var redirectStatuses = [301, 302, 303, 307, 308] Response.redirect = function(url, status) { if (redirectStatuses.indexOf(status) === -1) { throw new RangeError('Invalid status code') } return new Response(null, {status: status, headers: {location: url}}) } self.Headers = Headers self.Request = Request self.Response = Response self.fetch = function(input, init) { return new Promise(function(resolve, reject) { var request = new Request(input, init) var xhr = new XMLHttpRequest() xhr.onload = function() { var options = { status: xhr.status, statusText: xhr.statusText, headers: parseHeaders(xhr.getAllResponseHeaders() || '') } options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL') var body = 'response' in xhr ? xhr.response : xhr.responseText resolve(new Response(body, options)) } xhr.onerror = function() { reject(new TypeError('Network request failed')) } xhr.ontimeout = function() { reject(new TypeError('Network request failed')) } xhr.open(request.method, request.url, true) if (request.credentials === 'include') { xhr.withCredentials = true } else if (request.credentials === 'omit') { xhr.withCredentials = false } if ('responseType' in xhr && support.blob) { xhr.responseType = 'blob' } request.headers.forEach(function(value, name) { xhr.setRequestHeader(name, value) }) xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) }) } self.fetch.polyfill = true })(typeof self !== 'undefined' ? self : this); },{}],9:[function(require,module,exports){ (function (global){ (function(){'use strict';var k=this; function aa(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"== b&&"undefined"==typeof a.call)return"object";return b}function l(a){return"string"==typeof a}function ba(a,b,c){return a.call.apply(a.bind,arguments)}function ca(a,b,c){if(!a)throw Error();if(2b?1:0};var ha=Array.prototype.indexOf?function(a,b,c){return Array.prototype.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(l(a))return l(b)&&1==b.length?a.indexOf(b,c):-1;for(;cc?null:l(a)?a.charAt(c):a[c]}function la(a){return Array.prototype.concat.apply(Array.prototype,arguments)}function ma(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};var u;a:{var na=k.navigator;if(na){var oa=na.userAgent;if(oa){u=oa;break a}}u=""};var pa=q(u,"Opera")||q(u,"OPR"),v=q(u,"Trident")||q(u,"MSIE"),qa=q(u,"Edge"),ra=q(u,"Gecko")&&!(q(u.toLowerCase(),"webkit")&&!q(u,"Edge"))&&!(q(u,"Trident")||q(u,"MSIE"))&&!q(u,"Edge"),sa=q(u.toLowerCase(),"webkit")&&!q(u,"Edge");function ta(){var a=k.document;return a?a.documentMode:void 0}var ua; a:{var va="",wa=function(){var a=u;if(ra)return/rv\:([^\);]+)(\)|;)/.exec(a);if(qa)return/Edge\/([\d\.]+)/.exec(a);if(v)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(sa)return/WebKit\/(\S+)/.exec(a);if(pa)return/(?:Version)[ \/]?(\S+)/.exec(a)}();wa&&(va=wa?wa[1]:"");if(v){var xa=ta();if(null!=xa&&xa>parseFloat(va)){ua=String(xa);break a}}ua=va}var ya={}; function za(a){if(!ya[a]){for(var b=0,c=fa(String(ua)).split("."),d=fa(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f",4,2,function(a,b,c){return O(function(a,b){return a>b},a,b,c)});P("<=",4,2,function(a,b,c){return O(function(a,b){return a<=b},a,b,c)});P(">=",4,2,function(a,b,c){return O(function(a,b){return a>=b},a,b,c)});var Wa=P("=",3,2,function(a,b,c){return O(function(a,b){return a==b},a,b,c,!0)});P("!=",3,2,function(a,b,c){return O(function(a,b){return a!=b},a,b,c,!0)});P("and",2,2,function(a,b,c){return M(a,c)&&M(b,c)});P("or",1,2,function(a,b,c){return M(a,c)||M(b,c)});function Q(a,b,c){this.a=a;this.b=b||1;this.f=c||1};function Za(a,b){if(b.a.length&&4!=a.i)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");n.call(this,a.i);this.c=a;this.h=b;this.g=a.g;this.b=a.b}m(Za);Za.prototype.a=function(a){a=this.c.a(a);return $a(this.h,a)};Za.prototype.toString=function(){var a;a="Filter:"+J(this.c);return a+=J(this.h)};function ab(a,b){if(b.lengtha.v)throw Error("Function "+a.j+" expects at most "+a.v+" arguments, "+b.length+" given");a.B&&r(b,function(b,d){if(4!=b.i)throw Error("Argument "+d+" to function "+a.j+" is not of type Nodeset: "+b);});n.call(this,a.i);this.h=a;this.c=b;Ua(this,a.g||ja(b,function(a){return a.g}));Va(this,a.D&&!b.length||a.C&&!!b.length||ja(b,function(a){return a.b}))}m(ab); ab.prototype.a=function(a){return this.h.m.apply(null,la(a,this.c))};ab.prototype.toString=function(){var a="Function: "+this.h;if(this.c.length)var b=t(this.c,function(a,b){return a+J(b)},"Arguments:"),a=a+J(b);return a};function bb(a,b,c,d,e,f,g,h,p){this.j=a;this.i=b;this.g=c;this.D=d;this.C=e;this.m=f;this.A=g;this.v=void 0!==h?h:g;this.B=!!p}bb.prototype.toString=function(){return this.j};var cb={}; function R(a,b,c,d,e,f,g,h){if(cb.hasOwnProperty(a))throw Error("Function already created: "+a+".");cb[a]=new bb(a,b,c,d,!1,e,f,g,h)}R("boolean",2,!1,!1,function(a,b){return M(b,a)},1);R("ceiling",1,!1,!1,function(a,b){return Math.ceil(K(b,a))},1);R("concat",3,!1,!1,function(a,b){return t(ma(arguments,1),function(b,d){return b+L(d,a)},"")},2,null);R("contains",2,!1,!1,function(a,b,c){return q(L(b,a),L(c,a))},2);R("count",1,!1,!1,function(a,b){return b.a(a).l},1,1,!0); R("false",2,!1,!1,function(){return!1},0);R("floor",1,!1,!1,function(a,b){return Math.floor(K(b,a))},1);R("id",4,!1,!1,function(a,b){function c(a){if(w){var b=e.all[a];if(b){if(b.nodeType&&a==b.id)return b;if(b.length)return ka(b,function(b){return a==b.id})}return null}return e.getElementById(a)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument,d=L(b,a).split(/\s+/),f=[];r(d,function(a){a=c(a);!a||0<=ha(f,a)||f.push(a)});f.sort(La);var g=new C;r(f,function(a){F(g,a)});return g},1); R("lang",2,!1,!1,function(){return!1},1);R("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);R("local-name",3,!1,!0,function(a,b){var c=b?Ra(b.a(a)):a.a;return c?c.localName||c.nodeName.toLowerCase():""},0,1,!0);R("name",3,!1,!0,function(a,b){var c=b?Ra(b.a(a)):a.a;return c?c.nodeName.toLowerCase():""},0,1,!0);R("namespace-uri",3,!0,!1,function(){return""},0,1,!0); R("normalize-space",3,!1,!0,function(a,b){return(b?L(b,a):z(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);R("not",2,!1,!1,function(a,b){return!M(b,a)},1);R("number",1,!1,!0,function(a,b){return b?K(b,a):+z(a.a)},0,1);R("position",1,!0,!1,function(a){return a.b},0);R("round",1,!1,!1,function(a,b){return Math.round(K(b,a))},1);R("starts-with",2,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);return 0==b.lastIndexOf(a,0)},2);R("string",3,!1,!0,function(a,b){return b?L(b,a):z(a.a)},0,1); R("string-length",1,!1,!0,function(a,b){return(b?L(b,a):z(a.a)).length},0,1);R("substring",3,!1,!1,function(a,b,c,d){c=K(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?K(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=L(b,a);return Infinity==d?a.substring(e):a.substring(e,c+Math.round(d))},2,3);R("substring-after",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2); R("substring-before",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);R("sum",1,!1,!1,function(a,b){for(var c=H(b.a(a)),d=0,e=I(c);e;e=I(c))d+=+z(e);return d},1,1,!0);R("translate",3,!1,!1,function(a,b,c,d){b=L(b,a);c=L(c,a);var e=L(d,a);a={};for(d=0;d]=|\s+|./g,hb=/^\s/;function S(a,b){return a.b[a.a+(b||0)]}function T(a){return a.b[a.a++]}function ib(a){return a.b.length<=a.a};function jb(a){n.call(this,3);this.c=a.substring(1,a.length-1)}m(jb);jb.prototype.a=function(){return this.c};jb.prototype.toString=function(){return"Literal: "+this.c};function E(a,b){this.j=a.toLowerCase();var c;c="*"==this.j?"*":"http://www.w3.org/1999/xhtml";this.c=b?b.toLowerCase():c}E.prototype.a=function(a){var b=a.nodeType;if(1!=b&&2!=b)return!1;b=void 0!==a.localName?a.localName:a.nodeName;return"*"!=this.j&&this.j!=b.toLowerCase()?!1:"*"==this.c?!0:this.c==(a.namespaceURI?a.namespaceURI.toLowerCase():"http://www.w3.org/1999/xhtml")};E.prototype.f=function(){return this.j}; E.prototype.toString=function(){return"Name Test: "+("http://www.w3.org/1999/xhtml"==this.c?"":this.c+":")+this.j};function kb(a,b){n.call(this,a.i);this.h=a;this.c=b;this.g=a.g;this.b=a.b;if(1==this.c.length){var c=this.c[0];c.u||c.c!=lb||(c=c.o,"*"!=c.f()&&(this.f={name:c.f(),s:null}))}}m(kb);function mb(){n.call(this,4)}m(mb);mb.prototype.a=function(a){var b=new C;a=a.a;9==a.nodeType?F(b,a):F(b,a.ownerDocument);return b};mb.prototype.toString=function(){return"Root Helper Expression"};function nb(){n.call(this,4)}m(nb);nb.prototype.a=function(a){var b=new C;F(b,a.a);return b};nb.prototype.toString=function(){return"Context Helper Expression"}; function ob(a){return"/"==a||"//"==a}kb.prototype.a=function(a){var b=this.h.a(a);if(!(b instanceof C))throw Error("Filter expression must evaluate to nodeset.");a=this.c;for(var c=0,d=a.length;ca.length)throw Error("Unclosed literal string");return new jb(a)} function Hb(a){var b,c=[],d;if(ob(S(a.a))){b=T(a.a);d=S(a.a);if("/"==b&&(ib(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new mb;d=new mb;W(a,"Missing next location step.");b=Ib(a,b);c.push(b)}else{a:{b=S(a.a);d=b.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":T(a.a);b=Cb(a);W(a,'unclosed "("');Eb(a,")");break;case '"':case "'":b=Gb(a);break;default:if(isNaN(+b))if(!db(b)&&/(?![0-9])[\w]/.test(d)&&"("==S(a.a,1)){b=T(a.a); b=cb[b]||null;T(a.a);for(d=[];")"!=S(a.a);){W(a,"Missing function argument list.");d.push(Cb(a));if(","!=S(a.a))break;T(a.a)}W(a,"Unclosed function argument list.");Fb(a);b=new ab(b,d)}else{b=null;break a}else b=new Ab(+T(a.a))}"["==S(a.a)&&(d=new sb(Jb(a)),b=new Za(b,d))}if(b)if(ob(S(a.a)))d=b;else return b;else b=Ib(a,"/"),d=new nb,c.push(b)}for(;ob(S(a.a));)b=T(a.a),W(a,"Missing next location step."),b=Ib(a,b),c.push(b);return new kb(d,c)} function Ib(a,b){var c,d,e;if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==S(a.a))return d=new U(yb,new G("node")),T(a.a),d;if(".."==S(a.a))return d=new U(xb,new G("node")),T(a.a),d;var f;if("@"==S(a.a))f=lb,T(a.a),W(a,"Missing attribute name");else if("::"==S(a.a,1)){if(!/(?![0-9])[\w]/.test(S(a.a).charAt(0)))throw Error("Bad token: "+T(a.a));c=T(a.a);f=wb[c]||null;if(!f)throw Error("No axis with name: "+c);T(a.a);W(a,"Missing node name")}else f=tb;c=S(a.a);if(/(?![0-9])[\w\*]/.test(c.charAt(0)))if("("== S(a.a,1)){if(!db(c))throw Error("Invalid node type: "+c);c=T(a.a);if(!db(c))throw Error("Invalid type name: "+c);Eb(a,"(");W(a,"Bad nodetype");e=S(a.a).charAt(0);var g=null;if('"'==e||"'"==e)g=Gb(a);W(a,"Bad nodetype");Fb(a);c=new G(c,g)}else if(c=T(a.a),e=c.indexOf(":"),-1==e)c=new E(c);else{var g=c.substring(0,e),h;if("*"==g)h="*";else if(h=a.b(g),!h)throw Error("Namespace prefix not declared: "+g);c=c.substr(e+1);c=new E(c,h)}else throw Error("Bad token: "+T(a.a));e=new sb(Jb(a),f.a);return d|| new U(f,c,e,"//"==b)}function Jb(a){for(var b=[];"["==S(a.a);){T(a.a);W(a,"Missing predicate expression.");var c=Cb(a);b.push(c);W(a,"Unclosed predicate expression.");Eb(a,"]")}return b}function Db(a){if("-"==S(a.a))return T(a.a),new zb(Db(a));var b=Hb(a);if("|"!=S(a.a))a=b;else{for(b=[b];"|"==T(a.a);)W(a,"Missing next union location path."),b.push(Hb(a));a.a.a--;a=new rb(b)}return a};function Kb(a){switch(a.nodeType){case 1:return ea(Lb,a);case 9:return Kb(a.documentElement);case 11:case 10:case 6:case 12:return Mb;default:return a.parentNode?Kb(a.parentNode):Mb}}function Mb(){return null}function Lb(a,b){if(a.prefix==b)return a.namespaceURI||"http://www.w3.org/1999/xhtml";var c=a.getAttributeNode("xmlns:"+b);return c&&c.specified?c.value||null:a.parentNode&&9!=a.parentNode.nodeType?Lb(a.parentNode,b):null};function Nb(a,b){if(!a.length)throw Error("Empty XPath expression.");var c=fb(a);if(ib(c))throw Error("Invalid XPath expression.");b?"function"==aa(b)||(b=da(b.lookupNamespaceURI,b)):b=function(){return null};var d=Cb(new Bb(c,b));if(!ib(c))throw Error("Bad token: "+T(c));this.evaluate=function(a,b){var c=d.a(new Q(a));return new Y(c,b)}} function Y(a,b){if(0==b)if(a instanceof C)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof C))throw Error("value could not be converted to the specified type");this.resultType=b;var c;switch(b){case 2:this.stringValue=a instanceof C?Sa(a):""+a;break;case 1:this.numberValue=a instanceof C?+Sa(a):+a;break;case 3:this.booleanValue=a instanceof C?0=c.length?null:c[f++]};this.snapshotItem=function(a){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return a>=c.length|| 0>a?null:c[a]}}Y.ANY_TYPE=0;Y.NUMBER_TYPE=1;Y.STRING_TYPE=2;Y.BOOLEAN_TYPE=3;Y.UNORDERED_NODE_ITERATOR_TYPE=4;Y.ORDERED_NODE_ITERATOR_TYPE=5;Y.UNORDERED_NODE_SNAPSHOT_TYPE=6;Y.ORDERED_NODE_SNAPSHOT_TYPE=7;Y.ANY_UNORDERED_NODE_TYPE=8;Y.FIRST_ORDERED_NODE_TYPE=9;function Ob(a){this.lookupNamespaceURI=Kb(a)} function Pb(a,b){var c=a||k,d=c.Document&&c.Document.prototype||c.document;if(!d.evaluate||b)c.XPathResult=Y,d.evaluate=function(a,b,c,d){return(new Nb(a,c)).evaluate(b,d)},d.createExpression=function(a,b){return new Nb(a,b)},d.createNSResolver=function(a){return new Ob(a)}}var Qb=["wgxpath","install"],Z=k;Qb[0]in Z||!Z.execScript||Z.execScript("var "+Qb[0]);for(var Rb;Qb.length&&(Rb=Qb.shift());)Qb.length||void 0===Pb?Z[Rb]?Z=Z[Rb]:Z=Z[Rb]={}:Z[Rb]=Pb;module.exports.install=Pb;module.exports.XPathResultType={ANY_TYPE:0,NUMBER_TYPE:1,STRING_TYPE:2,BOOLEAN_TYPE:3,UNORDERED_NODE_ITERATOR_TYPE:4,ORDERED_NODE_ITERATOR_TYPE:5,UNORDERED_NODE_SNAPSHOT_TYPE:6,ORDERED_NODE_SNAPSHOT_TYPE:7,ANY_UNORDERED_NODE_TYPE:8,FIRST_ORDERED_NODE_TYPE:9};}).call(global) }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}],10:[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ // Backward Compat Table 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } var _httpPydioUsersApi = require('./http/PydioUsersApi'); var UsersApi = _interopRequireWildcard(_httpPydioUsersApi); var Connexion = require('./http/Connexion'), MetaCacheService = require('./http/MetaCacheService'), PydioApi = require('./http/PydioApi'), ResourcesManager = require('./http/ResourcesManager'), Logger = require('./lang/Logger'), Observable = require('./lang/Observable'), Action = require('./model/Action'), AjxpNode = require('./model/AjxpNode'), Controller = require('./model/Controller'), EmptyNodeProvider = require('./model/EmptyNodeProvider'), PydioDataModel = require('./model/PydioDataModel'), Registry = require('./model/Registry'), RemoteNodeProvider = require('./model/RemoteNodeProvider'), Repository = require('./model/Repository'), User = require('./model/User'), ContextMenu = require('./model/ContextMenu'), CookiesManager = require('./util/CookiesManager'), DOMUtils = require('./util/DOMUtils'), FuncUtils = require('./util/FuncUtils'), HasherUtils = require('./util/HasherUtils'), LangUtils = require('./util/LangUtils'), PassUtils = require('./util/PassUtils'), PathUtils = require('./util/PathUtils'), PeriodicalExecuter = require('./util/PeriodicalExecuter'), ActivityMonitor = require('./util/ActivityMonitor'), XMLUtils = require('./util/XMLUtils'), Pydio = require('./Pydio'); var PydioUsers = { Client: UsersApi.UsersApi, User: UsersApi.User }; var namespace = { Connexion: Connexion, MetaCacheService: MetaCacheService, PydioApi: PydioApi, PydioUsers: PydioUsers, ResourcesManager: ResourcesManager, Logger: Logger, Observable: Observable, Action: Action, AjxpNode: AjxpNode, Controller: Controller, EmptyNodeProvider: EmptyNodeProvider, PydioDataModel: PydioDataModel, Registry: Registry, RemoteNodeProvider: RemoteNodeProvider, Repository: Repository, User: User, ContextMenu: ContextMenu, CookiesManager: CookiesManager, DOMUtils: DOMUtils, FuncUtils: FuncUtils, HasherUtils: HasherUtils, LangUtils: LangUtils, PassUtils: PassUtils, PathUtils: PathUtils, PeriodicalExecuter: PeriodicalExecuter, ActivityMonitor: ActivityMonitor, XMLUtils: XMLUtils, Pydio: Pydio }; Object.assign(window, _extends({}, namespace, { PydioCore: namespace })); },{"./Pydio":"pydio","./http/Connexion":"pydio/http/connexion","./http/MetaCacheService":"pydio/http/meta-cache-service","./http/PydioApi":"pydio/http/api","./http/PydioUsersApi":"pydio/http/users-api","./http/ResourcesManager":"pydio/http/resources-manager","./lang/Logger":"pydio/lang/logger","./lang/Observable":"pydio/lang/observable","./model/Action":"pydio/model/action","./model/AjxpNode":"pydio/model/node","./model/ContextMenu":"pydio/model/context-menu","./model/Controller":"pydio/model/controller","./model/EmptyNodeProvider":"pydio/model/empty-node-provider","./model/PydioDataModel":"pydio/model/data-model","./model/Registry":"pydio/model/registry","./model/RemoteNodeProvider":"pydio/model/remote-node-provider","./model/Repository":"pydio/model/repository","./model/User":"pydio/model/user","./util/ActivityMonitor":"pydio/util/activity-monitor","./util/CookiesManager":"pydio/util/cookies","./util/DOMUtils":"pydio/util/dom","./util/FuncUtils":"pydio/util/func","./util/HasherUtils":"pydio/util/hasher","./util/LangUtils":"pydio/util/lang","./util/PassUtils":"pydio/util/pass","./util/PathUtils":"pydio/util/path","./util/PeriodicalExecuter":"pydio/util/periodical-executer","./util/XMLUtils":"pydio/util/xml"}],"pydio/http/api":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); /** * API Client */ var PydioApi = (function () { function PydioApi() { _classCallCheck(this, PydioApi); } PydioApi.prototype.setPydioObject = function setPydioObject(pydioObject) { this._pydioObject = pydioObject; this._baseUrl = pydioObject.Parameters.get('serverAccessPath'); }; PydioApi.prototype.request = function request(parameters) { var onComplete = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var onError = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var settings = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; // Connexion already handles secure_token var c = new Connexion(); if (settings.discrete) { c.discrete = true; } c.setParameters(parameters); if (settings.method) { c.setMethod(settings.method); } if (!onComplete) { onComplete = (function (transport) { if (transport.responseXML) return this.parseXmlMessage(transport.responseXML); }).bind(this); } c.onComplete = onComplete; if (settings.async === false) { c.sendSync(); } else { c.sendAsync(); } }; PydioApi.prototype.loadFile = function loadFile(filePath) { var onComplete = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var onError = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var c = new Connexion(filePath); c.setMethod('GET'); c.onComplete = onComplete; c.sendAsync(); }; /** * * @param file * @param fileParameterName * @param queryStringParams * @param onComplete * @param onError * @param onProgress * @returns XHR Handle to abort transfer */ PydioApi.prototype.uploadFile = function uploadFile(file, fileParameterName) { var queryStringParams = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; var onComplete = arguments.length <= 3 || arguments[3] === undefined ? function () {} : arguments[3]; var onError = arguments.length <= 4 || arguments[4] === undefined ? function () {} : arguments[4]; var onProgress = arguments.length <= 5 || arguments[5] === undefined ? function () {} : arguments[5]; var uploadUrl = arguments.length <= 6 || arguments[6] === undefined ? '' : arguments[6]; var xhrSettings = arguments.length <= 7 || arguments[7] === undefined ? {} : arguments[7]; if (!uploadUrl) { uploadUrl = pydio.Parameters.get('ajxpServerAccess'); } if (queryStringParams) { uploadUrl += (uploadUrl.indexOf('?') === -1 ? '?' : '&') + queryStringParams; } if (window.Connexion) { var _ret = (function () { // Warning, avoid double error var errorSent = false; var localError = function localError(xhr) { if (!errorSent) onError('Request failed with status :' + xhr.status); errorSent = true; }; var c = new Connexion(); return { v: c.uploadFile(file, fileParameterName, uploadUrl, onComplete, localError, onProgress, xhrSettings) }; })(); if (typeof _ret === 'object') return _ret.v; } }; /** * * @param userSelection UserSelection A Pydio DataModel with selected files * @param prototypeHiddenForm Element A hidden form element: currently relying on PrototypeJS. * @param dlActionName String Action name to trigger, download by default. * @param additionalParameters Object Optional set of key/values to pass to the download. */ PydioApi.prototype.downloadSelection = function downloadSelection(userSelection) { var dlActionName = arguments.length <= 1 || arguments[1] === undefined ? 'download' : arguments[1]; var additionalParameters = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var ajxpServerAccess = this._pydioObject.Parameters.get("ajxpServerAccess"); var agent = navigator.userAgent || ''; var agentIsMobile = agent.indexOf('iPhone') != -1 || agent.indexOf('iPod') != -1 || agent.indexOf('iPad') != -1 || agent.indexOf('iOs') != -1; var hiddenForm = pydio && pydio.UI && pydio.UI.hasHiddenDownloadForm(); if (agentIsMobile || !hiddenForm) { var downloadUrl = ajxpServerAccess + '&get_action=' + dlActionName; if (additionalParameters) { for (var param in additionalParameters) { if (additionalParameters.hasOwnProperty(param)) downloadUrl += "&" + param + "=" + additionalParameters[param]; } } if (userSelection) { downloadUrl = userSelection.updateFormOrUrl(null, downloadUrl); } document.location.href = downloadUrl; } else { var parameters = _extends({}, additionalParameters, { secure_token: this._pydioObject.Parameters.get("SECURE_TOKEN"), get_action: dlActionName }); var minisite_session = PydioApi.detectMinisiteSession(ajxpServerAccess); if (minisite_session) { parameters['minisite_session'] = minisite_session; } try { pydio.UI.sendDownloadToHiddenForm(userSelection, parameters); } catch (e) { if (window.console) window.console.error("Error while submitting hidden form for download", e); } } }; PydioApi.prototype.postPlainTextContent = function postPlainTextContent(filePath, content, finishedCallback) { this.request({ get_action: 'put_content', file: filePath, content: content }, (function (transport) { var success = this.parseXmlMessage(transport.responseXML); finishedCallback(success); }).bind(this), function () { finishedCallback(false); }); }; /** * Detect a minisite_session parameter in the URL * @param serverAccess * @returns string|bool */ PydioApi.detectMinisiteSession = function detectMinisiteSession(serverAccess) { var regex = new RegExp('.*?[&\\?]' + 'minisite_session' + '=(.*?)&?.*?'); var val = serverAccess.replace(regex, "$1"); return val === serverAccess ? false : val; }; /** * Detects if current browser supports HTML5 Upload. * @returns boolean */ PydioApi.supportsUpload = function supportsUpload() { if (window.Connexion) { return window.FormData || window.FileReader; } else if (window.jQuery) { return window.FormData; } return false; }; /** * Instanciate a PydioApi client if it's not already instanciated and return it. * @returns PydioApi */ PydioApi.getClient = function getClient() { if (PydioApi._PydioClient) return PydioApi._PydioClient; var client = new PydioApi(); PydioApi._PydioClient = client; return client; }; /** * Load a javascript library * @param fileName String * @param onLoadedCode Function Callback * @param aSync Boolean load library asynchroneously */ PydioApi.loadLibrary = function loadLibrary(fileName, onLoadedCode, aSync) { if (window.pydio && pydio.Parameters.get("ajxpVersion") && fileName.indexOf("?") == -1) { fileName += "?v=" + pydio.Parameters.get("ajxpVersion"); } PydioApi._libUrl = false; if (window.pydio && pydio.Parameters.get('SERVER_PREFIX_URI')) { PydioApi._libUrl = pydio.Parameters.get('SERVER_PREFIX_URI'); } var conn = new Connexion(); conn._libUrl = false; if (pydio.Parameters.get('SERVER_PREFIX_URI')) { conn._libUrl = pydio.Parameters.get('SERVER_PREFIX_URI'); } conn.loadLibrary(fileName, onLoadedCode, aSync); }; PydioApi.prototype.switchRepository = function switchRepository(repositoryId, completeCallback) { var params = { get_action: 'switch_repository', repository_id: repositoryId }; this.request(params, completeCallback); }; PydioApi.prototype.switchLanguage = function switchLanguage(lang, completeCallback) { var params = { get_action: 'get_i18n_messages', lang: lang, format: 'json' }; this.request(params, completeCallback); }; PydioApi.prototype.loadXmlRegistry = function loadXmlRegistry(completeCallback) { var xPath = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var params = { get_action: 'get_xml_registry' }; if (xPath) params[xPath] = xPath; this.request(params, completeCallback); }; PydioApi.prototype.getBootConf = function getBootConf(completeCallback) { var params = { get_action: 'get_boot_conf' }; var cB = (function (transport) { if (transport.responseJSON && transport.responseJSON.SECURE_TOKEN) { this._pydioObject.Parameters.set('SECURE_TOKEN', transport.responseJSON.SECURE_TOKEN); Connexion.updateServerAccess(this._pydioObject.Parameters); } if (completeCallback) { completeCallback(transport); } }).bind(this); this.request(params, cB); }; PydioApi.prototype.userSavePreference = function userSavePreference(prefName, prefValue) { this.request({ get_action: "save_user_pref", "pref_name_0": prefName, "pref_value_0": prefValue }, null, null, { discrete: true, method: 'post' }); }; PydioApi.prototype.userSavePreferences = function userSavePreferences(preferences, completeCallback) { var params = { 'get_action': 'save_user_pref' }; var i = 0; preferences.forEach(function (value, key) { params["pref_name_" + i] = key; params["pref_value_" + i] = value; i++; }); this.request(params, completeCallback, null, { discrete: true, method: 'post' }); }; PydioApi.prototype.userSavePassword = function userSavePassword(oldPass, newPass, seed, completeCallback) { this.request({ get_action: 'save_user_pref', pref_name_0: "password", pref_value_0: newPass, crt: oldPass, pass_seed: seed }, completeCallback, null, { discrete: true, method: 'post' }); }; PydioApi.prototype.buildUserAvatarUrl = function buildUserAvatarUrl(userId) { var avatarId = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; if (avatarId) { return this._pydioObject.Parameters.get('ajxpServerAccess') + "&get_action=get_binary_param&binary_id=" + avatarId + "&user_id=" + userId; } else { return null; } }; PydioApi.prototype.applyCheckHook = function applyCheckHook(node, hookName, hookArg, completeCallback, additionalParams) { var params = { get_action: "apply_check_hook", file: node.getPath(), hook_name: hookName, hook_arg: hookArg }; if (additionalParams) { params = LangUtils.objectMerge(params, additionalParams); } this.request(params, completeCallback, null, { async: false }); }; /** * Standard parser for server XML answers * @param xmlResponse DOMDocument */ PydioApi.prototype.parseXmlMessage = function parseXmlMessage(xmlResponse) { if (xmlResponse == null || xmlResponse.documentElement == null) return null; var childs = xmlResponse.documentElement.childNodes; var reloadNodes = [], error = false; this.LAST_ERROR_ID = null; for (var i = 0; i < childs.length; i++) { var child = childs[i]; if (child.tagName === "message") { var messageTxt = "No message"; if (child.firstChild) messageTxt = child.firstChild.nodeValue; if (child.getAttribute('type') == 'ERROR') { Logger.error(messageTxt); error = true; } else { Logger.log(messageTxt); } } else if (child.tagName === "prompt") { if (pydio && pydio.UI && pydio.UI.openPromptDialog) { var jsonData = _utilXMLUtils2['default'].XPathSelectSingleNode(childs[i], "data").firstChild.nodeValue; pydio.UI.openPromptDialog(JSON.parse(jsonData)); } return false; } else if (child.tagName == "reload_instruction") { var obName = child.getAttribute('object'); if (obName === 'data') { var node = child.getAttribute('node'); if (node) { reloadNodes.push(node); } else { var file = child.getAttribute('file'); if (file) { this._pydioObject.getContextHolder().setPendingSelection(file); } reloadNodes.push(this._pydioObject.getContextNode()); } } else if (obName == 'repository_list') { this._pydioObject.reloadRepositoriesList(); } } else if (child.nodeName == 'nodes_diff') { var dm = this._pydioObject.getContextHolder(); if (dm.getAjxpNodeProvider().parseAjxpNodesDiffs) { dm.getAjxpNodeProvider().parseAjxpNodesDiffs(childs[i], dm, this._pydioObject.user.activeRepository, !window.currentLightBox); } } else if (child.tagName == "logging_result") { if (child.getAttribute("secure_token")) { this._pydioObject.Parameters.set('SECURE_TOKEN', child.getAttribute("secure_token")); Connexion.updateServerAccess(this._pydioObject.Parameters); } var result = child.getAttribute('value'); var errorId = false; switch (result) { case '1': this._pydioObject.loadXmlRegistry(); break; case '0': case '-1': errorId = 285; break; case '2': this._pydioObject.loadXmlRegistry(); break; case '-2': errorId = 285; break; case '-3': errorId = 366; break; case '-4': errorId = 386; break; } if (errorId) { error = true; this.LAST_ERROR_ID = errorId; Logger.error(this._pydioObject.MessageHash[errorId]); } } else if (child.tagName == "trigger_bg_action") { var _name = child.getAttribute("name"); var messageId = child.getAttribute("messageId"); var parameters = {}; var callback = undefined; for (var j = 0; j < child.childNodes.length; j++) { var paramChild = child.childNodes[j]; if (paramChild.tagName == 'param') { parameters[paramChild.getAttribute("name")] = paramChild.getAttribute("value"); } else if (paramChild.tagName == 'clientCallback' && paramChild.firstChild && paramChild.firstChild.nodeValue) { var callbackCode = paramChild.firstChild.nodeValue; callback = new Function(callbackCode); } } if (_name == "javascript_instruction" && callback) { callback(); } } } this._pydioObject.notify("response.xml", xmlResponse); if (reloadNodes.length) { this._pydioObject.getContextHolder().multipleNodesReload(reloadNodes); } return !error; }; /** * Submits a form using Connexion class. * @param formName String The id of the form * @param post Boolean Whether to POST or GET * @param completeCallback Function Callback to be called on complete */ PydioApi.prototype.submitForm = function submitForm(formName) { var post = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; var completeCallback = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var params = {}; // TODO: UI IMPLEMENTATION $(formName).getElements().each(function (fElement) { var fValue = fElement.getValue(); if (fElement.name == 'get_action' && fValue.substr(0, 4) == 'http') { fValue = PathUtils.getBasename(fValue); } if (fElement.type == 'radio' && !fElement.checked) return; if (params[fElement.name] && fElement.name.endsWith('[]')) { var existing = params[fElement.name]; if (typeof existing == 'string') existing = [existing]; existing.push(fValue); params[fElement.name] = existing; } else { params[fElement.name] = fValue; } }); if (this._pydioObject.getContextNode()) { params['dir'] = this._pydioObject.getContextNode().getPath(); } var onComplete = undefined; if (completeCallback) { onComplete = completeCallback; } else { onComplete = (function (transport) { this.parseXmlMessage(transport.responseXML); }).bind(this); } this.request(params, onComplete, null, { method: post ? 'post' : 'get' }); }; PydioApi.prototype.postSelectionWithAction = function postSelectionWithAction(actionName) { var callback = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var selectionModel = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var additionalParameters = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3]; if (!selectionModel) { selectionModel = this._pydioObject.getContextHolder(); } var params = { get_action: actionName, dir: selectionModel.getContextNode().getPath() }; params['nodes[]'] = selectionModel.getFileNames(); if (additionalParameters) { params = Object.assign(params, additionalParameters); } this.request(params, callback); }; /** * Trigger a simple download * @param url String */ PydioApi.triggerDownload = function triggerDownload(url) { document.location.href = url; }; return PydioApi; })(); exports['default'] = PydioApi; module.exports = exports['default']; },{"../util/XMLUtils":"pydio/util/xml"}],"pydio/http/connexion":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); /** * Pydio encapsulation of XHR / Fetch */ require('whatwg-fetch'); var Connexion = (function () { /** * Constructor * @param baseUrl String The base url for services */ function Connexion(baseUrl) { _classCallCheck(this, Connexion); this._pydio = window.pydio; this._baseUrl = baseUrl || window.ajxpServerAccessPath; this._libUrl = window.ajxpResourcesFolder + '/build'; this._parameters = new Map(); this._method = 'post'; this.discrete = false; } Connexion.updateServerAccess = function updateServerAccess(parameters) { if (parameters.get('SECURE_TOKEN')) { Connexion.SECURE_TOKEN = parameters.get('SECURE_TOKEN'); } var serverAccessPath = parameters.get('ajxpServerAccess').split('?').shift(); if (parameters.get('SERVER_PREFIX_URI')) { parameters.set('ajxpResourcesFolder', parameters.get('SERVER_PREFIX_URI') + parameters.get('ajxpResourcesFolder')); serverAccessPath = parameters.get('SERVER_PREFIX_URI') + serverAccessPath + '?' + (Connexion.SECURE_TOKEN ? 'secure_token=' + Connexion.SECURE_TOKEN : ''); } else { serverAccessPath = serverAccessPath + '?' + (Connexion.SECURE_TOKEN ? 'secure_token=' + Connexion.SECURE_TOKEN : ''); } if (parameters.get('SERVER_PERMANENT_PARAMS')) { var permParams = parameters.get('SERVER_PERMANENT_PARAMS'); var permStrings = []; for (var permanent in permParams) { if (permParams.hasOwnProperty(permanent)) { permStrings.push(permanent + '=' + permParams[permanent]); } } permStrings = permStrings.join('&'); if (permStrings) { serverAccessPath += '&' + permStrings; } } parameters.set('ajxpServerAccess', serverAccessPath); // BACKWARD COMPAT window.ajxpServerAccessPath = serverAccessPath; if (window.pydioBootstrap && window.pydioBootstrap.parameters) { pydioBootstrap.parameters.set("ajxpServerAccess", serverAccessPath); pydioBootstrap.parameters.set("SECURE_TOKEN", Connexion.SECURE_TOKEN); } }; Connexion.log = function log(action, syncStatus) { if (!Connexion.PydioLogs) { Connexion.PydioLogs = []; } Connexion.PydioLogs.push({ action: action, sync: syncStatus }); }; /** * Add a parameter to the query * @param paramName String * @param paramValue String */ Connexion.prototype.addParameter = function addParameter(paramName, paramValue) { if (this._parameters.get(paramName) && paramName.endsWith('[]')) { var existing = this._parameters.get(paramName); if (!existing instanceof Array) { existing = [existing]; } existing.push(paramValue); this._parameters.set(paramName, existing); } else { this._parameters.set(paramName, paramValue); } }; /** * Sets the whole parameter as a bunch * @param hParameters Map */ Connexion.prototype.setParameters = function setParameters(hParameters) { if (hParameters instanceof Map) { this._parameters = hParameters; } else { if (hParameters._object) { console.error('Passed a legacy Hash object to Connexion.setParameters'); hParameters = hParameters._object; } for (var key in hParameters) { if (hParameters.hasOwnProperty(key)) { this._parameters.set(key, hParameters[key]); } } } }; /** * Set the query method (get post) * @param method String */ Connexion.prototype.setMethod = function setMethod(method) { this._method = method; }; /** * Add the secure token parameter */ Connexion.prototype.addSecureToken = function addSecureToken() { if (Connexion.SECURE_TOKEN && this._baseUrl.indexOf('secure_token') == -1 && !this._parameters.get('secure_token')) { this.addParameter('secure_token', Connexion.SECURE_TOKEN); } else if (this._baseUrl.indexOf('secure_token=') !== -1) { // Remove from baseUrl and set inside params var parts = this._baseUrl.split('secure_token='); var toks = parts[1].split('&'); var token = toks.shift(); var rest = toks.join('&'); this._baseUrl = parts[0] + (rest ? '&' + rest : ''); this._parameters.set('secure_token', token); } }; Connexion.prototype.addServerPermanentParams = function addServerPermanentParams() { if (!this._pydio || !this._pydio.Parameters.has('SERVER_PERMANENT_PARAMS')) { return; } var permParams = this._pydio.Parameters.get('SERVER_PERMANENT_PARAMS'); for (var permanent in permParams) { if (permParams.hasOwnProperty(permanent)) { this.addParameter(permanent, permParams[permanent]); } } }; /** * Show a small loader */ Connexion.prototype.showLoader = function showLoader() { if (this.discrete || !this._pydio) return; this._pydio.notify("connection-start"); }; /** * Hide a small loader */ Connexion.prototype.hideLoader = function hideLoader() { if (this.discrete || !this._pydio) return; this._pydio.notify("connection-end"); }; Connexion.prototype._send = function _send() { var _this = this; var aSync = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; Connexion.log(this._parameters.get("get_action"), aSync ? 'async' : 'sync'); this.addSecureToken(); this.addServerPermanentParams(); this.showLoader(); var oThis = this; var options = { method: this._method, credentials: 'same-origin' }; var url = this._baseUrl; if (!aSync) { options.synchronous = true; } var bodyParts = []; this._parameters.forEach(function (value, key) { if (value instanceof Array) { value.map(function (oneV) { bodyParts.push(key + '=' + encodeURIComponent(oneV)); }); } else { bodyParts.push(key + '=' + encodeURIComponent(value)); } }); var queryString = bodyParts.join('&'); if (this._method === 'post') { options.headers = { "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" }; options.body = queryString; } else { url += (url.indexOf('?') > -1 ? '&' : '?') + queryString; } window.fetch(url, options).then(function (response) { var h = response.headers.get('Content-type'); if (h.indexOf('/json') !== -1) { response.json().then(function (json) { oThis.applyComplete({ responseJSON: json }, response); }); } else if (h.indexOf('/xml') !== -1) { response.text().then(function (text) { oThis.applyComplete({ responseXML: _utilXMLUtils2['default'].parseXml(text) }, response); }); } else { response.text().then(function (text) { oThis.applyComplete({ responseText: text }, response); }); } return response; })['catch'](function (error) { if (_this._pydio) { _this._pydio.displayMessage('ERROR', 'Network error ' + error.message); } }); }; /** * Send Asynchronously */ Connexion.prototype.sendAsync = function sendAsync() { this._send(true); }; /** * Send synchronously */ Connexion.prototype.sendSync = function sendSync() { this._send(false); }; /** * Apply the complete callback, try to grab maximum of errors * @param parsedBody Transpot */ Connexion.prototype.applyComplete = function applyComplete(parsedBody, response) { this.hideLoader(); var pydio = this._pydio; var message = undefined, tokenMessage = undefined; var tok1 = "Ooops, it seems that your security token has expired! Please %s by hitting refresh or F5 in your browser!"; var tok2 = "reload the page"; if (window.MessageHash && window.MessageHash[437]) { tok1 = window.MessageHash[437]; tok2 = window.MessageHash[438]; } tokenMessage = tok1.replace("%s", "" + tok2 + ""); var ctype = response.headers.get('Content-type'); if (parsedBody.responseXML && parsedBody.responseXML.documentElement && parsedBody.responseXML.documentElement.nodeName == "parsererror") { message = "Parsing error : \n" + parsedBody.responseXML.documentElement.firstChild.textContent; } else if (parsedBody.responseXML && parsedBody.responseXML.parseError && parsedBody.responseXML.parseError.errorCode != 0) { message = "Parsing Error : \n" + parsedBody.responseXML.parseError.reason; } else if (ctype.indexOf("text/xml") > -1 && parsedBody.responseXML == null) { message = "Expected XML but got empty response!"; } else if (ctype.indexOf("text/xml") == -1 && ctype.indexOf("application/json") == -1 && parsedBody.responseText.indexOf("Fatal error") > -1) { message = parsedBody.responseText.replace("
", ""); } else if (response.status == 500) { message = "Internal Server Error: you should check your web server logs to find what's going wrong!"; } if (message) { if (message.startsWith("You are not allowed to access this resource.")) { message = tokenMessage; } if (pydio) { pydio.displayMessage("ERROR", message); } else { alert(message); } } if (parsedBody.responseXML && parsedBody.responseXML.documentElement) { var authNode = _utilXMLUtils2['default'].XPathSelectSingleNode(parsedBody.responseXML.documentElement, "require_auth"); if (authNode && pydio) { var root = pydio.getContextHolder().getRootNode(); if (root) { pydio.getContextHolder().setContextNode(root); root.clear(); } pydio.getController().fireAction('logout'); setTimeout(function () { pydio.getController().fireAction('login'); }, 350); } var messageNode = _utilXMLUtils2['default'].XPathSelectSingleNode(parsedBody.responseXML.documentElement, "message"); if (messageNode) { var messageType = messageNode.getAttribute("type").toUpperCase(); var messageContent = _utilXMLUtils2['default'].getDomNodeText(messageNode); if (messageContent.startsWith("You are not allowed to access this resource.")) { messageContent = tokenMessage; } if (pydio) { pydio.displayMessage(messageType, messageContent); } else { if (messageType == "ERROR") { alert(messageType + ":" + messageContent); } } if (messageType == "SUCCESS") messageNode.parentNode.removeChild(messageNode); } } if (this.onComplete) { parsedBody.status = response.status; parsedBody.responseObject = response; this.onComplete(parsedBody); } if (pydio) { pydio.fire("server_answer", this); } }; Connexion.prototype.uploadFile = function uploadFile(file, fileParameterName, uploadUrl, onComplete, onError, onProgress, xhrSettings) { if (xhrSettings === undefined) xhrSettings = {}; if (!onComplete) onComplete = function () {}; if (!onError) onError = function () {}; if (!onProgress) onProgress = function () {}; var xhr = this.initializeXHRForUpload(uploadUrl, onComplete, onError, onProgress, xhrSettings); if (window.FormData) { this.sendFileUsingFormData(xhr, file, fileParameterName); } else if (window.FileReader) { var fileReader = new FileReader(); fileReader.onload = (function (e) { this.xhrSendAsBinary(xhr, file.name, e.target.result, fileParameterName); }).bind(this); fileReader.readAsBinaryString(file); } else if (file.getAsBinary) { this.xhrSendAsBinary(xhr, file.name, file.getAsBinary(), fileParameterName); } return xhr; }; Connexion.prototype.initializeXHRForUpload = function initializeXHRForUpload(url, onComplete, onError, onProgress, xhrSettings) { if (xhrSettings === undefined) xhrSettings = {}; var xhr = new XMLHttpRequest(); var upload = xhr.upload; if (xhrSettings.withCredentials) { xhr.withCredentials = true; } upload.addEventListener("progress", function (e) { if (!e.lengthComputable) return; onProgress(e); }, false); xhr.onreadystatechange = (function () { if (xhr.readyState == 4) { if (xhr.status === 200) { onComplete(xhr); } else { onError(xhr); } } }).bind(this); upload.onerror = function () { onError(xhr); }; xhr.open("POST", url, true); return xhr; }; Connexion.prototype.sendFileUsingFormData = function sendFileUsingFormData(xhr, file, fileParameterName) { var formData = new FormData(); formData.append(fileParameterName, file); xhr.send(formData); }; Connexion.prototype.xhrSendAsBinary = function xhrSendAsBinary(xhr, fileName, fileData, fileParameterName) { var boundary = '----MultiPartFormBoundary' + new Date().getTime(); xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary=" + boundary); var body = "--" + boundary + "\r\n"; body += "Content-Disposition: form-data; name='" + fileParameterName + "'; filename='" + unescape(encodeURIComponent(fileName)) + "'\r\n"; body += "Content-Type: application/octet-stream\r\n\r\n"; body += fileData + "\r\n"; body += "--" + boundary + "--\r\n"; xhr.sendAsBinary(body); }; /** * Load a javascript library * @param fileName String * @param onLoadedCode Function Callback * @param aSync Boolean load library asynchroneously */ Connexion.prototype.loadLibrary = function loadLibrary(fileName, onLoadedCode, aSync) { var _this2 = this; if (window.pydioBootstrap && window.pydioBootstrap.parameters.get("ajxpVersion") && fileName.indexOf("?") == -1) { fileName += "?v=" + window.pydioBootstrap.parameters.get("ajxpVersion"); } var url = this._libUrl ? this._libUrl + '/' + fileName : fileName; var pydio = this._pydio; var scriptLoaded = function scriptLoaded(script) { try { if (window.execScript) { window.execScript(script); } else { window.my_code = script; var head = document.getElementsByTagName('head')[0]; var script_tag = document.createElement('script'); script_tag.type = 'text/javascript'; script_tag.innerHTML = 'eval(window.my_code)'; head.appendChild(script_tag); delete window.my_code; head.removeChild(script_tag); } if (onLoadedCode != null) onLoadedCode(); } catch (e) { alert('error loading ' + fileName + ':' + e.message); if (console) console.error(e); } if (pydio) pydio.fire("server_answer"); }; if (aSync) { window.fetch(url, { method: 'GET', credentials: 'same-origin' }).then(function (response) { return response.text(); }).then(function (script) { scriptLoaded(script); }); } else { (function () { // SHOULD BE REMOVED!! var xhr = new XMLHttpRequest(); xhr.onreadystatechange = (function () { if (xhr.readyState == 4) { if (xhr.status === 200) { scriptLoaded(xhr.responseText); } else { alert('error loading ' + fileName + ': Status code was ' + xhr.status); } } }).bind(_this2); xhr.open("GET", url, false); xhr.send(); })(); } }; return Connexion; })(); exports['default'] = Connexion; module.exports = exports['default']; },{"../util/XMLUtils":"pydio/util/xml","whatwg-fetch":8}],"pydio/http/meta-cache-service":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); /** * API Client */ var MetaCacheService = (function (_Observable) { _inherits(MetaCacheService, _Observable); MetaCacheService.getInstance = function getInstance() { if (!MetaCacheService.INSTANCE) { MetaCacheService.INSTANCE = new MetaCacheService(); } return MetaCacheService.INSTANCE; }; function MetaCacheService() { _classCallCheck(this, MetaCacheService); _Observable.call(this); this._streams = new Map(); } MetaCacheService.prototype.hasKey = function hasKey(streamName, keyName) { if (!this._streams.get(streamName)) { return false; } return this._streams.get(streamName).get('data').has(keyName); }; MetaCacheService.prototype.getByKey = function getByKey(streamName, keyName) { if (!this._streams.get(streamName)) { return null; } return this._streams.get(streamName).get('data').get(keyName); }; MetaCacheService.prototype.deleteKey = function deleteKey(streamName, keyName) { if (!this._streams.get(streamName)) { return; } this._streams.get(streamName).get('data')['delete'](keyName); }; MetaCacheService.prototype.setKey = function setKey(streamName, keyName, value) { if (!this._streams.get(streamName)) { throw Error('Stream ' + streamName + ' not registered, please register first'); } this._streams.get(streamName).get('data').set(keyName, value); }; MetaCacheService.prototype.clearMetaStreamKeys = function clearMetaStreamKeys(streamName) { if (this._streams.has(streamName)) { this._streams.get(streamName).set('data', new Map()); } }; MetaCacheService.prototype.registerMetaStream = function registerMetaStream(streamName, expirationPolicy) { if (this._streams.get(streamName)) { return; } var data = new Map(); data.set('expirationPolicy', expirationPolicy); data.set('data', new Map()); this._streams.set(streamName, data); pydio.observe("repository_list_refreshed", (function () { // Always keep the cache at workspace scope this._streams['delete'](streamName); }).bind(this)); }; MetaCacheService.prototype.metaForNode = function metaForNode(streamName, ajxpNode, loaderCallback, remoteParser, cacheLoader) { var _this = this; if (!this._streams.has(streamName)) { throw new Error('Cannot find meta stream ' + streamName + ', please register it before using it'); } var def = this._streams.get(streamName); var key = ajxpNode.getPath(); var expirationPolicy = def.get('expirationPolicy'); if (def.get('data').has(key)) { cacheLoader(def.get('data').get(key)); } else { (function () { var clearValueObserver = (function () { def.get('data')['delete'](key); }).bind(_this); // Cache response if success var cacheCallback = function cacheCallback(transport) { var newData = remoteParser(transport); if (newData !== null) { var cachedData = newData; if (newData instanceof AjxpNode) { cachedData = new AjxpNode(); cachedData.replaceBy(newData); } def.get('data').set(key, cachedData); if (expirationPolicy == MetaCacheService.EXPIRATION_LOCAL_NODE) { ajxpNode.observeOnce("node_removed", clearValueObserver); ajxpNode.observeOnce("node_replaced", clearValueObserver); } } }; loaderCallback(ajxpNode, cacheCallback); })(); } }; MetaCacheService.prototype.invalidateMetaForKeys = function invalidateMetaForKeys(streamName, keyPattern) { if (!this._streams.has(streamName)) { throw new Error('Cannot find meta stream ' + streamName + ', please register it before using it'); } var data = this._streams.get(streamName).get('data'); data.forEach(function (value, key) { if (key.match(keyPattern)) { data['delete'](key); } }); }; return MetaCacheService; })(_langObservable2['default']); MetaCacheService.EXPIRATION_LOCAL_NODE = 'LOCAL_NODE'; MetaCacheService.EXPIRATION_MANUAL_TRIGGER = 'MANUAL_TRIGGER'; exports['default'] = MetaCacheService; module.exports = exports['default']; },{"../lang/Observable":"pydio/lang/observable"}],"pydio/http/resources-manager":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var SystemJS = require('systemjs'); /** * A manager that can handle the loading of JS, CSS and checks dependencies */ var ResourcesManager = (function () { /** * Constructor */ function ResourcesManager() { _classCallCheck(this, ResourcesManager); this.mainFormContainerId = 'all_forms'; this.resources = {}; this.loaded = false; } /** * Adds a Javascript resource * @param fileName String * @param className String */ ResourcesManager.prototype.addJSResource = function addJSResource(fileName, className) { if (!this.resources.js) { this.resources.js = []; } this.resources.js.push({ fileName: fileName, className: className, autoload: false }); }; /** * Adds a CSS resource * @param fileName String */ ResourcesManager.prototype.addCSSResource = function addCSSResource(fileName) { if (!this.resources.css) { this.resources.css = []; } this.resources.css.push(fileName); }; /** * Adds a FORM from html snipper * @param formId String * @param htmlSnippet String */ ResourcesManager.prototype.addGuiForm = function addGuiForm(formId, htmlSnippet) { if (!this.resources.forms) { this.resources.forms = new Map(); } this.resources.forms.set(formId, htmlSnippet); }; /** * Add a dependency to another plugin * @param data Object */ ResourcesManager.prototype.addDependency = function addDependency(data) { if (!this.resources.dependencies) { this.resources.dependencies = []; } this.resources.dependencies.push(data); }; /** * Check if some dependencies must be loaded before * @returns Boolean */ ResourcesManager.prototype.hasDependencies = function hasDependencies() { return this.resources.dependencies || false; }; /** * Load resources * @param resourcesRegistry Pydio resources registry */ ResourcesManager.prototype.load = function load(resourcesRegistry) { var _this = this; var jsAutoloadOnly = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var callback = arguments.length <= 2 || arguments[2] === undefined ? FuncUtils.Empty : arguments[2]; if (this.loaded) { callback(); return; } if (this.hasDependencies() && !this.dependenciesLoaded) { this.resources.dependencies.forEach((function (el) { if (resourcesRegistry[el]) { // Load dependencies and try again resourcesRegistry[el].load(resourcesRegistry, false, (function () { this.dependenciesLoaded = true; this.load(resourcesRegistry, false, callback); }).bind(this)); } }).bind(this)); } if (this.resources.forms) { this.resources.forms.forEach((function (value, key) { // REMOVED //this.loadGuiForm(key, value); }).bind(this)); } if (this.resources.js) { (function () { var it = _this.resources.js.values(); var cb = (function () { var object = it.next(); if (object.value) { if (jsAutoloadOnly && !object.value.autoload) { cb(); return; } this.loadJSResource(object.value.fileName, object.value.className, cb, true); } else { this.loaded = true; callback(); } }).bind(_this); cb(); })(); } else { this.loaded = true; callback(); } if (this.resources.css) { this.resources.css.forEach((function (value) { this.loadCSSResource(value); }).bind(this)); } }; /** * Load a javascript file * @param fileName String * @param className String * @param callback Function * @param aSync Boolean */ ResourcesManager.prototype.loadJSResource = function loadJSResource(fileName, className, callback) { var aSync = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3]; if (!ResourcesManager.__configsParsed) { ResourcesManager.loadAutoLoadResources(); } SystemJS['import'](className).then(callback); }; /** * Load a CSS file * @param fileName String */ ResourcesManager.prototype.loadCSSResource = function loadCSSResource(fileName) { if (pydio.Parameters.get('SERVER_PREFIX_URI')) { fileName = pydio.Parameters.get('SERVER_PREFIX_URI') + fileName; } fileName = fileName + "?v=" + pydio.Parameters.get("ajxpVersion"); var found = false; var links = document.getElementsByTagName('link'); for (var i = 0; i < links.length; i++) { var link = links[i]; if (link.rel === 'stylesheet' && link.href.endsWith(fileName)) { found = true;break; } } if (!found) { var head = document.getElementsByTagName('head')[0]; var cssNode = document.createElement('link'); cssNode.type = 'text/css'; cssNode.rel = 'stylesheet'; cssNode.href = fileName; cssNode.media = 'screen'; head.appendChild(cssNode); } }; /** * Load the resources from XML * @param node XMLNode */ ResourcesManager.prototype.loadFromXmlNode = function loadFromXmlNode(node) { var clForm = {}, k = undefined; if (node.nodeName == "resources") { for (k = 0; k < node.childNodes.length; k++) { if (node.childNodes[k].nodeName == 'js') { this.addJSResource(ResourcesManager.getFileOrFallback(node.childNodes[k]), node.childNodes[k].getAttribute('className')); } else if (node.childNodes[k].nodeName == 'css') { this.addCSSResource(ResourcesManager.getFileOrFallback(node.childNodes[k])); } } } else if (node.nodeName == "dependencies") { for (k = 0; k < node.childNodes.length; k++) { if (node.childNodes[k].nodeName == "pluginResources") { this.addDependency(node.childNodes[k].getAttribute("pluginName")); } } } else if (node.nodeName == "clientForm") { if (!node.getAttribute("theme") || node.getAttribute("theme") == pydio.Parameters.get("theme")) { clForm = { formId: node.getAttribute("id"), formCode: node.firstChild.nodeValue }; } } if (clForm.formId) { this.addGuiForm(clForm.formId, clForm.formCode); } }; /** * * @param aliasName * @param aliasPath * @todo MOVE OUTSIDE? */ ResourcesManager.addImageLibrary = function addImageLibrary(aliasName, aliasPath) { if (!window.AjxpImageLibraries) window.AjxpImageLibraries = {}; window.AjxpImageLibraries[aliasName] = aliasPath; }; /** * Find the default images path * @param src Icon source * @param defaultPath Default path, can contain ICON_SIZE * @param size Integer size optional * @returns string */ ResourcesManager.resolveImageSource = function resolveImageSource(src, defaultPath, size) { if (!src) return ""; var imagesFolder = ajxpResourcesFolder + '/images'; if (pydioBootstrap.parameters.get('ajxpImagesCommon')) { imagesFolder = imagesFolder.replace('/' + pydioBootstrap.parameters.get('theme') + '/', '/common/'); } if (defaultPath && defaultPath[0] !== '/') { defaultPath = '/' + defaultPath; } if (!window.AjxpImageLibraries || src.indexOf("/") == -1) { return imagesFolder + (defaultPath ? size ? defaultPath.replace("ICON_SIZE", size) : defaultPath : '') + '/' + src; } var radic = src.substring(0, src.indexOf("/")); if (window.AjxpImageLibraries[radic]) { src = src.replace(radic, window.AjxpImageLibraries[radic]); if (pydioBootstrap.parameters.get("SERVER_PREFIX_URI")) { src = pydioBootstrap.parameters.get("SERVER_PREFIX_URI") + src; } return size ? src.replace("ICON_SIZE", size) : src; } else { return imagesFolder + (defaultPath ? size ? defaultPath.replace("ICON_SIZE", size) : defaultPath : '') + '/' + src; } }; /** * Check if resources are tagged autoload and load them * @param registry DOMDocument XML Registry */ ResourcesManager.loadAutoLoadResources = function loadAutoLoadResources() { var registry = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; if (!registry) { registry = window.pydio.Registry.getXML(); } var manager = new ResourcesManager(); var jsNodes = _utilXMLUtils2['default'].XPathSelectNodes(registry, 'plugins/*/client_settings/resources/js'); var node = undefined; var sysjsMap = {}; var sysjsMeta = { '*': { authorization: true } }; var requires = {}; for (var _iterator = jsNodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { if (_isArray) { if (_i >= _iterator.length) break; node = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) break; node = _i.value; } var namespace = node.getAttribute('className'); var filepath = ResourcesManager.getFileOrFallback(node); var deps = []; if (node.getAttribute('depends')) { deps = node.getAttribute('depends').split(','); } if (node.getAttribute('expose')) { ResourcesManager.__requires[node.getAttribute('expose')] = namespace; } sysjsMap[namespace] = filepath; sysjsMeta[namespace] = { format: 'global', deps: deps }; } SystemJS.config({ map: sysjsMap, meta: sysjsMeta }); ResourcesManager.__configsParsed = true; var cssNodes = _utilXMLUtils2['default'].XPathSelectNodes(registry, 'plugins/*/client_settings/resources/css[@autoload="true"]'); for (var _iterator2 = cssNodes, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { if (_isArray2) { if (_i2 >= _iterator2.length) break; node = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; node = _i2.value; } manager.loadCSSResource(ResourcesManager.getFileOrFallback(node)); } }; ResourcesManager.getFileOrFallback = function getFileOrFallback(node) { if (node.getAttribute('fallbackCondition') && eval(node.getAttribute('fallbackCondition'))) { return node.getAttribute('fallbackFile'); } else { return node.getAttribute('file'); } }; ResourcesManager.requireLib = function requireLib(module) { var promise = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; if (window[module]) return window[module]; if (ResourcesManager.__requires && ResourcesManager.__requires[module]) { var globalNS = ResourcesManager.__requires[module]; if (promise) { return SystemJS['import'](globalNS); } if (window[globalNS]) { return window[globalNS]; } else { throw new Error('Requiring a remote lib that was not previously loaded (' + globalNS + '). You may be missing a dependency declaration in manifest, or you can use requireLib(moduleName, true) to receive a Promise.'); } } else { throw new Error('Cannot find any reference to lib ' + module); } }; /** * Check if a module is registered (not necessarily loaded yet) * @param className * @returns {Map|boolean} */ ResourcesManager.moduleIsAvailable = function moduleIsAvailable(className) { var config = SystemJS.getConfig(); return config.map && config.map[className]; }; ResourcesManager.loadClassesAndApply = function loadClassesAndApply(classNames, callbackFunc) { if (!ResourcesManager.__configsParsed) { ResourcesManager.loadAutoLoadResources(); } Promise.all(classNames.map(function (c) { return SystemJS['import'](c); })).then(function () { callbackFunc(); })['catch'](function (reason) { console.error('Failed Loading ' + classNames.join(', ') + ' : ', reason); }); return; }; ResourcesManager.detectModuleToLoadAndApply = function detectModuleToLoadAndApply(callbackString, callbackFunc) { var async = arguments.length <= 2 || arguments[2] === undefined ? true : arguments[2]; if (!ResourcesManager.__configsParsed) { ResourcesManager.loadAutoLoadResources(); } var className = callbackString.split('.', 1).shift(); if (async) { SystemJS['import'](className).then(callbackFunc); } else { ResourcesManager.loadScriptSync(className, callbackFunc); } return; }; ResourcesManager.loadScriptSync = function loadScriptSync(name, callback) { return regeneratorRuntime.async(function loadScriptSync$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return regeneratorRuntime.awrap(SystemJS['import'](name)); case 2: callback(); case 3: case 'end': return context$2$0.stop(); } }, null, this); }; return ResourcesManager; })(); ResourcesManager.__configsParsed = false; ResourcesManager.__requires = {}; exports['default'] = ResourcesManager; module.exports = exports['default']; },{"../util/XMLUtils":"pydio/util/xml","systemjs":7}],"pydio/http/users-api":[function(require,module,exports){ (function (global){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _PydioApi = require('./PydioApi'); var _PydioApi2 = _interopRequireDefault(_PydioApi); var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var User = (function () { function User(id, label, type, group, avatar, temporary, external, extendedLabel) { _classCallCheck(this, User); this._id = id; this._label = label; this._type = type; if (this._type === 'group') { this._group = id; } this._avatar = avatar; this._temporary = temporary; this._external = external; this._extendedLabel = extendedLabel; } User.fromObject = function fromObject(user) { return new User(user.id, user.label, user.type, user.group, user.avatar, user.temporary, user.external); }; User.prototype.asObject = function asObject() { return { id: this._id, label: this._label, type: this._type, group: this._group, avatar: this._avatar, temporary: this._temporary, external: this._external, extendedLabel: this._extendedLabel }; }; User.prototype.getId = function getId() { return this._id; }; User.prototype.getLabel = function getLabel() { return this._label; }; User.prototype.getType = function getType() { return this._type; }; User.prototype.getGroup = function getGroup() { return this._group; }; User.prototype.getAvatar = function getAvatar() { return this._avatar; }; User.prototype.getTemporary = function getTemporary() { return this._temporary; }; User.prototype.getExternal = function getExternal() { return this._external; }; User.prototype.getExtendedLabel = function getExtendedLabel() { return this._extendedLabel; }; return User; })(); var UsersApi = (function () { function UsersApi() { _classCallCheck(this, UsersApi); } UsersApi.authorizedUsersStartingWith = function authorizedUsersStartingWith(token, callback) { var usersOnly = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; var existingOnly = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var params = { get_action: 'user_list_authorized_users', value: token, format: 'json' }; if (usersOnly) { params['users_only'] = 'true'; } if (existingOnly) { params['existing_only'] = 'true'; } _PydioApi2['default'].getClient().request(params, function (transport) { var suggestions = []; if (transport.responseXML) { var lis = _utilXMLUtils2['default'].XPathSelectNodes(transport.responseXML, '//li'); lis.map(function (li) { var spanLabel = _utilXMLUtils2['default'].XPathGetSingleNodeText(li, 'span[@class="user_entry_label"]'); suggestions.push(new User(li.getAttribute('data-entry_id'), li.getAttribute('data-label'), li.getAttribute('class'), li.getAttribute('data-group'), li.getAttribute('data-avatar'), li.getAttribute('data-temporary') ? true : false, li.getAttribute('data-external') == 'true', spanLabel)); }); } else if (transport.responseJSON) { var data = transport.responseJSON; data.map(function (entry) { var id = entry.id; var label = entry.label; var type = entry.type; var group = entry.group; var avatar = entry.avatar; var temporary = entry.temporary; var external = entry.external; suggestions.push(new User(id, label, type, group, avatar, temporary, external, label)); }); } callback(suggestions); }); }; UsersApi.createUserFromPost = function createUserFromPost(postValues, callback) { postValues['get_action'] = 'user_create_user'; _PydioApi2['default'].getClient().request(postValues, (function (transport) { callback(postValues, transport.responseJSON); }).bind(this)); }; UsersApi.deleteUser = function deleteUser(userId, callback) { _PydioApi2['default'].getClient().request({ get_action: 'user_delete_user', user_id: userId }, function (transport) { callback(); }); }; UsersApi.saveSelectionSupported = function saveSelectionSupported() { return global.pydio.getController().actions.get('user_team_create') !== undefined; }; UsersApi.deleteTeam = function deleteTeam(teamId, callback) { teamId = teamId.replace('/AJXP_TEAM/', ''); _PydioApi2['default'].getClient().request({ get_action: 'user_team_delete', team_id: teamId }, function (transport) { callback(transport.responseJSON); }); }; UsersApi.saveSelectionAsTeam = function saveSelectionAsTeam(teamName, userIds, callback) { _PydioApi2['default'].getClient().request({ get_action: 'user_team_create', team_label: teamName, 'user_ids[]': userIds }, function (transport) { callback(transport.responseJSON); }); }; UsersApi.addUserToTeam = function addUserToTeam(teamId, userId, callback) { teamId = teamId.replace('/AJXP_TEAM/', ''); _PydioApi2['default'].getClient().request({ get_action: 'user_team_add_user', team_id: teamId, user_id: userId }, function (transport) { callback(transport.responseJSON); }); }; UsersApi.removeUserFromTeam = function removeUserFromTeam(teamId, userId, callback) { teamId = teamId.replace('/AJXP_TEAM/', ''); _PydioApi2['default'].getClient().request({ get_action: 'user_team_delete_user', team_id: teamId, user_id: userId }, function (transport) { callback(transport.responseJSON); }); }; UsersApi.updateTeamLabel = function updateTeamLabel(teamId, newLabel, callback) { teamId = teamId.replace('/AJXP_TEAM/', ''); _PydioApi2['default'].getClient().request({ get_action: 'user_team_update_label', team_id: teamId, team_label: newLabel }, function (transport) { callback(transport.responseJSON); }); }; return UsersApi; })(); exports.User = User; exports.UsersApi = UsersApi; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"../util/XMLUtils":"pydio/util/xml","./PydioApi":"pydio/http/api"}],"pydio/lang/logger":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ "use strict"; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Logger = (function () { function Logger() { _classCallCheck(this, Logger); } Logger.log = function log(message) { if (window.console) console.log(message); }; Logger.error = function error(message) { if (window.console) console.error(message); }; Logger.debug = function debug(message) { if (window.console) console.debug(message); }; return Logger; })(); exports["default"] = Logger; module.exports = exports["default"]; },{}],"pydio/lang/observable":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Observable = (function () { function Observable() { _classCallCheck(this, Observable); } Observable.prototype._objectEventSetup = function _objectEventSetup(event_name) { this._observers = this._observers || {}; this._observers[event_name] = this._observers[event_name] || []; }; Observable.prototype.observe = function observe(event_name, observer) { if (typeof event_name == 'string' && typeof observer != 'undefined') { this._objectEventSetup(event_name); if (this._observers[event_name].indexOf(observer) == -1) this._observers[event_name].push(observer); } else { for (var e in event_name) { if (event_name.hasOwnProperty(e)) { this.observe(e, event_name[e]); } } } }; Observable.prototype.stopObserving = function stopObserving(event_name, observer) { this._objectEventSetup(event_name); if (event_name && observer) this._observers[event_name] = this._observers[event_name].filter(function (o) { return o != observer; });else if (event_name) { this._observers[event_name] = []; } else { this._observers = {}; } }; Observable.prototype.observeOnce = function observeOnce(event_name, outer_observer) { var inner_observer = (function () { outer_observer.apply(this, arguments); this.stopObserving(event_name, inner_observer); }).bind(this); this._objectEventSetup(event_name); this._observers[event_name].push(inner_observer); }; Observable.prototype.notify = function notify(event_name) { this._objectEventSetup(event_name); var collected_return_values = []; var args = Array.from(arguments).slice(1); var observersCopy = this._observers[event_name].slice(0); for (var i = 0; i < observersCopy.length; ++i) { collected_return_values.push(observersCopy[i].apply(observersCopy[i], args) || null); } return collected_return_values; }; Observable.prototype.hasObservers = function hasObservers() { return this._observers.length; }; return Observable; })(); exports['default'] = Observable; module.exports = exports['default']; },{}],"pydio/model/action":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _utilLangUtils = require('../util/LangUtils'); var _utilLangUtils2 = _interopRequireDefault(_utilLangUtils); var _httpResourcesManager = require('../http/ResourcesManager'); var _httpResourcesManager2 = _interopRequireDefault(_httpResourcesManager); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _utilFuncUtils = require('../util/FuncUtils'); var _utilFuncUtils2 = _interopRequireDefault(_utilFuncUtils); /** * A "Command" object, encapsulating its callbacks, display attributes, etc. */ var Action = (function (_Observable) { _inherits(Action, _Observable); /** * Standard constructor */ function Action() { _classCallCheck(this, Action); _Observable.call(this); this.__DEFAULT_ICON_PATH = "actions/ICON_SIZE"; this.options = _utilLangUtils2['default'].objectMerge({ name: '', icon_class: '', text: '', title: '', text_id: '', title_id: '', weight: 0, hasAccessKey: false, accessKey: '', subMenu: false, subMenuUpdateImage: false, subMenuUpdateTitle: false, callbackCode: '', callback: function callback() {}, listeners: [], activeCondition: null }, arguments[0] || {}); this.context = _utilLangUtils2['default'].objectMerge({ selection: true, dir: false, allowedMimes: [], evalMetadata: '', root: true, inZip: true, recycle: false, behaviour: 'hidden', actionBar: false, actionBarGroup: 'default', contextMenu: false, ajxpWidgets: null, infoPanel: false }, arguments[1] || {}); this.selectionContext = _utilLangUtils2['default'].objectMerge({ dir: false, file: true, recycle: false, behaviour: 'disabled', allowedMimes: [], evalMetadata: '', unique: true, multipleOnly: false, enableRoot: false }, arguments[2] || {}); this.rightsContext = _utilLangUtils2['default'].objectMerge({ noUser: true, userLogged: true, guestLogged: false, read: false, write: false, adminOnly: false }, arguments[3] || {}); this.subMenuItems = _utilLangUtils2['default'].objectMerge({ staticItems: null, dynamicItems: null, dynamicBuilderCode: null, popoverContent: null }, arguments[4] || {}); this.elements = []; this.contextHidden = false; this.deny = false; if (this.context.subMenu) { if (!this.options.actionBar) { alert('Warning, wrong action definition. Cannot use a subMenu if not displayed in the actionBar!'); } } } Action.prototype._evalScripts = function _evalScripts(data, localScopeMetadata) { var metadata = localScopeMetadata; return eval(data); }; /** * Sets the manager for this action * @param manager ActionsManager */ Action.prototype.setManager = function setManager(manager) { this.manager = manager; if (this.options.subMenu) { if (this.subMenuItems.staticItems) { this.buildSubmenuStaticItems(); } if (this.subMenuItems.dynamicItems || this.subMenuItems.dynamicBuilderCode) { this.prepareSubmenuDynamicBuilder(); } else if (this.subMenuItems.dynamicBuilderModule) { _httpResourcesManager2['default'].detectModuleToLoadAndApply(this.subMenuItems.dynamicBuilderModule, this.prepareSubmenuDynamicBuilder.bind(this)); } } if (this.options.listeners['init']) { try { window.listenerContext = this; if (typeof this.options.listeners['init'] == "string") { this._evalScripts(this.options.listeners['init']); } else { this.options.listeners['init'](); } } catch (e) { _langLogger2['default'].error('Error while evaluating init script for action ' + this.options.name); } } }; /** * Execute the action code */ Action.prototype.apply = function apply() { if (this.deny) return; this.manager.publishActionEvent("beforeApply-" + this.options.name); window.actionArguments = []; window.actionManager = this.manager; if (arguments[0]) window.actionArguments = arguments[0]; if (this.options.callbackCode) { try { this._evalScripts(this.options.callbackCode); } catch (e) { _langLogger2['default'].error(e); } } else if (this.options.callback) { this.options.callback(this.manager, arguments[0]); } if (this.options.subMenu && arguments[0] && arguments[0][0]) { this.notify("submenu_active", arguments[0][0]); } window.actionArguments = null; window.actionManager = null; this.manager.publishActionEvent("afterApply-" + this.options.name); }; /** * Updates the action status on context change * @param PydioDataModel dataModel * @param boolean usersEnabled * @param string crtUser * @returns void */ Action.prototype.fireContextChange = function fireContextChange(dataModel, usersEnabled, crtUser) { var crtIsRecycle = false; var crtInZip = false; var crtIsRoot = false; var crtAjxpMime = ''; var crtIsReadOnly = false; var crtNode = dataModel.getContextNode(); if (crtNode) { crtIsRecycle = crtNode.getAjxpMime() == "ajxp_recycle"; crtInZip = crtNode.hasAjxpMimeInBranch("ajxp_browsable_archive"); crtIsRoot = crtNode.isRoot(); crtAjxpMime = crtNode.getAjxpMime(); crtIsReadOnly = crtNode.hasMetadataInBranch("ajxp_readonly", "true"); } if (this.options.listeners["contextChange"]) { if (this.options.listeners["contextChange"] instanceof Function) { this.options.listeners["contextChange"](); } else { window.listenerContext = this; try { this._evalScripts(this.options.listeners["contextChange"]); } catch (e) { _langLogger2['default'].error("Error while evaluating script for contextChange event - action " + this.options.name); } } } var rightsContext = this.rightsContext; if (!rightsContext.noUser && !usersEnabled) { return this.hideForContext(); } if (rightsContext.userLogged == 'only' && crtUser == null || rightsContext.guestLogged && rightsContext.guestLogged == 'hidden' && crtUser != null && crtUser.id == 'guest') { return this.hideForContext(); } if (rightsContext.userLogged == 'hidden' && crtUser != null && !(crtUser.id == 'guest' && rightsContext.guestLogged && rightsContext.guestLogged == 'show')) { return this.hideForContext(); } if (rightsContext.adminOnly && (crtUser == null || !crtUser.isAdmin)) { return this.hideForContext(); } if (rightsContext.read && crtUser != null && !crtUser.canRead()) { return this.hideForContext(); } if (rightsContext.write && crtUser != null && !crtUser.canWrite()) { return this.hideForContext(); } if (rightsContext.write && crtIsReadOnly) { return this.hideForContext(); } if (this.context.allowedMimes.length) { if (this.context.allowedMimes.indexOf("*") == -1 && this.context.allowedMimes.indexOf(crtAjxpMime) == -1) { return this.hideForContext(); } if (this.context.allowedMimes.indexOf("^" + crtAjxpMime) != -1) { return this.hideForContext(); } } if (this.context.recycle) { if (this.context.recycle == 'only' && !crtIsRecycle) { return this.hideForContext(); } if (this.context.recycle == 'hidden' && crtIsRecycle) { return this.hideForContext(); } } if (!this.context.inZip && crtInZip) { return this.hideForContext(); } if (!this.context.root && crtIsRoot) { return this.hideForContext(); } this.showForContext(dataModel); }; /** * Upates the action status on selection change */ Action.prototype.fireSelectionChange = function fireSelectionChange() { if (this.options.listeners["selectionChange"]) { if (this.options.listeners["selectionChange"] instanceof Function) { this.options.listeners["selectionChange"](); } else { window.listenerContext = this; try { this._evalScripts(this.options.listeners["selectionChange"]); } catch (e) { _langLogger2['default'].error("Error while evaluating script for selectionChange event - action " + this.options.name); } } } if (this.options.activeCondition) { try { var result = this.options.activeCondition(); if (result === false) this.disable();else if (result === true) this.enable(); } catch (e) { _langLogger2['default'].error("Error while evaluating activeCondition() script for action " + this.options.name); } } if (this.contextHidden || !this.context.selection) { return; } var userSelection = arguments[0]; var hasRoot = false; if (userSelection != null) { hasRoot = userSelection.selectionHasRootNode(); var bUnique = userSelection.isUnique(); var bFile = userSelection.hasFile(); var bDir = userSelection.hasDir(); var bRecycle = userSelection.isRecycle(); } var selectionContext = this.selectionContext; if (selectionContext.allowedMimes.length) { if (selectionContext.behaviour == 'hidden') this.hide();else this.disable(); } if (selectionContext.evalMetadata && userSelection && userSelection.isUnique()) { var result = this._evalScripts(selectionContext.evalMetadata, userSelection.getUniqueNode().getMetadata()); if (!result) { if (selectionContext.behaviour == 'hidden') this.hide();else this.disable(); return; } } if (!selectionContext.enableRoot && hasRoot) { return this.disable(); } if (selectionContext.unique && !bUnique) { return this.disable(); } if (selectionContext.multipleOnly && bUnique) { return this.disable(); } if ((selectionContext.file || selectionContext.dir) && !bFile && !bDir) { return this.disable(); } if (selectionContext.dir && !selectionContext.file && bFile || !selectionContext.dir && selectionContext.file && bDir) { return this.disable(); } if (!selectionContext.recycle && bRecycle) { return this.disable(); } if (this.rightsContext.write && userSelection.hasReadOnly()) { return this.disable(); } if (selectionContext.allowedMimes.length && userSelection && selectionContext.allowedMimes.indexOf('*') == -1 && !userSelection.hasMime(selectionContext.allowedMimes)) { if (selectionContext.behaviour == 'hidden') return this.hide();else return this.disable(); } if (selectionContext.allowedMimes.length && userSelection && selectionContext.allowedMimes.indexOf("^") !== -1) { var forbiddenValueFound = false; selectionContext.allowedMimes.forEach(function (m) { if (m.indexOf("^") == -1) return; if (userSelection.hasMime([m.replace("^", "")])) { forbiddenValueFound = true; //throw $break; } }); if (forbiddenValueFound) { if (selectionContext.behaviour == 'hidden') return this.hide();else return this.disable(); } } this.show(); this.enable(); }; Action.prototype.getMenuData = function getMenuData() { var menuItem = { name: this.getKeyedText(), raw_name: this.options.text, alt: this.options.title, action_id: this.options.name, weight: this.options.weight || 0, callback: (function (e) { this.apply(); }).bind(this) }; if (this.options.icon_class) { menuItem.icon_class = this.options.icon_class; } if (this.options.subMenu) { menuItem.subMenu = []; if (this.subMenuItems.staticOptions) { menuItem.subMenu = this.subMenuItems.staticOptions; } if (this.subMenuItems.dynamicBuilder) { menuItem.subMenuBeforeShow = this.subMenuItems.dynamicBuilder; } } return menuItem; }; /** * Parses an XML fragment to configure this action * @param xmlNode Node XML Fragment describing the action */ Action.prototype.createFromXML = function createFromXML(xmlNode) { var _this = this; this.options.name = xmlNode.getAttribute('name'); for (var i = 0; i < xmlNode.childNodes.length; i++) { var node = xmlNode.childNodes[i]; var defaultAttributes = { dir: "dirDefault", file: "fileDefault", dragndrop: "dragndropDefault", ctrldragndrop: "ctrlDragndropDefault", expire: "expireDefault" }; for (var key in defaultAttributes) { if (!defaultAttributes.hasOwnProperty(key)) continue; var value = defaultAttributes[key]; if (xmlNode.getAttribute(value) && xmlNode.getAttribute(value) == "true") { if (!this.defaults) this.defaults = {}; this.defaults[key] = true; } } var j; if (node.nodeName == "processing") { var clientFormData = {}; for (j = 0; j < node.childNodes.length; j++) { var processNode = node.childNodes[j]; if (processNode.nodeName == "clientCallback") { if (processNode.getAttribute('module')) { (function () { var fName = processNode.getAttribute('module'); _this.options.callback = function (manager, otherArguments) { _httpResourcesManager2['default'].detectModuleToLoadAndApply(fName, function () { _utilFuncUtils2['default'].executeFunctionByName(fName, window, manager, otherArguments); }); }; if (_this.defaults && (_this.defaults['dragndrop'] || _this.defaults['ctrldragndrop'])) { _this.options.dragndropCheckModule = fName; } })(); } else if (processNode.firstChild) { this.options.callbackCode = processNode.firstChild.nodeValue.trim(); } } else if (processNode.nodeName == "clientListener") { if (processNode.getAttribute('module')) { (function () { var moduleName = processNode.getAttribute('module'); _this.options.listeners[processNode.getAttribute('name')] = (function () { _httpResourcesManager2['default'].detectModuleToLoadAndApply(moduleName, (function () { var func = _utilFuncUtils2['default'].getFunctionByName(moduleName, window); if (func) func.apply(this); }).bind(this)); }).bind(_this); })(); } else if (processNode.firstChild) { this.options.listeners[processNode.getAttribute('name')] = processNode.firstChild.nodeValue.trim(); } } else if (processNode.nodeName == "activeCondition" && processNode.firstChild) { this.options.activeCondition = new Function(processNode.firstChild.nodeValue.trim()); } } } else if (node.nodeName == "gui") { this.options.text_id = node.getAttribute('text'); this.options.title_id = node.getAttribute('title'); this.options.text = this.manager.getMessage(node.getAttribute('text')) || 'not_found'; this.options.title = this.manager.getMessage(node.getAttribute('title')) || 'not_found'; this.options.src = node.getAttribute('src'); this.options.icon_class = node.getAttribute('iconClass'); this.options.weight = node.getAttribute('weight') || 0; if (node.getAttribute('hasAccessKey') && node.getAttribute('hasAccessKey') == "true") { this.options.accessKey = node.getAttribute('accessKey'); this.options.hasAccessKey = true; } if (node.getAttribute('specialAccessKey')) { this.options.specialAccessKey = node.getAttribute('specialAccessKey'); } for (j = 0; j < node.childNodes.length; j++) { if (node.childNodes[j].nodeName == "context") { this.attributesToObject(this.context, node.childNodes[j]); if (this.context.ajxpWidgets) { this.context.ajxpWidgets = this.context.ajxpWidgets.split(','); } else { this.context.ajxpWidgets = []; } // Backward compatibility if (this.context.infoPanel) this.context.ajxpWidgets.push('InfoPanel'); if (this.context.actionBar) this.context.ajxpWidgets.push('ActionsToolbar'); } else if (node.childNodes[j].nodeName == "selectionContext") { this.attributesToObject(this.selectionContext, node.childNodes[j]); } } } else if (node.nodeName == "rightsContext") { this.attributesToObject(this.rightsContext, node); } else if (node.nodeName == "subMenu") { this.options.subMenu = true; if (node.getAttribute("updateImageOnSelect") && node.getAttribute("updateImageOnSelect") == "true") { this.options.subMenuUpdateImage = true; } if (node.getAttribute("updateTitleOnSelect") && node.getAttribute("updateTitleOnSelect") == "true") { this.options.subMenuUpdateTitle = true; } for (j = 0; j < node.childNodes.length; j++) { if (node.childNodes[j].nodeName == "staticItems" || node.childNodes[j].nodeName == "dynamicItems") { this.subMenuItems[node.childNodes[j].nodeName] = []; for (var k = 0; k < node.childNodes[j].childNodes.length; k++) { if (node.childNodes[j].childNodes[k].nodeName.startsWith("item")) { var item = {}; for (var z = 0; z < node.childNodes[j].childNodes[k].attributes.length; z++) { var attribute = node.childNodes[j].childNodes[k].attributes[z]; item[attribute.nodeName] = attribute.value; } this.subMenuItems[node.childNodes[j].nodeName].push(item); } } } else if (node.childNodes[j].nodeName == "dynamicBuilder") { if (node.childNodes[j].getAttribute("module")) { this.subMenuItems.dynamicBuilderModule = node.childNodes[j].getAttribute("module"); } else { this.subMenuItems.dynamicBuilderCode = node.childNodes[j].firstChild.nodeValue; } } } } } if (!this.options.hasAccessKey) return; if (this.options.accessKey == '' || !this.manager.getMessage(this.options.accessKey) || this.options.text.indexOf(this.manager.getMessage(this.options.accessKey)) == -1) { this.options.accessKey = this.options.text.charAt(0); } else { this.options.accessKey = this.manager.getMessage(this.options.accessKey); } }; /** * Creates the submenu items */ Action.prototype.buildSubmenuStaticItems = function buildSubmenuStaticItems() { var menuItems = []; if (this.subMenuItems.staticItems) { this.subMenuItems.staticItems.forEach(function (item) { var itemText = this.manager.getMessage(item.text); if (item.hasAccessKey && (item.hasAccessKey == 'true' || item.hasAccessKey === true) && this.manager.getMessage(item.accessKey)) { itemText = this.getKeyedText(this.manager.getMessage(item.text), true, this.manager.getMessage(item.accessKey)); if (!this.subMenuItems.accessKeys) this.subMenuItems.accessKeys = []; this.manager.registerKey(this.manager.getMessage(item.accessKey), this.options.name, item.command); } menuItems.push({ name: itemText, alt: this.manager.getMessage(item.title), image_unresolved: item.src, icon_class: item.icon_class, isDefault: item.isDefault ? true : false, callback: (function () { this.apply([item]); }).bind(this) }); }, this); } this.subMenuItems.staticOptions = menuItems; }; /** * Caches some data for dynamically built menus */ Action.prototype.prepareSubmenuDynamicBuilder = function prepareSubmenuDynamicBuilder() { this.subMenuItems.dynamicBuilder = (function (controller) { var menuItems = []; if (this.subMenuItems.dynamicBuilderCode) { window.builderContext = this; this._evalScripts(this.subMenuItems.dynamicBuilderCode); menuItems = this.builderMenuItems || []; } else if (this.subMenuItems.dynamicBuilderModule) { var func = _utilFuncUtils2['default'].getFunctionByName(this.subMenuItems.dynamicBuilderModule, window); if (func) { menuItems = func.apply(this); } } else { menuItems = []; this.subMenuItems.dynamicItems.forEach(function (item) { if (item.separator) { menuItems.push(item); return; } var action = undefined; if (item['actionId'] instanceof Action) { action = item['actionId']; } else { action = this.manager.actions.get(item['actionId']); } if (action.deny) return; var itemData = { name: action.getKeyedText(), alt: action.options.title, icon_class: action.options.icon_class, image_unresolved: action.options.src, callback: (function () { this.apply(); }).bind(action) }; if (action.options.subMenu) { itemData.subMenu = []; if (action.subMenuItems.staticOptions) { itemData.subMenu = action.subMenuItems.staticOptions; } if (action.subMenuItems.dynamicBuilder) { itemData.subMenuBeforeShow = action.subMenuItems.dynamicBuilder; } } menuItems.push(itemData); }, this); } return menuItems; }).bind(this); }; /** * Refresh icon image source * @param newSrc String The image source. Can reference an image library * @param iconClass String Optional class to replace image */ Action.prototype.setIconClassName = function setIconClassName(iconClass) { var icon_class = this.options.icon_class; this.notify("update_icon", { new_class: iconClass, previous_class: icon_class }); this.options.icon_class = iconClass; }; /** * Refresh the action label * @param newLabel String the new label * @param newTitle String the new tooltip */ Action.prototype.setLabel = function setLabel(newLabel, newTitle) { this.options.text = this.manager.getMessage(newLabel); this.notify("update_label", this.getKeyedText()); if (newTitle) { this.options.title = this.manager.getMessage(newTitle); this.notify("update_title", this.options.title); } }; Action.prototype.refreshInstances = function refreshInstances() {}; /** * Grab its label from the i18n */ Action.prototype.refreshFromI18NHash = function refreshFromI18NHash() { this.setLabel(this.options.text_id, this.options.title_id); }; /** * Return data necessary to build InfoPanel * @returns Object */ Action.prototype.toInfoPanel = function toInfoPanel() { return this.options; }; /** * Return necessary data to build contextual menu * @returns Object */ Action.prototype.toContextMenu = function toContextMenu() { return this.options; }; /** * Changes show/hide state */ Action.prototype.hideForContext = function hideForContext() { this.hide(); this.contextHidden = true; }; /** * Changes show/hide state */ Action.prototype.showForContext = function showForContext(dataModel) { this.contextHidden = false; this.show(); if (this.selectionContext) { this.fireSelectionChange(dataModel); } }; /** * Changes show/hide state * Notifies "hide" Event */ Action.prototype.hide = function hide() { this.deny = true; this.notify('hide'); }; /** * Changes show/hide state * Notifies "show" Event */ Action.prototype.show = function show() { this.deny = false; this.notify('show'); }; /** * Changes enable/disable state * Notifies "disable" Event */ Action.prototype.disable = function disable() { this.deny = true; this.notify('disable'); }; /** * Changes enable/disable state * Notifies "enable" Event */ Action.prototype.enable = function enable() { this.deny = false; this.notify('enable'); }; /** * To be called when removing */ Action.prototype.remove = function remove() { this.notify("remove"); }; /** * Create a text label with access-key underlined. * @param displayString String the label * @param hasAccessKey Boolean whether there is an accessKey or not * @param accessKey String The key to underline * @returns String */ Action.prototype.getKeyedText = function getKeyedText(displayString, hasAccessKey, accessKey) { if (!displayString) { displayString = this.options.text; } if (!hasAccessKey) { hasAccessKey = this.options.hasAccessKey; } if (!accessKey) { accessKey = this.options.accessKey; } if (!hasAccessKey) return displayString; var keyPos = displayString.toLowerCase().indexOf(accessKey.toLowerCase()); if (keyPos == -1) { return displayString + ' (' + accessKey + ')'; } if (displayString.charAt(keyPos) != accessKey) { // case differ accessKey = displayString.charAt(keyPos); } var returnString = displayString.substring(0, displayString.indexOf(accessKey)); returnString += '' + accessKey + ''; returnString += displayString.substring(displayString.indexOf(accessKey) + 1, displayString.length); return returnString; }; /** * Utilitary function to transform XML Node attributes into Object mapping keys. * @param object Object The target object * @param node Node The source node */ Action.prototype.attributesToObject = function attributesToObject(object, node) { for (var key in object) { if (!object.hasOwnProperty(key) || !node.getAttribute(key)) continue; var value = node.getAttribute(key); if (value == 'true') value = true;else if (value == 'false') value = false; if (key == 'allowedMimes') { if (value && value.split(',').length) { value = value.split(','); } else { value = []; } } object[key] = value; } }; return Action; })(_langObservable2['default']); exports['default'] = Action; module.exports = exports['default']; },{"../http/ResourcesManager":"pydio/http/resources-manager","../lang/Logger":"pydio/lang/logger","../lang/Observable":"pydio/lang/observable","../util/FuncUtils":"pydio/util/func","../util/LangUtils":"pydio/util/lang","../util/XMLUtils":"pydio/util/xml"}],"pydio/model/context-menu":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ "use strict"; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var ContextMenuModel = (function (_Observable) { _inherits(ContextMenuModel, _Observable); function ContextMenuModel() { _classCallCheck(this, ContextMenuModel); _Observable.apply(this, arguments); } ContextMenuModel.prototype["super"] = function _super() { this._currentNode = null; this._position = null; }; ContextMenuModel.getInstance = function getInstance() { if (!ContextMenuModel.__INSTANCE) { ContextMenuModel.__INSTANCE = new ContextMenuModel(); } return ContextMenuModel.__INSTANCE; }; ContextMenuModel.prototype.openAtPosition = function openAtPosition(clientX, clientY) { this._currentNode = null; this._position = { x: clientX, y: clientY }; this.notify("open"); }; ContextMenuModel.prototype.openNodeAtPosition = function openNodeAtPosition(node, clientX, clientY) { this._currentNode = node; this._position = { x: clientX, y: clientY }; this.notify("open", node); }; ContextMenuModel.prototype.getNode = function getNode() { return this._currentNode; }; ContextMenuModel.prototype.getPosition = function getPosition() { return this._position; }; ContextMenuModel.prototype.close = function close() { this._currentNode = null; this.notify("close"); }; return ContextMenuModel; })(_langObservable2["default"]); exports["default"] = ContextMenuModel; module.exports = exports["default"]; },{"../lang/Observable":"pydio/lang/observable"}],"pydio/model/controller":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _Action = require('./Action'); var _Action2 = _interopRequireDefault(_Action); /** * Singleton class that manages all actions. Can be called directly using pydio.getController(). */ var Controller = (function (_Observable) { _inherits(Controller, _Observable); /** * Standard constructor * @param pydioObject Pydio * @param dataModelElementId */ function Controller(pydioObject) { var dataModelElementId = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; _classCallCheck(this, Controller); _Observable.call(this); this._pydioObject = pydioObject; this._registeredKeys = new Map(); this.usersEnabled = pydioObject.Parameters.get("usersEnabled"); this.subMenus = []; this.actions = new Map(); this.defaultActions = new Map(); this.toolbars = new Map(); this._guiActions = new Map(); this.contextChangedObs = (function (event) { window.setTimeout((function () { this.fireContextChange(); }).bind(this), 0); }).bind(this); this.selectionChangedObs = (function (event) { window.setTimeout((function () { this.fireSelectionChange(); }).bind(this), 0); }).bind(this); if (dataModelElementId) { this.localDataModel = true; try { this._dataModel = document.getElementById(dataModelElementId).ajxpPaneObject.getDataModel(); } catch (e) {} if (this._dataModel) { this._connectDataModel(); } else { this._pydioObject.observeOnce("datamodel-loaded-" + dataModelElementId, (function () { this._dataModel = document.getElementById(dataModelElementId).ajxpPaneObject.getDataModel(); this._connectDataModel(); }).bind(this)); } } else { this.localDataModel = false; this._connectDataModel(); } if (this.usersEnabled) { this._pydioObject.observe("user_logged", (function (user) { this.setUser(user); }).bind(this)); if (this._pydioObject.user) { this.setUser(this._pydioObject.user); } } } Controller.prototype.publishActionEvent = function publishActionEvent(eventName, data) { this._pydioObject.fire(eventName, data); }; Controller.prototype._connectDataModel = function _connectDataModel() { if (this.localDataModel) { this._dataModel.observe("context_changed", this.contextChangedObs); this._dataModel.observe("selection_changed", this.selectionChangedObs); this.loadActionsFromRegistry(); this._pydioObject.observe("registry_loaded", (function (registry) { this.loadActionsFromRegistry(registry); }).bind(this)); } else { this._pydioObject.observe("context_changed", this.contextChangedObs); this._pydioObject.observe("selection_changed", this.selectionChangedObs); this._dataModel = this._pydioObject.getContextHolder(); } }; Controller.prototype.updateGuiActions = function updateGuiActions(actions) { actions.forEach((function (v, k) { this._guiActions.set(k, v); this.registerAction(v); }).bind(this)); //this.notify("actions_refreshed"); }; Controller.prototype.deleteFromGuiActions = function deleteFromGuiActions(actionName) { this._guiActions['delete'](actionName); //this.notify("actions_refreshed"); }; Controller.prototype.refreshGuiActionsI18n = function refreshGuiActionsI18n() { this._guiActions.forEach(function (value, key) { value.refreshFromI18NHash(); }); }; Controller.prototype.getDataModel = function getDataModel() { return this._dataModel; }; Controller.prototype.destroy = function destroy() { if (this.localDataModel && this._dataModel) { this._dataModel.stopObserving("context_changed", this.contextChangedObs); this._dataModel.stopObserving("selection_changed", this.selectionChangedObs); } }; Controller.prototype.getMessage = function getMessage(messageId) { try { return this._pydioObject.MessageHash[messageId]; } catch (e) { return messageId; } }; /** * COMPATIBILITY METHD * @param xmlDoc * @returns {*} */ Controller.prototype.parseXmlMessage = function parseXmlMessage(xmlDoc) { _langLogger2['default'].debug("Controller.parseXmlMessage() is deprecated, use PydioApi instead"); return _httpPydioApi2['default'].getClient().parseXmlMessage(xmlDoc); }; /** * Submits a form using Connexion class. * @param formName String The id of the form * @param post Boolean Whether to POST or GET * @param completeCallback Function Callback to be called on complete */ Controller.prototype.submitForm = function submitForm(formName, post, completeCallback) { _langLogger2['default'].debug("Controller.submitForm() is deprecated, use PydioApi instead"); return _httpPydioApi2['default'].getClient().submitForm(formName, post, completeCallback); }; /** * Stores the currently logged user object * @param oUser User User instance */ Controller.prototype.setUser = function setUser(oUser) { this.oUser = oUser; if (oUser != null && oUser.id != 'guest' && oUser.getPreference('lang') != null && oUser.getPreference('lang') != "" && oUser.getPreference('lang') != this._pydioObject.currentLanguage && !oUser.lock) { this._pydioObject.loadI18NMessages(oUser.getPreference('lang')); } }; /** * Filter the actions given the srcElement passed as arguments. * @param actionsSelectorAtt String An identifier among selectionContext, genericContext, a webfx object id * @param ignoreGroups Array a list of groups to ignore * @returns Array */ Controller.prototype.getContextActions = function getContextActions(actionsSelectorAtt, ignoreGroups, onlyGroups) { var contextActions = []; var defaultGroup = undefined; var contextActionsGroup = new Map(); this.actions.forEach((function (action) { if (!action.context.contextMenu && !(onlyGroups && onlyGroups.length)) return; if (actionsSelectorAtt == 'selectionContext' && !action.context.selection) return; if (actionsSelectorAtt == 'directoryContext' && !action.context.dir) return; if (actionsSelectorAtt == 'genericContext' && action.context.selection) return; if (action.contextHidden || action.deny) return; action.context.actionBarGroup.split(',').forEach(function (barGroup) { if (!contextActionsGroup.has(barGroup)) { contextActionsGroup.set(barGroup, []); } }); var isDefault = false; if (actionsSelectorAtt == 'selectionContext') { // set default in bold var userSelection = this._dataModel; if (!userSelection.isEmpty()) { var defaultAction = 'file'; if (userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(['ajxp_browsable_archive']))) { defaultAction = 'dir'; } if (this.defaultActions.get(defaultAction) && action.options.name == this.defaultActions.get(defaultAction)) { isDefault = true; } } } action.context.actionBarGroup.split(',').forEach(function (barGroup) { var menuItem = action.getMenuData(); menuItem.isDefault = isDefault; contextActionsGroup.get(barGroup).push(menuItem); if (isDefault) { defaultGroup = barGroup; } }); }).bind(this)); var first = true, keys = []; contextActionsGroup = this._sortToolbarsActions(contextActionsGroup); contextActionsGroup.forEach(function (v, k) { if (defaultGroup && k == defaultGroup) return; keys.push(k); }); keys.sort(); if (defaultGroup && contextActionsGroup.has(defaultGroup)) { keys.unshift(defaultGroup); } var actionsPushed = {}; keys.map(function (key) { var value = contextActionsGroup.get(key); if (!first) { contextActions.push({ separator: true }); } if (ignoreGroups && ignoreGroups.indexOf(key) !== -1) { return; } if (onlyGroups && onlyGroups.indexOf(key) === -1) { return; } first = false; value.forEach(function (mItem) { var actionId = mItem.action_id; if (!actionsPushed[actionId]) { contextActions.push(mItem); actionsPushed[actionId] = true; } }); }); return contextActions; }; Controller.prototype.getToolbarsActions = function getToolbarsActions() { var _this = this; var toolbarsList = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; var groupOtherList = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; var toolbars = new Map(), groupOtherBars = new Map(); var lastTbarAdded = undefined; this.actions.forEach((function (action) { if (action.context.actionBar) { action.context.actionBarGroup.split(",").map((function (barGroup) { if (toolbarsList.indexOf(barGroup) === -1 && groupOtherList.indexOf(barGroup) === -1) { return; } var tBarUpdate = toolbarsList.indexOf(barGroup) !== -1 ? toolbars : groupOtherBars; if (tBarUpdate.get(barGroup) == null) { tBarUpdate.set(barGroup, []); } tBarUpdate.get(barGroup).push(action); if (tBarUpdate === toolbars) { lastTbarAdded = barGroup; } }).bind(this)); } }).bind(this)); // Regroup actions artificially if (groupOtherList.length) { (function () { var submenuItems = []; groupOtherList.map((function (otherToolbar) { var otherActions = groupOtherBars.get(otherToolbar); if (!otherActions) return; otherActions.map(function (act) { submenuItems.push({ actionId: act }); }); if (groupOtherList.indexOf(otherToolbar) < groupOtherList.length - 1) { submenuItems.push({ separator: true }); } }).bind(_this)); var moreAction = new _Action2['default']({ name: 'group_more_action', icon_class: 'icon-none', text: MessageHash[456], title: MessageHash[456], hasAccessKey: false, subMenu: true, callback: function callback() {} }, { selection: false, dir: true, actionBar: true, actionBarGroup: '', contextMenu: false, infoPanel: false }, {}, {}, { dynamicItems: submenuItems }); _this.registerAction(moreAction); _this.actions.set("group_more_action", moreAction); toolbars.set('MORE_ACTION', [moreAction]); })(); } this._sortToolbarsActions(toolbars); return toolbars; }; /** * Generic method to get actions for a given component part. * @param ajxpClassName String * @param widgetId String * @returns [] */ Controller.prototype.getActionsForAjxpWidget = function getActionsForAjxpWidget(ajxpClassName, widgetId) { var actions = []; this.actions.forEach(function (action) { if (action.context.ajxpWidgets && (action.context.ajxpWidgets.indexOf(ajxpClassName + '::' + widgetId) != -1 || action.context.ajxpWidgets.indexOf(ajxpClassName) != -1) && !action.deny) actions.push(action); }); return actions; }; /** * Finds a default action and fires it. * @param defaultName String ("file", "dir", "dragndrop", "ctrldragndrop") */ Controller.prototype.fireDefaultAction = function fireDefaultAction(defaultName) { var actionName = this.defaultActions.get(defaultName); if (actionName) { arguments[0] = actionName; if (actionName === "ls") { var action = this.actions.get(actionName); if (action) action.enable(); // Force enable on default action } this.fireAction.apply(this, arguments); } }; /** * Fire an action based on its name * @param actionName String The name of the action */ Controller.prototype.fireAction = function fireAction(actionName) { var action = this.actions.get(actionName); if (action != null) { var args = Array.from(arguments).slice(1); action.apply(args); } }; /** * Registers an accesskey for a given action. * @param key String The access key * @param actionName String The name of the action * @param optionnalCommand String An optionnal argument * that will be passed to the action when fired. */ Controller.prototype.registerKey = function registerKey(key, actionName, optionnalCommand) { if (optionnalCommand) { actionName = actionName + "::" + optionnalCommand; } this._registeredKeys.set(key.toLowerCase(), actionName); }; /** * Remove all registered keys. */ Controller.prototype.clearRegisteredKeys = function clearRegisteredKeys() { this._registeredKeys = new Map(); }; /** * Triggers an action by its access key. * @param keyName String A key name */ Controller.prototype.fireActionByKey = function fireActionByKey(keyName) { if (this._registeredKeys.get(keyName)) { if (this._registeredKeys.get(keyName).indexOf("::") !== -1) { var parts = this._registeredKeys.get(keyName).split("::"); this.fireAction(parts[0], parts[1]); } else { this.fireAction(this._registeredKeys.get(keyName)); } return true; } return false; }; /** * Complex function called when drag'n'dropping. Basic checks of who is child of who. * @param fileName String The dragged element * @param destDir String The drop target node path * @param destNodeName String The drop target node name * @param copy Boolean Copy or Move */ Controller.prototype.applyDragMove = function applyDragMove(fileName, destDir, destNodeName, copy) { if (!copy && (!this.defaultActions.has('dragndrop') || this.getDefaultAction('dragndrop').deny) || copy && (!this.defaultActions.has('ctrldragndrop') || this.getDefaultAction('ctrldragndrop').deny)) { return; } var fileNames = undefined; if (fileName == null) fileNames = this._dataModel.getFileNames();else fileNames = [fileName]; // Check that dest is not the direct parent of source, ie current rep! if (destDir == this._dataModel.getContextNode().getPath()) { this._pydioObject.displayMessage('ERROR', MessageHash[203]); return; } // Check that dest is not child of source it self for (var i = 0; i < fileNames.length; i++) { if (destDir.lastIndexOf(fileNames[i], 0) === 0) { this._pydioObject.displayMessage('ERROR', MessageHash[202]); return; } } var params = {}; params['get_action'] = this.defaultActions.get(copy ? 'ctrldragndrop' : 'dragndrop'); params['nodes[]'] = fileNames; params['dest'] = destDir; params['dir'] = this._dataModel.getContextNode().getPath(); _httpPydioApi2['default'].getClient().request(params, (function (transport) { this.parseXmlMessage(transport.responseXML); }).bind(_httpPydioApi2['default'].getClient())); }; /** * Get the action defined as default for a given default string * @param defaultName String * @returns Action */ Controller.prototype.getDefaultAction = function getDefaultAction(defaultName) { if (this.defaultActions.has(defaultName)) { return this.actions.get(this.defaultActions.get(defaultName)); } return null; }; /** * Spreads a selection change to all actions and to registered components * by triggering ajaxplorer:actions_refreshed event. */ Controller.prototype.fireSelectionChange = function fireSelectionChange() { this.actions.forEach((function (action) { action.fireSelectionChange(this._dataModel); }).bind(this)); this.notify("actions_refreshed"); }; /** * Spreads a context change to all actions and to registered components * by triggering ajaxplorer:actions_refreshed event. */ Controller.prototype.fireContextChange = function fireContextChange() { this.actions.forEach((function (action) { action.fireContextChange(this._dataModel, this.usersEnabled, this.oUser); }).bind(this)); this.notify("actions_refreshed"); }; Controller.prototype.notify = function notify(eventName, memo) { if (this.localDataModel) { _Observable.prototype.notify.call(this, "actions_refreshed", memo); } else { this._pydioObject.fire("actions_refreshed"); } }; /** * Remove all actions */ Controller.prototype.removeActions = function removeActions() { this.actions.forEach(function (action) { action.remove(); }); this.actions = new Map(); this.clearRegisteredKeys(); }; /** * Create actions from XML Registry * @param registry DOMDocument */ Controller.prototype.loadActionsFromRegistry = function loadActionsFromRegistry() { var registry = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; if (!registry) { registry = pydio.getXmlRegistry(); } this.removeActions(); this.parseActions(registry); this._guiActions.forEach((function (act) { this.registerAction(act); }).bind(this)); this.notify("actions_loaded"); this.fireContextChange(); this.fireSelectionChange(); }; /** * Registers an action to this manager (default, accesskey). * @param action Action */ Controller.prototype.registerAction = function registerAction(action) { var actionName = action.options.name; this.actions.set(actionName, action); if (action.defaults) { for (var key in action.defaults) { if (action.defaults.hasOwnProperty(key)) { this.defaultActions.set(key, actionName); } } } if (action.options.hasAccessKey) { this.registerKey(action.options.accessKey, actionName); } if (action.options.specialAccessKey) { this.registerKey("key_" + action.options.specialAccessKey, actionName); } action.setManager(this); }; /** * Parse an XML action node and registers the action * @param documentElement DOMNode The node to parse */ Controller.prototype.parseActions = function parseActions(documentElement) { var actions = _utilXMLUtils2['default'].XPathSelectNodes(documentElement, "actions/action"); for (var i = 0; i < actions.length; i++) { if (actions[i].nodeName != 'action') continue; if (actions[i].getAttribute('enabled') == 'false') continue; var newAction = new _Action2['default'](); newAction.setManager(this); newAction.createFromXML(actions[i]); this.registerAction(newAction); } }; /** * Find an action by its name * @param actionName String * @returns Action */ Controller.prototype.getActionByName = function getActionByName(actionName) { return this.actions.get(actionName); }; Controller.prototype._sortToolbarsActions = function _sortToolbarsActions(toolbars) { // Sort toolbars.forEach(function (v, k) { if (!v.sort) return; v.sort(function (a, b) { var wA = a.weight || a.options && a.options.weight || 0; var wB = b.weight || b.options && b.options.weight || 0; return wA === wB ? 0 : wA > wB ? 1 : -1; }); }); return toolbars; }; return Controller; })(_langObservable2['default']); exports['default'] = Controller; module.exports = exports['default']; },{"../http/PydioApi":"pydio/http/api","../lang/Logger":"pydio/lang/logger","../lang/Observable":"pydio/lang/observable","../util/XMLUtils":"pydio/util/xml","./Action":"pydio/model/action"}],"pydio/model/data-model":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _AjxpNode = require('./AjxpNode'); var _AjxpNode2 = _interopRequireDefault(_AjxpNode); var _utilLangUtils = require('../util/LangUtils'); var _utilLangUtils2 = _interopRequireDefault(_utilLangUtils); var _utilPathUtils = require('../util/PathUtils'); var _utilPathUtils2 = _interopRequireDefault(_utilPathUtils); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); /** * Full container of the data tree. Contains the SelectionModel as well. */ var PydioDataModel = (function (_Observable) { _inherits(PydioDataModel, _Observable); /** * Constructor * > Warning, events are now LOCAL by default */ function PydioDataModel() { var localEvents = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; _classCallCheck(this, PydioDataModel); _Observable.call(this); this._currentRep = '/'; this._selectedNodes = []; this._bEmpty = true; this._globalEvents = !localEvents; this._bFile = false; this._bDir = false; this._isRecycle = false; this._pendingSelection = null; this._selectionSource = {}; this._rootNode = null; } PydioDataModel.RemoteDataModelFactory = function RemoteDataModelFactory(providerProperties) { var rootLabel = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1]; var dataModel = new PydioDataModel(true); var rNodeProvider = new RemoteNodeProvider(providerProperties); dataModel.setAjxpNodeProvider(rNodeProvider); var rootNode = new _AjxpNode2['default']("/", false, rootLabel, '', rNodeProvider); dataModel.setRootNode(rootNode); return dataModel; }; /** * Sets the data source that will feed the nodes with children. * @param iAjxpNodeProvider IAjxpNodeProvider */ PydioDataModel.prototype.setAjxpNodeProvider = function setAjxpNodeProvider(iAjxpNodeProvider) { this._iAjxpNodeProvider = iAjxpNodeProvider; }; /** * Return the current data source provider * @return IAjxpNodeProvider */ PydioDataModel.prototype.getAjxpNodeProvider = function getAjxpNodeProvider() { return this._iAjxpNodeProvider; }; /** * Changes the current context node. * @param ajxpNode AjxpNode Target node, either an existing one or a fake one containing the target part. * @param forceReload Boolean If set to true, the node will be reloaded even if already loaded. */ PydioDataModel.prototype.requireContextChange = function requireContextChange(ajxpNode) { var _this = this; var forceReload = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; if (ajxpNode == null) return; this.setSelectedNodes([]); var path = ajxpNode.getPath(); if ((path == "" || path == "/") && ajxpNode != this._rootNode) { ajxpNode = this._rootNode; } var paginationPage = null; if (ajxpNode.getMetadata().has('paginationData') && ajxpNode.getMetadata().get('paginationData').has('new_page') && ajxpNode.getMetadata().get('paginationData').get('new_page') != ajxpNode.getMetadata().get('paginationData').get('current')) { paginationPage = ajxpNode.getMetadata().get('paginationData').get('new_page'); forceReload = true; } if (ajxpNode != this._rootNode && (!ajxpNode.getParent() || ajxpNode.fake)) { // Find in arbo or build fake arbo var fakeNodes = []; ajxpNode = ajxpNode.findInArbo(this._rootNode, fakeNodes); if (fakeNodes.length) { var _ret = (function () { var firstFake = fakeNodes.shift(); firstFake.observeOnce("first_load", (function (e) { this.requireContextChange(ajxpNode); }).bind(_this)); firstFake.observeOnce("error", (function (message) { _langLogger2['default'].error(message); firstFake.notify("node_removed"); var parent = firstFake.getParent(); parent.removeChild(firstFake); //delete(firstFake); this.requireContextChange(parent); }).bind(_this)); _this.publish("context_loading"); firstFake.load(_this._iAjxpNodeProvider); return { v: undefined }; })(); if (typeof _ret === 'object') return _ret.v; } } ajxpNode.observeOnce("loaded", (function () { this.setContextNode(ajxpNode, true); this.publish("context_loaded"); if (this.getPendingSelection()) { var selPath = ajxpNode.getPath() + (ajxpNode.getPath() == "/" ? "" : "/") + this.getPendingSelection(); var selNode = ajxpNode.findChildByPath(selPath); if (selNode) { this.setSelectedNodes([selNode], this); } else { if (ajxpNode.getMetadata().get("paginationData") && arguments.length < 3) { var newPage = undefined; var currentPage = ajxpNode.getMetadata().get("paginationData").get("current"); this.loadPathInfoSync(selPath, function (foundNode) { newPage = foundNode.getMetadata().get("page_position"); }, { page_position: 'true' }); if (newPage && newPage !== currentPage) { ajxpNode.getMetadata().get("paginationData").set("new_page", newPage); this.requireContextChange(ajxpNode, true, true); return; } } } this.clearPendingSelection(); } }).bind(this)); ajxpNode.observeOnce("error", (function (message) { _langLogger2['default'].error(message); this.publish("context_loaded"); }).bind(this)); this.publish("context_loading"); try { if (forceReload) { if (paginationPage) { ajxpNode.getMetadata().get('paginationData').set('current', paginationPage); } ajxpNode.reload(this._iAjxpNodeProvider); } else { ajxpNode.load(this._iAjxpNodeProvider); } } catch (e) { this.publish("context_loaded"); } }; PydioDataModel.prototype.requireNodeReload = function requireNodeReload(nodeOrPath, completeCallback) { if (nodeOrPath instanceof String) { nodeOrPath = new _AjxpNode2['default'](nodeOrPath); } var onComplete = null; if (this._selectedNodes.length) { var found = -1; this._selectedNodes.map(function (node, key) { if (node.getPath() == nodeOrPath.getPath()) found = key; }); if (found !== -1) { // MAKE SURE SELECTION IS OK AFTER RELOAD this._selectedNodes = _utilLangUtils2['default'].arrayWithout(this._selectedNodes, found); this.publish("selection_changed", this); onComplete = (function (newNode) { this._selectedNodes.push(newNode); this._selectionSource = {}; this.publish("selection_changed", this); if (completeCallback) completeCallback(newNode); }).bind(this); } } this._iAjxpNodeProvider.refreshNodeAndReplace(nodeOrPath, onComplete); }; PydioDataModel.prototype.loadPathInfoSync = function loadPathInfoSync(path, callback) { var additionalParameters = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; this._iAjxpNodeProvider.loadLeafNodeSync(new _AjxpNode2['default'](path), callback, false, additionalParameters); }; PydioDataModel.prototype.loadPathInfoAsync = function loadPathInfoAsync(path, callback) { this._iAjxpNodeProvider.loadLeafNodeSync(new _AjxpNode2['default'](path), callback, true); }; /** * Sets the root of the data store * @param ajxpRootNode AjxpNode The parent node */ PydioDataModel.prototype.setRootNode = function setRootNode(ajxpRootNode) { this._rootNode = ajxpRootNode; this._rootNode.setRoot(); this._rootNode.observe("child_added", function (c) { //console.log(c); }); this.publish("root_node_changed", this._rootNode); this.setContextNode(this._rootNode); }; /** * Gets the current root node * @returns AjxpNode */ PydioDataModel.prototype.getRootNode = function getRootNode() { return this._rootNode; }; /** * Sets the current context node * @param ajxpDataNode AjxpNode * @param forceEvent Boolean If set to true, event will be triggered even if the current node is already the same. */ PydioDataModel.prototype.setContextNode = function setContextNode(ajxpDataNode, forceEvent) { if (this._contextNode && this._contextNode == ajxpDataNode && this._currentRep == ajxpDataNode.getPath() && !forceEvent) { return; // No changes } if (!ajxpDataNode) return; if (this._contextNodeReplacedObserver && this._contextNode) { this._contextNode.stopObserving("node_replaced", this._contextNodeReplacedObserver); } this._contextNode = ajxpDataNode; this._currentRep = ajxpDataNode.getPath(); this.publish("context_changed", ajxpDataNode); if (!this._contextNodeReplacedObserver) this._contextNodeReplacedObserver = this.contextNodeReplaced.bind(this); ajxpDataNode.observe("node_replaced", this._contextNodeReplacedObserver); }; PydioDataModel.prototype.contextNodeReplaced = function contextNodeReplaced(newNode) { this.setContextNode(newNode); }; /** * */ PydioDataModel.prototype.publish = function publish(eventName, optionalData) { var args = []; if (this._globalEvents) { if (window.pydio) { args.push(eventName); if (optionalData) args.push(optionalData); window.pydio.fire.apply(window.pydio, args); } else if (document.fire) { args.push("ajaxplorer:" + eventName); if (optionalData) args.push(optionalData); document.fire.apply(document, args); } if (optionalData) { args = [eventName, { memo: optionalData }]; } else { args = [eventName]; } this.notify.apply(this, args); } else { if (optionalData) { args = [eventName, { memo: optionalData }]; } else { args = [eventName]; } this.notify.apply(this, args); } }; /** * Get the current context node * @returns AjxpNode */ PydioDataModel.prototype.getContextNode = function getContextNode() { return this._contextNode; }; /** * After a copy or move operation, many nodes may have to be reloaded * This function tries to reload them in the right order and if necessary. * @param nodes AjxpNodes[] An array of nodes */ PydioDataModel.prototype.multipleNodesReload = function multipleNodesReload(nodes) { for (var i = 0; i < nodes.length; i++) { var nodePathOrNode = nodes[i]; var node; if (nodePathOrNode instanceof String) { node = new _AjxpNode2['default'](nodePathOrNode); if (node.getPath() == this._rootNode.getPath()) node = this._rootNode;else node = node.findInArbo(this._rootNode, []); } else { node = nodePathOrNode; } nodes[i] = node; } var children = []; nodes.sort(function (a, b) { if (a.isParentOf(b)) { children.push(b); return -1; } if (a.isChildOf(b)) { children.push(a); return +1; } return 0; }); children.map(function (c) { nodes = _utilLangUtils2['default'].arrayWithout(nodes, c); }); nodes.map(this.queueNodeReload.bind(this)); this.nextNodeReloader(); }; /** * Add a node to the queue of nodes to reload. * @param node AjxpNode */ PydioDataModel.prototype.queueNodeReload = function queueNodeReload(node) { if (!this.queue) this.queue = []; if (node) { this.queue.push(node); } }; /** * Queue processor for the nodes to reload */ PydioDataModel.prototype.nextNodeReloader = function nextNodeReloader() { if (!this.queue.length) { window.setTimeout((function () { this.publish("context_changed", this._contextNode); }).bind(this), 200); return; } var next = this.queue.shift(); var observer = this.nextNodeReloader.bind(this); next.observeOnce("loaded", observer); next.observeOnce("error", observer); if (next == this._contextNode || next.isParentOf(this._contextNode)) { this.requireContextChange(next, true); } else { next.reload(this._iAjxpNodeProvider); } }; /** * Insert a node somewhere in the datamodel * @param node AjxpNode * @param setSelectedAfterAdd bool */ PydioDataModel.prototype.addNode = function addNode(node) { var setSelectedAfterAdd = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var parentFake = new _AjxpNode2['default'](_utilPathUtils2['default'].getDirname(node.getPath())); var parent = parentFake.findInArbo(this.getRootNode(), undefined); if (!parent && _utilPathUtils2['default'].getDirname(node.getPath()) == "") parent = this.getRootNode(); if (parent) { var addedNode = parent.addChild(node); if (addedNode && setSelectedAfterAdd && this.getContextNode() == parent) { this.setSelectedNodes([addedNode], {}); } } }; /** * Remove a node by path somewhere * @param path string * @param imTime integer|null */ PydioDataModel.prototype.removeNodeByPath = function removeNodeByPath(path) { var imTime = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var fake = new _AjxpNode2['default'](path); var n = fake.findInArbo(this.getRootNode(), undefined); if (n) { if (imTime && n.getMetadata() && n.getMetadata().get("ajxp_im_time") && parseInt(n.getMetadata().get("ajxp_im_time")) >= imTime) { return false; } n.getParent().removeChild(n); return true; } return false; }; /** * Update a node somewhere in the datamodel * @param node AjxpNode * @param setSelectedAfterUpdate bool */ PydioDataModel.prototype.updateNode = function updateNode(node) { var setSelectedAfterUpdate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var original = node.getMetadata().get("original_path"); var fake, n; if (original && original != node.getPath() && _utilPathUtils2['default'].getDirname(original) != _utilPathUtils2['default'].getDirname(node.getPath())) { // Node was really moved to another folder fake = new _AjxpNode2['default'](original); n = fake.findInArbo(this.getRootNode(), undefined); if (n) { n.getParent().removeChild(n); } var parentFake = new _AjxpNode2['default'](_utilPathUtils2['default'].getDirname(node.getPath())); var parent = parentFake.findInArbo(this.getRootNode(), undefined); if (!parent && _utilPathUtils2['default'].getDirname(node.getPath()) == "") parent = this.getRootNode(); if (parent) { node.getMetadata().set("original_path", undefined); parent.addChild(node); } } else { if (node.getMetadata().get("original_path") === "/" && node.getPath() === "/") { n = this.getRootNode(); n.replaceMetadata(node.getMetadata()); if (setSelectedAfterUpdate && this.getContextNode() == n) { this.setSelectedNodes([n], {}); } return; } fake = new _AjxpNode2['default'](original); n = fake.findInArbo(this.getRootNode(), undefined); if (n && !n.isMoreRecentThan(node)) { node._isLoaded = n._isLoaded; n.replaceBy(node, "override"); if (setSelectedAfterUpdate && this.getContextNode() == n.getParent()) { this.setSelectedNodes([n], {}); } } } }; /** * Sets an array of nodes to be selected after the context is (re)loaded * @param selection AjxpNode[] */ PydioDataModel.prototype.setPendingSelection = function setPendingSelection(selection) { this._pendingSelection = selection; }; /** * Gets the array of nodes to be selected after the context is (re)loaded * @returns AjxpNode[] */ PydioDataModel.prototype.getPendingSelection = function getPendingSelection() { return this._pendingSelection; }; /** * Clears the nodes to be selected */ PydioDataModel.prototype.clearPendingSelection = function clearPendingSelection() { this._pendingSelection = null; }; /** * Set an array of nodes as the current selection * @param ajxpDataNodes AjxpNode[] The nodes to select * @param source String The source of this selection action */ PydioDataModel.prototype.setSelectedNodes = function setSelectedNodes(ajxpDataNodes, source) { if (this._selectedNodes.length == ajxpDataNodes.length) { if (ajxpDataNodes.length === 0) { return; } var equal = true; for (var k = 0; k < ajxpDataNodes.length; k++) { equal = equal && ajxpDataNodes[k] == this._selectedNodes[k]; } if (equal) { return; } } if (!source) { this._selectionSource = {}; } else { this._selectionSource = source; } this._selectedNodes = ajxpDataNodes; this._bEmpty = ajxpDataNodes && ajxpDataNodes.length ? false : true; this._bFile = this._bDir = this._isRecycle = false; if (!this._bEmpty) { for (var i = 0; i < ajxpDataNodes.length; i++) { var selectedNode = ajxpDataNodes[i]; if (selectedNode.isLeaf()) this._bFile = true;else this._bDir = true; if (selectedNode.isRecycle()) this._isRecycle = true; } } this.publish("selection_changed", this); }; /** * Gets the currently selected nodes * @returns AjxpNode[] */ PydioDataModel.prototype.getSelectedNodes = function getSelectedNodes() { return this._selectedNodes; }; /** * Gets the source of the last selection action * @returns String */ PydioDataModel.prototype.getSelectionSource = function getSelectionSource() { return this._selectionSource; }; /** * Manually sets the source of the selection * @param object */ PydioDataModel.prototype.setSelectionSource = function setSelectionSource(object) { this._selectionSource = object; }; /** * DEPRECATED */ PydioDataModel.prototype.getSelectedItems = function getSelectedItems() { throw new Error("Deprecated : use getSelectedNodes() instead"); }; /** * Select all the children of the current context node */ PydioDataModel.prototype.selectAll = function selectAll() { var nodes = []; var childrenMap = this._contextNode.getChildren(); childrenMap.forEach(function (child) { nodes.push(child); }); this.setSelectedNodes(nodes, "dataModel"); }; /** * Whether the selection is empty * @returns Boolean */ PydioDataModel.prototype.isEmpty = function isEmpty() { return this._selectedNodes ? this._selectedNodes.length == 0 : true; }; PydioDataModel.prototype.hasReadOnly = function hasReadOnly() { var test = false; try { this._selectedNodes.forEach(function (node) { if (node.hasMetadataInBranch("ajxp_readonly", "true")) { test = true; throw $break; } }); } catch (e) {} return test; }; PydioDataModel.prototype.selectionHasRootNode = function selectionHasRootNode() { var found = false; try { this._selectedNodes.forEach(function (el) { if (el.isRoot()) { found = true; throw new Error(); } }); } catch (e) {} return found; }; /** * Whether the selection is unique * @returns Boolean */ PydioDataModel.prototype.isUnique = function isUnique() { return this._selectedNodes && this._selectedNodes.length === 1; }; /** * Whether the selection has a file selected. * Should be hasLeaf * @returns Boolean */ PydioDataModel.prototype.hasFile = function hasFile() { return this._bFile; }; /** * Whether the selection has a dir selected * @returns Boolean */ PydioDataModel.prototype.hasDir = function hasDir() { return this._bDir; }; /** * Whether the current context is the recycle bin * @returns Boolean */ PydioDataModel.prototype.isRecycle = function isRecycle() { return this._isRecycle; }; /** * Whether the selection has more than one node selected * @returns Boolean */ PydioDataModel.prototype.isMultiple = function isMultiple() { return this._selectedNodes && this._selectedNodes.length > 1; }; /** * Whether the selection has a file with one of the mimes * @param mimeTypes Array Array of mime types * @returns Boolean */ PydioDataModel.prototype.hasMime = function hasMime(mimeTypes) { if (mimeTypes.length == 1 && mimeTypes[0] == "*") return true; var has = false; mimeTypes.map((function (mime) { if (has) return; for (var i = 0; i < this._selectedNodes.length; i++) { if (_utilPathUtils2['default'].getAjxpMimeType(this._selectedNodes[i]) === mime) { has = true; break; } } }).bind(this)); return has; }; /** * Get all selected filenames as an array. * @param separator String Is a separator, will return a string joined * @returns Array|String|bool */ PydioDataModel.prototype.getFileNames = function getFileNames(separator) { if (!this._selectedNodes.length) { alert('Please select a file!'); return false; } var tmp = new Array(this._selectedNodes.length); for (var i = 0; i < this._selectedNodes.length; i++) { tmp[i] = this._selectedNodes[i].getPath(); } if (separator) { return tmp.join(separator); } else { return tmp; } }; /** * Get all the filenames of the current context node children * @param separator String If passed, will join the array as a string * @return Array|String|bool */ PydioDataModel.prototype.getContextFileNames = function getContextFileNames(separator) { var allItems = this._contextNode.getChildren(); if (!allItems.length) { return false; } var names = []; for (var i = 0; i < allItems.length; i++) { names.push(_utilPathUtils2['default'].getBasename(allItems[i].getPath())); } if (separator) { return names.join(separator); } else { return names; } }; /** * Whether the context node has a child with this basename * @param newFileName String The name to check * @returns Boolean * @param local * @param contextNode */ PydioDataModel.prototype.fileNameExists = function fileNameExists(newFileName, local, contextNode) { if (!contextNode) { contextNode = this._contextNode; } if (local) { var test = (contextNode.getPath() == "/" ? "" : contextNode.getPath()) + "/" + newFileName; var found = false; try { contextNode.getChildren().forEach(function (c) { if (c.getPath() == test) { found = true; throw new Error(); } }); } catch (e) {} return found; } else { var nodeExists = false; this.loadPathInfoSync(contextNode.getPath() + "/" + newFileName, function (foundNode) { nodeExists = true; }); return nodeExists; } }; PydioDataModel.prototype.applyCheckHook = function applyCheckHook(node) { var additionalParams = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var client = _httpPydioApi2['default'].getClient(); var result; client.applyCheckHook(node, "before_create", node.getMetadata().get("filesize") || -1, function (transport) { result = client.parseXmlMessage(transport.responseXML); }, additionalParams); if (result === false) { throw new Error("Check failed"); } }; /** * Gets the first name of the current selection * @returns String */ PydioDataModel.prototype.getUniqueFileName = function getUniqueFileName() { if (this.getFileNames().length) return this.getFileNames()[0]; return null; }; /** * Gets the first node of the selection, or Null * @returns AjxpNode */ PydioDataModel.prototype.getUniqueNode = function getUniqueNode() { if (this._selectedNodes.length) { return this._selectedNodes[0]; } return null; }; /** * Gets a node from the current selection * @param i Integer the node index * @returns AjxpNode */ PydioDataModel.prototype.getNode = function getNode(i) { return this._selectedNodes[i]; }; /** * Will add the current selection nodes as serializable data to the element passed : * either as hidden input elements if it's a form, or as query parameters if it's an url * @param oFormElement HTMLForm The form * @param sUrl String An url to complete * @returns String */ PydioDataModel.prototype.updateFormOrUrl = function updateFormOrUrl(oFormElement, sUrl) { // CLEAR FROM PREVIOUS ACTIONS! if (oFormElement) { $(oFormElement).select('input[type="hidden"]').map(function (element) { if (element.name == "nodes[]" || element.name == "file") element.remove(); }); } // UPDATE THE 'DIR' FIELDS if (oFormElement && oFormElement['rep']) oFormElement['rep'].value = this._currentRep; sUrl += '&dir=' + encodeURIComponent(this._currentRep); // UPDATE THE 'file' FIELDS if (this.isEmpty()) return sUrl; var fileNames = this.getFileNames(); for (var i = 0; i < fileNames.length; i++) { sUrl += '&' + 'nodes[]=' + encodeURIComponent(fileNames[i]); if (oFormElement) this._addHiddenField(oFormElement, 'nodes[]', fileNames[i]); } if (fileNames.length == 1) { sUrl += '&' + 'file=' + encodeURIComponent(fileNames[0]); if (oFormElement) this._addHiddenField(oFormElement, 'file', fileNames[0]); } return sUrl; }; PydioDataModel.prototype._addHiddenField = function _addHiddenField(oFormElement, sFieldName, sFieldValue) { oFormElement.insert(new Element('input', { type: 'hidden', name: sFieldName, value: sFieldValue })); }; return PydioDataModel; })(_langObservable2['default']); exports['default'] = PydioDataModel; module.exports = exports['default']; },{"../http/PydioApi":"pydio/http/api","../lang/Logger":"pydio/lang/logger","../lang/Observable":"pydio/lang/observable","../util/LangUtils":"pydio/util/lang","../util/PathUtils":"pydio/util/path","./AjxpNode":"pydio/model/node"}],"pydio/model/empty-node-provider":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var EmptyNodeProvider = (function (_Observable) { _inherits(EmptyNodeProvider, _Observable); function EmptyNodeProvider() { _classCallCheck(this, EmptyNodeProvider); _Observable.call(this); } EmptyNodeProvider.prototype.initProvider = function initProvider(properties) { this.properties = properties; }; /** * * @param node AjxpNode * @param nodeCallback Function * @param childCallback Function */ EmptyNodeProvider.prototype.loadNode = function loadNode(node, nodeCallback, childCallback) {}; EmptyNodeProvider.prototype.loadLeafNodeSync = function loadLeafNodeSync(node, callback) {}; return EmptyNodeProvider; })(_langObservable2['default']); exports['default'] = EmptyNodeProvider; module.exports = exports['default']; },{"../lang/Observable":"pydio/lang/observable"}],"pydio/model/node":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _utilPathUtils = require('../util/PathUtils'); var _utilPathUtils2 = _interopRequireDefault(_utilPathUtils); var AjxpNode = (function (_Observable) { _inherits(AjxpNode, _Observable); /** * * @param path String * @param isLeaf Boolean * @param label String * @param icon String * @param iNodeProvider IAjxpNodeProvider */ function AjxpNode(path) { var isLeaf = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var label = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; var icon = arguments.length <= 3 || arguments[3] === undefined ? '' : arguments[3]; var iNodeProvider = arguments.length <= 4 || arguments[4] === undefined ? null : arguments[4]; _classCallCheck(this, AjxpNode); _Observable.call(this); this._path = path; if (this._path && this._path.length && this._path.length > 1) { if (this._path[this._path.length - 1] == "/") { this._path = this._path.substring(0, this._path.length - 1); } } this._isLeaf = isLeaf; this._label = label; this._icon = icon; this._isRoot = false; this._metadata = new Map(); this._children = new Map(); this._isLoaded = false; this.fake = false; this._iNodeProvider = iNodeProvider; } /** * The node is loaded or not * @returns Boolean */ AjxpNode.prototype.isLoaded = function isLoaded() { return this._isLoaded; }; /** * The node is currently loading * @returns Boolean */ AjxpNode.prototype.isLoading = function isLoading() { return this._isLoading; }; /** * Changes loaded status * @param bool Boolean */ AjxpNode.prototype.setLoaded = function setLoaded(bool) { this._isLoaded = bool; }; /** * Update node provider * @param iAjxpNodeProvider */ AjxpNode.prototype.updateProvider = function updateProvider(iAjxpNodeProvider) { this._iNodeProvider = iAjxpNodeProvider; }; /** * Loads the node using its own provider or the one passed * @param iAjxpNodeProvider IAjxpNodeProvider Optionnal * @param additionalParameters Object of optional parameters */ AjxpNode.prototype.load = function load(iAjxpNodeProvider) { var additionalParameters = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; if (this._isLoading) return; if (!iAjxpNodeProvider) { if (this._iNodeProvider) { iAjxpNodeProvider = this._iNodeProvider; } else { iAjxpNodeProvider = new RemoteNodeProvider(); } } this._isLoading = true; this.notify("loading"); if (this._isLoaded) { this._isLoading = false; this.notify("loaded"); return; } iAjxpNodeProvider.loadNode(this, (function (node) { this._isLoaded = true; this._isLoading = false; this.notify("loaded"); this.notify("first_load"); }).bind(this), null, false, -1, additionalParameters); }; /** * Remove children and reload node * @param iAjxpNodeProvider IAjxpNodeProvider Optionnal */ AjxpNode.prototype.reload = function reload(iAjxpNodeProvider) { var silentClear = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; this._isLoaded = false; this._children.forEach(function (child, key) { if (!silentClear) child.notify("node_removed"); child._parentNode = null; this._children['delete'](key); if (!silentClear) this.notify("child_removed", child); }, this); this.load(iAjxpNodeProvider); }; /** * Unload child and notify "force_clear" */ AjxpNode.prototype.clear = function clear() { this._children.forEach(function (child, key) { child.notify("node_removed"); child._parentNode = null; this._children['delete'](key); this.notify("child_removed", child); }, this); this._isLoaded = false; this.notify("force_clear"); }; /** * Sets this AjxpNode as being the root parent */ AjxpNode.prototype.setRoot = function setRoot() { this._isRoot = true; }; /** * Set the node children as a bunch * @param ajxpNodes AjxpNodes[] */ AjxpNode.prototype.setChildren = function setChildren(ajxpNodes) { this._children = new Map(); ajxpNodes.forEach((function (value) { this._children.set(value.getPath(), value); value.setParent(this); }).bind(this)); }; /** * Get all children as a bunch * @returns AjxpNode[] */ AjxpNode.prototype.getChildren = function getChildren() { return this._children; }; AjxpNode.prototype.getFirstChildIfExists = function getFirstChildIfExists() { if (this._children.size) { return this._children.values().next().value; } return null; }; AjxpNode.prototype.isMoreRecentThan = function isMoreRecentThan(otherNode) { return otherNode.getMetadata().get("ajxp_im_time") && this.getMetadata().get("ajxp_im_time") && parseInt(this.getMetadata().get("ajxp_im_time")) >= parseInt(otherNode.getMetadata().get("ajxp_im_time")); }; /** * Adds a child to children * @param ajxpNode AjxpNode The child */ AjxpNode.prototype.addChild = function addChild(ajxpNode) { ajxpNode.setParent(this); if (this._iNodeProvider) ajxpNode._iNodeProvider = this._iNodeProvider; var existingNode = this.findChildByPath(ajxpNode.getPath()); if (existingNode && !(existingNode instanceof String)) { if (!existingNode.isMoreRecentThan(ajxpNode)) { existingNode.replaceBy(ajxpNode, "override"); return existingNode; } else { return false; } } else { this._children.set(ajxpNode.getPath(), ajxpNode); this.notify("child_added", ajxpNode.getPath()); } return ajxpNode; }; /** * Removes the child from the children * @param ajxpNode AjxpNode */ AjxpNode.prototype.removeChild = function removeChild(ajxpNode) { var removePath = ajxpNode.getPath(); ajxpNode.notify("node_removed"); ajxpNode._parentNode = null; this._children['delete'](ajxpNode.getPath()); this.notify("child_removed", removePath); }; AjxpNode.prototype.replaceMetadata = function replaceMetadata(newMeta) { this._metadata = newMeta; this.notify("meta_replaced", this); }; /** * Replaces the current node by a new one. Copy all properties deeply * @param ajxpNode AjxpNode * @param metaMerge */ AjxpNode.prototype.replaceBy = function replaceBy(ajxpNode, metaMerge) { this._isLeaf = ajxpNode._isLeaf; var pathChanged = false; if (ajxpNode.getPath() && this._path != ajxpNode.getPath()) { var originalPath = this._path; if (this.getParent()) { var parentChildrenIndex = this.getParent()._children; parentChildrenIndex.set(ajxpNode.getPath(), this); parentChildrenIndex['delete'](originalPath); } this._path = ajxpNode.getPath(); pathChanged = true; } if (ajxpNode._label) { this._label = ajxpNode._label; } if (ajxpNode._icon) { this._icon = ajxpNode._icon; } if (ajxpNode._iNodeProvider) { this._iNodeProvider = ajxpNode._iNodeProvider; } //this._isRoot = ajxpNode._isRoot; this._isLoaded = ajxpNode._isLoaded; this.fake = ajxpNode.fake; var meta = ajxpNode.getMetadata(); if (metaMerge == "override") this._metadata = new Map(); meta.forEach((function (value, key) { if (metaMerge == "override") { this._metadata.set(key, value); } else { if (this._metadata.has(key) && value === "") { return; } this._metadata.set(key, value); } }).bind(this)); if (pathChanged && !this._isLeaf && this.getChildren().size) { window.setTimeout((function () { this.reload(this._iNodeProvider); }).bind(this), 100); return; } ajxpNode.getChildren().forEach((function (child) { this.addChild(child); }).bind(this)); this.notify("node_replaced", this); }; /** * Finds a child node by its path * @param path String * @returns AjxpNode */ AjxpNode.prototype.findChildByPath = function findChildByPath(path) { return this._children.get(path); }; /** * Sets the metadata as a bunch * @param data Map A Map */ AjxpNode.prototype.setMetadata = function setMetadata(data) { this._metadata = data; }; /** * Gets the metadat * @returns Map */ AjxpNode.prototype.getMetadata = function getMetadata() { return this._metadata; }; /** * Is this node a leaf * @returns Boolean */ AjxpNode.prototype.isLeaf = function isLeaf() { return this._isLeaf; }; AjxpNode.prototype.isBrowsable = function isBrowsable() { return !this._isLeaf || this.getAjxpMime() === 'ajxp_browsable_archive'; }; /** * @returns String */ AjxpNode.prototype.getPath = function getPath() { return this._path; }; /** * @returns String */ AjxpNode.prototype.getLabel = function getLabel() { return this._label; }; /** * @returns String */ AjxpNode.prototype.getIcon = function getIcon() { return this._icon; }; /** * @returns Boolean */ AjxpNode.prototype.isRecycle = function isRecycle() { return this.getAjxpMime() == 'ajxp_recycle'; }; /** * @returns String */ AjxpNode.prototype.getSvgSource = function getSvgSource() { return this.getMetadata().get("fonticon"); }; /** * Search the mime type in the parent branch * @param ajxpMime String * @returns Boolean */ AjxpNode.prototype.hasAjxpMimeInBranch = function hasAjxpMimeInBranch(ajxpMime) { if (this.getAjxpMime() == ajxpMime.toLowerCase()) return true; var parent = undefined, crt = this; while (parent = crt._parentNode) { if (parent.getAjxpMime() == ajxpMime.toLowerCase()) { return true; } crt = parent; } return false; }; /** * Search the mime type in the parent branch * @returns Boolean * @param metadataKey * @param metadataValue */ AjxpNode.prototype.hasMetadataInBranch = function hasMetadataInBranch(metadataKey, metadataValue) { if (this.getMetadata().has(metadataKey)) { if (metadataValue) { return this.getMetadata().get(metadataKey) == metadataValue; } else { return true; } } var parent = undefined, crt = this; while (parent = crt._parentNode) { if (parent.getMetadata().has(metadataKey)) { if (metadataValue) { return parent.getMetadata().get(metadataKey) == metadataValue; } else { return true; } } crt = parent; } return false; }; /** * Sets a reference to the parent node * @param parentNode AjxpNode */ AjxpNode.prototype.setParent = function setParent(parentNode) { this._parentNode = parentNode; }; /** * Gets the parent Node * @returns AjxpNode */ AjxpNode.prototype.getParent = function getParent() { return this._parentNode; }; /** * Finds this node by path if it already exists in arborescence * @param rootNode AjxpNode * @param fakeNodes AjxpNode[] * @returns AjxpNode|undefined */ AjxpNode.prototype.findInArbo = function findInArbo(rootNode, fakeNodes) { if (!this.getPath()) return; var pathParts = this.getPath().split("/"); var crtPath = "", crtNode = undefined, crtParentNode = rootNode; for (var i = 0; i < pathParts.length; i++) { if (pathParts[i] == "") continue; crtPath = crtPath + "/" + pathParts[i]; var node = crtParentNode.findChildByPath(crtPath); if (node && !(node instanceof String)) { crtNode = node; } else { if (fakeNodes === undefined) return undefined; crtNode = new AjxpNode(crtPath, false, _utilPathUtils2['default'].getBasename(crtPath)); crtNode.fake = true; crtNode.getMetadata().set("text", _utilPathUtils2['default'].getBasename(crtPath)); fakeNodes.push(crtNode); crtParentNode.addChild(crtNode); } crtParentNode = crtNode; } return crtNode; }; /** * @returns Boolean */ AjxpNode.prototype.isRoot = function isRoot() { return this._isRoot; }; /** * Check if it's the parent of the given node * @param node AjxpNode * @returns Boolean */ AjxpNode.prototype.isParentOf = function isParentOf(node) { var childPath = node.getPath(); var parentPath = this.getPath(); return childPath.substring(0, parentPath.length) === parentPath; }; /** * Check if it's a child of the given node * @param node AjxpNode * @returns Boolean */ AjxpNode.prototype.isChildOf = function isChildOf(node) { var childPath = this.getPath(); var parentPath = node.getPath(); return childPath.substring(0, parentPath.length) === parentPath; }; /** * Gets the current's node mime type, either by ajxp_mime or by extension. * @returns String */ AjxpNode.prototype.getAjxpMime = function getAjxpMime() { if (this._metadata && this._metadata.has("ajxp_mime")) return this._metadata.get("ajxp_mime").toLowerCase(); if (this._metadata && this.isLeaf()) return _utilPathUtils2['default'].getAjxpMimeType(this._metadata).toLowerCase(); return ""; }; AjxpNode.prototype.buildRandomSeed = function buildRandomSeed(ajxpNode) { var mtimeString = "&time_seed=" + this._metadata.get("ajxp_modiftime"); if (this.getParent()) { var preview_seed = this.getParent().getMetadata().get('preview_seed'); if (preview_seed) { mtimeString += "&rand=" + preview_seed; } } return mtimeString; }; return AjxpNode; })(_langObservable2['default']); exports['default'] = AjxpNode; module.exports = exports['default']; },{"../lang/Observable":"pydio/lang/observable","../util/PathUtils":"pydio/util/path"}],"pydio/model/registry":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _User = require('./User'); var _User2 = _interopRequireDefault(_User); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _httpResourcesManager = require('../http/ResourcesManager'); var _httpResourcesManager2 = _interopRequireDefault(_httpResourcesManager); var Registry = (function () { function Registry(pydioObject) { _classCallCheck(this, Registry); this._registry = null; this._extensionsRegistry = { "editor": [], "uploader": [] }; this._resourcesRegistry = {}; this._pydioObject = pydioObject; this._xPathLoading = false; this._globalLoading = false; } /** * Parse XML String directly * @param s */ Registry.prototype.loadFromString = function loadFromString(s) { this._registry = _utilXMLUtils2['default'].parseXml(s).documentElement; }; /** * Load registry from server * @param xPath * @param completeFunc * @param repositoryId */ Registry.prototype.load = function load() { var xPath = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; var completeFunc = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var repositoryId = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; if (xPath === null && this._globalLoading || xPath && this._xPathLoading === xPath) { return; } if (xPath) this._xPathLoading = xPath;else this._globalLoading = true; var onComplete = (function (transport) { if (xPath) this._xPathLoading = false;else this._globalLoading = false; if (transport.responseXML == null || transport.responseXML.documentElement == null) return; if (transport.responseXML.documentElement.nodeName == "ajxp_registry") { this._registry = transport.responseXML.documentElement; if (!completeFunc) { this._pydioObject.fire("registry_loaded", this._registry); } } else if (transport.responseXML.documentElement.nodeName == "ajxp_registry_part") { this.refreshXmlRegistryPart(transport.responseXML.documentElement); } if (completeFunc) completeFunc(this._registry); }).bind(this); var params = { get_action: 'get_xml_registry' }; if (xPath) { params['xPath'] = xPath; } if (repositoryId) { params['ws_id'] = repositoryId; // for caching only } _httpPydioApi2['default'].getClient().request(params, onComplete, null, { method: 'get' }); }; /** * Inserts a document fragment retrieved from server inside the full tree. * The node must contains the xPath attribute to locate it inside the registry. * Event ajaxplorer:registry_part_loaded is triggerd once this is done. * @param documentElement DOMNode */ Registry.prototype.refreshXmlRegistryPart = function refreshXmlRegistryPart(documentElement) { var xPath = documentElement.getAttribute("xPath"); var existingNode = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, xPath); var parentNode = undefined; if (existingNode && existingNode.parentNode) { parentNode = existingNode.parentNode; parentNode.removeChild(existingNode); if (documentElement.firstChild) { parentNode.appendChild(documentElement.firstChild.cloneNode(true)); } } else if (xPath.indexOf("/") > -1) { // try selecting parentNode var parentPath = xPath.substring(0, xPath.lastIndexOf("/")); parentNode = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, parentPath); if (parentNode && documentElement.firstChild) { parentNode.appendChild(documentElement.firstChild.cloneNode(true)); } } else { if (documentElement.firstChild) this._registry.appendChild(documentElement.firstChild.cloneNode(true)); } this._pydioObject.fire("registry_part_loaded", xPath); }; /** * Translate the XML answer to a new User object */ Registry.prototype.parseUser = function parseUser() { var user = null, userNode = undefined; if (this._registry) { userNode = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, "user"); } if (userNode) { var userId = userNode.getAttribute('id'); var children = userNode.childNodes; if (userId) { user = new _User2['default'](userId, children); } } return user; }; /** * * @returns {Element|*|null} */ Registry.prototype.getXML = function getXML() { return this._registry; }; /** * Find Extension initialisation nodes (activeCondition, onInit, etc), parses * the XML and execute JS. * @param xmlNode {Element} The extension node * @param extensionDefinition Object Information already collected about this extension * @returns Boolean */ Registry.prototype.initExtension = function initExtension(xmlNode, extensionDefinition) { var activeCondition = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/activeCondition'); if (activeCondition && activeCondition.firstChild) { try { var func = new Function(activeCondition.firstChild.nodeValue.trim()); if (func() === false) return false; } catch (e) {} } if (xmlNode.nodeName == 'editor') { Object.assign(extensionDefinition, { openable: xmlNode.getAttribute("openable") == "true", modalOnly: xmlNode.getAttribute("modalOnly") == "true", previewProvider: xmlNode.getAttribute("previewProvider") == "true", order: xmlNode.getAttribute("order") ? parseInt(xmlNode.getAttribute("order")) : 0, formId: xmlNode.getAttribute("formId") || null, text: this._pydioObject.MessageHash[xmlNode.getAttribute("text")], title: this._pydioObject.MessageHash[xmlNode.getAttribute("title")], icon: xmlNode.getAttribute("icon"), icon_class: xmlNode.getAttribute("iconClass"), editorActions: xmlNode.getAttribute("actions"), editorClass: xmlNode.getAttribute("className"), mimes: xmlNode.getAttribute("mimes").split(","), write: xmlNode.getAttribute("write") && xmlNode.getAttribute("write") == "true" ? true : false, canWrite: xmlNode.getAttribute("canWrite") && xmlNode.getAttribute("canWrite") == "true" ? true : false }); } else if (xmlNode.nodeName == 'uploader') { var th = this._pydioObject.Parameters.get('theme'); var clientForm = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/clientForm[@theme="' + th + '"]'); if (!clientForm) { clientForm = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/clientForm'); } if (clientForm && clientForm.getAttribute('module')) { extensionDefinition.moduleName = clientForm.getAttribute('module'); } if (xmlNode.getAttribute("order")) { extensionDefinition.order = parseInt(xmlNode.getAttribute("order")); } else { extensionDefinition.order = 0; } var extensionOnInit = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/extensionOnInit'); if (extensionOnInit && extensionOnInit.firstChild) { try { // @TODO: THIS WILL LIKELY TRIGGER PROTOTYPE CODE eval(extensionOnInit.firstChild.nodeValue); } catch (e) { _langLogger2['default'].error("Ignoring Error in extensionOnInit code:"); _langLogger2['default'].error(extensionOnInit.firstChild.nodeValue); _langLogger2['default'].error(e.message); } } var dialogOnOpen = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/dialogOnOpen'); if (dialogOnOpen && dialogOnOpen.firstChild) { extensionDefinition.dialogOnOpen = dialogOnOpen.firstChild.nodeValue; } var dialogOnComplete = _utilXMLUtils2['default'].XPathSelectSingleNode(xmlNode, 'processing/dialogOnComplete'); if (dialogOnComplete && dialogOnComplete.firstChild) { extensionDefinition.dialogOnComplete = dialogOnComplete.firstChild.nodeValue; } } return true; }; /** * Refresh the currently active extensions * Extensions are editors and uploaders for the moment. */ Registry.prototype.refreshExtensionsRegistry = function refreshExtensionsRegistry() { this._extensionsRegistry = { "editor": [], "uploader": [] }; var extensions = _utilXMLUtils2['default'].XPathSelectNodes(this._registry, "plugins/editor|plugins/uploader"); for (var i = 0; i < extensions.length; i++) { var extensionDefinition = { id: extensions[i].getAttribute("id"), xmlNode: extensions[i], resourcesManager: new _httpResourcesManager2['default']() }; this._resourcesRegistry[extensionDefinition.id] = extensionDefinition.resourcesManager; var resourceNodes = _utilXMLUtils2['default'].XPathSelectNodes(extensions[i], "client_settings/resources|dependencies|clientForm"); for (var j = 0; j < resourceNodes.length; j++) { extensionDefinition.resourcesManager.loadFromXmlNode(resourceNodes[j]); } if (this.initExtension(extensions[i], extensionDefinition)) { this._extensionsRegistry[extensions[i].nodeName].push(extensionDefinition); } } _httpResourcesManager2['default'].loadAutoLoadResources(this._registry); }; /** * Find the currently active extensions by type * @param extensionType String "editor" or "uploader" * @returns {array} */ Registry.prototype.getActiveExtensionByType = function getActiveExtensionByType(extensionType) { return this._extensionsRegistry[extensionType]; }; /** * Find a given editor by its id * @param editorId String * @returns AbstractEditor */ Registry.prototype.findEditorById = function findEditorById(editorId) { return this._extensionsRegistry.editor.find(function (el) { return el.id == editorId; }); }; /** * Find Editors that can handle a given mime type * @param mime String * @returns AbstractEditor[] * @param restrictToPreviewProviders */ Registry.prototype.findEditorsForMime = function findEditorsForMime(mime, restrictToPreviewProviders) { var user = this._pydioObject.user; var editors = [], checkWrite = false; if (user != null && !user.canWrite()) { checkWrite = true; } this._extensionsRegistry.editor.forEach(function (el) { if (el.mimes.indexOf(mime) !== -1 || el.mimes.indexOf('*') !== -1) { if (restrictToPreviewProviders && !el.previewProvider) return; if (!checkWrite || !el.write) editors.push(el); } }); if (editors.length && editors.length > 1) { editors = editors.sort(function (a, b) { return (a.order || 0) - (b.order || 0); }); } return editors; }; /** * Trigger the load method of the resourcesManager. * @param resourcesManager ResourcesManager * @param callback triggered after JS loaded */ Registry.prototype.loadEditorResources = function loadEditorResources(resourcesManager, callback) { resourcesManager.load(this._resourcesRegistry, false, callback); }; /** * * @param pluginQuery * @returns {Map} */ Registry.prototype.getPluginConfigs = function getPluginConfigs(pluginQuery) { var xpath = 'plugins/*[@id="core.' + pluginQuery + '"]/plugin_configs/property | plugins/*[@id="' + pluginQuery + '"]/plugin_configs/property'; if (pluginQuery.indexOf('.') == -1) { xpath = 'plugins/' + pluginQuery + '/plugin_configs/property |' + xpath; } var properties = _utilXMLUtils2['default'].XPathSelectNodes(this._registry, xpath); var configs = new Map(); properties.forEach(function (propNode) { configs.set(propNode.getAttribute("name"), JSON.parse(propNode.firstChild.nodeValue)); }); return configs; }; /** * * @param pluginId * @param paramName * @returns {string} */ Registry.prototype.getDefaultImageFromParameters = function getDefaultImageFromParameters(pluginId, paramName) { var node = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, "plugins/*[@id='" + pluginId + "']/server_settings/global_param[@name='" + paramName + "']"); if (!node) return ''; return node.getAttribute("defaultImage") || ''; }; /** * * @param type * @param name * @returns {bool} */ Registry.prototype.hasPluginOfType = function hasPluginOfType(type, name) { var node = undefined; if (name == null) { node = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, 'plugins/ajxp_plugin[contains(@id, "' + type + '.")] | plugins/' + type + '[@id]'); } else { node = _utilXMLUtils2['default'].XPathSelectSingleNode(this._registry, 'plugins/ajxp_plugin[@id="' + type + '.' + name + '"] | plugins/' + type + '[@id="' + type + '.' + name + '"]'); } return node != undefined; }; return Registry; })(); exports['default'] = Registry; module.exports = exports['default']; },{"../http/PydioApi":"pydio/http/api","../http/ResourcesManager":"pydio/http/resources-manager","../lang/Logger":"pydio/lang/logger","../util/XMLUtils":"pydio/util/xml","./User":"pydio/model/user"}],"pydio/model/remote-node-provider":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _httpMetaCacheService = require('../http/MetaCacheService'); var _httpMetaCacheService2 = _interopRequireDefault(_httpMetaCacheService); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _utilPathUtils = require('../util/PathUtils'); var _utilPathUtils2 = _interopRequireDefault(_utilPathUtils); var _utilXMLUtils = require('../util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _AjxpNode = require('./AjxpNode'); var _AjxpNode2 = _interopRequireDefault(_AjxpNode); /** * Implementation of the IAjxpNodeProvider interface based on a remote server access. * Default for all repositories. */ var RemoteNodeProvider = (function () { /** * Constructor */ function RemoteNodeProvider() { var properties = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; _classCallCheck(this, RemoteNodeProvider); this.discrete = false; if (properties) this.initProvider(properties); } /** * Initialize properties * @param properties Object */ RemoteNodeProvider.prototype.initProvider = function initProvider(properties) { this.properties = new Map(); for (var p in properties) { if (properties.hasOwnProperty(p)) this.properties.set(p, properties[p]); } if (this.properties && this.properties.has('connexion_discrete')) { this.discrete = true; this.properties['delete']('connexion_discrete'); } if (this.properties && this.properties.has('cache_service')) { this.cacheService = this.properties.get('cache_service'); this.properties['delete']('cache_service'); _httpMetaCacheService2['default'].getInstance().registerMetaStream(this.cacheService['metaStreamName'], this.cacheService['expirationPolicy']); } }; /** * Load a node * @param node AjxpNode * @param nodeCallback Function On node loaded * @param childCallback Function On child added * @param recursive * @param depth * @param optionalParameters */ RemoteNodeProvider.prototype.loadNode = function loadNode(node) { var nodeCallback = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var childCallback = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var recursive = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var depth = arguments.length <= 4 || arguments[4] === undefined ? -1 : arguments[4]; var optionalParameters = arguments.length <= 5 || arguments[5] === undefined ? null : arguments[5]; var params = { get_action: 'ls', options: 'al' }; if (recursive) { params['recursive'] = true; params['depth'] = depth; } var path = node.getPath(); // Double encode # character var paginationHash = undefined; if (node.getMetadata().has("paginationData")) { paginationHash = "%23" + node.getMetadata().get("paginationData").get("current"); path += paginationHash; params['remote_order'] = 'true'; var remoteOrderData = node.getMetadata().get("remote_order"); if (remoteOrderData) { if (remoteOrderData._object) remoteOrderData = ProtoCompat.hash2map(remoteOrderData); remoteOrderData.forEach(function (value, key) { params[key] = value; }); } } params['dir'] = path; if (this.properties) { this.properties.forEach(function (value, key) { params[key] = value + (key == 'dir' && paginationHash ? paginationHash : ''); }); } if (optionalParameters) { params = _extends({}, params, optionalParameters); } var parser = (function (transport) { this.parseNodes(node, transport, nodeCallback, childCallback); return node; }).bind(this); if (this.cacheService) { var loader = (function (ajxpNode, cacheCallback) { _httpPydioApi2['default'].getClient().request(params, cacheCallback, null, { discrete: this.discrete }); }).bind(this); var cacheLoader = (function (newNode) { node.replaceBy(newNode); nodeCallback(node); }).bind(this); _httpMetaCacheService2['default'].getInstance().metaForNode(this.cacheService['metaStreamName'], node, loader, parser, cacheLoader); } else { _httpPydioApi2['default'].getClient().request(params, parser, null, { discrete: this.discrete }); } }; /** * Load a node * @param node AjxpNode * @param nodeCallback Function On node loaded * @param aSync bool * @param additionalParameters object */ RemoteNodeProvider.prototype.loadLeafNodeSync = function loadLeafNodeSync(node, nodeCallback) { var aSync = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; var additionalParameters = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; var params = _extends({ get_action: 'ls', options: 'al', dir: _utilPathUtils2['default'].getDirname(node.getPath()), file: _utilPathUtils2['default'].getBasename(node.getPath()) }, additionalParameters); if (this.properties) { params = _extends({}, params, this.properties); } var complete = (function (transport) { try { if (node.isRoot()) { this.parseNodes(node, transport, nodeCallback, null, true); } else { this.parseNodes(node, transport, null, nodeCallback, true); } } catch (e) { _langLogger2['default'].error('Loading error :' + e.message); } }).bind(this); _httpPydioApi2['default'].getClient().request(params, complete, null, { async: aSync }); }; RemoteNodeProvider.prototype.refreshNodeAndReplace = function refreshNodeAndReplace(node, onComplete) { var params = { get_action: 'ls', options: 'al', dir: _utilPathUtils2['default'].getDirname(node.getPath()), file: _utilPathUtils2['default'].getBasename(node.getPath()) }; if (this.properties) { params = _extends({}, params, this.properties); } var nodeCallback = function nodeCallback(newNode) { node.replaceBy(newNode, "override"); if (onComplete) onComplete(node); }; _httpPydioApi2['default'].getClient().request(params, (function (transport) { try { if (node.isRoot()) { this.parseNodes(node, transport, nodeCallback, null, true); } else { this.parseNodes(node, transport, null, nodeCallback, true); } } catch (e) { _langLogger2['default'].error(e); } }).bind(this)); }; /** * Parse the answer and create AjxpNodes * @param origNode AjxpNode * @param transport Ajax.Response * @param nodeCallback Function * @param childCallback Function * @param childrenOnly */ RemoteNodeProvider.prototype.parseNodes = function parseNodes(origNode, transport, nodeCallback, childCallback, childrenOnly) { var _this = this; if (!transport.responseXML || !transport.responseXML.documentElement) { _langLogger2['default'].debug('Loading node ' + origNode.getPath() + ' has wrong response: ' + transport.responseText); if (nodeCallback) nodeCallback(origNode); origNode.setLoaded(false); if (!transport.responseText) { throw new Error('Empty response!'); } throw new Error('Invalid XML Document (see console)'); } var rootNode = transport.responseXML.documentElement; if (!childrenOnly) { var contextNode = this.parseAjxpNode(rootNode); origNode.replaceBy(contextNode, "merge"); } // CHECK FOR MESSAGE OR ERRORS var errorNode = _utilXMLUtils2['default'].XPathSelectSingleNode(rootNode, "error|message"); if (errorNode) { var type = undefined; if (errorNode.nodeName == "message") { type = errorNode.getAttribute('type'); } if (type == "ERROR") { origNode.notify("error", errorNode.firstChild.nodeValue + '(Source:' + origNode.getPath() + ')'); } } // CHECK FOR AUTH PROMPT REQUIRED var authNode = _utilXMLUtils2['default'].XPathSelectSingleNode(rootNode, "prompt"); if (authNode && pydio && pydio.UI && pydio.UI.openPromptDialog) { var jsonData = _utilXMLUtils2['default'].XPathSelectSingleNode(authNode, "data").firstChild.nodeValue; pydio.UI.openPromptDialog(JSON.parse(jsonData)); return false; } // CHECK FOR PAGINATION DATA var paginationNode = _utilXMLUtils2['default'].XPathSelectSingleNode(rootNode, "pagination"); if (paginationNode) { (function () { var paginationData = new Map(); Array.from(paginationNode.attributes).forEach((function (att) { paginationData.set(att.nodeName, att.value); }).bind(_this)); origNode.getMetadata().set('paginationData', paginationData); })(); } else if (origNode.getMetadata().get('paginationData')) { origNode.getMetadata()['delete']('paginationData'); } // CHECK FOR COMPONENT CONFIGS CONTEXTUAL DATA var configs = _utilXMLUtils2['default'].XPathSelectSingleNode(rootNode, "client_configs"); if (configs) { origNode.getMetadata().set('client_configs', configs); } // NOW PARSE CHILDREN var children = _utilXMLUtils2['default'].XPathSelectNodes(rootNode, "tree"); children.forEach((function (childNode) { var child = this.parseAjxpNode(childNode); if (!childrenOnly) { origNode.addChild(child); } var cLoaded = undefined; if (_utilXMLUtils2['default'].XPathSelectNodes(childNode, 'tree').length) { _utilXMLUtils2['default'].XPathSelectNodes(childNode, 'tree').forEach((function (c) { var newChild = this.parseAjxpNode(c); if (newChild) { child.addChild(newChild); } }).bind(this)); cLoaded = true; } if (childCallback) { childCallback(child); } if (cLoaded) child.setLoaded(true); }).bind(this)); if (nodeCallback) { nodeCallback(origNode); } }; RemoteNodeProvider.prototype.parseAjxpNodesDiffs = function parseAjxpNodesDiffs(xmlElement, targetDataModel, targetRepositoryId) { var setContextChildrenSelected = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var removes = _utilXMLUtils2['default'].XPathSelectNodes(xmlElement, "remove/tree"); var adds = _utilXMLUtils2['default'].XPathSelectNodes(xmlElement, "add/tree"); var updates = _utilXMLUtils2['default'].XPathSelectNodes(xmlElement, "update/tree"); var notifyServerChange = []; if (removes && removes.length) { removes.forEach(function (r) { var p = r.getAttribute("filename"); if (r.getAttribute("node_repository_id") && r.getAttribute("node_repository_id") !== targetRepositoryId) { return; } var imTime = parseInt(r.getAttribute("ajxp_im_time")); targetDataModel.removeNodeByPath(p, imTime); notifyServerChange.push(p); }); } if (adds && adds.length && targetDataModel.getAjxpNodeProvider().parseAjxpNode) { adds.forEach(function (tree) { if (tree.getAttribute("node_repository_id") && tree.getAttribute("node_repository_id") !== targetRepositoryId) { return; } var newNode = targetDataModel.getAjxpNodeProvider().parseAjxpNode(tree); targetDataModel.addNode(newNode, setContextChildrenSelected); notifyServerChange.push(newNode.getPath()); }); } if (updates && updates.length && targetDataModel.getAjxpNodeProvider().parseAjxpNode) { updates.forEach(function (tree) { if (tree.getAttribute("node_repository_id") && tree.getAttribute("node_repository_id") !== targetRepositoryId) { return; } var newNode = targetDataModel.getAjxpNodeProvider().parseAjxpNode(tree); var original = newNode.getMetadata().get("original_path"); targetDataModel.updateNode(newNode, setContextChildrenSelected); notifyServerChange.push(newNode.getPath()); if (original) notifyServerChange.push(original); }); } if (notifyServerChange.length) { targetDataModel.notify("server_update", notifyServerChange); } }; /** * Parses XML Node and create AjxpNode * @param xmlNode XMLNode * @returns AjxpNode */ RemoteNodeProvider.prototype.parseAjxpNode = function parseAjxpNode(xmlNode) { var node = new _AjxpNode2['default'](xmlNode.getAttribute('filename'), xmlNode.getAttribute('is_file') == "1" || xmlNode.getAttribute('is_file') == "true", xmlNode.getAttribute('text'), xmlNode.getAttribute('icon')); var metadata = new Map(); for (var i = 0; i < xmlNode.attributes.length; i++) { metadata.set(xmlNode.attributes[i].nodeName, xmlNode.attributes[i].value); } node.setMetadata(metadata); return node; }; return RemoteNodeProvider; })(); exports['default'] = RemoteNodeProvider; module.exports = exports['default']; },{"../http/MetaCacheService":"pydio/http/meta-cache-service","../http/PydioApi":"pydio/http/api","../lang/Logger":"pydio/lang/logger","../util/PathUtils":"pydio/util/path","../util/XMLUtils":"pydio/util/xml","./AjxpNode":"pydio/model/node"}],"pydio/model/repository":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _httpResourcesManager = require('../http/ResourcesManager'); var _httpResourcesManager2 = _interopRequireDefault(_httpResourcesManager); /** * Container for a Repository. */ var Repository = (function () { /** * Constructor * @param id String * @param xmlDef XMLNode */ function Repository(id, xmlDef) { _classCallCheck(this, Repository); this.label = ''; this.id = id; this.accessType = ''; this.nodeProviderDef = undefined; this.allowCrossRepositoryCopy = false; this.userEditable = false; this.slug = ''; this.owner = ''; this.description = ''; this._hasContentFilter = false; this._hasUserScope = false; this._repositoryType = 'local'; this._accessStatus = null; this._lastConnection = null; this.icon = ''; this.resourcesManager = new _httpResourcesManager2['default'](); if (xmlDef) this.loadFromXml(xmlDef); } /** * @returns String */ Repository.prototype.getId = function getId() { return this.id; }; /** * @returns String */ Repository.prototype.getShareId = function getShareId() { return this.id.replace(/ocs_remote_share_/, ''); }; /** * @returns String */ Repository.prototype.getLabel = function getLabel() { return this.label; }; /** * @param label String */ Repository.prototype.setLabel = function setLabel(label) { this.label = label; }; Repository.prototype.getLettersBadge = function getLettersBadge() { if (!this.label) return ''; return this.label.split(" ").map(function (word) { return word.substr(0, 1); }).slice(0, 2).join(""); }; /** * @return String */ Repository.prototype.getDescription = function getDescription() { return this.description; }; /** * @returns String */ Repository.prototype.getIcon = function getIcon() { return this.icon; }; /** * @param icon String */ Repository.prototype.setIcon = function setIcon(icon) { this.icon = icon; }; /** * @return String */ Repository.prototype.getOwner = function getOwner() { return this.owner; }; /** * @returns String */ Repository.prototype.getAccessType = function getAccessType() { return this.accessType; }; /** * @param access String */ Repository.prototype.setAccessType = function setAccessType(access) { this.accessType = access; }; /** * Triggers ResourcesManager.load */ Repository.prototype.loadResources = function loadResources() { this.resourcesManager.load(null, true); }; /** * @returns Object */ Repository.prototype.getNodeProviderDef = function getNodeProviderDef() { return this.nodeProviderDef; }; /** * @param slug String */ Repository.prototype.setSlug = function setSlug(slug) { this.slug = slug; }; /** * @returns String */ Repository.prototype.getSlug = function getSlug() { return this.slug; }; Repository.prototype.getOverlay = function getOverlay() { return this.getOwner() ? _httpResourcesManager2['default'].resolveImageSource("shared.png", "overlays/ICON_SIZE", 8) : ""; }; /** * @returns {boolean} */ Repository.prototype.hasContentFilter = function hasContentFilter() { return this._hasContentFilter; }; /** * @returns {boolean} */ Repository.prototype.hasUserScope = function hasUserScope() { return this._hasUserScope; }; /** * @returns {string} */ Repository.prototype.getRepositoryType = function getRepositoryType() { return this._repositoryType; }; /** * @returns {string} */ Repository.prototype.getAccessStatus = function getAccessStatus() { return this._accessStatus; }; Repository.prototype.setAccessStatus = function setAccessStatus(status) { this._accessStatus = status; }; Repository.prototype.getLastConnection = function getLastConnection() { return this._lastConnection; }; /** * Parses XML Node * @param repoNode XMLNode */ Repository.prototype.loadFromXml = function loadFromXml(repoNode) { if (repoNode.getAttribute('allowCrossRepositoryCopy') && repoNode.getAttribute('allowCrossRepositoryCopy') == "true") { this.allowCrossRepositoryCopy = true; } if (repoNode.getAttribute('hasContentFilter') && repoNode.getAttribute('hasContentFilter') == "true") { this._hasContentFilter = true; } if (repoNode.getAttribute('userScope') && repoNode.getAttribute('userScope') == "true") { this._hasUserScope = true; } if (repoNode.getAttribute('repository_type')) { this._repositoryType = repoNode.getAttribute('repository_type'); } if (repoNode.getAttribute('access_status')) { this._accessStatus = repoNode.getAttribute('access_status'); } if (repoNode.getAttribute('last_connection')) { this._lastConnection = repoNode.getAttribute('last_connection'); } if (repoNode.getAttribute('user_editable_repository') && repoNode.getAttribute('user_editable_repository') == "true") { this.userEditable = true; } if (repoNode.getAttribute('access_type')) { this.setAccessType(repoNode.getAttribute('access_type')); } if (repoNode.getAttribute('repositorySlug')) { this.setSlug(repoNode.getAttribute('repositorySlug')); } if (repoNode.getAttribute('owner')) { this.owner = repoNode.getAttribute('owner'); } for (var i = 0; i < repoNode.childNodes.length; i++) { var childNode = repoNode.childNodes[i]; if (childNode.nodeName == "label") { this.setLabel(childNode.firstChild.nodeValue); } else if (childNode.nodeName == "description") { this.description = childNode.firstChild.nodeValue; } else if (childNode.nodeName == "client_settings") { if (childNode.getAttribute('icon_tpl_id')) { this.setIcon(window.pydio.Parameters.get('serverAccessPath') + '&get_action=get_user_template_logo&template_id=' + childNode.getAttribute('icon_tpl_id') + '&icon_format=small'); } else { this.setIcon(childNode.getAttribute('icon')); } for (var j = 0; j < childNode.childNodes.length; j++) { var subCh = childNode.childNodes[j]; if (subCh.nodeName == 'resources') { this.resourcesManager.loadFromXmlNode(subCh); } else if (subCh.nodeName == 'node_provider') { var nodeProviderName = subCh.getAttribute("ajxpClass"); var nodeProviderOptions = JSON.parse(subCh.getAttribute("ajxpOptions")); this.nodeProviderDef = { name: nodeProviderName, options: nodeProviderOptions }; } } } } }; return Repository; })(); exports['default'] = Repository; module.exports = exports['default']; },{"../http/ResourcesManager":"pydio/http/resources-manager"}],"pydio/model/user":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _langLogger = require('../lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _httpPydioApi = require('../http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _Repository = require('./Repository'); var _Repository2 = _interopRequireDefault(_Repository); /** * Abstraction of the currently logged user. Can be a "fake" user when users management * system is disabled */ var User = (function () { /** * Constructor * @param id String The user unique id * @param xmlDef XMLNode Registry Fragment */ function User(id, xmlDef) { _classCallCheck(this, User); /** * @var String */ this.id = id; /** * @var String */ this.activeRepository = undefined; /** * @var Boolean */ this.read = false; /** * @var Boolean */ this.write = false, /** * @var Boolean */ this.crossRepositoryCopy = false, /** * @var Map() */ this.preferences = new Map(), /** * @var Map() */ this.repositories = new Map(), /** * @var Map() */ this.crossRepositories = new Map(), /** * @var Map() */ this.repoIcons = new Map(), /** * @var Map() */ this.repoSearchEngines = new Map(), /** * @var Boolean */ this.isAdmin = false; /** * @var String */ this.lock = false; /** * * @type Map * @private */ this._parsedJSONCache = new Map(); if (xmlDef) this.loadFromXml(xmlDef); } /** * Set current repository * @param id String * @param read Boolean * @param write Boolean */ User.prototype.setActiveRepository = function setActiveRepository(id, read, write) { this.activeRepository = id; this.read = read == "1"; this.write = write == "1"; if (this.repositories.has(id)) { this.crossRepositoryCopy = this.repositories.get(id).allowCrossRepositoryCopy; } if (this.crossRepositories.has(id)) { this.crossRepositories['delete'](id); } }; /** * Gets the current active repository * @returns String */ User.prototype.getActiveRepository = function getActiveRepository() { return this.activeRepository; }; /** * Whether current repo is allowed to be read * @returns Boolean */ User.prototype.canRead = function canRead() { return this.read; }; /** * Whether current repo is allowed to be written * @returns Boolean */ User.prototype.canWrite = function canWrite() { return this.write; }; /** * Whether current repo is allowed to be cross-copied * @returns Boolean */ User.prototype.canCrossRepositoryCopy = function canCrossRepositoryCopy() { return this.crossRepositoryCopy; }; /** * Get a user preference by its name * @returns Mixed */ User.prototype.getPreference = function getPreference(prefName, fromJSON) { if (fromJSON) { var test = this._parsedJSONCache.get(prefName); if (test) return test; } var value = this.preferences.get(prefName); if (fromJSON) { if (value) { try { if (typeof value == "object") return value; var parsed = JSON.parse(value); this._parsedJSONCache.set(prefName, parsed); if (!parsed) return {}; return parsed; } catch (e) { if (window.console) { _langLogger2['default'].log("Error parsing JSON in preferences (" + prefName + "). You should contact system admin and clear user preferences."); } else { alert("Error parsing JSON in preferences. You should contact system admin and clear user preferences."); } } } return {}; } return value; }; /** * Get all repositories * @returns Map */ User.prototype.getRepositoriesList = function getRepositoriesList() { return this.repositories; }; /** * Set a preference value * @param prefName String * @param prefValue Mixed * @param toJSON Boolean Whether to convert the value to JSON representation */ User.prototype.setPreference = function setPreference(prefName, prefValue) { var toJSON = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; if (toJSON) { this._parsedJSONCache['delete'](prefName); try { prefValue = JSON.stringify(prefValue); } catch (e) { if (console) { var isCyclic = function isCyclic(obj) { var seenObjects = []; function detect(obj) { if (obj && typeof obj === 'object') { if (seenObjects.indexOf(obj) !== -1) { return true; } seenObjects.push(obj); for (var key in obj) { if (obj.hasOwnProperty(key) && detect(obj[key])) { console.log(obj, 'cycle at ' + key); return true; } } } return false; } return detect(obj); }; console.log("Caught toJSON error " + e.message, prefValue, isCyclic(prefValue)); } return; } } this.preferences.set(prefName, prefValue); }; /** * Set the repositories as a bunch * @param repoHash Map */ User.prototype.setRepositoriesList = function setRepositoriesList(repoHash) { this.repositories = repoHash; // filter repositories once for all this.crossRepositories = new Map(); this.repositories.forEach((function (value, key) { if (value.allowCrossRepositoryCopy && value.accessType != 'inbox') { this.crossRepositories.set(key, value); } }).bind(this)); }; /** * Whether there are any repositories allowing crossCopy * @returns Boolean */ User.prototype.hasCrossRepositories = function hasCrossRepositories() { return this.crossRepositories.size; }; /** * Get repositories allowing cross copy * @returns {Map} */ User.prototype.getCrossRepositories = function getCrossRepositories() { return this.crossRepositories; }; /** * Get the current repository Icon * @param repoId String * @returns String */ User.prototype.getRepositoryIcon = function getRepositoryIcon(repoId) { return this.repoIcon.get(repoId); }; /** * Get the repository search engine * @param repoId String * @returns String */ User.prototype.getRepoSearchEngine = function getRepoSearchEngine(repoId) { return this.repoSearchEngines.get(repoId); }; /** * Send the preference to the server for saving * @param prefName String */ User.prototype.savePreference = function savePreference(prefName) { if (!this.preferences.has(prefName)) return; var prefValue = this.preferences.get(prefName); window.setTimeout(function () { _httpPydioApi2['default'].getClient().userSavePreference(prefName, prefValue); }, 250); }; /** * Send all preferences to the server. If oldPass, newPass and seed are set, also save pass. * @param oldPass String * @param newPass String * @param seed String * @param onCompleteFunc Function */ User.prototype.savePreferences = function savePreferences(oldPass, newPass, seed, onCompleteFunc) { if (oldPass && newPass) { _httpPydioApi2['default'].getClient().userSavePassword(oldPass, newPass, seed, onCompleteFunc); } else { _httpPydioApi2['default'].getClient().userSavePreferences(this.preferences, onCompleteFunc); } }; /** * Parse the registry fragment to load this user * @param userNodes DOMNode */ User.prototype.loadFromXml = function loadFromXml(userNodes) { var repositories = new Map(), activeNode = undefined; var i = undefined, j = undefined; for (i = 0; i < userNodes.length; i++) { if (userNodes[i].nodeName == "active_repo") { activeNode = userNodes[i]; } else if (userNodes[i].nodeName == "repositories") { for (j = 0; j < userNodes[i].childNodes.length; j++) { var repoChild = userNodes[i].childNodes[j]; if (repoChild.nodeName == "repo") { var repository = new _Repository2['default'](repoChild.getAttribute("id"), repoChild); repositories.set(repoChild.getAttribute("id"), repository); } } this.setRepositoriesList(repositories); } else if (userNodes[i].nodeName == "preferences") { for (j = 0; j < userNodes[i].childNodes.length; j++) { var prefChild = userNodes[i].childNodes[j]; if (prefChild.nodeName == "pref") { var value = prefChild.getAttribute("value"); if (!value && prefChild.firstChild) { // Retrieve value from CDATA value = prefChild.firstChild.nodeValue; } this.setPreference(prefChild.getAttribute("name"), value); } } } else if (userNodes[i].nodeName == "special_rights") { var attr = userNodes[i].getAttribute("is_admin"); if (attr && attr === "1") this.isAdmin = true; if (userNodes[i].getAttribute("lock")) { this.lock = userNodes[i].getAttribute("lock"); } } } // Make sure it happens at the end if (activeNode) { this.setActiveRepository(activeNode.getAttribute('id'), activeNode.getAttribute('read'), activeNode.getAttribute('write')); } }; return User; })(); exports['default'] = User; module.exports = exports['default']; },{"../http/PydioApi":"pydio/http/api","../lang/Logger":"pydio/lang/logger","./Repository":"pydio/model/repository"}],"pydio/util/activity-monitor":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('../lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); /** * A monitor for user "idle" state to prevent session timing out. */ var ActivityMonitor = (function (_Observable) { _inherits(ActivityMonitor, _Observable); /** * Constructor * @param pydio Pydio */ function ActivityMonitor(pydio) { var _this = this; _classCallCheck(this, ActivityMonitor); _Observable.call(this); var serverSessionTime = pydio.Parameters.get('session_timeout'); var clientSessionTime = pydio.Parameters.get('client_timeout'); var warningMinutes = pydio.Parameters.get('client_timeout_warning'); this._pydio = pydio; this._warningMinutes = 3; this._renewMinutes = 10; this._logoutMinutes = 0; this._lastActive = 0; this._state = 'active'; this._longTaskRunning = false; if (!serverSessionTime) return; if (serverSessionTime <= 60 * this._renewMinutes) { this._renewMinutes = 2; } if (clientSessionTime === -1) { this._renewTime = serverSessionTime - this._renewMinutes * 60; if (this._pydio.user) { this.startServerLongPoller(); } this._pydio.observe('user_logged', function (u) { if (u) _this.startServerLongPoller();else _this.stopServerLongPoller(); }); return; } this._serverSessionTime = serverSessionTime; if (warningMinutes) { this._warningMinutes = warningMinutes; this._warningTime = clientSessionTime - this._warningMinutes * 60; } else { this._warningTime = false; } this._logoutTime = clientSessionTime - this._logoutMinutes * 60; this._renewTime = serverSessionTime - this._renewMinutes * 60; this._lastActive = this.getNow(); this._activityObserver = null; if (this._pydio.user) { this.register(); } this._pydio.observe('user_logged', function (u) { _this.updateLastActive(); if (u) _this.register();else _this.unregister(); }); /* document.observe("ajaxplorer:user_logged", function(){ // Be sure not to multiply the setInterval this._lastActive = this.getNow(); if(this.interval) clearInterval(this.interval); if(this.serverInterval) clearInterval(this.serverInterval); $(document.body).stopObserving("keypress", activityObserver); $(document.body).stopObserving("mouseover", activityObserver); $(document.body).stopObserving("mousemove", activityObserver); document.stopObserving("ajaxplorer:server_answer", activityObserver); this._state = 'inactive'; if(ajaxplorer.user) { this._state = 'active'; $(document.body).observe("keypress", activityObserver ); $(document.body).observe("mouseover", activityObserver ); $(document.body).observe("mousemove", activityObserver ); document.observe("ajaxplorer:server_answer", activityObserver ); this.interval = setInterval(this.idleObserver.bind(this), 5000); this.serverInterval = setInterval(this.serverObserver.bind(this), Math.min((Math.pow(2,31)-1), this._renewTime*1000)); } }.bind(this)); document.observe("ajaxplorer:longtask_starting", function(){ this._longTaskRunning = true; }.bind(this)); document.observe("ajaxplorer:longtask_finished", function(){ this._longTaskRunning = false; }.bind(this)); */ } ActivityMonitor.prototype.startServerLongPoller = function startServerLongPoller() { if (this._serverInterval) return; this._serverInterval = setInterval(this.serverPoller.bind(this), Math.min(Math.pow(2, 31) - 1, this._renewTime * 1000)); }; ActivityMonitor.prototype.stopServerLongPoller = function stopServerLongPoller() { if (this._serverInterval) { clearInterval(this._serverInterval); this._serverInterval = null; } }; ActivityMonitor.prototype.startIdlePoller = function startIdlePoller() { var restartAt = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; if (restartAt) { if (this._idleInterval) clearInterval(this._idleInterval); this._idleInterval = setInterval(this.idleObserver.bind(this), restartAt); } else { if (this._idleInterval) return; this._idleInterval = setInterval(this.idleObserver.bind(this), 5000); } }; ActivityMonitor.prototype.stopIdlePoller = function stopIdlePoller() { if (this._idleInterval) { clearInterval(this._idleInterval); this._idleInterval = null; } }; ActivityMonitor.prototype.register = function register() { var _this2 = this; if (this._activityObserver !== null) { // Already registered return; } this._state = 'active'; this._activityObserver = this.activityObserver.bind(this); this._pydio.observe('user_activity', this._activityObserver); this._pydio.observe('server_answer', this._activityObserver); this._pydio.observe('longtask_starting', function () { _this2._longTaskRunning = true; }); this._pydio.observe('longtask_finished', function () { _this2._longTaskRunning = false; }); this.startIdlePoller(); this.startServerLongPoller(); }; ActivityMonitor.prototype.unregister = function unregister() { var _this3 = this; if (this._activityObserver === null) { // Already inactive return; } this.stopIdlePoller(); this.stopServerLongPoller(); this._state = 'inactive'; this._pydio.stopObserving('user_activity', this._activityObserver); this._pydio.stopObserving('server_answer', this._activityObserver); this._pydio.stopObserving('longtask_starting', function () { _this3._longTaskRunning = true; }); this._pydio.stopObserving('longtask_finished', function () { _this3._longTaskRunning = false; }); this._activityObserver = null; }; /** * Listener to clear the timer */ ActivityMonitor.prototype.activityObserver = function activityObserver(event) { if (event && (event.memo && event.memo.discrete || event.discrete)) { return; } if (this._state === 'warning') { this.exitIdleState(); return; } if (this._internalTimer) clearTimeout(this._internalTimer); this._internalTimer = setTimeout(this.updateLastActive.bind(this), 1000); }; /** * Set last activity time */ ActivityMonitor.prototype.updateLastActive = function updateLastActive() { this._lastActive = this.getNow(); }; /** * Pings the server */ ActivityMonitor.prototype.serverPoller = function serverPoller() { PydioApi.getClient().request({ get_action: 'ping' }, null, null, { method: 'get', discrete: true }); }; /** * Listener for "idle" state of the user */ ActivityMonitor.prototype.idleObserver = function idleObserver() { var _this4 = this; var idleTime = this.getNow() - this._lastActive; if (this._state === 'inactive') return; if (this._longTaskRunning) { this.updateLastActive(); return; } //console.log(idleTime, this._logoutTime); if (idleTime >= this._logoutTime) { this.removeWarningState(); this._state = 'active'; this.stopIdlePoller(); this.stopServerLongPoller(); setTimeout(function () { _this4._pydio.getController().fireDefaultAction("expire"); }, 1000); return; } if (this._warningTime && idleTime >= this._warningTime) { var timerString = this.getWarningTimer(this._logoutTime - idleTime); this.setWarningState(timerString); } }; /** * Reactivate window */ ActivityMonitor.prototype.exitIdleState = function exitIdleState() { this.removeWarningState(); this.updateLastActive(); this._state = 'active'; this.startIdlePoller(5000); }; /** * Put the window in "warning" state : overlay, shaking timer, chronometer. */ ActivityMonitor.prototype.setWarningState = function setWarningState(warningTimerString) { this._state = 'warning'; this.startIdlePoller(1000); this._pydio.notify('activity_state_change', { activeState: 'warning', lastActiveSince: this._warningTime / 60, timerString: warningTimerString }); }; /** * Chronometer for warning before timeout * @param time Integer */ ActivityMonitor.prototype.getWarningTimer = function getWarningTimer(time) { return Math.floor(time / 60) + 'mn' + time % 60 + 's'; }; /** * Removes the overlay of warning state */ ActivityMonitor.prototype.removeWarningState = function removeWarningState() { this._pydio.notify('activity_state_change', { activeState: 'active' }); }; /** * Utility to get the time * @returns Integer */ ActivityMonitor.prototype.getNow = function getNow() { return Math.round(new Date().getTime() / 1000); }; return ActivityMonitor; })(_langObservable2['default']); exports['default'] = ActivityMonitor; module.exports = exports['default']; },{"../lang/Observable":"pydio/lang/observable"}],"pydio/util/cookies":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * * Pure Javascript (ES6) Cookie Manager inspired by CookieJar that was relying on PrototypeJS. * * ---- * CookieJAR Original Header * * Javascript code to store data as JSON strings in cookies. * It uses prototype.js 1.5.1 (http://www.prototypejs.org) * * Author : Lalit Patel * Website: http://www.lalit.org/lab/jsoncookies * License: Creative Commons Attribution-ShareAlike 2.5 * http://creativecommons.org/licenses/by-sa/2.5/ * Version: 0.4 * Updated: Aug 11, 2007 10:09am * * Chnage Log: * v 0.4 * - Removed a extra comma in options (was breaking in IE and Opera). (Thanks Jason) * - Removed the parameter name from the initialize function * - Changed the way expires date was being calculated. (Thanks David) * v 0.3 * - Removed dependancy on json.js (http://www.json.org/json.js) * - empty() function only deletes the cookies set by CookieJar */ 'use strict'; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var CookiesManager = (function () { CookiesManager.supported = function supported() { return document && document.cookie !== undefined; }; /** * Initializes the cookie jar with the options. */ function CookiesManager(options) { _classCallCheck(this, CookiesManager); /** * Append before all cookie names to differntiate them. */ this._appendString = "__PYDIO__"; this.options = { expires: 3600, // seconds (1 hr) path: '', // cookie path domain: '', // cookie domain secure: '' // secure ? }; this.options = LangUtils.objectMerge(this.options, options || {}); if (this.options.expires != '') { var date = new Date(); date = new Date(date.getTime() + this.options.expires * 1000); this.options.expires = '; expires=' + date.toGMTString(); } if (this.options.path != '') { this.options.path = '; path=' + encodeURI(this.options.path); } if (this.options.domain != '') { this.options.domain = '; domain=' + encodeURI(this.options.domain); } if (this.options.secure == 'secure') { this.options.secure = '; secure'; } else { this.options.secure = ''; } } /** * Adds a name values pair. */ CookiesManager.prototype.putCookie = function putCookie(name, value) { name = this._appendString + name; var cookie = this.options; var type = typeof value; switch (type) { case 'undefined': case 'function': case 'unknown': return false; case 'boolean': case 'string': case 'number': value = String(value.toString()); } var cookie_str = name + "=" + encodeURI(JSON.stringify(value)); try { document.cookie = cookie_str + cookie.expires + cookie.path + cookie.domain + cookie.secure; } catch (e) { return false; } return true; }; /** * Removes a particular cookie (name value pair) form the Cookie Jar. */ CookiesManager.prototype.removeCookie = function removeCookie(name) { name = this._appendString + name; var cookie = this.options; try { var date = new Date(); date.setTime(date.getTime() - 3600 * 1000); var expires = '; expires=' + date.toGMTString(); document.cookie = name + "=" + expires + cookie.path + cookie.domain + cookie.secure; } catch (e) { return false; } return true; }; /** * Return a particular cookie by name; */ CookiesManager.prototype.getCookie = function getCookie(name) { name = this._appendString + name; var cookies = document.cookie.match(name + '=(.*?)(;|$)'); if (cookies) { return JSON.parse(decodeURI(cookies[1])); } else { return null; } }; /** * Empties the Cookie Jar. Deletes all the cookies. */ CookiesManager.prototype.emptyAll = function emptyAll() { var keys = this.getKeys(); var size = keys.size(); for (var i = 0; i < size; i++) { this.removeCookie(keys[i]); } }; /** * Returns all cookies as a single object */ CookiesManager.prototype.getPack = function getPack() { var pack = {}; var keys = this.getKeys(); var size = keys.size(); for (var i = 0; i < size; i++) { pack[keys[i]] = this.get(keys[i]); } return pack; }; /** * Returns all keys. */ CookiesManager.prototype.getKeys = function getKeys() { var keys = []; var keyRe = /[^=; ]+(?=\=)/g; var str = document.cookie; var CJRe = new RegExp("^" + this._appendString); var match; while ((match = keyRe.exec(str)) != undefined) { if (CJRe.test(match[0].strip())) { keys.push(match[0].strip().gsub("^" + this._appendString, "")); } } return keys; }; return CookiesManager; })(); exports['default'] = CookiesManager; module.exports = exports['default']; },{}],"pydio/util/dom":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ /** * Utilitary class for language specific methods */ 'use strict'; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var DOMUtils = (function () { function DOMUtils() { _classCallCheck(this, DOMUtils); } DOMUtils.getBeziersTransition = function getBeziersTransition() { return 'all 550ms cubic-bezier(0.23, 1, 0.32, 1) 0ms'; }; DOMUtils.getBoxShadowDepth = function getBoxShadowDepth() { var depth = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0]; return '0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23)'; }; DOMUtils.getUrlFromBase = function getUrlFromBase() { return document.getElementsByTagName('base').length ? document.getElementsByTagName('base')[0].href : ''; }; DOMUtils.getViewportWidth = function getViewportWidth() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; }; DOMUtils.getViewportHeight = function getViewportHeight() { return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; }; DOMUtils.imageLoader = function imageLoader(imageUrl, onLoad, onError) { var loader = document.createElement('img'); loader.onload = onLoad.bind(loader); loader.onerror = onError.bind(loader); loader.src = imageUrl; }; DOMUtils.observeWindowResize = function observeWindowResize(callback) { if (window.addEventListener) { window.addEventListener('resize', callback); } else { window.attachEvent('onresize', callback); } }; DOMUtils.stopObservingWindowResize = function stopObservingWindowResize(callback) { if (window.removeEventListener) { window.removeEventListener('resize', callback); } else { window.detachEvent('onresize', callback); } }; return DOMUtils; })(); exports['default'] = DOMUtils; module.exports = exports['default']; },{}],"pydio/util/func":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ /** * Utilitary class for language specific methods */ "use strict"; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var FuncUtils = (function () { function FuncUtils() { _classCallCheck(this, FuncUtils); } FuncUtils.Empty = function Empty() {}; FuncUtils.Identity = function Identity(object) { return object; }; FuncUtils.executeFunctionByName = function executeFunctionByName(functionName, context) { var args = Array.prototype.slice.call(arguments, 2); var namespaces = functionName.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; } return context[func].apply(context, args); }; FuncUtils.getFunctionByName = function getFunctionByName(functionName, context) { var args = Array.prototype.slice.call(arguments, 2); var namespaces = functionName.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { if (!context[namespaces[i]]) { return null; } context = context[namespaces[i]]; } return context[func]; }; FuncUtils.bufferCallback = function bufferCallback(name, time, callback) { if (window[name]) { window.clearTimeout(window[name]); } window[name] = window.setTimeout(callback, time); }; return FuncUtils; })(); exports["default"] = FuncUtils; module.exports = exports["default"]; },{}],"pydio/util/hasher":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ /** * Utilitary class for hashing methods */ 'use strict'; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var HasherUtils = (function () { /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ function HasherUtils() { _classCallCheck(this, HasherUtils); } /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ /* * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings */ HasherUtils.hex_md5 = function hex_md5(s) { return HasherUtils.binl2hex(HasherUtils.core_md5(HasherUtils.str2binl(s), s.length * HasherUtils.chrsz)); }; HasherUtils.b64_md5 = function b64_md5(s) { return HasherUtils.binl2b64(HasherUtils.core_md5(HasherUtils.str2binl(s), s.length * HasherUtils.chrsz)); }; HasherUtils.str_md5 = function str_md5(s) { return HasherUtils.binl2str(HasherUtils.core_md5(HasherUtils.str2binl(s), s.length * HasherUtils.chrsz)); }; HasherUtils.hex_hmac_md5 = function hex_hmac_md5(key, data) { return HasherUtils.binl2hex(HasherUtils.core_hmac_md5(key, data)); }; HasherUtils.b64_hmac_md5 = function b64_hmac_md5(key, data) { return HasherUtils.binl2b64(HasherUtils.core_hmac_md5(key, data)); }; HasherUtils.str_hmac_md5 = function str_hmac_md5(key, data) { return HasherUtils.binl2str(HasherUtils.core_hmac_md5(key, data)); }; HasherUtils.base64_encode = function base64_encode(data) { // http://kevin.vanzonneveld.net // + original by: Tyler Akins (http://rumkin.com) // + improved by: Bayron Guevara // + improved by: Thunder.m // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Pellentesque Malesuada // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // - depends on: utf8_encode // * example 1: base64_encode('Kevin van Zonneveld'); // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' // mozilla has this native // - but breaks in 2.0.0.12! //if (typeof window['atob'] == 'function') { // return atob(data); //} var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc, tmp_arr = []; if (!data) { return data; } data = HasherUtils.utf8_encode(data + ''); do { // pack three octets into four hexets o1 = data.charCodeAt(i++); o2 = data.charCodeAt(i++); o3 = data.charCodeAt(i++); bits = o1 << 16 | o2 << 8 | o3; h1 = bits >> 18 & 0x3f; h2 = bits >> 12 & 0x3f; h3 = bits >> 6 & 0x3f; h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); } while (i < data.length); enc = tmp_arr.join(''); switch (data.length % 3) { case 1: enc = enc.slice(0, -2) + '=='; break; case 2: enc = enc.slice(0, -1) + '='; break; } return enc; }; HasherUtils.utf8_encode = function utf8_encode(string) { // http://kevin.vanzonneveld.net // + original by: Webtoolkit.info (http://www.webtoolkit.info/) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: sowberry // + tweaked by: Jack // + bugfixed by: Onno Marsman // + improved by: Yves Sucaet // + bugfixed by: Onno Marsman // * example 1: utf8_encode('Kevin van Zonneveld'); // * returns 1: 'Kevin van Zonneveld' string = (string + '').replace(/\r\n/g, "\n").replace(/\r/g, "\n"); var utftext = ""; var start, end; var stringl; start = end = 0; stringl = string.length; for (var n = 0; n < stringl; n++) { var c1 = string.charCodeAt(n); var enc = null; if (c1 < 128) { end++; } else if (c1 > 127 && c1 < 2048) { enc = String.fromCharCode(c1 >> 6 | 192) + String.fromCharCode(c1 & 63 | 128); } else { enc = String.fromCharCode(c1 >> 12 | 224) + String.fromCharCode(c1 >> 6 & 63 | 128) + String.fromCharCode(c1 & 63 | 128); } if (enc != null) { if (end > start) { utftext += string.substring(start, end); } utftext += enc; start = end = n + 1; } } if (end > start) { utftext += string.substring(start, string.length); } return utftext; }; /* * Perform a simple self-test to see if the VM is working */ HasherUtils.md5_vm_test = function md5_vm_test() { return HasherUtils.hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; }; /* * Calculate the MD5 of an array of little-endian words, and a bit length */ HasherUtils.core_md5 = function core_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << len % 32; x[(len + 64 >>> 9 << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = HasherUtils.md5_ff(a, b, c, d, x[i + 0], 7, -680876936); d = HasherUtils.md5_ff(d, a, b, c, x[i + 1], 12, -389564586); c = HasherUtils.md5_ff(c, d, a, b, x[i + 2], 17, 606105819); b = HasherUtils.md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); a = HasherUtils.md5_ff(a, b, c, d, x[i + 4], 7, -176418897); d = HasherUtils.md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); c = HasherUtils.md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); b = HasherUtils.md5_ff(b, c, d, a, x[i + 7], 22, -45705983); a = HasherUtils.md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); d = HasherUtils.md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); c = HasherUtils.md5_ff(c, d, a, b, x[i + 10], 17, -42063); b = HasherUtils.md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); a = HasherUtils.md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); d = HasherUtils.md5_ff(d, a, b, c, x[i + 13], 12, -40341101); c = HasherUtils.md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); b = HasherUtils.md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); a = HasherUtils.md5_gg(a, b, c, d, x[i + 1], 5, -165796510); d = HasherUtils.md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); c = HasherUtils.md5_gg(c, d, a, b, x[i + 11], 14, 643717713); b = HasherUtils.md5_gg(b, c, d, a, x[i + 0], 20, -373897302); a = HasherUtils.md5_gg(a, b, c, d, x[i + 5], 5, -701558691); d = HasherUtils.md5_gg(d, a, b, c, x[i + 10], 9, 38016083); c = HasherUtils.md5_gg(c, d, a, b, x[i + 15], 14, -660478335); b = HasherUtils.md5_gg(b, c, d, a, x[i + 4], 20, -405537848); a = HasherUtils.md5_gg(a, b, c, d, x[i + 9], 5, 568446438); d = HasherUtils.md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); c = HasherUtils.md5_gg(c, d, a, b, x[i + 3], 14, -187363961); b = HasherUtils.md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); a = HasherUtils.md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); d = HasherUtils.md5_gg(d, a, b, c, x[i + 2], 9, -51403784); c = HasherUtils.md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); b = HasherUtils.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); a = HasherUtils.md5_hh(a, b, c, d, x[i + 5], 4, -378558); d = HasherUtils.md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); c = HasherUtils.md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); b = HasherUtils.md5_hh(b, c, d, a, x[i + 14], 23, -35309556); a = HasherUtils.md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); d = HasherUtils.md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); c = HasherUtils.md5_hh(c, d, a, b, x[i + 7], 16, -155497632); b = HasherUtils.md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); a = HasherUtils.md5_hh(a, b, c, d, x[i + 13], 4, 681279174); d = HasherUtils.md5_hh(d, a, b, c, x[i + 0], 11, -358537222); c = HasherUtils.md5_hh(c, d, a, b, x[i + 3], 16, -722521979); b = HasherUtils.md5_hh(b, c, d, a, x[i + 6], 23, 76029189); a = HasherUtils.md5_hh(a, b, c, d, x[i + 9], 4, -640364487); d = HasherUtils.md5_hh(d, a, b, c, x[i + 12], 11, -421815835); c = HasherUtils.md5_hh(c, d, a, b, x[i + 15], 16, 530742520); b = HasherUtils.md5_hh(b, c, d, a, x[i + 2], 23, -995338651); a = HasherUtils.md5_ii(a, b, c, d, x[i + 0], 6, -198630844); d = HasherUtils.md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); c = HasherUtils.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); b = HasherUtils.md5_ii(b, c, d, a, x[i + 5], 21, -57434055); a = HasherUtils.md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); d = HasherUtils.md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); c = HasherUtils.md5_ii(c, d, a, b, x[i + 10], 15, -1051523); b = HasherUtils.md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); a = HasherUtils.md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); d = HasherUtils.md5_ii(d, a, b, c, x[i + 15], 10, -30611744); c = HasherUtils.md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); b = HasherUtils.md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); a = HasherUtils.md5_ii(a, b, c, d, x[i + 4], 6, -145523070); d = HasherUtils.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); c = HasherUtils.md5_ii(c, d, a, b, x[i + 2], 15, 718787259); b = HasherUtils.md5_ii(b, c, d, a, x[i + 9], 21, -343485551); a = HasherUtils.safe_add(a, olda); b = HasherUtils.safe_add(b, oldb); c = HasherUtils.safe_add(c, oldc); d = HasherUtils.safe_add(d, oldd); } return [a, b, c, d]; }; /* * These functions implement the four basic operations the algorithm uses. */ HasherUtils.md5_cmn = function md5_cmn(q, a, b, x, s, t) { return HasherUtils.safe_add(HasherUtils.bit_rol(HasherUtils.safe_add(HasherUtils.safe_add(a, q), HasherUtils.safe_add(x, t)), s), b); }; HasherUtils.md5_ff = function md5_ff(a, b, c, d, x, s, t) { return HasherUtils.md5_cmn(b & c | ~b & d, a, b, x, s, t); }; HasherUtils.md5_gg = function md5_gg(a, b, c, d, x, s, t) { return HasherUtils.md5_cmn(b & d | c & ~d, a, b, x, s, t); }; HasherUtils.md5_hh = function md5_hh(a, b, c, d, x, s, t) { return HasherUtils.md5_cmn(b ^ c ^ d, a, b, x, s, t); }; HasherUtils.md5_ii = function md5_ii(a, b, c, d, x, s, t) { return HasherUtils.md5_cmn(c ^ (b | ~d), a, b, x, s, t); }; /* * Calculate the HMAC-MD5, of a key and some data */ HasherUtils.core_hmac_md5 = function core_hmac_md5(key, data) { var bkey = HasherUtils.str2binl(key); if (bkey.length > 16) bkey = HasherUtils.core_md5(bkey, key.length * HasherUtils.chrsz); var ipad = new Array(16), opad = new Array(16); for (var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = HasherUtils.core_md5(ipad.concat(HasherUtils.str2binl(data)), 512 + data.length * HasherUtils.chrsz); return HasherUtils.core_md5(opad.concat(hash), 512 + 128); }; /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ HasherUtils.safe_add = function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return msw << 16 | lsw & 0xFFFF; }; /* * Bitwise rotate a 32-bit number to the left. */ HasherUtils.bit_rol = function bit_rol(num, cnt) { return num << cnt | num >>> 32 - cnt; }; /* * Convert a string to an array of little-endian words * If HasherUtils.chrsz is ASCII, characters >255 have their hi-byte silently ignored. */ HasherUtils.str2binl = function str2binl(str) { var bin = []; var mask = (1 << HasherUtils.chrsz) - 1; for (var i = 0; i < str.length * HasherUtils.chrsz; i += HasherUtils.chrsz) bin[i >> 5] |= (str.charCodeAt(i / HasherUtils.chrsz) & mask) << i % 32; return bin; }; /* * Convert an array of little-endian words to a string */ HasherUtils.binl2str = function binl2str(bin) { var str = ""; var mask = (1 << HasherUtils.chrsz) - 1; for (var i = 0; i < bin.length * 32; i += HasherUtils.chrsz) str += String.fromCharCode(bin[i >> 5] >>> i % 32 & mask); return str; }; /* * Convert an array of little-endian words to a hex string. */ HasherUtils.binl2hex = function binl2hex(binarray) { var hex_tab = HasherUtils.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for (var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 0xF) + hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 & 0xF); } return str; }; /* * Convert an array of little-endian words to a base-64 string */ HasherUtils.binl2b64 = function binl2b64(binarray) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var str = ""; for (var i = 0; i < binarray.length * 4; i += 3) { var triplet = (binarray[i >> 2] >> 8 * (i % 4) & 0xFF) << 16 | (binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4) & 0xFF) << 8 | binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4) & 0xFF; for (var j = 0; j < 4; j++) { if (i * 8 + j * 6 > binarray.length * 32) str += HasherUtils.b64pad;else str += tab.charAt(triplet >> 6 * (3 - j) & 0x3F); } } return str; }; return HasherUtils; })(); exports['default'] = HasherUtils; HasherUtils.hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ HasherUtils.b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ HasherUtils.chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ module.exports = exports['default']; },{}],"pydio/util/lang":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ /** * Utilitary class for language specific methods */ 'use strict'; exports.__esModule = true; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var LangUtils = (function () { function LangUtils() { _classCallCheck(this, LangUtils); } LangUtils.arrayWithout = function arrayWithout(array, key) { if (!array.length) return array; if (key >= array.length) return array; var newArray; if (key == 0) newArray = array.slice(1);else if (key == array.length - 1) newArray = array.slice(0, -1);else newArray = array.slice(0, key).concat(array.slice(key + 1)); return newArray; }; LangUtils.objectMerge = function objectMerge(obj1, obj2) { return _extends({}, obj1, obj2); }; LangUtils.parseUrl = function parseUrl(data) { var matches = []; //var e=/((http|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+\.[^#?\s]+)(#[\w\-]+)?/; var detect = /(pydio:\/)?\/?([^:\/\s]+)((\/\w+)*\/)(.*)(#[\w\-]+)?/g; var results = data.match(detect); if (results && results.length) { var e = /^((pydio):\/)?\/?([^:\/\s]+)((\/\w+)*\/)(.*)(#[\w\-]+)?$/; for (var i = 0; i < results.length; i++) { if (results[i].match(e)) { matches.push({ url: RegExp['$&'], protocol: RegExp.$2, host: RegExp.$3, path: RegExp.$4, file: RegExp.$6, hash: RegExp.$7 }); } } } return matches; }; LangUtils.computeStringSlug = function computeStringSlug(value) { for (var i = 0, len = LangUtils.slugTable.length; i < len; i++) value = value.replace(LangUtils.slugTable[i].re, LangUtils.slugTable[i].ch); // 1) met en bas de casse // 2) remplace les espace par des tirets // 3) enleve tout les caratères non alphanumeriques // 4) enlève les doubles tirets return value.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '').replace(/\-{2,}/g, '-'); }; LangUtils.forceJSONArrayToObject = function forceJSONArrayToObject(container, value) { if (container[value] instanceof Array) { // Clone var copy = container[value].slice(0); container[value] = {}; for (var i = 0; i < copy.length; i++) { container[value][i] = copy[i]; } } }; LangUtils.deepCopy = function deepCopy(source) { return LangUtils.mergeObjectsRecursive({}, source); }; LangUtils.simpleCopy = function simpleCopy(source) { var copy = {}; for (var property in source) { if (source.hasOwnProperty(property)) { copy[property] = source[property]; } } return copy; }; LangUtils.mergeObjectsRecursive = function mergeObjectsRecursive(source, destination) { var newObject = {}, property; for (property in source) { if (source.hasOwnProperty(property)) { //if (source[property] === null) continue; if (destination.hasOwnProperty(property)) { if (source[property] instanceof Object && destination instanceof Object) { newObject[property] = LangUtils.mergeObjectsRecursive(source[property], destination[property]); } else { newObject[property] = destination[property]; } } else { if (source[property] instanceof Object) { newObject[property] = LangUtils.mergeObjectsRecursive(source[property], {}); } else { newObject[property] = source[property]; } } } } for (property in destination) { if (destination.hasOwnProperty(property) && !newObject.hasOwnProperty(property) /*&& destination[property] !== null*/) { if (destination[property] instanceof Object) { newObject[property] = LangUtils.mergeObjectsRecursive(destination[property], {}); } else { newObject[property] = destination[property]; } } } return newObject; }; LangUtils.objectValues = function objectValues(object) { var results = []; for (var property in object) if (object.hasOwnProperty(property)) { results.push(object[property]); } return results; }; LangUtils.trimLeft = function trimLeft(string, charlist) { if (charlist === undefined) { charlist = "\s"; } return string.replace(new RegExp("^[" + charlist + "]+"), ""); }; LangUtils.trimRight = function trimRight(string, charlist) { if (charlist === undefined) { charlist = "\s"; } return string.replace(new RegExp("[" + charlist + "]+$"), ""); }; LangUtils.trim = function trim(string, charlist) { return LangUtils.trimLeft(LangUtils.trimRight(string, charlist), charlist); }; return LangUtils; })(); exports['default'] = LangUtils; LangUtils.slugTable = [{ re: /[\xC0-\xC6]/g, ch: 'A' }, { re: /[\xE0-\xE6]/g, ch: 'a' }, { re: /[\xC8-\xCB]/g, ch: 'E' }, { re: /[\xE8-\xEB]/g, ch: 'e' }, { re: /[\xCC-\xCF]/g, ch: 'I' }, { re: /[\xEC-\xEF]/g, ch: 'i' }, { re: /[\xD2-\xD6]/g, ch: 'O' }, { re: /[\xF2-\xF6]/g, ch: 'o' }, { re: /[\xD9-\xDC]/g, ch: 'U' }, { re: /[\xF9-\xFC]/g, ch: 'u' }, { re: /[\xC7-\xE7]/g, ch: 'c' }, { re: /[\xD1]/g, ch: 'N' }, { re: /[\xF1]/g, ch: 'n' }]; module.exports = exports['default']; },{}],"pydio/util/pass":[function(require,module,exports){ (function (global){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _httpResourcesManager = require('../http/ResourcesManager'); var _httpResourcesManager2 = _interopRequireDefault(_httpResourcesManager); /** * * Utils to compute password strength * */ var PassUtils = (function () { function PassUtils() { _classCallCheck(this, PassUtils); } PassUtils.getState = function getState() { var passValue = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0]; var confirmValue = arguments.length <= 1 || arguments[1] === undefined ? '' : arguments[1]; var crtState = arguments.length <= 2 || arguments[2] === undefined ? { valid: false } : arguments[2]; var onChange = arguments.length <= 3 || arguments[3] === undefined ? function (status) {} : arguments[3]; var state = { valid: true, passErrorText: null, passHintText: null, confirmErrorText: null }; if (!passValue && !confirmValue) { state.valid = false; } else { PassUtils.checkPasswordStrength(passValue, function (valid, message) { state.valid = valid; if (!valid) { state.passErrorText = message; } else { state.passHintText = message; } }); if (!confirmValue) { state.valid = false; state.confirmErrorText = global.pydio.MessageHash[621]; } else if (confirmValue !== passValue) { state.valid = false; state.confirmErrorText = global.pydio.MessageHash[238]; } } if (crtState.valid !== state.valid) { onChange(state.valid); } return state; }; PassUtils.getOptions = function getOptions() { if (PassUtils.Options) { return PassUtils.Options; } PassUtils.Options = { pydioMessages: [379, 380, 381, 382, 383, 384, 385], messages: ["Unsafe password word!", "Too short", "Very weak", "Weak", "Medium", "Strong", "Very strong"], colors: ["#f00", "#999", "#C70F0F", "#C70F0F", "#FF8432", "#279D00", "#279D00"], scores: [10, 15, 30, 40], common: ["password", "123456", "123", "1234", "mypass", "pass", "letmein", "qwerty", "monkey", "asdfgh", "zxcvbn", "pass"], minchar: 8 }; var pydioMin = parseInt(global.pydio.getPluginConfigs("core.auth").get("PASSWORD_MINLENGTH")); if (pydioMin) { PassUtils.Options.minchar = pydioMin; } return PassUtils.Options; }; PassUtils.checkPasswordStrength = function checkPasswordStrength(value, callback) { try { var PassPolicyLib = _httpResourcesManager2['default'].requireLib("PasswordPolicy", false); if (PassPolicyLib && PassPolicyLib.Checker) { var Checker = PassPolicyLib.Checker; if (Checker) { Checker.checkPasswordStrength(value, callback); return; } } } catch (e) {} // Update with Pydio options var options = PassUtils.getOptions(); if (options.minchar && value.length < options.minchar) { callback(false, global.pydio.MessageHash[380]); return; } var wrappedCallback = function wrappedCallback(msgId, percent) { var s = options.messages[msgId]; try { s = global.pydio.MessageHash[options.pydioMessages[msgId]]; } catch (e) {} callback(percent > 1, s); }; var strength = PassUtils.getPasswordScore(value, options.minchar); if (strength == -200) { wrappedCallback(0, 0); } else { if (strength < 0 && strength > -199) { wrappedCallback(1, 10); } else { if (strength <= options.scores[0]) { wrappedCallback(2, 10); } else { if (strength > options.scores[0] && strength <= options.scores[1]) { wrappedCallback(3, 25); } else if (strength > options.scores[1] && strength <= options.scores[2]) { wrappedCallback(4, 55); } else if (strength > options.scores[2] && strength <= options.scores[3]) { wrappedCallback(5, 80); } else { wrappedCallback(6, 98); } } } } }; PassUtils.getPasswordScore = function getPasswordScore(value, minchar) { var strength = 0; if (value.length < minchar) { strength = strength - 100; } else { if (value.length >= minchar && value.length <= minchar + 2) { strength = strength + 6; } else { if (value.length >= minchar + 3 && value.length <= minchar + 4) { strength = strength + 12; } else { if (value.length >= minchar + 5) { strength = strength + 18; } } } } if (value.match(/[a-z]/)) { strength = strength + 1; } if (value.match(/[A-Z]/)) { strength = strength + 5; } if (value.match(/\d+/)) { strength = strength + 5; } if (value.match(/(.*[0-9].*[0-9].*[0-9])/)) { strength = strength + 7; } if (value.match(/.[!,@#$%^&*?_~]/)) { strength = strength + 5; } if (value.match(/(.*[!,@#$%^&*?_~].*[!,@#$%^&*?_~])/)) { strength = strength + 7; } if (value.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) { strength = strength + 2; } if (value.match(/([a-zA-Z])/) && value.match(/([0-9])/)) { strength = strength + 3; } if (value.match(/([a-zA-Z0-9].*[!,@#$%^&*?_~])|([!,@#$%^&*?_~].*[a-zA-Z0-9])/)) { strength = strength + 3; } var common = ["password", "123456", "123", "1234", "mypass", "pass", "letmein", "qwerty", "monkey", "asdfgh", "zxcvbn", "pass"]; if (common.indexOf(value.toLowerCase()) !== -1) { strength = -200; } return strength; }; return PassUtils; })(); exports['default'] = PassUtils; module.exports = exports['default']; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"../http/ResourcesManager":"pydio/http/resources-manager"}],"pydio/util/path":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ /** * Utilitary class for manipulating file/folders pathes */ "use strict"; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var PathUtils = (function () { function PathUtils() { _classCallCheck(this, PathUtils); } PathUtils.getBasename = function getBasename(fileName) { if (fileName == null) return null; var separator = "/"; if (fileName.indexOf("\\") != -1) separator = "\\"; return fileName.substr(fileName.lastIndexOf(separator) + 1, fileName.length); }; PathUtils.getDirname = function getDirname(fileName) { return fileName.substr(0, fileName.lastIndexOf("/")); }; PathUtils.getAjxpMimeType = function getAjxpMimeType(item) { if (!item) return ""; if (item instanceof Map) { return item.get('ajxp_mime') || PathUtils.getFileExtension(item.get('filename')); } else if (item.getMetadata) { return item.getMetadata().get('ajxp_mime') || PathUtils.getFileExtension(item.getPath()); } else { return item.getAttribute('ajxp_mime') || PathUtils.getFileExtension(item.getAttribute('filename')); } }; PathUtils.getFileExtension = function getFileExtension(fileName) { if (!fileName || fileName == "") return ""; var split = PathUtils.getBasename(fileName).split('.'); if (split.length > 1) return split[split.length - 1].toLowerCase(); return ''; }; PathUtils.roundFileSize = function roundFileSize(filesize) { var size_unit = arguments.length <= 1 || arguments[1] === undefined ? "o" : arguments[1]; if (filesize >= 1073741824) { filesize = Math.round(filesize / 1073741824 * 100) / 100 + " G" + size_unit; } else if (filesize >= 1048576) { filesize = Math.round(filesize / 1048576 * 100) / 100 + " M" + size_unit; } else if (filesize >= 1024) { filesize = Math.round(filesize / 1024 * 100) / 100 + " K" + size_unit; } else { filesize = filesize + " " + size_unit; } return filesize; }; /** * * @param dateObject Date * @param format String * @returns {*} */ PathUtils.formatModifDate = function formatModifDate(dateObject, format) { if (!format && window && window.pydio && pydio.MessageHash) { format = pydio.MessageHash["date_format"]; } if (!format) return 'no format'; format = format.replace("d", dateObject.getDate() < 10 ? '0' + dateObject.getDate() : dateObject.getDate()); format = format.replace("D", dateObject.getDay()); format = format.replace("Y", dateObject.getFullYear()); format = format.replace("y", dateObject.getYear()); var month = dateObject.getMonth() + 1; format = format.replace("m", month < 10 ? '0' + month : month); format = format.replace("H", (dateObject.getHours() < 10 ? '0' : '') + dateObject.getHours()); // Support 12 hour format compatibility format = format.replace("h", dateObject.getHours() % 12 || 12); format = format.replace("p", dateObject.getHours() < 12 ? "am" : "pm"); format = format.replace("P", dateObject.getHours() < 12 ? "AM" : "PM"); format = format.replace("i", (dateObject.getMinutes() < 10 ? '0' : '') + dateObject.getMinutes()); format = format.replace("s", (dateObject.getSeconds() < 10 ? '0' : '') + dateObject.getSeconds()); return format; }; return PathUtils; })(); exports["default"] = PathUtils; module.exports = exports["default"]; },{}],"pydio/util/periodical-executer":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ "use strict"; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var PeriodicalExecuter = (function () { function PeriodicalExecuter(callback, frequency) { _classCallCheck(this, PeriodicalExecuter); this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); } PeriodicalExecuter.prototype.registerCallback = function registerCallback() { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }; PeriodicalExecuter.prototype.execute = function execute() { this.callback(this); }; PeriodicalExecuter.prototype.stop = function stop() { if (!this.timer) return; clearInterval(this.timer); this.timer = null; }; PeriodicalExecuter.prototype.onTimerEvent = function onTimerEvent() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.execute(); this.currentlyExecuting = false; } catch (e) { this.currentlyExecuting = false; throw e; } } }; return PeriodicalExecuter; })(); exports["default"] = PeriodicalExecuter; module.exports = exports["default"]; },{}],"pydio/util/xml":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . * */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _wickedGoodXpath = require('wicked-good-xpath'); var _wickedGoodXpath2 = _interopRequireDefault(_wickedGoodXpath); _wickedGoodXpath2['default'].install(); /** * Utilitary class for manipulating XML */ var XMLUtils = (function () { function XMLUtils() { _classCallCheck(this, XMLUtils); } /** * Selects the first XmlNode that matches the XPath expression. * * @param element {Element | Document} root element for the search * @param query {String} XPath query * @return {Element} first matching element * @signature function(element, query) */ XMLUtils.XPathSelectSingleNode = function XPathSelectSingleNode(element, query) { try { if (element['selectSingleNode'] && typeof element.selectSingleNode === "function") { var res = element.selectSingleNode(query); if (res) return res; } } catch (e) {} if (!XMLUtils.__xpe && window.XPathEvaluator) { try { XMLUtils.__xpe = new XPathEvaluator(); } catch (e) {} } if (!XMLUtils.__xpe) { query = document.createExpression(query, null); var result = query.evaluate(element, 7, null); return result.snapshotLength ? result.snapshotItem(0) : null; } var xpe = XMLUtils.__xpe; try { return xpe.evaluate(query, element, xpe.createNSResolver(element), XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; } catch (err) { throw new Error("selectSingleNode: query: " + query + ", element: " + element + ", error: " + err); } }; /** * Selects a list of nodes matching the XPath expression. * * @param element {Element | Document} root element for the search * @param query {String} XPath query * @return {Element[]} List of matching elements * @signature function(element, query) */ XMLUtils.XPathSelectNodes = function XPathSelectNodes(element, query) { try { if (typeof element.selectNodes === "function") { try { if (element.ownerDocument && element.ownerDocument.setProperty) { element.ownerDocument.setProperty("SelectionLanguage", "XPath"); } else if (element.setProperty) { element.setProperty("SelectionLanguage", "XPath"); } } catch (e) {} var res = Array.from(element.selectNodes(query)); if (res) return res; } } catch (e) {} var xpe = XMLUtils.__xpe; if (!xpe && window.XPathEvaluator) { try { XMLUtils.__xpe = xpe = new XPathEvaluator(); } catch (e) {} } var result, nodes = [], i; if (!XMLUtils.__xpe) { query = document.createExpression(query, null); result = query.evaluate(element, 7, null); nodes = []; for (i = 0; i < result.snapshotLength; i++) { if (Element.extend) { nodes[i] = Element.extend(result.snapshotItem(i)); } else { nodes[i] = result.snapshotItem(i); } } return nodes; } try { result = xpe.evaluate(query, element, xpe.createNSResolver(element), XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); } catch (err) { throw new Error("selectNodes: query: " + query + ", element: " + element + ", error: " + err); } for (i = 0; i < result.snapshotLength; i++) { nodes[i] = result.snapshotItem(i); } return nodes; }; /** * Selects the first XmlNode that matches the XPath expression and returns the text content of the element * * @param element {Element|Document} root element for the search * @param query {String} XPath query * @return {String} the joined text content of the found element or null if not appropriate. * @signature function(element, query) */ XMLUtils.XPathGetSingleNodeText = function XPathGetSingleNodeText(element, query) { var node = XMLUtils.XPathSelectSingleNode(element, query); return XMLUtils.getDomNodeText(node); }; XMLUtils.getDomNodeText = function getDomNodeText(node) { var includeCData = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; if (!node || !node.nodeType) { return null; } switch (node.nodeType) { case 1: // NODE_ELEMENT var i, a = [], nodes = node.childNodes, length = nodes.length; for (i = 0; i < length; i++) { a[i] = XMLUtils.getDomNodeText(nodes[i], includeCData); } return a.join(""); case 2: // NODE_ATTRIBUTE return node.value; case 3: // NODE_TEXT return node.nodeValue; case 4: // CDATA if (includeCData) return node.nodeValue; break; } return null; }; /** * @param xmlStr * @returns {*} */ XMLUtils.parseXml = function parseXml(xmlStr) { if (typeof window.DOMParser != "undefined") { return new window.DOMParser().parseFromString(xmlStr, "text/xml"); } if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("MSXML2.DOMDocument.6.0")) { var xmlDoc = new window.ActiveXObject("MSXML2.DOMDocument.6.0"); xmlDoc.validateOnParse = false; xmlDoc.async = false; xmlDoc.loadXML(xmlStr); xmlDoc.setProperty('SelectionLanguage', 'XPath'); return xmlDoc; } throw new Error('Cannot parse XML string'); }; return XMLUtils; })(); exports['default'] = XMLUtils; module.exports = exports['default']; },{"wicked-good-xpath":9}],"pydio":[function(require,module,exports){ /* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _langObservable = require('./lang/Observable'); var _langObservable2 = _interopRequireDefault(_langObservable); var _langLogger = require('./lang/Logger'); var _langLogger2 = _interopRequireDefault(_langLogger); var _httpPydioApi = require('./http/PydioApi'); var _httpPydioApi2 = _interopRequireDefault(_httpPydioApi); var _modelRegistry = require('./model/Registry'); var _modelRegistry2 = _interopRequireDefault(_modelRegistry); var _modelAjxpNode = require('./model/AjxpNode'); var _modelAjxpNode2 = _interopRequireDefault(_modelAjxpNode); var _modelPydioDataModel = require('./model/PydioDataModel'); var _modelPydioDataModel2 = _interopRequireDefault(_modelPydioDataModel); var _modelRemoteNodeProvider = require('./model/RemoteNodeProvider'); var _modelRemoteNodeProvider2 = _interopRequireDefault(_modelRemoteNodeProvider); var _modelRepository = require('./model/Repository'); var _modelRepository2 = _interopRequireDefault(_modelRepository); var _modelController = require('./model/Controller'); var _modelController2 = _interopRequireDefault(_modelController); var _utilXMLUtils = require('./util/XMLUtils'); var _utilXMLUtils2 = _interopRequireDefault(_utilXMLUtils); var _utilPathUtils = require('./util/PathUtils'); var _utilPathUtils2 = _interopRequireDefault(_utilPathUtils); var _utilLangUtils = require('./util/LangUtils'); var _utilLangUtils2 = _interopRequireDefault(_utilLangUtils); var _utilActivityMonitor = require('./util/ActivityMonitor'); var _utilActivityMonitor2 = _interopRequireDefault(_utilActivityMonitor); /** * This is the main class for launching the whole framework, * with or without a UI. * It can be launched by PydioBootstrap or directly by giving the right parameters. */ var Pydio = (function (_Observable) { _inherits(Pydio, _Observable); /** * Pydio Constructor takes a Map of start parameters. * * @param parameters {Map} */ function Pydio(parameters) { _classCallCheck(this, Pydio); _Observable.call(this); this.Parameters = parameters; this._initLoadRep = parameters.get('initLoadRep') || null; this.usersEnabled = parameters.get('usersEnabled') || null; this.currentLanguage = parameters.get('currentLanguage') || null; this.appTitle = "Pydio"; if (this.Parameters.has("customWording")) { this.appTitle = this.Parameters.get("customWording").title || "Pydio"; } this.user = null; this.MessageHash = {}; if (window.MessageHash) this.MessageHash = window.MessageHash; this.ApiClient = _httpPydioApi2['default'].getClient(); this.ApiClient.setPydioObject(this); this.ActivityMonitor = new _utilActivityMonitor2['default'](this); this.Registry = new _modelRegistry2['default'](this); this._rootNode = new _modelAjxpNode2['default']("/", "Root"); this._dataModel = this._contextHolder = new _modelPydioDataModel2['default'](false); this._dataModel.setAjxpNodeProvider(new _modelRemoteNodeProvider2['default']()); this._dataModel.setRootNode(this._rootNode); // Must happen AFTER datamodel initization. this.Controller = new _modelController2['default'](this); } Pydio.prototype.fire = function fire(eventName, data) { this.notify(eventName, data); }; /** * * @param {User|null} userObject */ Pydio.prototype.updateUser = function updateUser(userObject) { var skipEvent = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; this.user = userObject; if (!skipEvent) { this.notify('user_logged', userObject); } }; /** * * @returns {null|User} */ Pydio.prototype.getUser = function getUser() { return this.user; }; /** * Refresh user/preferences registry part */ Pydio.prototype.refreshUserData = function refreshUserData() { var _this = this; this.observeOnce("registry_part_loaded", function (event) { if (event !== "user/preferences") return; _this.updateUser(_this.Registry.parseUser(), false); }); this.Registry.load("user/preferences"); }; /** * Real initialisation sequence. Will Trigger the whole GUI building. * Event ajaxplorer:loaded is fired at the end. */ Pydio.prototype.init = function init() { var _this2 = this; if (!this.Parameters.has('SECURE_TOKEN')) { _httpPydioApi2['default'].getClient().getBootConf((function () { this.init(); }).bind(this)); return; } this.observe("registry_loaded", function () { _this2.Registry.refreshExtensionsRegistry(); _this2.updateUser(_this2.Registry.parseUser(), false); if (_this2.user) { var repId = _this2.user.getActiveRepository(); var repList = _this2.user.getRepositoriesList(); var repositoryObject = repList.get(repId); if (repositoryObject) repositoryObject.loadResources(); } if (_this2.UI.guiLoaded) { _this2.UI.refreshTemplateParts(); _this2.Registry.refreshExtensionsRegistry(); _this2.Controller.loadActionsFromRegistry(_this2.getXmlRegistry()); } else { _this2.observe("gui_loaded", function () { _this2.UI.refreshTemplateParts(); _this2.Registry.refreshExtensionsRegistry(); _this2.Controller.loadActionsFromRegistry(_this2.getXmlRegistry()); }); } _this2.loadActiveRepository(); if (_this2.Parameters.has("USER_GUI_ACTION")) { (function () { var a = _this2.Parameters.get("USER_GUI_ACTION"); _this2.Parameters['delete']("USER_GUI_ACTION"); setTimeout(function () { _this2.Controller.fireAction(a); }, 1000); })(); } }); var starterFunc = (function () { var _this3 = this; ResourcesManager.loadClassesAndApply(["React", "PydioReactUI"], function () { _this3.UI = new window.PydioReactUI.Builder(_this3); _this3.UI.initTemplates(); _this3.fire("registry_loaded", _this3.Registry.getXML()); setTimeout(function () { _this3.fire('loaded'); }, 200); }); }).bind(this); if (this.Parameters.get("PRELOADED_REGISTRY")) { this.Registry.loadFromString(this.Parameters.get("PRELOADED_REGISTRY")); this.Parameters['delete']("PRELOADED_REGISTRY"); starterFunc(); } else { this.loadXmlRegistry(false, null, starterFunc); } this.observe("server_message", function (xml) { var reload = _utilXMLUtils2['default'].XPathSelectSingleNode(xml, "tree/require_registry_reload"); if (reload) { if (reload.getAttribute("repositoryId") != _this2.repositoryId) { _this2.loadXmlRegistry(false, null, null, reload.getAttribute("repositoryId")); _this2.repositoryId = null; } } }); }; /** * Loads the XML Registry, an image of the application in its current state * sent by the server. * @param sync Boolean Whether to send synchronously or not. * @param xPath String An XPath to load only a subpart of the registry */ Pydio.prototype.loadXmlRegistry = function loadXmlRegistry(sync) { var xPath = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var completeFunc = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; var targetRepositoryId = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3]; this.Registry.load(xPath, completeFunc, targetRepositoryId === null ? Math.random() : targetRepositoryId); }; /** * Get the XML Registry * @returns Document */ Pydio.prototype.getXmlRegistry = function getXmlRegistry() { return this.Registry.getXML(); }; /** * Find the current repository (from the current user) and load it. */ Pydio.prototype.loadActiveRepository = function loadActiveRepository() { var _this4 = this; var repositoryObject = new _modelRepository2['default'](null); if (this.user === null) { this.loadRepository(repositoryObject); this.fire("repository_list_refreshed", { list: false, active: false }); return; } var repId = this.user.getActiveRepository(); var repList = this.user.getRepositoriesList(); repositoryObject = repList.get(repId); if (!repositoryObject) { if (this.user.lock) { (function () { _this4.Controller.loadActionsFromRegistry(_this4.getXmlRegistry()); var lock = _this4.user.lock.split(",").shift(); window.setTimeout(function () { _this4.Controller.fireAction(lock); }, 50); })(); } else { alert("No active repository found for user!"); } return; } if (this.user.getPreference("pending_folder") && this.user.getPreference("pending_folder") != "-1") { this._initLoadRep = this.user.getPreference("pending_folder"); this.user.setPreference("pending_folder", "-1"); this.user.savePreference("pending_folder"); } this.loadRepository(repositoryObject); this.fire("repository_list_refreshed", { list: repList, active: repId }); }; /** * Refresh the repositories list for the current user */ Pydio.prototype.reloadRepositoriesList = function reloadRepositoriesList() { var _this5 = this; if (!this.user) return; this.observeOnce("registry_part_loaded", function (data) { if (data != "user/repositories") return; _this5.updateUser(_this5.Registry.parseUser()); _this5.fire("repository_list_refreshed", { list: _this5.user.getRepositoriesList(), active: _this5.user.getActiveRepository() }); }); this.loadXmlRegistry(false, "user/repositories"); }; /** * Load a Repository instance * @param repository Repository */ Pydio.prototype.loadRepository = function loadRepository(repository) { var _this6 = this; if (this.repositoryId != null && this.repositoryId == repository.getId()) { _langLogger2['default'].debug('Repository already loaded, do nothing'); } this._contextHolder.setSelectedNodes([]); if (repository == null) return; repository.loadResources(); var repositoryId = repository.getId(); var newIcon = repository.getIcon(); var providerDef = repository.getNodeProviderDef(); var rootNode = undefined; if (providerDef != null) { var provider = eval('new ' + providerDef.name + '()'); if (providerDef.options) { provider.initProvider(providerDef.options); } this._contextHolder.setAjxpNodeProvider(provider); rootNode = new _modelAjxpNode2['default']("/", false, repository.getLabel(), newIcon, provider); } else { rootNode = new _modelAjxpNode2['default']("/", false, repository.getLabel(), newIcon); // Default this._contextHolder.setAjxpNodeProvider(new _modelRemoteNodeProvider2['default']()); } var initLoadRep = this._initLoadRep && this._initLoadRep !== '/' ? this._initLoadRep.valueOf() : null; var firstLoadObs = function firstLoadObs() {}; if (initLoadRep) { firstLoadObs = function () { _this6.goTo(initLoadRep); _this6._initLoadRep = null; }; } this._contextHolder.setRootNode(rootNode); rootNode.observeOnce('first_load', (function () { this._contextHolder.notify('context_changed', rootNode); firstLoadObs(); }).bind(this)); this.repositoryId = repositoryId; rootNode.load(); }; /** * Require a context change to the given path * @param nodeOrPath AjxpNode|String A node or a path */ Pydio.prototype.goTo = function goTo(nodeOrPath) { var gotoNode = undefined; var path = undefined; if (typeof nodeOrPath == "string") { path = nodeOrPath; gotoNode = new _modelAjxpNode2['default'](nodeOrPath); } else { gotoNode = nodeOrPath; path = gotoNode.getPath(); if (nodeOrPath.getMetadata().has("repository_id") && nodeOrPath.getMetadata().get("repository_id") != this.repositoryId && nodeOrPath.getAjxpMime() != "repository" && nodeOrPath.getAjxpMime() != "repository_editable") { if (this.user) { this.user.setPreference("pending_folder", nodeOrPath.getPath()); this._initLoadRep = nodeOrPath.getPath(); } this.triggerRepositoryChange(nodeOrPath.getMetadata().get("repository_id")); return; } } if (this._repositoryCurrentlySwitching && this.user) { this.user.setPreference("pending_folder", gotoNode.getPath()); this._initLoadRep = gotoNode.getPath(); return; } var current = this._contextHolder.getContextNode(); if (current && current.getPath() == path) { return; } if (path === "" || path === "/") { this._contextHolder.requireContextChange(this._contextHolder.getRootNode()); return; } else { gotoNode = gotoNode.findInArbo(this._contextHolder.getRootNode()); if (gotoNode) { // Node is already here if (!gotoNode.isBrowsable()) { this._contextHolder.setPendingSelection(_utilPathUtils2['default'].getBasename(path)); this._contextHolder.requireContextChange(gotoNode.getParent()); } else { this._contextHolder.requireContextChange(gotoNode); } } else { // Check on server if it does exist, then load this._contextHolder.loadPathInfoAsync(path, (function (foundNode) { if (!foundNode.isBrowsable()) { this._contextHolder.setPendingSelection(_utilPathUtils2['default'].getBasename(path)); gotoNode = new _modelAjxpNode2['default'](_utilPathUtils2['default'].getDirname(path)); } else { gotoNode = foundNode; } this._contextHolder.requireContextChange(gotoNode); }).bind(this)); } } }; /** * Change the repository of the current user and reload list and current. * @param repositoryId String Id of the new repository */ Pydio.prototype.triggerRepositoryChange = function triggerRepositoryChange(repositoryId, callback) { var _this7 = this; this.fire("trigger_repository_switch"); this._repositoryCurrentlySwitching = true; var onComplete = function onComplete(transport) { if (transport.responseXML) { _this7.ApiClient.parseXmlMessage(transport.responseXML); } _this7.loadXmlRegistry(false, null, null, repositoryId); _this7.repositoryId = null; if (typeof callback == "function") callback(); _this7._repositoryCurrentlySwitching = false; }; var root = this._contextHolder.getRootNode(); if (root) { root.clear(); } this.ApiClient.switchRepository(repositoryId, onComplete); }; Pydio.prototype.getPluginConfigs = function getPluginConfigs(pluginQuery) { return this.Registry.getPluginConfigs(pluginQuery); }; Pydio.prototype.listLanguagesWithCallback = function listLanguagesWithCallback(callback) { var langs = this.Parameters.get("availableLanguages") || { "en": "Default" }; var current = this.currentLanguage; Object.keys(langs).sort().map(function (key) { callback(key, langs[key], current === key); }); }; /** * Reload all messages from server and trigger updateI18nTags * @param newLanguage String * @param callback Function */ Pydio.prototype.loadI18NMessages = function loadI18NMessages(newLanguage) { var callback = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; this.ApiClient.switchLanguage(newLanguage, (function (transport) { if (transport.responseJSON) { this.MessageHash = transport.responseJSON; if (window && window.MessageHash) { window.MessageHash = this.MessageHash; } for (var key in this.MessageHash) { if (this.MessageHash.hasOwnProperty(key)) { this.MessageHash[key] = this.MessageHash[key].replace("\\n", "\n"); } } this.Controller.refreshGuiActionsI18n(); this.loadXmlRegistry(); this.fireContextRefresh(); this.currentLanguage = newLanguage; if (callback) callback(); } }).bind(this)); }; /** * Get the main controller * @returns ActionManager */ Pydio.prototype.getController = function getController() { return this.Controller; }; /** * Display an information or error message to the user * @param messageType String ERROR or SUCCESS * @param message String the message */ Pydio.prototype.displayMessage = function displayMessage(messageType, message) { var urls = _utilLangUtils2['default'].parseUrl(message); if (urls.length && this.user && this.user.repositories) { urls.forEach((function (match) { var repo = this.user.repositories.get(match.host); if (!repo) return; message = message.replace(match.url, repo.label + ":" + match.path + match.file); }).bind(this)); } if (messageType == 'ERROR') _langLogger2['default'].error(message);else _langLogger2['default'].log(message); if (this.UI) { this.UI.displayMessage(messageType, message); } }; /************************************************* * * PROXY METHODS FOR DATAMODEL * ************************************************/ /** * Accessor for updating the datamodel context * @param ajxpContextNode AjxpNode * @param ajxpSelectedNodes AjxpNode[] * @param selectionSource String */ Pydio.prototype.updateContextData = function updateContextData(ajxpContextNode, ajxpSelectedNodes, selectionSource) { if (ajxpContextNode) { this._contextHolder.requireContextChange(ajxpContextNode); } if (ajxpSelectedNodes) { this._contextHolder.setSelectedNodes(ajxpSelectedNodes, selectionSource); } }; /** * @returns AjxpDataModel */ Pydio.prototype.getContextHolder = function getContextHolder() { return this._contextHolder; }; /** * @returns AjxpNode */ Pydio.prototype.getContextNode = function getContextNode() { return this._contextHolder.getContextNode() || new _modelAjxpNode2['default'](""); }; /** * @returns AjxpDataModel */ Pydio.prototype.getUserSelection = function getUserSelection() { return this._contextHolder; }; /** * Accessor for datamodel.requireContextChange() */ Pydio.prototype.fireContextRefresh = function fireContextRefresh() { this.getContextHolder().requireContextChange(this.getContextNode(), true); }; /** * Accessor for datamodel.requireContextChange() */ Pydio.prototype.fireNodeRefresh = function fireNodeRefresh(nodePathOrNode, completeCallback) { this.getContextHolder().requireNodeReload(nodePathOrNode, completeCallback); }; /** * Accessor for datamodel.requireContextChange() */ Pydio.prototype.fireContextUp = function fireContextUp() { if (this.getContextNode().isRoot()) return; this.updateContextData(this.getContextNode().getParent()); }; /** * Proxy to ResourcesManager.requireLib for ease of writing * @param module * @param promise * @returns {*} */ Pydio.requireLib = function requireLib(module) { var promise = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; return require('pydio/http/resources-manager').requireLib(module, promise); }; return Pydio; })(_langObservable2['default']); exports['default'] = Pydio; module.exports = exports['default']; },{"./http/PydioApi":"pydio/http/api","./lang/Logger":"pydio/lang/logger","./lang/Observable":"pydio/lang/observable","./model/AjxpNode":"pydio/model/node","./model/Controller":"pydio/model/controller","./model/PydioDataModel":"pydio/model/data-model","./model/Registry":"pydio/model/registry","./model/RemoteNodeProvider":"pydio/model/remote-node-provider","./model/Repository":"pydio/model/repository","./util/ActivityMonitor":"pydio/util/activity-monitor","./util/LangUtils":"pydio/util/lang","./util/PathUtils":"pydio/util/path","./util/XMLUtils":"pydio/util/xml","pydio/http/resources-manager":"pydio/http/resources-manager"}]},{},[10]) //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9saWIvX2VtcHR5LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYnVmZmVyL25vZGVfbW9kdWxlcy9pc2FycmF5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc3lzdGVtanMvZGlzdC9zeXN0ZW0uc3JjLmpzIiwibm9kZV9tb2R1bGVzL3doYXR3Zy1mZXRjaC9mZXRjaC5qcyIsIm5vZGVfbW9kdWxlcy93aWNrZWQtZ29vZC14cGF0aC9kaXN0L3dneHBhdGguaW5zdGFsbC1ub2RlLmpzIiwicmVzL2J1aWxkL2NvcmUvaW5kZXguanMiLCJyZXMvYnVpbGQvY29yZS9odHRwL1B5ZGlvQXBpLmpzIiwicmVzL2J1aWxkL2NvcmUvaHR0cC9Db25uZXhpb24uanMiLCJyZXMvYnVpbGQvY29yZS9odHRwL01ldGFDYWNoZVNlcnZpY2UuanMiLCJyZXMvYnVpbGQvY29yZS9odHRwL1Jlc291cmNlc01hbmFnZXIuanMiLCJyZXMvYnVpbGQvY29yZS9odHRwL1B5ZGlvVXNlcnNBcGkuanMiLCJyZXMvYnVpbGQvY29yZS9sYW5nL0xvZ2dlci5qcyIsInJlcy9idWlsZC9jb3JlL2xhbmcvT2JzZXJ2YWJsZS5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL0FjdGlvbi5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL0NvbnRleHRNZW51IiwicmVzL2J1aWxkL2NvcmUvbW9kZWwvQ29udHJvbGxlci5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL1B5ZGlvRGF0YU1vZGVsLmpzIiwicmVzL2J1aWxkL2NvcmUvbW9kZWwvRW1wdHlOb2RlUHJvdmlkZXIuanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9BanhwTm9kZS5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL1JlZ2lzdHJ5LmpzIiwicmVzL2J1aWxkL2NvcmUvbW9kZWwvUmVtb3RlTm9kZVByb3ZpZGVyLmpzIiwicmVzL2J1aWxkL2NvcmUvbW9kZWwvUmVwb3NpdG9yeS5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL1VzZXIuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL0FjdGl2aXR5TW9uaXRvci5qcyIsInJlcy9idWlsZC9jb3JlL3V0aWwvQ29va2llc01hbmFnZXIuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL0RPTVV0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9GdW5jVXRpbHMuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL0hhc2hlclV0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9MYW5nVXRpbHMuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL1Bhc3NVdGlscy5qcyIsInJlcy9idWlsZC9jb3JlL3V0aWwvUGF0aFV0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9QZXJpb2RpY2FsRXhlY3V0ZXIuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL1hNTFV0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvUHlkaW8iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVIQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM1Z0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNoNkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ2xkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN2Y0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbk9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM3lCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNubkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3QyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9YQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeFNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdllBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgbG9va3VwID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nO1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuICB2YXIgQXJyID0gKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJylcbiAgICA/IFVpbnQ4QXJyYXlcbiAgICA6IEFycmF5XG5cblx0dmFyIFBMVVMgICA9ICcrJy5jaGFyQ29kZUF0KDApXG5cdHZhciBTTEFTSCAgPSAnLycuY2hhckNvZGVBdCgwKVxuXHR2YXIgTlVNQkVSID0gJzAnLmNoYXJDb2RlQXQoMClcblx0dmFyIExPV0VSICA9ICdhJy5jaGFyQ29kZUF0KDApXG5cdHZhciBVUFBFUiAgPSAnQScuY2hhckNvZGVBdCgwKVxuXHR2YXIgUExVU19VUkxfU0FGRSA9ICctJy5jaGFyQ29kZUF0KDApXG5cdHZhciBTTEFTSF9VUkxfU0FGRSA9ICdfJy5jaGFyQ29kZUF0KDApXG5cblx0ZnVuY3Rpb24gZGVjb2RlIChlbHQpIHtcblx0XHR2YXIgY29kZSA9IGVsdC5jaGFyQ29kZUF0KDApXG5cdFx0aWYgKGNvZGUgPT09IFBMVVMgfHxcblx0XHQgICAgY29kZSA9PT0gUExVU19VUkxfU0FGRSlcblx0XHRcdHJldHVybiA2MiAvLyAnKydcblx0XHRpZiAoY29kZSA9PT0gU0xBU0ggfHxcblx0XHQgICAgY29kZSA9PT0gU0xBU0hfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjMgLy8gJy8nXG5cdFx0aWYgKGNvZGUgPCBOVU1CRVIpXG5cdFx0XHRyZXR1cm4gLTEgLy9ubyBtYXRjaFxuXHRcdGlmIChjb2RlIDwgTlVNQkVSICsgMTApXG5cdFx0XHRyZXR1cm4gY29kZSAtIE5VTUJFUiArIDI2ICsgMjZcblx0XHRpZiAoY29kZSA8IFVQUEVSICsgMjYpXG5cdFx0XHRyZXR1cm4gY29kZSAtIFVQUEVSXG5cdFx0aWYgKGNvZGUgPCBMT1dFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBMT1dFUiArIDI2XG5cdH1cblxuXHRmdW5jdGlvbiBiNjRUb0J5dGVBcnJheSAoYjY0KSB7XG5cdFx0dmFyIGksIGosIGwsIHRtcCwgcGxhY2VIb2xkZXJzLCBhcnJcblxuXHRcdGlmIChiNjQubGVuZ3RoICUgNCA+IDApIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNCcpXG5cdFx0fVxuXG5cdFx0Ly8gdGhlIG51bWJlciBvZiBlcXVhbCBzaWducyAocGxhY2UgaG9sZGVycylcblx0XHQvLyBpZiB0aGVyZSBhcmUgdHdvIHBsYWNlaG9sZGVycywgdGhhbiB0aGUgdHdvIGNoYXJhY3RlcnMgYmVmb3JlIGl0XG5cdFx0Ly8gcmVwcmVzZW50IG9uZSBieXRlXG5cdFx0Ly8gaWYgdGhlcmUgaXMgb25seSBvbmUsIHRoZW4gdGhlIHRocmVlIGNoYXJhY3RlcnMgYmVmb3JlIGl0IHJlcHJlc2VudCAyIGJ5dGVzXG5cdFx0Ly8gdGhpcyBpcyBqdXN0IGEgY2hlYXAgaGFjayB0byBub3QgZG8gaW5kZXhPZiB0d2ljZVxuXHRcdHZhciBsZW4gPSBiNjQubGVuZ3RoXG5cdFx0cGxhY2VIb2xkZXJzID0gJz0nID09PSBiNjQuY2hhckF0KGxlbiAtIDIpID8gMiA6ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAxKSA/IDEgOiAwXG5cblx0XHQvLyBiYXNlNjQgaXMgNC8zICsgdXAgdG8gdHdvIGNoYXJhY3RlcnMgb2YgdGhlIG9yaWdpbmFsIGRhdGFcblx0XHRhcnIgPSBuZXcgQXJyKGI2NC5sZW5ndGggKiAzIC8gNCAtIHBsYWNlSG9sZGVycylcblxuXHRcdC8vIGlmIHRoZXJlIGFyZSBwbGFjZWhvbGRlcnMsIG9ubHkgZ2V0IHVwIHRvIHRoZSBsYXN0IGNvbXBsZXRlIDQgY2hhcnNcblx0XHRsID0gcGxhY2VIb2xkZXJzID4gMCA/IGI2NC5sZW5ndGggLSA0IDogYjY0Lmxlbmd0aFxuXG5cdFx0dmFyIEwgPSAwXG5cblx0XHRmdW5jdGlvbiBwdXNoICh2KSB7XG5cdFx0XHRhcnJbTCsrXSA9IHZcblx0XHR9XG5cblx0XHRmb3IgKGkgPSAwLCBqID0gMDsgaSA8IGw7IGkgKz0gNCwgaiArPSAzKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDE4KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpIDw8IDEyKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpIDw8IDYpIHwgZGVjb2RlKGI2NC5jaGFyQXQoaSArIDMpKVxuXHRcdFx0cHVzaCgodG1wICYgMHhGRjAwMDApID4+IDE2KVxuXHRcdFx0cHVzaCgodG1wICYgMHhGRjAwKSA+PiA4KVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdGlmIChwbGFjZUhvbGRlcnMgPT09IDIpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA+PiA0KVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH0gZWxzZSBpZiAocGxhY2VIb2xkZXJzID09PSAxKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDEwKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpIDw8IDQpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAyKSkgPj4gMilcblx0XHRcdHB1c2goKHRtcCA+PiA4KSAmIDB4RkYpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFyclxuXHR9XG5cblx0ZnVuY3Rpb24gdWludDhUb0Jhc2U2NCAodWludDgpIHtcblx0XHR2YXIgaSxcblx0XHRcdGV4dHJhQnl0ZXMgPSB1aW50OC5sZW5ndGggJSAzLCAvLyBpZiB3ZSBoYXZlIDEgYnl0ZSBsZWZ0LCBwYWQgMiBieXRlc1xuXHRcdFx0b3V0cHV0ID0gXCJcIixcblx0XHRcdHRlbXAsIGxlbmd0aFxuXG5cdFx0ZnVuY3Rpb24gZW5jb2RlIChudW0pIHtcblx0XHRcdHJldHVybiBsb29rdXAuY2hhckF0KG51bSlcblx0XHR9XG5cblx0XHRmdW5jdGlvbiB0cmlwbGV0VG9CYXNlNjQgKG51bSkge1xuXHRcdFx0cmV0dXJuIGVuY29kZShudW0gPj4gMTggJiAweDNGKSArIGVuY29kZShudW0gPj4gMTIgJiAweDNGKSArIGVuY29kZShudW0gPj4gNiAmIDB4M0YpICsgZW5jb2RlKG51bSAmIDB4M0YpXG5cdFx0fVxuXG5cdFx0Ly8gZ28gdGhyb3VnaCB0aGUgYXJyYXkgZXZlcnkgdGhyZWUgYnl0ZXMsIHdlJ2xsIGRlYWwgd2l0aCB0cmFpbGluZyBzdHVmZiBsYXRlclxuXHRcdGZvciAoaSA9IDAsIGxlbmd0aCA9IHVpbnQ4Lmxlbmd0aCAtIGV4dHJhQnl0ZXM7IGkgPCBsZW5ndGg7IGkgKz0gMykge1xuXHRcdFx0dGVtcCA9ICh1aW50OFtpXSA8PCAxNikgKyAodWludDhbaSArIDFdIDw8IDgpICsgKHVpbnQ4W2kgKyAyXSlcblx0XHRcdG91dHB1dCArPSB0cmlwbGV0VG9CYXNlNjQodGVtcClcblx0XHR9XG5cblx0XHQvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG5cdFx0c3dpdGNoIChleHRyYUJ5dGVzKSB7XG5cdFx0XHRjYXNlIDE6XG5cdFx0XHRcdHRlbXAgPSB1aW50OFt1aW50OC5sZW5ndGggLSAxXVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMilcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA8PCA0KSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSAnPT0nXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlIDI6XG5cdFx0XHRcdHRlbXAgPSAodWludDhbdWludDgubGVuZ3RoIC0gMl0gPDwgOCkgKyAodWludDhbdWludDgubGVuZ3RoIC0gMV0pXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUodGVtcCA+PiAxMClcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA+PiA0KSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgMikgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz0nXG5cdFx0XHRcdGJyZWFrXG5cdFx0fVxuXG5cdFx0cmV0dXJuIG91dHB1dFxuXHR9XG5cblx0ZXhwb3J0cy50b0J5dGVBcnJheSA9IGI2NFRvQnl0ZUFycmF5XG5cdGV4cG9ydHMuZnJvbUJ5dGVBcnJheSA9IHVpbnQ4VG9CYXNlNjRcbn0odHlwZW9mIGV4cG9ydHMgPT09ICd1bmRlZmluZWQnID8gKHRoaXMuYmFzZTY0anMgPSB7fSkgOiBleHBvcnRzKSlcbiIsbnVsbCwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzYXJyYXknKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gU2xvd0J1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5CdWZmZXIucG9vbFNpemUgPSA4MTkyIC8vIG5vdCB1c2VkIGJ5IHRoaXMgaW1wbGVtZW50YXRpb25cblxudmFyIHJvb3RQYXJlbnQgPSB7fVxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBEdWUgdG8gdmFyaW91cyBicm93c2VyIGJ1Z3MsIHNvbWV0aW1lcyB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uIHdpbGwgYmUgdXNlZCBldmVuXG4gKiB3aGVuIHRoZSBicm93c2VyIHN1cHBvcnRzIHR5cGVkIGFycmF5cy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqICAgLSBGaXJlZm94IDQtMjkgbGFja3Mgc3VwcG9ydCBmb3IgYWRkaW5nIG5ldyBwcm9wZXJ0aWVzIHRvIGBVaW50OEFycmF5YCBpbnN0YW5jZXMsXG4gKiAgICAgU2VlOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzguXG4gKlxuICogICAtIFNhZmFyaSA1LTcgbGFja3Mgc3VwcG9ydCBmb3IgY2hhbmdpbmcgdGhlIGBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yYCBwcm9wZXJ0eVxuICogICAgIG9uIG9iamVjdHMuXG4gKlxuICogICAtIENocm9tZSA5LTEwIGlzIG1pc3NpbmcgdGhlIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24uXG4gKlxuICogICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgICBpbmNvcnJlY3QgbGVuZ3RoIGluIHNvbWUgc2l0dWF0aW9ucy5cblxuICogV2UgZGV0ZWN0IHRoZXNlIGJ1Z2d5IGJyb3dzZXJzIGFuZCBzZXQgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYCB0byBgZmFsc2VgIHNvIHRoZXlcbiAqIGdldCB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyBzbG93ZXIgYnV0IGJlaGF2ZXMgY29ycmVjdGx5LlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IGdsb2JhbC5UWVBFRF9BUlJBWV9TVVBQT1JUICE9PSB1bmRlZmluZWRcbiAgPyBnbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVFxuICA6IHR5cGVkQXJyYXlTdXBwb3J0KClcblxuZnVuY3Rpb24gdHlwZWRBcnJheVN1cHBvcnQgKCkge1xuICBmdW5jdGlvbiBCYXIgKCkge31cbiAgdHJ5IHtcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoMSlcbiAgICBhcnIuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfVxuICAgIGFyci5jb25zdHJ1Y3RvciA9IEJhclxuICAgIHJldHVybiBhcnIuZm9vKCkgPT09IDQyICYmIC8vIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkXG4gICAgICAgIGFyci5jb25zdHJ1Y3RvciA9PT0gQmFyICYmIC8vIGNvbnN0cnVjdG9yIGNhbiBiZSBzZXRcbiAgICAgICAgdHlwZW9mIGFyci5zdWJhcnJheSA9PT0gJ2Z1bmN0aW9uJyAmJiAvLyBjaHJvbWUgOS0xMCBsYWNrIGBzdWJhcnJheWBcbiAgICAgICAgYXJyLnN1YmFycmF5KDEsIDEpLmJ5dGVMZW5ndGggPT09IDAgLy8gaWUxMCBoYXMgYnJva2VuIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIGtNYXhMZW5ndGggKCkge1xuICByZXR1cm4gQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgICA/IDB4N2ZmZmZmZmZcbiAgICA6IDB4M2ZmZmZmZmZcbn1cblxuLyoqXG4gKiBDbGFzczogQnVmZmVyXG4gKiA9PT09PT09PT09PT09XG4gKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBhcmUgYXVnbWVudGVkXG4gKiB3aXRoIGZ1bmN0aW9uIHByb3BlcnRpZXMgZm9yIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBBUEkgZnVuY3Rpb25zLiBXZSB1c2VcbiAqIGBVaW50OEFycmF5YCBzbyB0aGF0IHNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0IHJldHVybnNcbiAqIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIEJ5IGF1Z21lbnRpbmcgdGhlIGluc3RhbmNlcywgd2UgY2FuIGF2b2lkIG1vZGlmeWluZyB0aGUgYFVpbnQ4QXJyYXlgXG4gKiBwcm90b3R5cGUuXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlciAoYXJnKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBCdWZmZXIpKSB7XG4gICAgLy8gQXZvaWQgZ29pbmcgdGhyb3VnaCBhbiBBcmd1bWVudHNBZGFwdG9yVHJhbXBvbGluZSBpbiB0aGUgY29tbW9uIGNhc2UuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSByZXR1cm4gbmV3IEJ1ZmZlcihhcmcsIGFyZ3VtZW50c1sxXSlcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcihhcmcpXG4gIH1cblxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpcy5sZW5ndGggPSAwXG4gICAgdGhpcy5wYXJlbnQgPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gZnJvbU51bWJlcih0aGlzLCBhcmcpXG4gIH1cblxuICAvLyBTbGlnaHRseSBsZXNzIGNvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh0aGlzLCBhcmcsIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogJ3V0ZjgnKVxuICB9XG5cbiAgLy8gVW51c3VhbC5cbiAgcmV0dXJuIGZyb21PYmplY3QodGhpcywgYXJnKVxufVxuXG5mdW5jdGlvbiBmcm9tTnVtYmVyICh0aGF0LCBsZW5ndGgpIHtcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChsZW5ndGgpIHwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoYXRbaV0gPSAwXG4gICAgfVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcgKHRoYXQsIHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycgfHwgZW5jb2RpbmcgPT09ICcnKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIC8vIEFzc3VtcHRpb246IGJ5dGVMZW5ndGgoKSByZXR1cm4gdmFsdWUgaXMgYWx3YXlzIDwga01heExlbmd0aC5cbiAgdmFyIGxlbmd0aCA9IGJ5dGVMZW5ndGgoc3RyaW5nLCBlbmNvZGluZykgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG5cbiAgdGhhdC53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmplY3QpKSByZXR1cm4gZnJvbUJ1ZmZlcih0aGF0LCBvYmplY3QpXG5cbiAgaWYgKGlzQXJyYXkob2JqZWN0KSkgcmV0dXJuIGZyb21BcnJheSh0aGF0LCBvYmplY3QpXG5cbiAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVzdCBzdGFydCB3aXRoIG51bWJlciwgYnVmZmVyLCBhcnJheSBvciBzdHJpbmcnKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAob2JqZWN0LmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gZnJvbVR5cGVkQXJyYXkodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgfVxuXG4gIGlmIChvYmplY3QubGVuZ3RoKSByZXR1cm4gZnJvbUFycmF5TGlrZSh0aGF0LCBvYmplY3QpXG5cbiAgcmV0dXJuIGZyb21Kc29uT2JqZWN0KHRoYXQsIG9iamVjdClcbn1cblxuZnVuY3Rpb24gZnJvbUJ1ZmZlciAodGhhdCwgYnVmZmVyKSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGJ1ZmZlci5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBidWZmZXIuY29weSh0aGF0LCAwLCAwLCBsZW5ndGgpXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbi8vIER1cGxpY2F0ZSBvZiBmcm9tQXJyYXkoKSB0byBrZWVwIGZyb21BcnJheSgpIG1vbm9tb3JwaGljLlxuZnVuY3Rpb24gZnJvbVR5cGVkQXJyYXkgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIC8vIFRydW5jYXRpbmcgdGhlIGVsZW1lbnRzIGlzIHByb2JhYmx5IG5vdCB3aGF0IHBlb3BsZSBleHBlY3QgZnJvbSB0eXBlZFxuICAvLyBhcnJheXMgd2l0aCBCWVRFU19QRVJfRUxFTUVOVCA+IDEgYnV0IGl0J3MgY29tcGF0aWJsZSB3aXRoIHRoZSBiZWhhdmlvclxuICAvLyBvZiB0aGUgb2xkIEJ1ZmZlciBjb25zdHJ1Y3Rvci5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAodGhhdCwgYXJyYXkpIHtcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgYXJyYXkuYnl0ZUxlbmd0aFxuICAgIHRoYXQgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0ID0gZnJvbVR5cGVkQXJyYXkodGhhdCwgbmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG4vLyBEZXNlcmlhbGl6ZSB7IHR5cGU6ICdCdWZmZXInLCBkYXRhOiBbMSwyLDMsLi4uXSB9IGludG8gYSBCdWZmZXIgb2JqZWN0LlxuLy8gUmV0dXJucyBhIHplcm8tbGVuZ3RoIGJ1ZmZlciBmb3IgaW5wdXRzIHRoYXQgZG9uJ3QgY29uZm9ybSB0byB0aGUgc3BlYy5cbmZ1bmN0aW9uIGZyb21Kc29uT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgdmFyIGFycmF5XG4gIHZhciBsZW5ndGggPSAwXG5cbiAgaWYgKG9iamVjdC50eXBlID09PSAnQnVmZmVyJyAmJiBpc0FycmF5KG9iamVjdC5kYXRhKSkge1xuICAgIGFycmF5ID0gb2JqZWN0LmRhdGFcbiAgICBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIH1cbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gIEJ1ZmZlci5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGVcbiAgQnVmZmVyLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXlcbn0gZWxzZSB7XG4gIC8vIHByZS1zZXQgZm9yIHZhbHVlcyB0aGF0IG1heSBleGlzdCBpbiB0aGUgZnV0dXJlXG4gIEJ1ZmZlci5wcm90b3R5cGUubGVuZ3RoID0gdW5kZWZpbmVkXG4gIEJ1ZmZlci5wcm90b3R5cGUucGFyZW50ID0gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGFsbG9jYXRlICh0aGF0LCBsZW5ndGgpIHtcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgdGhhdCA9IEJ1ZmZlci5fYXVnbWVudChuZXcgVWludDhBcnJheShsZW5ndGgpKVxuICAgIHRoYXQuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0Lmxlbmd0aCA9IGxlbmd0aFxuICAgIHRoYXQuX2lzQnVmZmVyID0gdHJ1ZVxuICB9XG5cbiAgdmFyIGZyb21Qb29sID0gbGVuZ3RoICE9PSAwICYmIGxlbmd0aCA8PSBCdWZmZXIucG9vbFNpemUgPj4+IDFcbiAgaWYgKGZyb21Qb29sKSB0aGF0LnBhcmVudCA9IHJvb3RQYXJlbnRcblxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwga01heExlbmd0aGAgaGVyZSBiZWNhdXNlIHRoYXQgZmFpbHMgd2hlblxuICAvLyBsZW5ndGggaXMgTmFOICh3aGljaCBpcyBvdGhlcndpc2UgY29lcmNlZCB0byB6ZXJvLilcbiAgaWYgKGxlbmd0aCA+PSBrTWF4TGVuZ3RoKCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZTogMHgnICsga01heExlbmd0aCgpLnRvU3RyaW5nKDE2KSArICcgYnl0ZXMnKVxuICB9XG4gIHJldHVybiBsZW5ndGggfCAwXG59XG5cbmZ1bmN0aW9uIFNsb3dCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTbG93QnVmZmVyKSkgcmV0dXJuIG5ldyBTbG93QnVmZmVyKHN1YmplY3QsIGVuY29kaW5nKVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKHN1YmplY3QsIGVuY29kaW5nKVxuICBkZWxldGUgYnVmLnBhcmVudFxuICByZXR1cm4gYnVmXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAoYSwgYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnRzIG11c3QgYmUgQnVmZmVycycpXG4gIH1cblxuICBpZiAoYSA9PT0gYikgcmV0dXJuIDBcblxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcblxuICB2YXIgaSA9IDBcbiAgdmFyIGxlbiA9IE1hdGgubWluKHgsIHkpXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIGJyZWFrXG5cbiAgICArK2lcbiAgfVxuXG4gIGlmIChpICE9PSBsZW4pIHtcbiAgICB4ID0gYVtpXVxuICAgIHkgPSBiW2ldXG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIWlzQXJyYXkobGlzdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3QgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzLicpXG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoMClcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGxlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgbGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKVxuICB2YXIgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBpdGVtID0gbGlzdFtpXVxuICAgIGl0ZW0uY29weShidWYsIHBvcylcbiAgICBwb3MgKz0gaXRlbS5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSBzdHJpbmcgPSAnJyArIHN0cmluZ1xuXG4gIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChsZW4gPT09IDApIHJldHVybiAwXG5cbiAgLy8gVXNlIGEgZm9yIGxvb3AgdG8gYXZvaWQgcmVjdXJzaW9uXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgLy8gRGVwcmVjYXRlZFxuICAgICAgY2FzZSAncmF3JzpcbiAgICAgIGNhc2UgJ3Jhd3MnOlxuICAgICAgICByZXR1cm4gbGVuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gbGVuICogMlxuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGxlbiA+Pj4gMVxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoIC8vIGFzc3VtZSB1dGY4XG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcblxuZnVuY3Rpb24gc2xvd1RvU3RyaW5nIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIHN0YXJ0ID0gc3RhcnQgfCAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA9PT0gSW5maW5pdHkgPyB0aGlzLmxlbmd0aCA6IGVuZCB8IDBcblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAoZW5kIDw9IHN0YXJ0KSByZXR1cm4gJydcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBiaW5hcnlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHV0ZjE2bGVTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoIHwgMFxuICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gJydcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1dGY4U2xpY2UodGhpcywgMCwgbGVuZ3RoKVxuICByZXR1cm4gc2xvd1RvU3RyaW5nLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIHRydWVcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpID09PSAwXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkubWF0Y2goLy57Mn0vZykuam9pbignICcpXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KSBzdHIgKz0gJyAuLi4gJ1xuICB9XG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIDBcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5kZXhPZiA9IGZ1bmN0aW9uIGluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCkge1xuICBpZiAoYnl0ZU9mZnNldCA+IDB4N2ZmZmZmZmYpIGJ5dGVPZmZzZXQgPSAweDdmZmZmZmZmXG4gIGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAtMHg4MDAwMDAwMCkgYnl0ZU9mZnNldCA9IC0weDgwMDAwMDAwXG4gIGJ5dGVPZmZzZXQgPj49IDBcblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiAtMVxuICBpZiAoYnl0ZU9mZnNldCA+PSB0aGlzLmxlbmd0aCkgcmV0dXJuIC0xXG5cbiAgLy8gTmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBNYXRoLm1heCh0aGlzLmxlbmd0aCArIGJ5dGVPZmZzZXQsIDApXG5cbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDApIHJldHVybiAtMSAvLyBzcGVjaWFsIGNhc2U6IGxvb2tpbmcgZm9yIGVtcHR5IHN0cmluZyBhbHdheXMgZmFpbHNcbiAgICByZXR1cm4gU3RyaW5nLnByb3RvdHlwZS5pbmRleE9mLmNhbGwodGhpcywgdmFsLCBieXRlT2Zmc2V0KVxuICB9XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIHJldHVybiBhcnJheUluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0KVxuICB9XG4gIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZih0aGlzLCBbIHZhbCBdLCBieXRlT2Zmc2V0KVxuICB9XG5cbiAgZnVuY3Rpb24gYXJyYXlJbmRleE9mIChhcnIsIHZhbCwgYnl0ZU9mZnNldCkge1xuICAgIHZhciBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKHZhciBpID0gMDsgYnl0ZU9mZnNldCArIGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChhcnJbYnl0ZU9mZnNldCArIGldID09PSB2YWxbZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXhdKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsLmxlbmd0aCkgcmV0dXJuIGJ5dGVPZmZzZXQgKyBmb3VuZEluZGV4XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3VuZEluZGV4ID0gLTFcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG4vLyBgZ2V0YCBpcyBkZXByZWNhdGVkXG5CdWZmZXIucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIGdldCAob2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuZ2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy5yZWFkVUludDgob2Zmc2V0KVxufVxuXG4vLyBgc2V0YCBpcyBkZXByZWNhdGVkXG5CdWZmZXIucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIHNldCAodiwgb2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuc2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy53cml0ZVVJbnQ4KHYsIG9mZnNldClcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICAvLyBtdXN0IGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGRpZ2l0c1xuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAoc3RyTGVuICUgMiAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGlmIChpc05hTihwYXJzZWQpKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGV4IHN0cmluZycpXG4gICAgYnVmW29mZnNldCArIGldID0gcGFyc2VkXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiaW5hcnlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBhc2NpaVdyaXRlKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmFzZTY0V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihiYXNlNjRUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIHVjczJXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjE2bGVUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiB3cml0ZSAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZylcbiAgaWYgKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5jb2RpbmcgPSAndXRmOCdcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgZW5jb2RpbmcpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBvZmZzZXRbLCBsZW5ndGhdWywgZW5jb2RpbmddKVxuICB9IGVsc2UgaWYgKGlzRmluaXRlKG9mZnNldCkpIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCB8IDBcbiAgICAgIGlmIChlbmNvZGluZyA9PT0gdW5kZWZpbmVkKSBlbmNvZGluZyA9ICd1dGY4J1xuICAgIH0gZWxzZSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICAvLyBsZWdhY3kgd3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0LCBsZW5ndGgpIC0gcmVtb3ZlIGluIHYwLjEzXG4gIH0gZWxzZSB7XG4gICAgdmFyIHN3YXAgPSBlbmNvZGluZ1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgb2Zmc2V0ID0gbGVuZ3RoIHwgMFxuICAgIGxlbmd0aCA9IHN3YXBcbiAgfVxuXG4gIHZhciByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdhdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgLy8gV2FybmluZzogbWF4TGVuZ3RoIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgaW4gYmFzZTY0V3JpdGVcbiAgICAgICAgcmV0dXJuIGJhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1Y3MyV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuICB2YXIgcmVzID0gW11cblxuICB2YXIgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgdmFyIGZpcnN0Qnl0ZSA9IGJ1ZltpXVxuICAgIHZhciBjb2RlUG9pbnQgPSBudWxsXG4gICAgdmFyIGJ5dGVzUGVyU2VxdWVuY2UgPSAoZmlyc3RCeXRlID4gMHhFRikgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKSA/IDNcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpID8gMlxuICAgICAgOiAxXG5cbiAgICBpZiAoaSArIGJ5dGVzUGVyU2VxdWVuY2UgPD0gZW5kKSB7XG4gICAgICB2YXIgc2Vjb25kQnl0ZSwgdGhpcmRCeXRlLCBmb3VydGhCeXRlLCB0ZW1wQ29kZVBvaW50XG5cbiAgICAgIHN3aXRjaCAoYnl0ZXNQZXJTZXF1ZW5jZSkge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA8IDB4ODApIHtcbiAgICAgICAgICAgIGNvZGVQb2ludCA9IGZpcnN0Qnl0ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweDFGKSA8PCAweDYgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0YpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHhDIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAodGhpcmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3RkYgJiYgKHRlbXBDb2RlUG9pbnQgPCAweEQ4MDAgfHwgdGVtcENvZGVQb2ludCA+IDB4REZGRikpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgZm91cnRoQnl0ZSA9IGJ1ZltpICsgM11cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKGZvdXJ0aEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4MTIgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4QyB8ICh0aGlyZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAoZm91cnRoQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4RkZGRiAmJiB0ZW1wQ29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY29kZVBvaW50ID09PSBudWxsKSB7XG4gICAgICAvLyB3ZSBkaWQgbm90IGdlbmVyYXRlIGEgdmFsaWQgY29kZVBvaW50IHNvIGluc2VydCBhXG4gICAgICAvLyByZXBsYWNlbWVudCBjaGFyIChVK0ZGRkQpIGFuZCBhZHZhbmNlIG9ubHkgMSBieXRlXG4gICAgICBjb2RlUG9pbnQgPSAweEZGRkRcbiAgICAgIGJ5dGVzUGVyU2VxdWVuY2UgPSAxXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPiAweEZGRkYpIHtcbiAgICAgIC8vIGVuY29kZSB0byB1dGYxNiAoc3Vycm9nYXRlIHBhaXIgZGFuY2UpXG4gICAgICBjb2RlUG9pbnQgLT0gMHgxMDAwMFxuICAgICAgcmVzLnB1c2goY29kZVBvaW50ID4+PiAxMCAmIDB4M0ZGIHwgMHhEODAwKVxuICAgICAgY29kZVBvaW50ID0gMHhEQzAwIHwgY29kZVBvaW50ICYgMHgzRkZcbiAgICB9XG5cbiAgICByZXMucHVzaChjb2RlUG9pbnQpXG4gICAgaSArPSBieXRlc1BlclNlcXVlbmNlXG4gIH1cblxuICByZXR1cm4gZGVjb2RlQ29kZVBvaW50c0FycmF5KHJlcylcbn1cblxuLy8gQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjI3NDcyNzIvNjgwNzQyLCB0aGUgYnJvd3NlciB3aXRoXG4vLyB0aGUgbG93ZXN0IGxpbWl0IGlzIENocm9tZSwgd2l0aCAweDEwMDAwIGFyZ3MuXG4vLyBXZSBnbyAxIG1hZ25pdHVkZSBsZXNzLCBmb3Igc2FmZXR5XG52YXIgTUFYX0FSR1VNRU5UU19MRU5HVEggPSAweDEwMDBcblxuZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5IChjb2RlUG9pbnRzKSB7XG4gIHZhciBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIHZhciByZXMgPSAnJ1xuICB2YXIgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBiaW5hcnlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSArIDFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWZcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgbmV3QnVmID0gQnVmZmVyLl9hdWdtZW50KHRoaXMuc3ViYXJyYXkoc3RhcnQsIGVuZCkpXG4gIH0gZWxzZSB7XG4gICAgdmFyIHNsaWNlTGVuID0gZW5kIC0gc3RhcnRcbiAgICBuZXdCdWYgPSBuZXcgQnVmZmVyKHNsaWNlTGVuLCB1bmRlZmluZWQpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGljZUxlbjsgaSsrKSB7XG4gICAgICBuZXdCdWZbaV0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH1cblxuICBpZiAobmV3QnVmLmxlbmd0aCkgbmV3QnVmLnBhcmVudCA9IHRoaXMucGFyZW50IHx8IHRoaXNcblxuICByZXR1cm4gbmV3QnVmXG59XG5cbi8qXG4gKiBOZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGJ1ZmZlciBpc24ndCB0cnlpbmcgdG8gd3JpdGUgb3V0IG9mIGJvdW5kcy5cbiAqL1xuZnVuY3Rpb24gY2hlY2tPZmZzZXQgKG9mZnNldCwgZXh0LCBsZW5ndGgpIHtcbiAgaWYgKChvZmZzZXQgJSAxKSAhPT0gMCB8fCBvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb2Zmc2V0IGlzIG5vdCB1aW50JylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50TEUgPSBmdW5jdGlvbiByZWFkVUludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuICB9XG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXVxuICB2YXIgbXVsID0gMVxuICB3aGlsZSAoYnl0ZUxlbmd0aCA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gcmVhZFVJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiByZWFkVUludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDgpIHwgdGhpc1tvZmZzZXQgKyAxXVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAoKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpKSArXG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSAqIDB4MTAwMDAwMClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiByZWFkVUludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIHJlYWRJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aFxuICB2YXIgbXVsID0gMVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWldXG4gIHdoaWxlIChpID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0taV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gcmVhZEludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgaWYgKCEodGhpc1tvZmZzZXRdICYgMHg4MCkpIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiByZWFkSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAxXSB8ICh0aGlzW29mZnNldF0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gcmVhZEludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24gcmVhZEZsb2F0QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiByZWFkRG91YmxlTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDUyLCA4KVxufVxuXG5mdW5jdGlvbiBjaGVja0ludCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2J1ZmZlciBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndmFsdWUgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlVUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCksIDApXG5cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlVUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCksIDApXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVVSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweGZmLCAwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDE2IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZiArIHZhbHVlICsgMVxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGJ1Zi5sZW5ndGggLSBvZmZzZXQsIDIpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID0gKHZhbHVlICYgKDB4ZmYgPDwgKDggKiAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSkpKSA+Pj5cbiAgICAgIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpICogOFxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCA0KTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSA+Pj4gKGxpdHRsZUVuZGlhbiA/IGkgOiAzIC0gaSkgKiA4KSAmIDB4ZmZcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBsaW1pdCA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgdmFyIGkgPSAwXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiB3cml0ZUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IHZhbHVlIDwgMCA/IDEgOiAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuZnVuY3Rpb24gd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA0LCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA4LCAxLjc5NzY5MzEzNDg2MjMxNTdFKzMwOCwgLTEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxuICByZXR1cm4gb2Zmc2V0ICsgOFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVCRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbi8vIGNvcHkodGFyZ2V0QnVmZmVyLCB0YXJnZXRTdGFydD0wLCBzb3VyY2VTdGFydD0wLCBzb3VyY2VFbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuY29weSA9IGZ1bmN0aW9uIGNvcHkgKHRhcmdldCwgdGFyZ2V0U3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kICYmIGVuZCAhPT0gMCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldFN0YXJ0ID49IHRhcmdldC5sZW5ndGgpIHRhcmdldFN0YXJ0ID0gdGFyZ2V0Lmxlbmd0aFxuICBpZiAoIXRhcmdldFN0YXJ0KSB0YXJnZXRTdGFydCA9IDBcbiAgaWYgKGVuZCA+IDAgJiYgZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm4gMFxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCB0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBGYXRhbCBlcnJvciBjb25kaXRpb25zXG4gIGlmICh0YXJnZXRTdGFydCA8IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIH1cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgPCBlbmQgLSBzdGFydCkge1xuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCArIHN0YXJ0XG4gIH1cblxuICB2YXIgbGVuID0gZW5kIC0gc3RhcnRcbiAgdmFyIGlcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0ICYmIHN0YXJ0IDwgdGFyZ2V0U3RhcnQgJiYgdGFyZ2V0U3RhcnQgPCBlbmQpIHtcbiAgICAvLyBkZXNjZW5kaW5nIGNvcHkgZnJvbSBlbmRcbiAgICBmb3IgKGkgPSBsZW4gLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSBpZiAobGVuIDwgMTAwMCB8fCAhQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBhc2NlbmRpbmcgY29weSBmcm9tIHN0YXJ0XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0YXJnZXQuX3NldCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksIHRhcmdldFN0YXJ0KVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBmaWxsKHZhbHVlLCBzdGFydD0wLCBlbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gIGlmICghdmFsdWUpIHZhbHVlID0gMFxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQpIGVuZCA9IHRoaXMubGVuZ3RoXG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignZW5kIDwgc3RhcnQnKVxuXG4gIC8vIEZpbGwgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBzdGFydCA+PSB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3N0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoZW5kIDwgMCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCBvdXQgb2YgYm91bmRzJylcblxuICB2YXIgaVxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIHRoaXNbaV0gPSB2YWx1ZVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSB1dGY4VG9CeXRlcyh2YWx1ZS50b1N0cmluZygpKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgYEFycmF5QnVmZmVyYCB3aXRoIHRoZSAqY29waWVkKiBtZW1vcnkgb2YgdGhlIGJ1ZmZlciBpbnN0YW5jZS5cbiAqIEFkZGVkIGluIE5vZGUgMC4xMi4gT25seSBhdmFpbGFibGUgaW4gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IEFycmF5QnVmZmVyLlxuICovXG5CdWZmZXIucHJvdG90eXBlLnRvQXJyYXlCdWZmZXIgPSBmdW5jdGlvbiB0b0FycmF5QnVmZmVyICgpIHtcbiAgaWYgKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgICAgcmV0dXJuIChuZXcgQnVmZmVyKHRoaXMpKS5idWZmZXJcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KHRoaXMubGVuZ3RoKVxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGJ1Zi5sZW5ndGg7IGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICBidWZbaV0gPSB0aGlzW2ldXG4gICAgICB9XG4gICAgICByZXR1cm4gYnVmLmJ1ZmZlclxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCdWZmZXIudG9BcnJheUJ1ZmZlciBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlcicpXG4gIH1cbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG52YXIgQlAgPSBCdWZmZXIucHJvdG90eXBlXG5cbi8qKlxuICogQXVnbWVudCBhIFVpbnQ4QXJyYXkgKmluc3RhbmNlKiAobm90IHRoZSBVaW50OEFycmF5IGNsYXNzISkgd2l0aCBCdWZmZXIgbWV0aG9kc1xuICovXG5CdWZmZXIuX2F1Z21lbnQgPSBmdW5jdGlvbiBfYXVnbWVudCAoYXJyKSB7XG4gIGFyci5jb25zdHJ1Y3RvciA9IEJ1ZmZlclxuICBhcnIuX2lzQnVmZmVyID0gdHJ1ZVxuXG4gIC8vIHNhdmUgcmVmZXJlbmNlIHRvIG9yaWdpbmFsIFVpbnQ4QXJyYXkgc2V0IG1ldGhvZCBiZWZvcmUgb3ZlcndyaXRpbmdcbiAgYXJyLl9zZXQgPSBhcnIuc2V0XG5cbiAgLy8gZGVwcmVjYXRlZFxuICBhcnIuZ2V0ID0gQlAuZ2V0XG4gIGFyci5zZXQgPSBCUC5zZXRcblxuICBhcnIud3JpdGUgPSBCUC53cml0ZVxuICBhcnIudG9TdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9Mb2NhbGVTdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9KU09OID0gQlAudG9KU09OXG4gIGFyci5lcXVhbHMgPSBCUC5lcXVhbHNcbiAgYXJyLmNvbXBhcmUgPSBCUC5jb21wYXJlXG4gIGFyci5pbmRleE9mID0gQlAuaW5kZXhPZlxuICBhcnIuY29weSA9IEJQLmNvcHlcbiAgYXJyLnNsaWNlID0gQlAuc2xpY2VcbiAgYXJyLnJlYWRVSW50TEUgPSBCUC5yZWFkVUludExFXG4gIGFyci5yZWFkVUludEJFID0gQlAucmVhZFVJbnRCRVxuICBhcnIucmVhZFVJbnQ4ID0gQlAucmVhZFVJbnQ4XG4gIGFyci5yZWFkVUludDE2TEUgPSBCUC5yZWFkVUludDE2TEVcbiAgYXJyLnJlYWRVSW50MTZCRSA9IEJQLnJlYWRVSW50MTZCRVxuICBhcnIucmVhZFVJbnQzMkxFID0gQlAucmVhZFVJbnQzMkxFXG4gIGFyci5yZWFkVUludDMyQkUgPSBCUC5yZWFkVUludDMyQkVcbiAgYXJyLnJlYWRJbnRMRSA9IEJQLnJlYWRJbnRMRVxuICBhcnIucmVhZEludEJFID0gQlAucmVhZEludEJFXG4gIGFyci5yZWFkSW50OCA9IEJQLnJlYWRJbnQ4XG4gIGFyci5yZWFkSW50MTZMRSA9IEJQLnJlYWRJbnQxNkxFXG4gIGFyci5yZWFkSW50MTZCRSA9IEJQLnJlYWRJbnQxNkJFXG4gIGFyci5yZWFkSW50MzJMRSA9IEJQLnJlYWRJbnQzMkxFXG4gIGFyci5yZWFkSW50MzJCRSA9IEJQLnJlYWRJbnQzMkJFXG4gIGFyci5yZWFkRmxvYXRMRSA9IEJQLnJlYWRGbG9hdExFXG4gIGFyci5yZWFkRmxvYXRCRSA9IEJQLnJlYWRGbG9hdEJFXG4gIGFyci5yZWFkRG91YmxlTEUgPSBCUC5yZWFkRG91YmxlTEVcbiAgYXJyLnJlYWREb3VibGVCRSA9IEJQLnJlYWREb3VibGVCRVxuICBhcnIud3JpdGVVSW50OCA9IEJQLndyaXRlVUludDhcbiAgYXJyLndyaXRlVUludExFID0gQlAud3JpdGVVSW50TEVcbiAgYXJyLndyaXRlVUludEJFID0gQlAud3JpdGVVSW50QkVcbiAgYXJyLndyaXRlVUludDE2TEUgPSBCUC53cml0ZVVJbnQxNkxFXG4gIGFyci53cml0ZVVJbnQxNkJFID0gQlAud3JpdGVVSW50MTZCRVxuICBhcnIud3JpdGVVSW50MzJMRSA9IEJQLndyaXRlVUludDMyTEVcbiAgYXJyLndyaXRlVUludDMyQkUgPSBCUC53cml0ZVVJbnQzMkJFXG4gIGFyci53cml0ZUludExFID0gQlAud3JpdGVJbnRMRVxuICBhcnIud3JpdGVJbnRCRSA9IEJQLndyaXRlSW50QkVcbiAgYXJyLndyaXRlSW50OCA9IEJQLndyaXRlSW50OFxuICBhcnIud3JpdGVJbnQxNkxFID0gQlAud3JpdGVJbnQxNkxFXG4gIGFyci53cml0ZUludDE2QkUgPSBCUC53cml0ZUludDE2QkVcbiAgYXJyLndyaXRlSW50MzJMRSA9IEJQLndyaXRlSW50MzJMRVxuICBhcnIud3JpdGVJbnQzMkJFID0gQlAud3JpdGVJbnQzMkJFXG4gIGFyci53cml0ZUZsb2F0TEUgPSBCUC53cml0ZUZsb2F0TEVcbiAgYXJyLndyaXRlRmxvYXRCRSA9IEJQLndyaXRlRmxvYXRCRVxuICBhcnIud3JpdGVEb3VibGVMRSA9IEJQLndyaXRlRG91YmxlTEVcbiAgYXJyLndyaXRlRG91YmxlQkUgPSBCUC53cml0ZURvdWJsZUJFXG4gIGFyci5maWxsID0gQlAuZmlsbFxuICBhcnIuaW5zcGVjdCA9IEJQLmluc3BlY3RcbiAgYXJyLnRvQXJyYXlCdWZmZXIgPSBCUC50b0FycmF5QnVmZmVyXG5cbiAgcmV0dXJuIGFyclxufVxuXG52YXIgSU5WQUxJRF9CQVNFNjRfUkUgPSAvW14rXFwvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHN0cmlwcyBvdXQgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgXFxuIGFuZCBcXHQgZnJvbSB0aGUgc3RyaW5nLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgc3RyID0gc3RyaW5ndHJpbShzdHIpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHN0cmluZ3RyaW0gKHN0cikge1xuICBpZiAoc3RyLnRyaW0pIHJldHVybiBzdHIudHJpbSgpXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBjb2RlUG9pbnQgPSBzdHJpbmcuY2hhckNvZGVBdChpKVxuXG4gICAgLy8gaXMgc3Vycm9nYXRlIGNvbXBvbmVudFxuICAgIGlmIChjb2RlUG9pbnQgPiAweEQ3RkYgJiYgY29kZVBvaW50IDwgMHhFMDAwKSB7XG4gICAgICAvLyBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCFsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIG5vIGxlYWQgeWV0XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBsZWFkXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyAyIGxlYWRzIGluIGEgcm93XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBjb2RlUG9pbnQgPSAobGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCkgKyAweDEwMDAwXG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICB9XG5cbiAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpIGJyZWFrXG4gICAgZHN0W2kgKyBvZmZzZXRdID0gc3JjW2ldXG4gIH1cbiAgcmV0dXJuIGlcbn1cbiIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKGFycikge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChhcnIpID09ICdbb2JqZWN0IEFycmF5XSc7XG59O1xuIiwiZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24gKGJ1ZmZlciwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG1cbiAgdmFyIGVMZW4gPSAobkJ5dGVzICogOCkgLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSAoZSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBtID0gZSAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBlID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBtTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IG0gPSAobSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICgodmFsdWUgKiBjKSAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiLypcbiAqIFN5c3RlbUpTIHYwLjIwLjE5IERldlxuICovXG4oZnVuY3Rpb24gKCkge1xuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogRW52aXJvbm1lbnRcbiAqL1xudmFyIGlzQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgaXNOb2RlID0gdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHByb2Nlc3MudmVyc2lvbnMgJiYgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlO1xudmFyIGlzV2luZG93cyA9IHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgcHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3N0cmluZycgJiYgcHJvY2Vzcy5wbGF0Zm9ybS5tYXRjaCgvXndpbi8pO1xuXG52YXIgZW52R2xvYmFsID0gdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnID8gc2VsZiA6IGdsb2JhbDtcbi8qXG4gKiBTaW1wbGUgU3ltYm9sKCkgc2hpbVxuICovXG52YXIgaGFzU3ltYm9sID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCc7XG5mdW5jdGlvbiBjcmVhdGVTeW1ib2wgKG5hbWUpIHtcbiAgcmV0dXJuIGhhc1N5bWJvbCA/IFN5bWJvbCgpIDogJ0BAJyArIG5hbWU7XG59XG5cblxuXG5cblxuLypcbiAqIEVudmlyb25tZW50IGJhc2VVUklcbiAqL1xudmFyIGJhc2VVUkk7XG5cbi8vIGVudmlyb25lbnQgYmFzZVVSSSBkZXRlY3Rpb25cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUpIHtcbiAgYmFzZVVSSSA9IGRvY3VtZW50LmJhc2VVUkk7XG5cbiAgaWYgKCFiYXNlVVJJKSB7XG4gICAgdmFyIGJhc2VzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2Jhc2UnKTtcbiAgICBiYXNlVVJJID0gYmFzZXNbMF0gJiYgYmFzZXNbMF0uaHJlZiB8fCB3aW5kb3cubG9jYXRpb24uaHJlZjtcbiAgfVxufVxuZWxzZSBpZiAodHlwZW9mIGxvY2F0aW9uICE9ICd1bmRlZmluZWQnKSB7XG4gIGJhc2VVUkkgPSBsb2NhdGlvbi5ocmVmO1xufVxuXG4vLyBzYW5pdGl6ZSBvdXQgdGhlIGhhc2ggYW5kIHF1ZXJ5c3RyaW5nXG5pZiAoYmFzZVVSSSkge1xuICBiYXNlVVJJID0gYmFzZVVSSS5zcGxpdCgnIycpWzBdLnNwbGl0KCc/JylbMF07XG4gIHZhciBzbGFzaEluZGV4ID0gYmFzZVVSSS5sYXN0SW5kZXhPZignLycpO1xuICBpZiAoc2xhc2hJbmRleCAhPT0gLTEpXG4gICAgYmFzZVVSSSA9IGJhc2VVUkkuc3Vic3RyKDAsIHNsYXNoSW5kZXggKyAxKTtcbn1cbmVsc2UgaWYgKHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiBwcm9jZXNzLmN3ZCkge1xuICBiYXNlVVJJID0gJ2ZpbGU6Ly8nICsgKGlzV2luZG93cyA/ICcvJyA6ICcnKSArIHByb2Nlc3MuY3dkKCk7XG4gIGlmIChpc1dpbmRvd3MpXG4gICAgYmFzZVVSSSA9IGJhc2VVUkkucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xufVxuZWxzZSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ05vIGVudmlyb25tZW50IGJhc2VVUkknKTtcbn1cblxuLy8gZW5zdXJlIGJhc2VVUkkgaGFzIHRyYWlsaW5nIFwiL1wiXG5pZiAoYmFzZVVSSVtiYXNlVVJJLmxlbmd0aCAtIDFdICE9PSAnLycpXG4gIGJhc2VVUkkgKz0gJy8nO1xuXG4vKlxuICogTG9hZGVyRXJyb3Igd2l0aCBjaGFpbmluZyBmb3IgbG9hZGVyIHN0YWNrc1xuICovXG52YXIgZXJyQXJncyA9IG5ldyBFcnJvcigwLCAnXycpLmZpbGVOYW1lID09ICdfJztcbmZ1bmN0aW9uIExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2sgKGNoaWxkRXJyLCBuZXdNZXNzYWdlKSB7XG4gIC8vIENvbnZlcnQgZmlsZTovLy8gVVJMcyB0byBwYXRocyBpbiBOb2RlXG4gIGlmICghaXNCcm93c2VyKVxuICAgIG5ld01lc3NhZ2UgPSBuZXdNZXNzYWdlLnJlcGxhY2UoaXNXaW5kb3dzID8gL2ZpbGU6XFwvXFwvXFwvL2cgOiAvZmlsZTpcXC9cXC8vZywgJycpO1xuXG4gIHZhciBtZXNzYWdlID0gKGNoaWxkRXJyLm1lc3NhZ2UgfHwgY2hpbGRFcnIpICsgJ1xcbiAgJyArIG5ld01lc3NhZ2U7XG5cbiAgdmFyIGVycjtcbiAgaWYgKGVyckFyZ3MgJiYgY2hpbGRFcnIuZmlsZU5hbWUpXG4gICAgZXJyID0gbmV3IEVycm9yKG1lc3NhZ2UsIGNoaWxkRXJyLmZpbGVOYW1lLCBjaGlsZEVyci5saW5lTnVtYmVyKTtcbiAgZWxzZVxuICAgIGVyciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcblxuXG4gIHZhciBzdGFjayA9IGNoaWxkRXJyLm9yaWdpbmFsRXJyID8gY2hpbGRFcnIub3JpZ2luYWxFcnIuc3RhY2sgOiBjaGlsZEVyci5zdGFjaztcblxuICBpZiAoaXNOb2RlKVxuICAgIC8vIG5vZGUgZG9lc24ndCBzaG93IHRoZSBtZXNzYWdlIG90aGVyd2lzZVxuICAgIGVyci5zdGFjayA9IG1lc3NhZ2UgKyAnXFxuICAnICsgc3RhY2s7XG4gIGVsc2VcbiAgICBlcnIuc3RhY2sgPSBzdGFjaztcblxuICBlcnIub3JpZ2luYWxFcnIgPSBjaGlsZEVyci5vcmlnaW5hbEVyciB8fCBjaGlsZEVycjtcblxuICByZXR1cm4gZXJyO1xufVxuXG4vKlxuICogT3B0aW1pemVkIFVSTCBub3JtYWxpemF0aW9uIGFzc3VtaW5nIGEgc3ludGF4LXZhbGlkIFVSTCBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gdGhyb3dSZXNvbHZlRXJyb3IgKHJlbFVybCwgcGFyZW50VXJsKSB7XG4gIHRocm93IG5ldyBSYW5nZUVycm9yKCdVbmFibGUgdG8gcmVzb2x2ZSBcIicgKyByZWxVcmwgKyAnXCIgdG8gJyArIHBhcmVudFVybCk7XG59XG5mdW5jdGlvbiByZXNvbHZlSWZOb3RQbGFpbiAocmVsVXJsLCBwYXJlbnRVcmwpIHtcbiAgcmVsVXJsID0gcmVsVXJsLnRyaW0oKTtcbiAgdmFyIHBhcmVudFByb3RvY29sID0gcGFyZW50VXJsICYmIHBhcmVudFVybC5zdWJzdHIoMCwgcGFyZW50VXJsLmluZGV4T2YoJzonKSArIDEpO1xuXG4gIHZhciBmaXJzdENoYXIgPSByZWxVcmxbMF07XG4gIHZhciBzZWNvbmRDaGFyID0gcmVsVXJsWzFdO1xuXG4gIC8vIHByb3RvY29sLXJlbGF0aXZlXG4gIGlmIChmaXJzdENoYXIgPT09ICcvJyAmJiBzZWNvbmRDaGFyID09PSAnLycpIHtcbiAgICBpZiAoIXBhcmVudFByb3RvY29sKVxuICAgICAgdGhyb3dSZXNvbHZlRXJyb3IocmVsVXJsLCBwYXJlbnRVcmwpO1xuICAgIHJldHVybiBwYXJlbnRQcm90b2NvbCArIHJlbFVybDtcbiAgfVxuICAvLyByZWxhdGl2ZS11cmxcbiAgZWxzZSBpZiAoZmlyc3RDaGFyID09PSAnLicgJiYgKHNlY29uZENoYXIgPT09ICcvJyB8fCBzZWNvbmRDaGFyID09PSAnLicgJiYgKHJlbFVybFsyXSA9PT0gJy8nIHx8IHJlbFVybC5sZW5ndGggPT09IDIgJiYgKHJlbFVybCArPSAnLycpKSB8fFxuICAgICAgcmVsVXJsLmxlbmd0aCA9PT0gMSAgJiYgKHJlbFVybCArPSAnLycpKSB8fFxuICAgICAgZmlyc3RDaGFyID09PSAnLycpIHtcbiAgICB2YXIgcGFyZW50SXNQbGFpbiA9ICFwYXJlbnRQcm90b2NvbCB8fCBwYXJlbnRVcmxbcGFyZW50UHJvdG9jb2wubGVuZ3RoXSAhPT0gJy8nO1xuXG4gICAgLy8gcmVhZCBwYXRobmFtZSBmcm9tIHBhcmVudCBpZiBhIFVSTFxuICAgIC8vIHBhdGhuYW1lIHRha2VuIHRvIGJlIHBhcnQgYWZ0ZXIgbGVhZGluZyBcIi9cIlxuICAgIHZhciBwYXRobmFtZTtcbiAgICBpZiAocGFyZW50SXNQbGFpbikge1xuICAgICAgLy8gcmVzb2x2aW5nIHRvIGEgcGxhaW4gcGFyZW50IC0+IHNraXAgc3RhbmRhcmQgVVJMIHByZWZpeCwgYW5kIHRyZWF0IGVudGlyZSBwYXJlbnQgYXMgcGF0aG5hbWVcbiAgICAgIGlmIChwYXJlbnRVcmwgPT09IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3dSZXNvbHZlRXJyb3IocmVsVXJsLCBwYXJlbnRVcmwpO1xuICAgICAgcGF0aG5hbWUgPSBwYXJlbnRVcmw7XG4gICAgfVxuICAgIGVsc2UgaWYgKHBhcmVudFVybFtwYXJlbnRQcm90b2NvbC5sZW5ndGggKyAxXSA9PT0gJy8nKSB7XG4gICAgICAvLyByZXNvbHZpbmcgdG8gYSA6Ly8gc28gd2UgbmVlZCB0byByZWFkIG91dCB0aGUgYXV0aCBhbmQgaG9zdFxuICAgICAgaWYgKHBhcmVudFByb3RvY29sICE9PSAnZmlsZTonKSB7XG4gICAgICAgIHBhdGhuYW1lID0gcGFyZW50VXJsLnN1YnN0cihwYXJlbnRQcm90b2NvbC5sZW5ndGggKyAyKTtcbiAgICAgICAgcGF0aG5hbWUgPSBwYXRobmFtZS5zdWJzdHIocGF0aG5hbWUuaW5kZXhPZignLycpICsgMSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcGF0aG5hbWUgPSBwYXJlbnRVcmwuc3Vic3RyKDgpO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIC8vIHJlc29sdmluZyB0byA6LyBzbyBwYXRobmFtZSBpcyB0aGUgLy4uLiBwYXJ0XG4gICAgICBwYXRobmFtZSA9IHBhcmVudFVybC5zdWJzdHIocGFyZW50UHJvdG9jb2wubGVuZ3RoICsgMSk7XG4gICAgfVxuXG4gICAgaWYgKGZpcnN0Q2hhciA9PT0gJy8nKSB7XG4gICAgICBpZiAocGFyZW50SXNQbGFpbilcbiAgICAgICAgdGhyb3dSZXNvbHZlRXJyb3IocmVsVXJsLCBwYXJlbnRVcmwpO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gcGFyZW50VXJsLnN1YnN0cigwLCBwYXJlbnRVcmwubGVuZ3RoIC0gcGF0aG5hbWUubGVuZ3RoIC0gMSkgKyByZWxVcmw7XG4gICAgfVxuXG4gICAgLy8gam9pbiB0b2dldGhlciBhbmQgc3BsaXQgZm9yIHJlbW92YWwgb2YgLi4gYW5kIC4gc2VnbWVudHNcbiAgICAvLyBsb29waW5nIHRoZSBzdHJpbmcgaW5zdGVhZCBvZiBhbnl0aGluZyBmYW5jeSBmb3IgcGVyZiByZWFzb25zXG4gICAgLy8gJy4uLy4uLy4uLy4uLy4uL3onIHJlc29sdmVkIHRvICd4L3knIGlzIGp1c3QgJ3onIHJlZ2FyZGxlc3Mgb2YgcGFyZW50SXNQbGFpblxuICAgIHZhciBzZWdtZW50ZWQgPSBwYXRobmFtZS5zdWJzdHIoMCwgcGF0aG5hbWUubGFzdEluZGV4T2YoJy8nKSArIDEpICsgcmVsVXJsO1xuXG4gICAgdmFyIG91dHB1dCA9IFtdO1xuICAgIHZhciBzZWdtZW50SW5kZXggPSAtMTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VnbWVudGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAvLyBidXN5IHJlYWRpbmcgYSBzZWdtZW50IC0gb25seSB0ZXJtaW5hdGUgb24gJy8nXG4gICAgICBpZiAoc2VnbWVudEluZGV4ICE9PSAtMSkge1xuICAgICAgICBpZiAoc2VnbWVudGVkW2ldID09PSAnLycpIHtcbiAgICAgICAgICBvdXRwdXQucHVzaChzZWdtZW50ZWQuc3Vic3RyaW5nKHNlZ21lbnRJbmRleCwgaSArIDEpKTtcbiAgICAgICAgICBzZWdtZW50SW5kZXggPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gbmV3IHNlZ21lbnQgLSBjaGVjayBpZiBpdCBpcyByZWxhdGl2ZVxuICAgICAgaWYgKHNlZ21lbnRlZFtpXSA9PT0gJy4nKSB7XG4gICAgICAgIC8vIC4uLyBzZWdtZW50XG4gICAgICAgIGlmIChzZWdtZW50ZWRbaSArIDFdID09PSAnLicgJiYgKHNlZ21lbnRlZFtpICsgMl0gPT09ICcvJyB8fCBpICsgMiA9PT0gc2VnbWVudGVkLmxlbmd0aCkpIHtcbiAgICAgICAgICBvdXRwdXQucG9wKCk7XG4gICAgICAgICAgaSArPSAyO1xuICAgICAgICB9XG4gICAgICAgIC8vIC4vIHNlZ21lbnRcbiAgICAgICAgZWxzZSBpZiAoc2VnbWVudGVkW2kgKyAxXSA9PT0gJy8nIHx8IGkgKyAxID09PSBzZWdtZW50ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgaSArPSAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIC8vIHRoZSBzdGFydCBvZiBhIG5ldyBzZWdtZW50IGFzIGJlbG93XG4gICAgICAgICAgc2VnbWVudEluZGV4ID0gaTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIHBsYWluIFVSSSBiYWNrdHJhY2tpbmcgZXJyb3IgKC4uLywgcGFja2FnZTp4IC0+IGVycm9yKVxuICAgICAgICBpZiAocGFyZW50SXNQbGFpbiAmJiBvdXRwdXQubGVuZ3RoID09PSAwKVxuICAgICAgICAgIHRocm93UmVzb2x2ZUVycm9yKHJlbFVybCwgcGFyZW50VXJsKTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gaXQgaXMgdGhlIHN0YXJ0IG9mIGEgbmV3IHNlZ21lbnRcbiAgICAgIHNlZ21lbnRJbmRleCA9IGk7XG4gICAgfVxuICAgIC8vIGZpbmlzaCByZWFkaW5nIG91dCB0aGUgbGFzdCBzZWdtZW50XG4gICAgaWYgKHNlZ21lbnRJbmRleCAhPT0gLTEpXG4gICAgICBvdXRwdXQucHVzaChzZWdtZW50ZWQuc3Vic3RyKHNlZ21lbnRJbmRleCkpO1xuXG4gICAgcmV0dXJuIHBhcmVudFVybC5zdWJzdHIoMCwgcGFyZW50VXJsLmxlbmd0aCAtIHBhdGhuYW1lLmxlbmd0aCkgKyBvdXRwdXQuam9pbignJyk7XG4gIH1cblxuICAvLyBzYW5pdGl6ZXMgYW5kIHZlcmlmaWVzIChieSByZXR1cm5pbmcgdW5kZWZpbmVkIGlmIG5vdCBhIHZhbGlkIFVSTC1saWtlIGZvcm0pXG4gIC8vIFdpbmRvd3MgZmlsZXBhdGggY29tcGF0aWJpbGl0eSBpcyBhbiBhZGRlZCBjb252ZW5pZW5jZSBoZXJlXG4gIHZhciBwcm90b2NvbEluZGV4ID0gcmVsVXJsLmluZGV4T2YoJzonKTtcbiAgaWYgKHByb3RvY29sSW5kZXggIT09IC0xKSB7XG4gICAgaWYgKGlzTm9kZSkge1xuICAgICAgLy8gQzpcXHggYmVjb21lcyBmaWxlOi8vL2M6L3ggKHdlIGRvbid0IHN1cHBvcnQgQ3xcXHgpXG4gICAgICBpZiAocmVsVXJsWzFdID09PSAnOicgJiYgcmVsVXJsWzJdID09PSAnXFxcXCcgJiYgcmVsVXJsWzBdLm1hdGNoKC9bYS16XS9pKSlcbiAgICAgICAgcmV0dXJuICdmaWxlOi8vLycgKyByZWxVcmwucmVwbGFjZSgvXFxcXC9nLCAnLycpO1xuICAgIH1cbiAgICByZXR1cm4gcmVsVXJsO1xuICB9XG59XG5cbnZhciByZXNvbHZlZFByb21pc2UkMSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4vKlxuICogU2ltcGxlIEFycmF5IHZhbHVlcyBzaGltXG4gKi9cbmZ1bmN0aW9uIGFycmF5VmFsdWVzIChhcnIpIHtcbiAgaWYgKGFyci52YWx1ZXMpXG4gICAgcmV0dXJuIGFyci52YWx1ZXMoKTtcblxuICBpZiAodHlwZW9mIFN5bWJvbCA9PT0gJ3VuZGVmaW5lZCcgfHwgIVN5bWJvbC5pdGVyYXRvcilcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1N5bWJvbC5pdGVyYXRvciBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlcicpO1xuXG4gIHZhciBpdGVyYWJsZSA9IHt9O1xuICBpdGVyYWJsZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYXJyKTtcbiAgICB2YXIga2V5SW5kZXggPSAwO1xuICAgIHJldHVybiB7XG4gICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChrZXlJbmRleCA8IGtleXMubGVuZ3RoKVxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogYXJyW2tleXNba2V5SW5kZXgrK11dLFxuICAgICAgICAgICAgZG9uZTogZmFsc2VcbiAgICAgICAgICB9O1xuICAgICAgICBlbHNlXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbHVlOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBkb25lOiB0cnVlXG4gICAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuICByZXR1cm4gaXRlcmFibGU7XG59XG5cbi8qXG4gKiAzLiBSZWZsZWN0LkxvYWRlclxuICpcbiAqIFdlIHNraXAgdGhlIGVudGlyZSBuYXRpdmUgaW50ZXJuYWwgcGlwZWxpbmUsIGp1c3QgcHJvdmlkaW5nIHRoZSBiYXJlIEFQSVxuICovXG4vLyAzLjEuMVxuZnVuY3Rpb24gTG9hZGVyICgpIHtcbiAgdGhpcy5yZWdpc3RyeSA9IG5ldyBSZWdpc3RyeSgpO1xufVxuLy8gMy4zLjFcbkxvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBMb2FkZXI7XG5cbmZ1bmN0aW9uIGVuc3VyZUluc3RhbnRpYXRlZCAobW9kdWxlKSB7XG4gIGlmICghKG1vZHVsZSBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSkpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTW9kdWxlIGluc3RhbnRpYXRpb24gZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBuYW1lc3BhY2Ugb2JqZWN0LicpO1xuICByZXR1cm4gbW9kdWxlO1xufVxuXG4vLyAzLjMuMlxuTG9hZGVyLnByb3RvdHlwZS5pbXBvcnQgPSBmdW5jdGlvbiAoa2V5LCBwYXJlbnQpIHtcbiAgaWYgKHR5cGVvZiBrZXkgIT09ICdzdHJpbmcnKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0xvYWRlciBpbXBvcnQgbWV0aG9kIG11c3QgYmUgcGFzc2VkIGEgbW9kdWxlIGtleSBzdHJpbmcnKTtcbiAgLy8gY3VzdG9tIHJlc29sdmVJbnN0YW50aWF0ZSBjb21iaW5lZCBob29rIGZvciBiZXR0ZXIgcGVyZlxuICB2YXIgbG9hZGVyID0gdGhpcztcbiAgcmV0dXJuIHJlc29sdmVkUHJvbWlzZSQxXG4gIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gbG9hZGVyW1JFU09MVkVfSU5TVEFOVElBVEVdKGtleSwgcGFyZW50KTtcbiAgfSlcbiAgLnRoZW4oZW5zdXJlSW5zdGFudGlhdGVkKVxuICAvLy50aGVuKE1vZHVsZS5ldmFsdWF0ZSlcbiAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICB0aHJvdyBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrKGVyciwgJ0xvYWRpbmcgJyArIGtleSArIChwYXJlbnQgPyAnIGZyb20gJyArIHBhcmVudCA6ICcnKSk7XG4gIH0pO1xufTtcbi8vIDMuMy4zXG52YXIgUkVTT0xWRSA9IExvYWRlci5yZXNvbHZlID0gY3JlYXRlU3ltYm9sKCdyZXNvbHZlJyk7XG5cbi8qXG4gKiBDb21iaW5lZCByZXNvbHZlIC8gaW5zdGFudGlhdGUgaG9va1xuICpcbiAqIE5vdCBpbiBjdXJyZW50IHJlZHVjZWQgc3BlYywgYnV0IG5lY2Vzc2FyeSB0byBzZXBhcmF0ZSBSRVNPTFZFIGZyb20gUkVTT0xWRSArIElOU1RBTlRJQVRFIGFzIGRlc2NyaWJlZFxuICogaW4gdGhlIHNwZWMgbm90ZXMgb2YgdGhpcyByZXBvIHRvIGVuc3VyZSB0aGF0IGxvYWRlci5yZXNvbHZlIGRvZXNuJ3QgaW5zdGFudGlhdGUgd2hlbiBub3Qgd2FudGVkLlxuICpcbiAqIFdlIGltcGxlbWVudCBSRVNPTFZFX0lOU1RBTlRJQVRFIGFzIGEgc2luZ2xlIGhvb2sgaW5zdGVhZCBvZiBhIHNlcGFyYXRlIElOU1RBTlRJQVRFIGluIG9yZGVyIHRvIGF2b2lkXG4gKiB0aGUgbmVlZCBmb3IgZG91YmxlIHJlZ2lzdHJ5IGxvb2t1cHMgYXMgYSBwZXJmb3JtYW5jZSBvcHRpbWl6YXRpb24uXG4gKi9cbnZhciBSRVNPTFZFX0lOU1RBTlRJQVRFID0gTG9hZGVyLnJlc29sdmVJbnN0YW50aWF0ZSA9IGNyZWF0ZVN5bWJvbCgncmVzb2x2ZUluc3RhbnRpYXRlJyk7XG5cbi8vIGRlZmF1bHQgcmVzb2x2ZUluc3RhbnRpYXRlIGlzIGp1c3QgdG8gY2FsbCByZXNvbHZlIGFuZCB0aGVuIGdldCBmcm9tIHRoZSByZWdpc3RyeVxuLy8gdGhpcyBwcm92aWRlcyBjb21wYXRpYmlsaXR5IGZvciB0aGUgcmVzb2x2ZUluc3RhbnRpYXRlIG9wdGltaXphdGlvblxuTG9hZGVyLnByb3RvdHlwZVtSRVNPTFZFX0lOU1RBTlRJQVRFXSA9IGZ1bmN0aW9uIChrZXksIHBhcmVudCkge1xuICB2YXIgbG9hZGVyID0gdGhpcztcbiAgcmV0dXJuIGxvYWRlci5yZXNvbHZlKGtleSwgcGFyZW50KVxuICAudGhlbihmdW5jdGlvbiAocmVzb2x2ZWQpIHtcbiAgICByZXR1cm4gbG9hZGVyLnJlZ2lzdHJ5LmdldChyZXNvbHZlZCk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gZW5zdXJlUmVzb2x1dGlvbiAocmVzb2x2ZWRLZXkpIHtcbiAgaWYgKHJlc29sdmVkS2V5ID09PSB1bmRlZmluZWQpXG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ05vIHJlc29sdXRpb24gZm91bmQuJyk7XG4gIHJldHVybiByZXNvbHZlZEtleTtcbn1cblxuTG9hZGVyLnByb3RvdHlwZS5yZXNvbHZlID0gZnVuY3Rpb24gKGtleSwgcGFyZW50KSB7XG4gIHZhciBsb2FkZXIgPSB0aGlzO1xuICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlJDFcbiAgLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGxvYWRlcltSRVNPTFZFXShrZXksIHBhcmVudCk7XG4gIH0pXG4gIC50aGVuKGVuc3VyZVJlc29sdXRpb24pXG4gIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgdGhyb3cgTG9hZGVyRXJyb3JfX0NoZWNrX2Vycm9yX21lc3NhZ2VfZm9yX2xvYWRlcl9zdGFjayhlcnIsICdSZXNvbHZpbmcgJyArIGtleSArIChwYXJlbnQgPyAnIHRvICcgKyBwYXJlbnQgOiAnJykpO1xuICB9KTtcbn07XG5cbi8vIDMuMy40IChpbXBvcnQgd2l0aG91dCBldmFsdWF0ZSlcbi8vIHRoaXMgaXMgbm90IGRvY3VtZW50ZWQgYmVjYXVzZSB0aGUgdXNlIG9mIGRlZmVycmVkIGV2YWx1YXRpb24gYXMgaW4gTW9kdWxlLmV2YWx1YXRlIGlzIG5vdFxuLy8gZG9jdW1lbnRlZCwgYXMgaXQgaXMgbm90IGNvbnNpZGVyZWQgYSBzdGFibGUgZmVhdHVyZSB0byBiZSBlbmNvdXJhZ2VkXG4vLyBMb2FkZXIucHJvdG90eXBlLmxvYWQgbWF5IHdlbGwgYmUgZGVwcmVjYXRlZCBpZiB0aGlzIHN0YXlzIGRpc2FibGVkXG4vKiBMb2FkZXIucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiAoa2V5LCBwYXJlbnQpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzW1JFU09MVkVfSU5TVEFOVElBVEVdKGtleSwgcGFyZW50IHx8IHRoaXMua2V5KSlcbiAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICB0aHJvdyBhZGRUb0Vycm9yKGVyciwgJ0xvYWRpbmcgJyArIGtleSArIChwYXJlbnQgPyAnIGZyb20gJyArIHBhcmVudCA6ICcnKSk7XG4gIH0pO1xufTsgKi9cblxuLypcbiAqIDQuIFJlZ2lzdHJ5XG4gKlxuICogSW5zdGVhZCBvZiBzdHJ1Y3R1cmluZyB0aHJvdWdoIGEgTWFwLCBqdXN0IHVzZSBhIGRpY3Rpb25hcnkgb2JqZWN0XG4gKiBXZSB0aHJvdyBmb3IgY29uc3RydWN0aW9uIGF0dGVtcHRzIHNvIHRoaXMgZG9lc24ndCBhZmZlY3QgdGhlIHB1YmxpYyBBUElcbiAqXG4gKiBSZWdpc3RyeSBoYXMgYmVlbiBhZGp1c3RlZCB0byB1c2UgTmFtZXNwYWNlIG9iamVjdHMgb3ZlciBNb2R1bGVTdGF0dXMgb2JqZWN0c1xuICogYXMgcGFydCBvZiBzaW1wbGlmeWluZyBsb2FkZXIgQVBJIGltcGxlbWVudGF0aW9uXG4gKi9cbnZhciBpdGVyYXRvclN1cHBvcnQgPSB0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wuaXRlcmF0b3I7XG52YXIgUkVHSVNUUlkgPSBjcmVhdGVTeW1ib2woJ3JlZ2lzdHJ5Jyk7XG5mdW5jdGlvbiBSZWdpc3RyeSgpIHtcbiAgdGhpc1tSRUdJU1RSWV0gPSB7fTtcbn1cbi8vIDQuNC4xXG5pZiAoaXRlcmF0b3JTdXBwb3J0KSB7XG4gIC8vIDQuNC4yXG4gIFJlZ2lzdHJ5LnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH07XG5cbiAgLy8gNC40LjNcbiAgUmVnaXN0cnkucHJvdG90eXBlLmVudHJpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHJlZ2lzdHJ5ID0gdGhpc1tSRUdJU1RSWV07XG4gICAgcmV0dXJuIGFycmF5VmFsdWVzKE9iamVjdC5rZXlzKHJlZ2lzdHJ5KS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIFtrZXksIHJlZ2lzdHJ5W2tleV1dO1xuICAgIH0pKTtcbiAgfTtcbn1cblxuLy8gNC40LjRcblJlZ2lzdHJ5LnByb3RvdHlwZS5rZXlzID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gYXJyYXlWYWx1ZXMoT2JqZWN0LmtleXModGhpc1tSRUdJU1RSWV0pKTtcbn07XG4vLyA0LjQuNVxuUmVnaXN0cnkucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHJlZ2lzdHJ5ID0gdGhpc1tSRUdJU1RSWV07XG4gIHJldHVybiBhcnJheVZhbHVlcyhPYmplY3Qua2V5cyhyZWdpc3RyeSkubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gcmVnaXN0cnlba2V5XTtcbiAgfSkpO1xufTtcbi8vIDQuNC42XG5SZWdpc3RyeS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gdGhpc1tSRUdJU1RSWV1ba2V5XTtcbn07XG4vLyA0LjQuN1xuUmVnaXN0cnkucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIChrZXksIG5hbWVzcGFjZSkge1xuICBpZiAoIShuYW1lc3BhY2UgaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpKVxuICAgIHRocm93IG5ldyBFcnJvcignUmVnaXN0cnkgbXVzdCBiZSBzZXQgd2l0aCBhbiBpbnN0YW5jZSBvZiBNb2R1bGUgTmFtZXNwYWNlJyk7XG4gIHRoaXNbUkVHSVNUUlldW2tleV0gPSBuYW1lc3BhY2U7XG4gIHJldHVybiB0aGlzO1xufTtcbi8vIDQuNC44XG5SZWdpc3RyeS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwodGhpc1tSRUdJU1RSWV0sIGtleSk7XG59O1xuLy8gNC40LjlcblJlZ2lzdHJ5LnByb3RvdHlwZS5kZWxldGUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzW1JFR0lTVFJZXSwga2V5KSkge1xuICAgIGRlbGV0ZSB0aGlzW1JFR0lTVFJZXVtrZXldO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn07XG5cbi8qXG4gKiBTaW1wbGUgTW9kdWxlTmFtZXNwYWNlIEV4b3RpYyBvYmplY3QgYmFzZWQgb24gYSBiYXNlT2JqZWN0XG4gKiBXZSBleHBvcnQgdGhpcyBmb3IgYWxsb3dpbmcgYSBmYXN0LXBhdGggZm9yIG1vZHVsZSBuYW1lc3BhY2UgY3JlYXRpb24gb3ZlciBNb2R1bGUgZGVzY3JpcHRvcnNcbiAqL1xuLy8gdmFyIEVWQUxVQVRFID0gY3JlYXRlU3ltYm9sKCdldmFsdWF0ZScpO1xudmFyIEJBU0VfT0JKRUNUID0gY3JlYXRlU3ltYm9sKCdiYXNlT2JqZWN0Jyk7XG5cbi8vIDguMy4xIFJlZmxlY3QuTW9kdWxlXG4vKlxuICogQmVzdC1lZmZvcnQgc2ltcGxpZmllZCBub24tc3BlYyBpbXBsZW1lbnRhdGlvbiBiYXNlZCBvblxuICogYSBiYXNlT2JqZWN0IHJlZmVyZW5jZWQgdmlhIGdldHRlcnMuXG4gKlxuICogQWxsb3dzOlxuICpcbiAqICAgbG9hZGVyLnJlZ2lzdHJ5LnNldCgneCcsIG5ldyBNb2R1bGUoeyBkZWZhdWx0OiAneCcgfSkpO1xuICpcbiAqIE9wdGlvbmFsIGV2YWx1YXRpb24gZnVuY3Rpb24gcHJvdmlkZXMgZXhwZXJpbWVudGFsIE1vZHVsZS5ldmFsdWF0ZVxuICogc3VwcG9ydCBmb3Igbm9uLWV4ZWN1dGVkIG1vZHVsZXMgaW4gcmVnaXN0cnkuXG4gKi9cbmZ1bmN0aW9uIE1vZHVsZU5hbWVzcGFjZSAoYmFzZU9iamVjdC8qLCBldmFsdWF0ZSovKSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBCQVNFX09CSkVDVCwge1xuICAgIHZhbHVlOiBiYXNlT2JqZWN0XG4gIH0pO1xuXG4gIC8vIGV2YWx1YXRlIGRlZmVycyBuYW1lc3BhY2UgcG9wdWxhdGlvblxuICAvKiBpZiAoZXZhbHVhdGUpIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgRVZBTFVBVEUsIHtcbiAgICAgIHZhbHVlOiBldmFsdWF0ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH1cbiAgZWxzZSB7ICovXG4gICAgT2JqZWN0LmtleXMoYmFzZU9iamVjdCkuZm9yRWFjaChleHRlbmROYW1lc3BhY2UsIHRoaXMpO1xuICAvL31cbn1cbi8vIDguNC4yXG5Nb2R1bGVOYW1lc3BhY2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZylcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE1vZHVsZU5hbWVzcGFjZS5wcm90b3R5cGUsIFN5bWJvbC50b1N0cmluZ1RhZywge1xuICAgIHZhbHVlOiAnTW9kdWxlJ1xuICB9KTtcblxuZnVuY3Rpb24gZXh0ZW5kTmFtZXNwYWNlIChrZXkpIHtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGtleSwge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpc1tCQVNFX09CSkVDVF1ba2V5XTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKiBmdW5jdGlvbiBkb0V2YWx1YXRlIChldmFsdWF0ZSwgY29udGV4dCkge1xuICB0cnkge1xuICAgIGV2YWx1YXRlLmNhbGwoY29udGV4dCk7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZTtcbiAgfVxufVxuXG4vLyA4LjQuMSBNb2R1bGUuZXZhbHVhdGUuLi4gbm90IGRvY3VtZW50ZWQgb3IgdXNlZCBiZWNhdXNlIHRoaXMgaXMgcG90ZW50aWFsbHkgdW5zdGFibGVcbk1vZHVsZS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIChucykge1xuICB2YXIgZXZhbHVhdGUgPSBuc1tFVkFMVUFURV07XG4gIGlmIChldmFsdWF0ZSkge1xuICAgIG5zW0VWQUxVQVRFXSA9IHVuZGVmaW5lZDtcbiAgICB2YXIgZXJyID0gZG9FdmFsdWF0ZShldmFsdWF0ZSk7XG4gICAgaWYgKGVycikge1xuICAgICAgLy8gY2FjaGUgdGhlIGVycm9yXG4gICAgICBuc1tFVkFMVUFURV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH07XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIE9iamVjdC5rZXlzKG5zW0JBU0VfT0JKRUNUXSkuZm9yRWFjaChleHRlbmROYW1lc3BhY2UsIG5zKTtcbiAgfVxuICAvLyBtYWtlIGNoYWluYWJsZVxuICByZXR1cm4gbnM7XG59OyAqL1xuXG4vKlxuICogUmVnaXN0ZXIgTG9hZGVyXG4gKlxuICogQnVpbGRzIGRpcmVjdGx5IG9uIHRvcCBvZiBsb2FkZXIgcG9seWZpbGwgdG8gcHJvdmlkZTpcbiAqIC0gbG9hZGVyLnJlZ2lzdGVyIHN1cHBvcnRcbiAqIC0gaG9va2FibGUgaGlnaGVyLWxldmVsIHJlc29sdmVcbiAqIC0gaW5zdGFudGlhdGUgaG9vayByZXR1cm5pbmcgYSBNb2R1bGVOYW1lc3BhY2Ugb3IgdW5kZWZpbmVkIGZvciBlcyBtb2R1bGUgbG9hZGluZ1xuICogLSBsb2FkZXIgZXJyb3IgYmVoYXZpb3VyIGFzIGluIEhUTUwgYW5kIGxvYWRlciBzcGVjcywgY2FjaGluZyBsb2FkIGFuZCBldmFsIGVycm9ycyBzZXBhcmF0ZWx5XG4gKiAtIGJ1aWxkIHRyYWNpbmcgc3VwcG9ydCBieSBwcm92aWRpbmcgYSAudHJhY2U9dHJ1ZSBhbmQgLmxvYWRzIG9iamVjdCBmb3JtYXRcbiAqL1xuXG52YXIgUkVHSVNURVJfSU5URVJOQUwgPSBjcmVhdGVTeW1ib2woJ3JlZ2lzdGVyLWludGVybmFsJyk7XG5cbmZ1bmN0aW9uIFJlZ2lzdGVyTG9hZGVyJDEgKCkge1xuICBMb2FkZXIuY2FsbCh0aGlzKTtcblxuICB2YXIgcmVnaXN0cnlEZWxldGUgPSB0aGlzLnJlZ2lzdHJ5LmRlbGV0ZTtcbiAgdGhpcy5yZWdpc3RyeS5kZWxldGUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIGRlbGV0ZWQgPSByZWdpc3RyeURlbGV0ZS5jYWxsKHRoaXMsIGtleSk7XG5cbiAgICAvLyBhbHNvIGRlbGV0ZSBmcm9tIHJlZ2lzdGVyIHJlZ2lzdHJ5IGlmIGxpbmtlZFxuICAgIGlmIChyZWNvcmRzLmhhc093blByb3BlcnR5KGtleSkgJiYgIXJlY29yZHNba2V5XS5saW5rUmVjb3JkKSB7XG4gICAgICBkZWxldGUgcmVjb3Jkc1trZXldO1xuICAgICAgZGVsZXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlbGV0ZWQ7XG4gIH07XG5cbiAgdmFyIHJlY29yZHMgPSB7fTtcblxuICB0aGlzW1JFR0lTVEVSX0lOVEVSTkFMXSA9IHtcbiAgICAvLyBsYXN0IGFub255bW91cyBTeXN0ZW0ucmVnaXN0ZXIgY2FsbFxuICAgIGxhc3RSZWdpc3RlcjogdW5kZWZpbmVkLFxuICAgIC8vIGluLWZsaWdodCBlcyBtb2R1bGUgbG9hZCByZWNvcmRzXG4gICAgcmVjb3JkczogcmVjb3Jkc1xuICB9O1xuXG4gIC8vIHRyYWNpbmdcbiAgdGhpcy50cmFjZSA9IGZhbHNlO1xufVxuXG5SZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoTG9hZGVyLnByb3RvdHlwZSk7XG5SZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFJlZ2lzdGVyTG9hZGVyJDE7XG5cbnZhciBJTlNUQU5USUFURSA9IFJlZ2lzdGVyTG9hZGVyJDEuaW5zdGFudGlhdGUgPSBjcmVhdGVTeW1ib2woJ2luc3RhbnRpYXRlJyk7XG5cbi8vIGRlZmF1bHQgbm9ybWFsaXplIGlzIHRoZSBXaGF0V0cgc3R5bGUgbm9ybWFsaXplclxuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGVbUmVnaXN0ZXJMb2FkZXIkMS5yZXNvbHZlID0gTG9hZGVyLnJlc29sdmVdID0gZnVuY3Rpb24gKGtleSwgcGFyZW50S2V5KSB7XG4gIHJldHVybiByZXNvbHZlSWZOb3RQbGFpbihrZXksIHBhcmVudEtleSB8fCBiYXNlVVJJKTtcbn07XG5cblJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlW0lOU1RBTlRJQVRFXSA9IGZ1bmN0aW9uIChrZXksIHByb2Nlc3NBbm9uUmVnaXN0ZXIpIHt9O1xuXG4vLyBvbmNlIGV2YWx1YXRlZCwgdGhlIGxpbmtSZWNvcmQgaXMgc2V0IHRvIHVuZGVmaW5lZCBsZWF2aW5nIGp1c3QgdGhlIG90aGVyIGxvYWQgcmVjb3JkIHByb3BlcnRpZXNcbi8vIHRoaXMgYWxsb3dzIHRyYWNraW5nIG5ldyBiaW5kaW5nIGxpc3RlbmVycyBmb3IgZXMgbW9kdWxlcyB0aHJvdWdoIGltcG9ydGVyU2V0dGVyc1xuLy8gZm9yIGR5bmFtaWMgbW9kdWxlcywgdGhlIGxvYWQgcmVjb3JkIGlzIHJlbW92ZWQgZW50aXJlbHkuXG5mdW5jdGlvbiBjcmVhdGVMb2FkUmVjb3JkIChzdGF0ZSwga2V5LCByZWdpc3RyYXRpb24pIHtcbiAgcmV0dXJuIHN0YXRlLnJlY29yZHNba2V5XSA9IHtcbiAgICBrZXk6IGtleSxcblxuICAgIC8vIGRlZmluZWQgU3lzdGVtLnJlZ2lzdGVyIGNhY2hlXG4gICAgcmVnaXN0cmF0aW9uOiByZWdpc3RyYXRpb24sXG5cbiAgICAvLyBtb2R1bGUgbmFtZXNwYWNlIG9iamVjdFxuICAgIG1vZHVsZTogdW5kZWZpbmVkLFxuXG4gICAgLy8gZXMtb25seVxuICAgIC8vIHRoaXMgc3RpY2tzIGFyb3VuZCBzbyBuZXcgbW9kdWxlIGxvYWRzIGNhbiBsaXN0ZW4gdG8gYmluZGluZyBjaGFuZ2VzXG4gICAgLy8gZm9yIGFscmVhZHktbG9hZGVkIG1vZHVsZXMgYnkgYWRkaW5nIHRoZW1zZWx2ZXMgdG8gdGhlaXIgaW1wb3J0ZXJTZXR0ZXJzXG4gICAgaW1wb3J0ZXJTZXR0ZXJzOiB1bmRlZmluZWQsXG5cbiAgICBsb2FkRXJyb3I6IHVuZGVmaW5lZCxcbiAgICBldmFsRXJyb3I6IHVuZGVmaW5lZCxcblxuICAgIC8vIGluLWZsaWdodCBsaW5raW5nIHJlY29yZFxuICAgIGxpbmtSZWNvcmQ6IHtcbiAgICAgIC8vIHByb21pc2UgZm9yIGluc3RhbnRpYXRlZFxuICAgICAgaW5zdGFudGlhdGVQcm9taXNlOiB1bmRlZmluZWQsXG4gICAgICBkZXBlbmRlbmNpZXM6IHVuZGVmaW5lZCxcbiAgICAgIGV4ZWN1dGU6IHVuZGVmaW5lZCxcbiAgICAgIGV4ZWN1dGluZ1JlcXVpcmU6IGZhbHNlLFxuXG4gICAgICAvLyB1bmRlcmx5aW5nIG1vZHVsZSBvYmplY3QgYmluZGluZ3NcbiAgICAgIG1vZHVsZU9iajogdW5kZWZpbmVkLFxuXG4gICAgICAvLyBlcyBvbmx5LCBhbHNvIGluZGljYXRlcyBpZiBlcyBvciBub3RcbiAgICAgIHNldHRlcnM6IHVuZGVmaW5lZCxcblxuICAgICAgLy8gcHJvbWlzZSBmb3IgaW5zdGFudGlhdGVkIGRlcGVuZGVuY2llcyAoZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zIHBvcHVsYXRlZClcbiAgICAgIGRlcHNJbnN0YW50aWF0ZVByb21pc2U6IHVuZGVmaW5lZCxcbiAgICAgIC8vIHdpbGwgYmUgdGhlIGFycmF5IG9mIGRlcGVuZGVuY3kgbG9hZCByZWNvcmQgb3IgYSBtb2R1bGUgbmFtZXNwYWNlXG4gICAgICBkZXBlbmRlbmN5SW5zdGFudGlhdGlvbnM6IHVuZGVmaW5lZCxcblxuICAgICAgLy8gTkIgb3B0aW1pemF0aW9uIGFuZCB3YXkgb2YgZW5zdXJpbmcgbW9kdWxlIG9iamVjdHMgaW4gc2V0dGVyc1xuICAgICAgLy8gaW5kaWNhdGVzIHNldHRlcnMgd2hpY2ggc2hvdWxkIHJ1biBwcmUtZXhlY3V0aW9uIG9mIHRoYXQgZGVwZW5kZW5jeVxuICAgICAgLy8gc2V0dGVycyBpcyB0aGVuIGp1c3QgZm9yIGNvbXBsZXRlbHkgZXhlY3V0ZWQgbW9kdWxlIG9iamVjdHNcbiAgICAgIC8vIGFsdGVybmF0aXZlbHkgd2UganVzdCBwYXNzIHRoZSBwYXJ0aWFsbHkgZmlsbGVkIG1vZHVsZSBvYmplY3RzIGFzXG4gICAgICAvLyBhcmd1bWVudHMgaW50byB0aGUgZXhlY3V0ZSBmdW5jdGlvblxuICAgICAgLy8gaG9pc3RlZDogdW5kZWZpbmVkXG4gICAgfVxuICB9O1xufVxuXG5SZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZVtMb2FkZXIucmVzb2x2ZUluc3RhbnRpYXRlXSA9IGZ1bmN0aW9uIChrZXksIHBhcmVudEtleSkge1xuICB2YXIgbG9hZGVyID0gdGhpcztcbiAgdmFyIHN0YXRlID0gdGhpc1tSRUdJU1RFUl9JTlRFUk5BTF07XG4gIHZhciByZWdpc3RyeSA9IHRoaXMucmVnaXN0cnlbUkVHSVNUUlldO1xuXG4gIHJldHVybiByZXNvbHZlSW5zdGFudGlhdGUobG9hZGVyLCBrZXksIHBhcmVudEtleSwgcmVnaXN0cnksIHN0YXRlKVxuICAudGhlbihmdW5jdGlvbiAoaW5zdGFudGlhdGVkKSB7XG4gICAgaWYgKGluc3RhbnRpYXRlZCBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSlcbiAgICAgIHJldHVybiBpbnN0YW50aWF0ZWQ7XG5cbiAgICAvLyByZXNvbHZlSW5zdGFudGlhdGUgYWx3YXlzIHJldHVybnMgYSBsb2FkIHJlY29yZCB3aXRoIGEgbGluayByZWNvcmQgYW5kIG5vIG1vZHVsZSB2YWx1ZVxuICAgIHZhciBsaW5rID0gaW5zdGFudGlhdGVkLmxpbmtSZWNvcmQ7XG5cbiAgICAvLyBpZiBhbHJlYWR5IGJlYXRlbiB0byBkb25lLCByZXR1cm5cbiAgICBpZiAoIWxpbmspIHtcbiAgICAgIGlmIChpbnN0YW50aWF0ZWQubW9kdWxlKVxuICAgICAgICByZXR1cm4gaW5zdGFudGlhdGVkLm1vZHVsZTtcbiAgICAgIHRocm93IGluc3RhbnRpYXRlZC5ldmFsRXJyb3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlZXBJbnN0YW50aWF0ZURlcHMobG9hZGVyLCBpbnN0YW50aWF0ZWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSlcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZW5zdXJlRXZhbHVhdGUobG9hZGVyLCBpbnN0YW50aWF0ZWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSwgdW5kZWZpbmVkKTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlSW5zdGFudGlhdGUgKGxvYWRlciwga2V5LCBwYXJlbnRLZXksIHJlZ2lzdHJ5LCBzdGF0ZSkge1xuICAvLyBub3JtYWxpemF0aW9uIHNob3J0cGF0aCBmb3IgYWxyZWFkeS1ub3JtYWxpemVkIGtleVxuICAvLyBjb3VsZCBhZGQgYSBwbGFpbiBuYW1lIGZpbHRlciwgYnV0IGRvZXNuJ3QgeWV0IHNlZW0gbmVjZXNzYXJ5IGZvciBwZXJmXG4gIHZhciBtb2R1bGUgPSByZWdpc3RyeVtrZXldO1xuICBpZiAobW9kdWxlKVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobW9kdWxlKTtcblxuICB2YXIgbG9hZCA9IHN0YXRlLnJlY29yZHNba2V5XTtcblxuICAvLyBhbHJlYWR5IGxpbmtlZCBidXQgbm90IGluIG1haW4gcmVnaXN0cnkgaXMgaWdub3JlZFxuICBpZiAobG9hZCAmJiAhbG9hZC5tb2R1bGUpIHtcbiAgICBpZiAobG9hZC5sb2FkRXJyb3IpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobG9hZC5sb2FkRXJyb3IpO1xuICAgIHJldHVybiBpbnN0YW50aWF0ZShsb2FkZXIsIGxvYWQsIGxvYWQubGlua1JlY29yZCwgcmVnaXN0cnksIHN0YXRlKTtcbiAgfVxuXG4gIHJldHVybiBsb2FkZXIucmVzb2x2ZShrZXksIHBhcmVudEtleSlcbiAgLnRoZW4oZnVuY3Rpb24gKHJlc29sdmVkS2V5KSB7XG4gICAgLy8gbWFpbiBsb2FkZXIgcmVnaXN0cnkgYWx3YXlzIHRha2VzIHByZWZlcmVuY2VcbiAgICBtb2R1bGUgPSByZWdpc3RyeVtyZXNvbHZlZEtleV07XG4gICAgaWYgKG1vZHVsZSlcbiAgICAgIHJldHVybiBtb2R1bGU7XG5cbiAgICBsb2FkID0gc3RhdGUucmVjb3Jkc1tyZXNvbHZlZEtleV07XG5cbiAgICAvLyBhbHJlYWR5IGhhcyBhIG1vZHVsZSB2YWx1ZSBidXQgbm90IGFscmVhZHkgaW4gdGhlIHJlZ2lzdHJ5IChsb2FkLm1vZHVsZSlcbiAgICAvLyBtZWFucyBpdCB3YXMgcmVtb3ZlZCBieSByZWdpc3RyeS5kZWxldGUsIHNvIHdlIHNob3VsZFxuICAgIC8vIGRpc2dhcmQgdGhlIGN1cnJlbnQgbG9hZCByZWNvcmQgY3JlYXRpbmcgYSBuZXcgb25lIG92ZXIgaXRcbiAgICAvLyBidXQga2VlcCBhbnkgZXhpc3RpbmcgcmVnaXN0cmF0aW9uXG4gICAgaWYgKCFsb2FkIHx8IGxvYWQubW9kdWxlKVxuICAgICAgbG9hZCA9IGNyZWF0ZUxvYWRSZWNvcmQoc3RhdGUsIHJlc29sdmVkS2V5LCBsb2FkICYmIGxvYWQucmVnaXN0cmF0aW9uKTtcblxuICAgIGlmIChsb2FkLmxvYWRFcnJvcilcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChsb2FkLmxvYWRFcnJvcik7XG5cbiAgICB2YXIgbGluayA9IGxvYWQubGlua1JlY29yZDtcbiAgICBpZiAoIWxpbmspXG4gICAgICByZXR1cm4gbG9hZDtcblxuICAgIHJldHVybiBpbnN0YW50aWF0ZShsb2FkZXIsIGxvYWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVQcm9jZXNzQW5vblJlZ2lzdGVyIChsb2FkZXIsIGxvYWQsIHN0YXRlKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxhc3RSZWdpc3RlciA9IHN0YXRlLmxhc3RSZWdpc3RlcjtcblxuICAgIGlmICghbGFzdFJlZ2lzdGVyKVxuICAgICAgcmV0dXJuICEhbG9hZC5yZWdpc3RyYXRpb247XG5cbiAgICBzdGF0ZS5sYXN0UmVnaXN0ZXIgPSB1bmRlZmluZWQ7XG4gICAgbG9hZC5yZWdpc3RyYXRpb24gPSBsYXN0UmVnaXN0ZXI7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaW5zdGFudGlhdGUgKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlKSB7XG4gIHJldHVybiBsaW5rLmluc3RhbnRpYXRlUHJvbWlzZSB8fCAobGluay5pbnN0YW50aWF0ZVByb21pc2UgPVxuICAvLyBpZiB0aGVyZSBpcyBhbHJlYWR5IGFuIGV4aXN0aW5nIHJlZ2lzdHJhdGlvbiwgc2tpcCBydW5uaW5nIGluc3RhbnRpYXRlXG4gIChsb2FkLnJlZ2lzdHJhdGlvbiA/IFByb21pc2UucmVzb2x2ZSgpIDogUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgc3RhdGUubGFzdFJlZ2lzdGVyID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiBsb2FkZXJbSU5TVEFOVElBVEVdKGxvYWQua2V5LCBsb2FkZXJbSU5TVEFOVElBVEVdLmxlbmd0aCA+IDEgJiYgY3JlYXRlUHJvY2Vzc0Fub25SZWdpc3Rlcihsb2FkZXIsIGxvYWQsIHN0YXRlKSk7XG4gIH0pKVxuICAudGhlbihmdW5jdGlvbiAoaW5zdGFudGlhdGlvbikge1xuICAgIC8vIGRpcmVjdCBtb2R1bGUgcmV0dXJuIGZyb20gaW5zdGFudGlhdGUgLT4gd2UncmUgZG9uZVxuICAgIGlmIChpbnN0YW50aWF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICghKGluc3RhbnRpYXRpb24gaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnN0YW50aWF0ZSBkaWQgbm90IHJldHVybiBhIHZhbGlkIE1vZHVsZSBvYmplY3QuJyk7XG5cbiAgICAgIGRlbGV0ZSBzdGF0ZS5yZWNvcmRzW2xvYWQua2V5XTtcbiAgICAgIGlmIChsb2FkZXIudHJhY2UpXG4gICAgICAgIHRyYWNlTG9hZChsb2FkZXIsIGxvYWQsIGxpbmspO1xuICAgICAgcmV0dXJuIHJlZ2lzdHJ5W2xvYWQua2V5XSA9IGluc3RhbnRpYXRpb247XG4gICAgfVxuXG4gICAgLy8gcnVuIHRoZSBjYWNoZWQgbG9hZGVyLnJlZ2lzdGVyIGRlY2xhcmF0aW9uIGlmIHRoZXJlIGlzIG9uZVxuICAgIHZhciByZWdpc3RyYXRpb24gPSBsb2FkLnJlZ2lzdHJhdGlvbjtcbiAgICAvLyBjbGVhciB0byBhbGxvdyBuZXcgcmVnaXN0cmF0aW9ucyBmb3IgZnV0dXJlIGxvYWRzIChjb21iaW5lZCB3aXRoIHJlZ2lzdHJ5IGRlbGV0ZSlcbiAgICBsb2FkLnJlZ2lzdHJhdGlvbiA9IHVuZGVmaW5lZDtcbiAgICBpZiAoIXJlZ2lzdHJhdGlvbilcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ01vZHVsZSBpbnN0YW50aWF0aW9uIGRpZCBub3QgY2FsbCBhbiBhbm9ueW1vdXMgb3IgY29ycmVjdGx5IG5hbWVkIFN5c3RlbS5yZWdpc3Rlci4nKTtcblxuICAgIGxpbmsuZGVwZW5kZW5jaWVzID0gcmVnaXN0cmF0aW9uWzBdO1xuXG4gICAgbG9hZC5pbXBvcnRlclNldHRlcnMgPSBbXTtcblxuICAgIGxpbmsubW9kdWxlT2JqID0ge307XG5cbiAgICAvLyBwcm9jZXNzIFN5c3RlbS5yZWdpc3RlckR5bmFtaWMgZGVjbGFyYXRpb25cbiAgICBpZiAocmVnaXN0cmF0aW9uWzJdKSB7XG4gICAgICBsaW5rLm1vZHVsZU9iai5kZWZhdWx0ID0gbGluay5tb2R1bGVPYmouX191c2VEZWZhdWx0ID0ge307XG4gICAgICBsaW5rLmV4ZWN1dGluZ1JlcXVpcmUgPSByZWdpc3RyYXRpb25bMV07XG4gICAgICBsaW5rLmV4ZWN1dGUgPSByZWdpc3RyYXRpb25bMl07XG4gICAgfVxuXG4gICAgLy8gcHJvY2VzcyBTeXN0ZW0ucmVnaXN0ZXIgZGVjbGFyYXRpb25cbiAgICBlbHNlIHtcbiAgICAgIHJlZ2lzdGVyRGVjbGFyYXRpdmUobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyYXRpb25bMV0pO1xuICAgIH1cblxuICAgIHJldHVybiBsb2FkO1xuICB9KVxuICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgIGxvYWQubGlua1JlY29yZCA9IHVuZGVmaW5lZDtcbiAgICB0aHJvdyBsb2FkLmxvYWRFcnJvciA9IGxvYWQubG9hZEVycm9yIHx8IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnSW5zdGFudGlhdGluZyAnICsgbG9hZC5rZXkpO1xuICB9KSk7XG59XG5cbi8vIGxpa2UgcmVzb2x2ZUluc3RhbnRpYXRlLCBidXQgcmV0dXJuaW5nIGxvYWQgcmVjb3JkcyBmb3IgbGlua2luZ1xuZnVuY3Rpb24gcmVzb2x2ZUluc3RhbnRpYXRlRGVwIChsb2FkZXIsIGtleSwgcGFyZW50S2V5LCByZWdpc3RyeSwgc3RhdGUsIHRyYWNlRGVwTWFwKSB7XG4gIC8vIG5vcm1hbGl6YXRpb24gc2hvcnRwYXRocyBmb3IgYWxyZWFkeS1ub3JtYWxpemVkIGtleVxuICAvLyBESVNBQkxFRCB0byBwcmlvcml0aXNlIGNvbnNpc3RlbnQgcmVzb2x2ZXIgY2FsbHNcbiAgLy8gY291bGQgYWRkIGEgcGxhaW4gbmFtZSBmaWx0ZXIsIGJ1dCBkb2Vzbid0IHlldCBzZWVtIG5lY2Vzc2FyeSBmb3IgcGVyZlxuICAvKiB2YXIgbG9hZCA9IHN0YXRlLnJlY29yZHNba2V5XTtcbiAgdmFyIG1vZHVsZSA9IHJlZ2lzdHJ5W2tleV07XG5cbiAgaWYgKG1vZHVsZSkge1xuICAgIGlmICh0cmFjZURlcE1hcClcbiAgICAgIHRyYWNlRGVwTWFwW2tleV0gPSBrZXk7XG5cbiAgICAvLyByZWdpc3RyeSBhdXRob3JpdHkgY2hlY2sgaW4gY2FzZSBtb2R1bGUgd2FzIGRlbGV0ZWQgb3IgcmVwbGFjZWQgaW4gbWFpbiByZWdpc3RyeVxuICAgIGlmIChsb2FkICYmIGxvYWQubW9kdWxlICYmIGxvYWQubW9kdWxlID09PSBtb2R1bGUpXG4gICAgICByZXR1cm4gbG9hZDtcbiAgICBlbHNlXG4gICAgICByZXR1cm4gbW9kdWxlO1xuICB9XG5cbiAgLy8gYWxyZWFkeSBsaW5rZWQgYnV0IG5vdCBpbiBtYWluIHJlZ2lzdHJ5IGlzIGlnbm9yZWRcbiAgaWYgKGxvYWQgJiYgIWxvYWQubW9kdWxlKSB7XG4gICAgaWYgKHRyYWNlRGVwTWFwKVxuICAgICAgdHJhY2VEZXBNYXBba2V5XSA9IGtleTtcbiAgICByZXR1cm4gaW5zdGFudGlhdGUobG9hZGVyLCBsb2FkLCBsb2FkLmxpbmtSZWNvcmQsIHJlZ2lzdHJ5LCBzdGF0ZSk7XG4gIH0gKi9cbiAgcmV0dXJuIGxvYWRlci5yZXNvbHZlKGtleSwgcGFyZW50S2V5KVxuICAudGhlbihmdW5jdGlvbiAocmVzb2x2ZWRLZXkpIHtcbiAgICBpZiAodHJhY2VEZXBNYXApXG4gICAgICB0cmFjZURlcE1hcFtrZXldID0gcmVzb2x2ZWRLZXk7XG5cbiAgICAvLyBub3JtYWxpemF0aW9uIHNob3J0cGF0aHMgZm9yIGFscmVhZHktbm9ybWFsaXplZCBrZXlcbiAgICB2YXIgbG9hZCA9IHN0YXRlLnJlY29yZHNbcmVzb2x2ZWRLZXldO1xuICAgIHZhciBtb2R1bGUgPSByZWdpc3RyeVtyZXNvbHZlZEtleV07XG5cbiAgICAvLyBtYWluIGxvYWRlciByZWdpc3RyeSBhbHdheXMgdGFrZXMgcHJlZmVyZW5jZVxuICAgIGlmIChtb2R1bGUgJiYgKCFsb2FkIHx8IGxvYWQubW9kdWxlICYmIG1vZHVsZSAhPT0gbG9hZC5tb2R1bGUpKVxuICAgICAgcmV0dXJuIG1vZHVsZTtcblxuICAgIGlmIChsb2FkICYmIGxvYWQubG9hZEVycm9yKVxuICAgICAgdGhyb3cgbG9hZC5sb2FkRXJyb3I7XG5cbiAgICAvLyBhbHJlYWR5IGhhcyBhIG1vZHVsZSB2YWx1ZSBidXQgbm90IGFscmVhZHkgaW4gdGhlIHJlZ2lzdHJ5IChsb2FkLm1vZHVsZSlcbiAgICAvLyBtZWFucyBpdCB3YXMgcmVtb3ZlZCBieSByZWdpc3RyeS5kZWxldGUsIHNvIHdlIHNob3VsZFxuICAgIC8vIGRpc2dhcmQgdGhlIGN1cnJlbnQgbG9hZCByZWNvcmQgY3JlYXRpbmcgYSBuZXcgb25lIG92ZXIgaXRcbiAgICAvLyBidXQga2VlcCBhbnkgZXhpc3RpbmcgcmVnaXN0cmF0aW9uXG4gICAgaWYgKCFsb2FkIHx8ICFtb2R1bGUgJiYgbG9hZC5tb2R1bGUpXG4gICAgICBsb2FkID0gY3JlYXRlTG9hZFJlY29yZChzdGF0ZSwgcmVzb2x2ZWRLZXksIGxvYWQgJiYgbG9hZC5yZWdpc3RyYXRpb24pO1xuXG4gICAgdmFyIGxpbmsgPSBsb2FkLmxpbmtSZWNvcmQ7XG4gICAgaWYgKCFsaW5rKVxuICAgICAgcmV0dXJuIGxvYWQ7XG5cbiAgICByZXR1cm4gaW5zdGFudGlhdGUobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdHJhY2VMb2FkIChsb2FkZXIsIGxvYWQsIGxpbmspIHtcbiAgbG9hZGVyLmxvYWRzID0gbG9hZGVyLmxvYWRzIHx8IHt9O1xuICBsb2FkZXIubG9hZHNbbG9hZC5rZXldID0ge1xuICAgIGtleTogbG9hZC5rZXksXG4gICAgZGVwczogbGluay5kZXBlbmRlbmNpZXMsXG4gICAgZHluYW1pY0RlcHM6IFtdLFxuICAgIGRlcE1hcDogbGluay5kZXBNYXAgfHwge31cbiAgfTtcbn1cblxuLypcbiAqIENvbnZlcnQgYSBDSlMgbW9kdWxlLmV4cG9ydHMgaW50byBhIHZhbGlkIG9iamVjdCBmb3IgbmV3IE1vZHVsZTpcbiAqXG4gKiAgIG5ldyBNb2R1bGUoZ2V0RXNNb2R1bGUobW9kdWxlLmV4cG9ydHMpKVxuICpcbiAqIFNldHMgdGhlIGRlZmF1bHQgdmFsdWUgdG8gdGhlIG1vZHVsZSwgd2hpbGUgYWxzbyByZWFkaW5nIG9mZiBuYW1lZCBleHBvcnRzIGNhcmVmdWxseS5cbiAqL1xuZnVuY3Rpb24gcmVnaXN0ZXJEZWNsYXJhdGl2ZSAobG9hZGVyLCBsb2FkLCBsaW5rLCBkZWNsYXJlKSB7XG4gIHZhciBtb2R1bGVPYmogPSBsaW5rLm1vZHVsZU9iajtcbiAgdmFyIGltcG9ydGVyU2V0dGVycyA9IGxvYWQuaW1wb3J0ZXJTZXR0ZXJzO1xuXG4gIHZhciBkZWZpbmVkRXhwb3J0cyA9IGZhbHNlO1xuXG4gIC8vIGNsb3N1cmUgZXNwZWNpYWxseSBub3QgYmFzZWQgb24gbGluayB0byBhbGxvdyBsaW5rIHJlY29yZCBkaXNwb3NhbFxuICB2YXIgZGVjbGFyZWQgPSBkZWNsYXJlLmNhbGwoZW52R2xvYmFsLCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09ICdvYmplY3QnKSB7XG4gICAgICB2YXIgY2hhbmdlZCA9IGZhbHNlO1xuICAgICAgZm9yICh2YXIgcCBpbiBuYW1lKSB7XG4gICAgICAgIHZhbHVlID0gbmFtZVtwXTtcbiAgICAgICAgaWYgKHAgIT09ICdfX3VzZURlZmF1bHQnICYmICghKHAgaW4gbW9kdWxlT2JqKSB8fCBtb2R1bGVPYmpbcF0gIT09IHZhbHVlKSkge1xuICAgICAgICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgIG1vZHVsZU9ialtwXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY2hhbmdlZCA9PT0gZmFsc2UpXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBpZiAoKGRlZmluZWRFeHBvcnRzIHx8IG5hbWUgaW4gbW9kdWxlT2JqKSAmJiBtb2R1bGVPYmpbbmFtZV0gPT09IHZhbHVlKVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICBtb2R1bGVPYmpbbmFtZV0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGltcG9ydGVyU2V0dGVycy5sZW5ndGg7IGkrKylcbiAgICAgIGltcG9ydGVyU2V0dGVyc1tpXShtb2R1bGVPYmopO1xuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9LCBuZXcgQ29udGV4dHVhbExvYWRlcihsb2FkZXIsIGxvYWQua2V5KSk7XG5cbiAgbGluay5zZXR0ZXJzID0gZGVjbGFyZWQuc2V0dGVycztcbiAgbGluay5leGVjdXRlID0gZGVjbGFyZWQuZXhlY3V0ZTtcbiAgaWYgKGRlY2xhcmVkLmV4cG9ydHMpIHtcbiAgICBsaW5rLm1vZHVsZU9iaiA9IG1vZHVsZU9iaiA9IGRlY2xhcmVkLmV4cG9ydHM7XG4gICAgZGVmaW5lZEV4cG9ydHMgPSB0cnVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGluc3RhbnRpYXRlRGVwcyAobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUpIHtcbiAgaWYgKGxpbmsuZGVwc0luc3RhbnRpYXRlUHJvbWlzZSlcbiAgICByZXR1cm4gbGluay5kZXBzSW5zdGFudGlhdGVQcm9taXNlO1xuXG4gIHZhciBkZXBzSW5zdGFudGlhdGVQcm9taXNlcyA9IEFycmF5KGxpbmsuZGVwZW5kZW5jaWVzLmxlbmd0aCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5rLmRlcGVuZGVuY2llcy5sZW5ndGg7IGkrKylcbiAgICBkZXBzSW5zdGFudGlhdGVQcm9taXNlc1tpXSA9IHJlc29sdmVJbnN0YW50aWF0ZURlcChsb2FkZXIsIGxpbmsuZGVwZW5kZW5jaWVzW2ldLCBsb2FkLmtleSwgcmVnaXN0cnksIHN0YXRlLCBsb2FkZXIudHJhY2UgJiYgbGluay5kZXBNYXAgfHwgKGxpbmsuZGVwTWFwID0ge30pKTtcblxuICB2YXIgZGVwc0luc3RhbnRpYXRlUHJvbWlzZSA9IFByb21pc2UuYWxsKGRlcHNJbnN0YW50aWF0ZVByb21pc2VzKVxuICAudGhlbihmdW5jdGlvbiAoZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zKSB7XG4gICAgbGluay5kZXBlbmRlbmN5SW5zdGFudGlhdGlvbnMgPSBkZXBlbmRlbmN5SW5zdGFudGlhdGlvbnM7XG5cbiAgICAvLyBydW4gc2V0dGVycyB0byBzZXQgdXAgYmluZGluZ3MgdG8gaW5zdGFudGlhdGVkIGRlcGVuZGVuY2llc1xuICAgIGlmIChsaW5rLnNldHRlcnMpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzZXR0ZXIgPSBsaW5rLnNldHRlcnNbaV07XG4gICAgICAgIGlmIChzZXR0ZXIpIHtcbiAgICAgICAgICB2YXIgaW5zdGFudGlhdGlvbiA9IGRlcGVuZGVuY3lJbnN0YW50aWF0aW9uc1tpXTtcblxuICAgICAgICAgIGlmIChpbnN0YW50aWF0aW9uIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlKSB7XG4gICAgICAgICAgICBzZXR0ZXIoaW5zdGFudGlhdGlvbik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKGluc3RhbnRpYXRpb24ubG9hZEVycm9yKVxuICAgICAgICAgICAgICB0aHJvdyBpbnN0YW50aWF0aW9uLmxvYWRFcnJvcjtcbiAgICAgICAgICAgIHNldHRlcihpbnN0YW50aWF0aW9uLm1vZHVsZSB8fCBpbnN0YW50aWF0aW9uLmxpbmtSZWNvcmQubW9kdWxlT2JqKTtcbiAgICAgICAgICAgIC8vIHRoaXMgYXBwbGllcyB0byBib3RoIGVzIGFuZCBkeW5hbWljIHJlZ2lzdHJhdGlvbnNcbiAgICAgICAgICAgIGlmIChpbnN0YW50aWF0aW9uLmltcG9ydGVyU2V0dGVycylcbiAgICAgICAgICAgICAgaW5zdGFudGlhdGlvbi5pbXBvcnRlclNldHRlcnMucHVzaChzZXR0ZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBsb2FkO1xuICB9KTtcblxuICBpZiAobG9hZGVyLnRyYWNlKVxuICAgIGRlcHNJbnN0YW50aWF0ZVByb21pc2UgPSBkZXBzSW5zdGFudGlhdGVQcm9taXNlLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgdHJhY2VMb2FkKGxvYWRlciwgbG9hZCwgbGluayk7XG4gICAgICByZXR1cm4gbG9hZDtcbiAgICB9KTtcblxuICBkZXBzSW5zdGFudGlhdGVQcm9taXNlID0gZGVwc0luc3RhbnRpYXRlUHJvbWlzZS5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgLy8gdGhyb3cgdXAgdGhlIGluc3RhbnRpYXRlRGVwcyBzdGFja1xuICAgIGxpbmsuZGVwc0luc3RhbnRpYXRlUHJvbWlzZSA9IHVuZGVmaW5lZDtcbiAgICB0aHJvdyBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrKGVyciwgJ0xvYWRpbmcgJyArIGxvYWQua2V5KTtcbiAgfSk7XG5cbiAgZGVwc0luc3RhbnRpYXRlUHJvbWlzZS5jYXRjaChmdW5jdGlvbiAoKSB7fSk7XG5cbiAgcmV0dXJuIGxpbmsuZGVwc0luc3RhbnRpYXRlUHJvbWlzZSA9IGRlcHNJbnN0YW50aWF0ZVByb21pc2U7XG59XG5cbmZ1bmN0aW9uIGRlZXBJbnN0YW50aWF0ZURlcHMgKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHNlZW4gPSBbXTtcbiAgICB2YXIgbG9hZENudCA9IDA7XG4gICAgZnVuY3Rpb24gcXVldWVMb2FkIChsb2FkKSB7XG4gICAgICB2YXIgbGluayA9IGxvYWQubGlua1JlY29yZDtcbiAgICAgIGlmICghbGluaylcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBpZiAoc2Vlbi5pbmRleE9mKGxvYWQpICE9PSAtMSlcbiAgICAgICAgcmV0dXJuO1xuICAgICAgc2Vlbi5wdXNoKGxvYWQpO1xuXG4gICAgICBsb2FkQ250Kys7XG4gICAgICBpbnN0YW50aWF0ZURlcHMobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUpXG4gICAgICAudGhlbihwcm9jZXNzTG9hZCwgcmVqZWN0KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvY2Vzc0xvYWQgKGxvYWQpIHtcbiAgICAgIGxvYWRDbnQtLTtcbiAgICAgIHZhciBsaW5rID0gbG9hZC5saW5rUmVjb3JkO1xuICAgICAgaWYgKGxpbmspIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5rLmRlcGVuZGVuY2llcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBkZXBMb2FkID0gbGluay5kZXBlbmRlbmN5SW5zdGFudGlhdGlvbnNbaV07XG4gICAgICAgICAgaWYgKCEoZGVwTG9hZCBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSkpXG4gICAgICAgICAgICBxdWV1ZUxvYWQoZGVwTG9hZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChsb2FkQ250ID09PSAwKVxuICAgICAgICByZXNvbHZlKCk7XG4gICAgfVxuICAgIHF1ZXVlTG9hZChsb2FkKTtcbiAgfSk7XG59XG5cbi8qXG4gKiBTeXN0ZW0ucmVnaXN0ZXJcbiAqL1xuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUucmVnaXN0ZXIgPSBmdW5jdGlvbiAoa2V5LCBkZXBzLCBkZWNsYXJlKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXNbUkVHSVNURVJfSU5URVJOQUxdO1xuXG4gIC8vIGFub255bW91cyBtb2R1bGVzIGdldCBzdG9yZWQgYXMgbGFzdEFub25cbiAgaWYgKGRlY2xhcmUgPT09IHVuZGVmaW5lZCkge1xuICAgIHN0YXRlLmxhc3RSZWdpc3RlciA9IFtrZXksIGRlcHMsIHVuZGVmaW5lZF07XG4gIH1cblxuICAvLyBldmVyeXRoaW5nIGVsc2UgcmVnaXN0ZXJzIGludG8gdGhlIHJlZ2lzdGVyIGNhY2hlXG4gIGVsc2Uge1xuICAgIHZhciBsb2FkID0gc3RhdGUucmVjb3Jkc1trZXldIHx8IGNyZWF0ZUxvYWRSZWNvcmQoc3RhdGUsIGtleSwgdW5kZWZpbmVkKTtcbiAgICBsb2FkLnJlZ2lzdHJhdGlvbiA9IFtkZXBzLCBkZWNsYXJlLCB1bmRlZmluZWRdO1xuICB9XG59O1xuXG4vKlxuICogU3lzdGVtLnJlZ2lzdGVyRHlhbm1pY1xuICovXG5SZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5yZWdpc3RlckR5bmFtaWMgPSBmdW5jdGlvbiAoa2V5LCBkZXBzLCBleGVjdXRpbmdSZXF1aXJlLCBleGVjdXRlKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXNbUkVHSVNURVJfSU5URVJOQUxdO1xuXG4gIC8vIGFub255bW91cyBtb2R1bGVzIGdldCBzdG9yZWQgYXMgbGFzdEFub25cbiAgaWYgKHR5cGVvZiBrZXkgIT09ICdzdHJpbmcnKSB7XG4gICAgc3RhdGUubGFzdFJlZ2lzdGVyID0gW2tleSwgZGVwcywgZXhlY3V0aW5nUmVxdWlyZV07XG4gIH1cblxuICAvLyBldmVyeXRoaW5nIGVsc2UgcmVnaXN0ZXJzIGludG8gdGhlIHJlZ2lzdGVyIGNhY2hlXG4gIGVsc2Uge1xuICAgIHZhciBsb2FkID0gc3RhdGUucmVjb3Jkc1trZXldIHx8IGNyZWF0ZUxvYWRSZWNvcmQoc3RhdGUsIGtleSwgdW5kZWZpbmVkKTtcbiAgICBsb2FkLnJlZ2lzdHJhdGlvbiA9IFtkZXBzLCBleGVjdXRpbmdSZXF1aXJlLCBleGVjdXRlXTtcbiAgfVxufTtcblxuLy8gQ29udGV4dHVhbExvYWRlciBjbGFzc1xuLy8gYmFja3dhcmRzLWNvbXBhdGlibGUgd2l0aCBwcmV2aW91cyBTeXN0ZW0ucmVnaXN0ZXIgY29udGV4dCBhcmd1bWVudCBieSBleHBvc2luZyAuaWQsIC5rZXlcbmZ1bmN0aW9uIENvbnRleHR1YWxMb2FkZXIgKGxvYWRlciwga2V5KSB7XG4gIHRoaXMubG9hZGVyID0gbG9hZGVyO1xuICB0aGlzLmtleSA9IHRoaXMuaWQgPSBrZXk7XG4gIHRoaXMubWV0YSA9IHtcbiAgICB1cmw6IGtleVxuICAgIC8vIHNjcmlwdEVsZW1lbnQ6IG51bGxcbiAgfTtcbn1cbi8qQ29udGV4dHVhbExvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBmdW5jdGlvbiAoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBzdWJjbGFzcyB0aGUgY29udGV4dHVhbCBsb2FkZXIgb25seSBSZWZsZWN0LkxvYWRlci4nKTtcbn07Ki9cbkNvbnRleHR1YWxMb2FkZXIucHJvdG90eXBlLmltcG9ydCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgaWYgKHRoaXMubG9hZGVyLnRyYWNlKVxuICAgIHRoaXMubG9hZGVyLmxvYWRzW3RoaXMua2V5XS5keW5hbWljRGVwcy5wdXNoKGtleSk7XG4gIHJldHVybiB0aGlzLmxvYWRlci5pbXBvcnQoa2V5LCB0aGlzLmtleSk7XG59O1xuLypDb250ZXh0dWFsTG9hZGVyLnByb3RvdHlwZS5yZXNvbHZlID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gdGhpcy5sb2FkZXIucmVzb2x2ZShrZXksIHRoaXMua2V5KTtcbn07Ki9cblxuLy8gdGhpcyBpcyB0aGUgZXhlY3V0aW9uIGZ1bmN0aW9uIGJvdW5kIHRvIHRoZSBNb2R1bGUgbmFtZXNwYWNlIHJlY29yZFxuZnVuY3Rpb24gZW5zdXJlRXZhbHVhdGUgKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlLCBzZWVuKSB7XG4gIGlmIChsb2FkLm1vZHVsZSlcbiAgICByZXR1cm4gbG9hZC5tb2R1bGU7XG5cbiAgaWYgKGxvYWQuZXZhbEVycm9yKVxuICAgIHRocm93IGxvYWQuZXZhbEVycm9yO1xuXG4gIGlmIChzZWVuICYmIHNlZW4uaW5kZXhPZihsb2FkKSAhPT0gLTEpXG4gICAgcmV0dXJuIGxvYWQubGlua1JlY29yZC5tb2R1bGVPYmo7XG5cbiAgLy8gZm9yIEVTIGxvYWRzIHdlIGFsd2F5cyBydW4gZW5zdXJlRXZhbHVhdGUgb24gdG9wLWxldmVsLCBzbyBlbXB0eSBzZWVuIGlzIHBhc3NlZCByZWdhcmRsZXNzXG4gIC8vIGZvciBkeW5hbWljIGxvYWRzLCB3ZSBwYXNzIHNlZW4gaWYgYWxzbyBkeW5hbWljXG4gIHZhciBlcnIgPSBkb0V2YWx1YXRlKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlLCBsaW5rLnNldHRlcnMgPyBbXSA6IHNlZW4gfHwgW10pO1xuICBpZiAoZXJyKVxuICAgIHRocm93IGVycjtcblxuICByZXR1cm4gbG9hZC5tb2R1bGU7XG59XG5cbmZ1bmN0aW9uIG1ha2VEeW5hbWljUmVxdWlyZSAobG9hZGVyLCBrZXksIGRlcGVuZGVuY2llcywgZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zLCByZWdpc3RyeSwgc3RhdGUsIHNlZW4pIHtcbiAgLy8gd2UgY2FuIG9ubHkgcmVxdWlyZSBmcm9tIGFscmVhZHkta25vd24gZGVwZW5kZW5jaWVzXG4gIHJldHVybiBmdW5jdGlvbiAobmFtZSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwZW5kZW5jaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoZGVwZW5kZW5jaWVzW2ldID09PSBuYW1lKSB7XG4gICAgICAgIHZhciBkZXBMb2FkID0gZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zW2ldO1xuICAgICAgICB2YXIgbW9kdWxlO1xuXG4gICAgICAgIGlmIChkZXBMb2FkIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlKVxuICAgICAgICAgIG1vZHVsZSA9IGRlcExvYWQ7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtb2R1bGUgPSBlbnN1cmVFdmFsdWF0ZShsb2FkZXIsIGRlcExvYWQsIGRlcExvYWQubGlua1JlY29yZCwgcmVnaXN0cnksIHN0YXRlLCBzZWVuKTtcblxuICAgICAgICByZXR1cm4gJ19fdXNlRGVmYXVsdCcgaW4gbW9kdWxlID8gbW9kdWxlLl9fdXNlRGVmYXVsdCA6IG1vZHVsZTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNb2R1bGUgJyArIG5hbWUgKyAnIG5vdCBkZWNsYXJlZCBhcyBhIFN5c3RlbS5yZWdpc3RlckR5bmFtaWMgZGVwZW5kZW5jeSBvZiAnICsga2V5KTtcbiAgfTtcbn1cblxuLy8gZW5zdXJlcyB0aGUgZ2l2ZW4gZXMgbG9hZCBpcyBldmFsdWF0ZWRcbi8vIHJldHVybnMgdGhlIGVycm9yIGlmIGFueVxuZnVuY3Rpb24gZG9FdmFsdWF0ZSAobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUsIHNlZW4pIHtcbiAgc2Vlbi5wdXNoKGxvYWQpO1xuXG4gIHZhciBlcnI7XG5cbiAgLy8gZXMgbW9kdWxlcyBldmFsdWF0ZSBkZXBlbmRlbmNpZXMgZmlyc3RcbiAgLy8gbm9uIGVzIG1vZHVsZXMgZXhwbGljaXRseSBjYWxsIG1vZHVsZUV2YWx1YXRlIHRocm91Z2ggcmVxdWlyZVxuICBpZiAobGluay5zZXR0ZXJzKSB7XG4gICAgdmFyIGRlcExvYWQsIGRlcExpbms7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5rLmRlcGVuZGVuY2llcy5sZW5ndGg7IGkrKykge1xuICAgICAgZGVwTG9hZCA9IGxpbmsuZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zW2ldO1xuXG4gICAgICBpZiAoZGVwTG9hZCBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSlcbiAgICAgICAgY29udGludWU7XG5cbiAgICAgIC8vIGN1c3RvbSBNb2R1bGUgcmV0dXJuZWQgZnJvbSBpbnN0YW50aWF0ZVxuICAgICAgZGVwTGluayA9IGRlcExvYWQubGlua1JlY29yZDtcbiAgICAgIGlmIChkZXBMaW5rICYmIHNlZW4uaW5kZXhPZihkZXBMb2FkKSA9PT0gLTEpIHtcbiAgICAgICAgaWYgKGRlcExvYWQuZXZhbEVycm9yKVxuICAgICAgICAgIGVyciA9IGRlcExvYWQuZXZhbEVycm9yO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgLy8gZHluYW1pYyAvIGRlY2xhcmF0aXZlIGJvdW5kYXJpZXMgY2xlYXIgdGhlIFwic2VlblwiIGxpc3RcbiAgICAgICAgICAvLyB3ZSBqdXN0IGxldCBjcm9zcyBmb3JtYXQgY2lyY3VsYXIgdGhyb3cgYXMgd291bGQgaGFwcGVuIGluIHJlYWwgaW1wbGVtZW50YXRpb25zXG4gICAgICAgICAgZXJyID0gZG9FdmFsdWF0ZShsb2FkZXIsIGRlcExvYWQsIGRlcExpbmssIHJlZ2lzdHJ5LCBzdGF0ZSwgZGVwTGluay5zZXR0ZXJzID8gc2VlbiA6IFtdKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVycikge1xuICAgICAgICBsb2FkLmxpbmtSZWNvcmQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGxvYWQuZXZhbEVycm9yID0gTG9hZGVyRXJyb3JfX0NoZWNrX2Vycm9yX21lc3NhZ2VfZm9yX2xvYWRlcl9zdGFjayhlcnIsICdFdmFsdWF0aW5nICcgKyBsb2FkLmtleSk7XG4gICAgICAgIHJldHVybiBsb2FkLmV2YWxFcnJvcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBsaW5rLmV4ZWN1dGUgd29uJ3QgZXhpc3QgZm9yIE1vZHVsZSByZXR1cm5zIGZyb20gaW5zdGFudGlhdGUgb24gdG9wLWxldmVsIGxvYWRcbiAgaWYgKGxpbmsuZXhlY3V0ZSkge1xuICAgIC8vIEVTIFN5c3RlbS5yZWdpc3RlciBleGVjdXRlXG4gICAgLy8gXCJ0aGlzXCIgaXMgbnVsbCBpbiBFU1xuICAgIGlmIChsaW5rLnNldHRlcnMpIHtcbiAgICAgIGVyciA9IGRlY2xhcmF0aXZlRXhlY3V0ZShsaW5rLmV4ZWN1dGUpO1xuICAgIH1cbiAgICAvLyBTeXN0ZW0ucmVnaXN0ZXJEeW5hbWljIGV4ZWN1dGVcbiAgICAvLyBcInRoaXNcIiBpcyBcImV4cG9ydHNcIiBpbiBDSlNcbiAgICBlbHNlIHtcbiAgICAgIHZhciBtb2R1bGUgPSB7IGlkOiBsb2FkLmtleSB9O1xuICAgICAgdmFyIG1vZHVsZU9iaiA9IGxpbmsubW9kdWxlT2JqO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZSwgJ2V4cG9ydHMnLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbiAoZXhwb3J0cykge1xuICAgICAgICAgIG1vZHVsZU9iai5kZWZhdWx0ID0gbW9kdWxlT2JqLl9fdXNlRGVmYXVsdCA9IGV4cG9ydHM7XG4gICAgICAgIH0sXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBtb2R1bGVPYmouX191c2VEZWZhdWx0O1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdmFyIHJlcXVpcmUgPSBtYWtlRHluYW1pY1JlcXVpcmUobG9hZGVyLCBsb2FkLmtleSwgbGluay5kZXBlbmRlbmNpZXMsIGxpbmsuZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zLCByZWdpc3RyeSwgc3RhdGUsIHNlZW4pO1xuXG4gICAgICAvLyBldmFsdWF0ZSBkZXBzIGZpcnN0XG4gICAgICBpZiAoIWxpbmsuZXhlY3V0aW5nUmVxdWlyZSlcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5rLmRlcGVuZGVuY2llcy5sZW5ndGg7IGkrKylcbiAgICAgICAgICByZXF1aXJlKGxpbmsuZGVwZW5kZW5jaWVzW2ldKTtcblxuICAgICAgZXJyID0gZHluYW1pY0V4ZWN1dGUobGluay5leGVjdXRlLCByZXF1aXJlLCBtb2R1bGVPYmouZGVmYXVsdCwgbW9kdWxlKTtcblxuICAgICAgLy8gcGljayB1cCBkZWZpbmVQcm9wZXJ0eSBjYWxscyB0byBtb2R1bGUuZXhwb3J0cyB3aGVuIHdlIGNhblxuICAgICAgaWYgKG1vZHVsZS5leHBvcnRzICE9PSBtb2R1bGVPYmouX191c2VEZWZhdWx0KVxuICAgICAgICBtb2R1bGVPYmouZGVmYXVsdCA9IG1vZHVsZU9iai5fX3VzZURlZmF1bHQgPSBtb2R1bGUuZXhwb3J0cztcblxuICAgICAgdmFyIG1vZHVsZURlZmF1bHQgPSBtb2R1bGVPYmouZGVmYXVsdDtcblxuICAgICAgLy8gX19lc01vZHVsZSBmbGFnIGV4dGVuc2lvbiBzdXBwb3J0IHZpYSBsaWZ0aW5nXG4gICAgICBpZiAobW9kdWxlRGVmYXVsdCAmJiBtb2R1bGVEZWZhdWx0Ll9fZXNNb2R1bGUpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBtb2R1bGVEZWZhdWx0KSB7XG4gICAgICAgICAgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZHVsZURlZmF1bHQsIHApKVxuICAgICAgICAgICAgbW9kdWxlT2JqW3BdID0gbW9kdWxlRGVmYXVsdFtwXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIGRpc3Bvc2UgbGluayByZWNvcmRcbiAgbG9hZC5saW5rUmVjb3JkID0gdW5kZWZpbmVkO1xuXG4gIGlmIChlcnIpXG4gICAgcmV0dXJuIGxvYWQuZXZhbEVycm9yID0gTG9hZGVyRXJyb3JfX0NoZWNrX2Vycm9yX21lc3NhZ2VfZm9yX2xvYWRlcl9zdGFjayhlcnIsICdFdmFsdWF0aW5nICcgKyBsb2FkLmtleSk7XG5cbiAgcmVnaXN0cnlbbG9hZC5rZXldID0gbG9hZC5tb2R1bGUgPSBuZXcgTW9kdWxlTmFtZXNwYWNlKGxpbmsubW9kdWxlT2JqKTtcblxuICAvLyBpZiBub3QgYW4gZXNtIG1vZHVsZSwgcnVuIGltcG9ydGVyIHNldHRlcnMgYW5kIGNsZWFyIHRoZW1cbiAgLy8gdGhpcyBhbGxvd3MgZHluYW1pYyBtb2R1bGVzIHRvIHVwZGF0ZSB0aGVtc2VsdmVzIGludG8gZXMgbW9kdWxlc1xuICAvLyBhcyBzb29uIGFzIGV4ZWN1dGlvbiBoYXMgY29tcGxldGVkXG4gIGlmICghbGluay5zZXR0ZXJzKSB7XG4gICAgaWYgKGxvYWQuaW1wb3J0ZXJTZXR0ZXJzKVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2FkLmltcG9ydGVyU2V0dGVycy5sZW5ndGg7IGkrKylcbiAgICAgICAgbG9hZC5pbXBvcnRlclNldHRlcnNbaV0obG9hZC5tb2R1bGUpO1xuICAgIGxvYWQuaW1wb3J0ZXJTZXR0ZXJzID0gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8vIHt9IGlzIHRoZSBjbG9zZXN0IHdlIGNhbiBnZXQgdG8gY2FsbCh1bmRlZmluZWQpXG52YXIgbnVsbENvbnRleHQgPSB7fTtcbmlmIChPYmplY3QuZnJlZXplKVxuICBPYmplY3QuZnJlZXplKG51bGxDb250ZXh0KTtcblxuZnVuY3Rpb24gZGVjbGFyYXRpdmVFeGVjdXRlIChleGVjdXRlKSB7XG4gIHRyeSB7XG4gICAgZXhlY3V0ZS5jYWxsKG51bGxDb250ZXh0KTtcbiAgfVxuICBjYXRjaCAoZSkge1xuICAgIHJldHVybiBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGR5bmFtaWNFeGVjdXRlIChleGVjdXRlLCByZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgdHJ5IHtcbiAgICB2YXIgb3V0cHV0ID0gZXhlY3V0ZS5jYWxsKGVudkdsb2JhbCwgcmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKTtcbiAgICBpZiAob3V0cHV0ICE9PSB1bmRlZmluZWQpXG4gICAgICBtb2R1bGUuZXhwb3J0cyA9IG91dHB1dDtcbiAgfVxuICBjYXRjaCAoZSkge1xuICAgIHJldHVybiBlO1xuICB9XG59XG5cbnZhciByZXNvbHZlZFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbmZ1bmN0aW9uIG5vb3AgKCkge31cblxudmFyIGVtcHR5TW9kdWxlID0gbmV3IE1vZHVsZU5hbWVzcGFjZSh7fSk7XG5cbmZ1bmN0aW9uIHByb3RlY3RlZENyZWF0ZU5hbWVzcGFjZSAoYmluZGluZ3MpIHtcbiAgaWYgKGJpbmRpbmdzIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlKVxuICAgIHJldHVybiBiaW5kaW5ncztcblxuICBpZiAoYmluZGluZ3MgJiYgYmluZGluZ3MuX19lc01vZHVsZSlcbiAgICByZXR1cm4gbmV3IE1vZHVsZU5hbWVzcGFjZShiaW5kaW5ncyk7XG5cbiAgcmV0dXJuIG5ldyBNb2R1bGVOYW1lc3BhY2UoeyBkZWZhdWx0OiBiaW5kaW5ncywgX191c2VEZWZhdWx0OiBiaW5kaW5ncyB9KTtcbn1cblxudmFyIGhhc1N0cmluZ1RhZztcbmZ1bmN0aW9uIGlzTW9kdWxlIChtKSB7XG4gIGlmIChoYXNTdHJpbmdUYWcgPT09IHVuZGVmaW5lZClcbiAgICBoYXNTdHJpbmdUYWcgPSB0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiAhIVN5bWJvbC50b1N0cmluZ1RhZztcbiAgcmV0dXJuIG0gaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UgfHwgaGFzU3RyaW5nVGFnICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtKSA9PSAnW29iamVjdCBNb2R1bGVdJztcbn1cblxudmFyIENPTkZJRyA9IGNyZWF0ZVN5bWJvbCgnbG9hZGVyLWNvbmZpZycpO1xudmFyIE1FVEFEQVRBID0gY3JlYXRlU3ltYm9sKCdtZXRhZGF0YScpO1xuXG5cblxudmFyIGlzV29ya2VyID0gdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBpbXBvcnRTY3JpcHRzICE9PSAndW5kZWZpbmVkJztcblxuZnVuY3Rpb24gd2FybiAobXNnLCBmb3JjZSkge1xuICBpZiAoZm9yY2UgfHwgdGhpcy53YXJuaW5ncyAmJiB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgY29uc29sZS53YXJuKVxuICAgIGNvbnNvbGUud2Fybihtc2cpO1xufVxuXG5mdW5jdGlvbiBjaGVja0luc3RhbnRpYXRlV2FzbSAobG9hZGVyLCB3YXNtQnVmZmVyLCBwcm9jZXNzQW5vblJlZ2lzdGVyKSB7XG4gIHZhciBieXRlcyA9IG5ldyBVaW50OEFycmF5KHdhc21CdWZmZXIpO1xuXG4gIC8vIGRldGVjdCBieSBsZWFkaW5nIGJ5dGVzXG4gIC8vIENhbiBiZSAobmV3IFVpbnQzMkFycmF5KGZldGNoZWQpKVswXSA9PT0gMHg2RDczNjEwMCB3aGVuIHdvcmtpbmcgaW4gTm9kZVxuICBpZiAoYnl0ZXNbMF0gPT09IDAgJiYgYnl0ZXNbMV0gPT09IDk3ICYmIGJ5dGVzWzJdID09PSAxMTUpIHtcbiAgICByZXR1cm4gV2ViQXNzZW1ibHkuY29tcGlsZSh3YXNtQnVmZmVyKS50aGVuKGZ1bmN0aW9uIChtKSB7XG4gICAgICB2YXIgZGVwcyA9IFtdO1xuICAgICAgdmFyIHNldHRlcnMgPSBbXTtcbiAgICAgIHZhciBpbXBvcnRPYmogPSB7fTtcblxuICAgICAgLy8gd2UgY2FuIG9ubHkgc2V0IGltcG9ydHMgaWYgc3VwcG9ydGVkIChlZyBTYWZhcmkgZG9lc250IHN1cHBvcnQpXG4gICAgICBpZiAoV2ViQXNzZW1ibHkuTW9kdWxlLmltcG9ydHMpXG4gICAgICAgIFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKG0pLmZvckVhY2goZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICB2YXIga2V5ID0gaS5tb2R1bGU7XG4gICAgICAgICAgc2V0dGVycy5wdXNoKGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICBpbXBvcnRPYmpba2V5XSA9IG07XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGRlcHMuaW5kZXhPZihrZXkpID09PSAtMSlcbiAgICAgICAgICAgIGRlcHMucHVzaChrZXkpO1xuICAgICAgICB9KTtcbiAgICAgIGxvYWRlci5yZWdpc3RlcihkZXBzLCBmdW5jdGlvbiAoX2V4cG9ydCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHNldHRlcnM6IHNldHRlcnMsXG4gICAgICAgICAgZXhlY3V0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX2V4cG9ydChuZXcgV2ViQXNzZW1ibHkuSW5zdGFuY2UobSwgaW1wb3J0T2JqKS5leHBvcnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICAgIHByb2Nlc3NBbm9uUmVnaXN0ZXIoKTtcblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbn1cblxudmFyIHBhcmVudE1vZHVsZUNvbnRleHQ7XG5mdW5jdGlvbiBsb2FkTm9kZU1vZHVsZSAoa2V5LCBiYXNlVVJMKSB7XG4gIGlmIChrZXlbMF0gPT09ICcuJylcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vZGUgbW9kdWxlICcgKyBrZXkgKyAnIGNhblxcJ3QgYmUgbG9hZGVkIGFzIGl0IGlzIG5vdCBhIHBhY2thZ2UgcmVxdWlyZS4nKTtcblxuICBpZiAoIXBhcmVudE1vZHVsZUNvbnRleHQpIHtcbiAgICB2YXIgTW9kdWxlID0gdGhpcy5fbm9kZVJlcXVpcmUoJ21vZHVsZScpO1xuICAgIHZhciBiYXNlID0gZGVjb2RlVVJJKGJhc2VVUkwuc3Vic3RyKGlzV2luZG93cyA/IDggOiA3KSk7XG4gICAgcGFyZW50TW9kdWxlQ29udGV4dCA9IG5ldyBNb2R1bGUoYmFzZSk7XG4gICAgcGFyZW50TW9kdWxlQ29udGV4dC5wYXRocyA9IE1vZHVsZS5fbm9kZU1vZHVsZVBhdGhzKGJhc2UpO1xuICB9XG4gIHJldHVybiBwYXJlbnRNb2R1bGVDb250ZXh0LnJlcXVpcmUoa2V5KTtcbn1cblxuZnVuY3Rpb24gZXh0ZW5kIChhLCBiKSB7XG4gIGZvciAodmFyIHAgaW4gYikge1xuICAgIGlmICghT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpXG4gICAgICBjb250aW51ZTtcbiAgICBhW3BdID0gYltwXTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZCAoYSwgYikge1xuICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICBpZiAoIU9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKVxuICAgICAgY29udGludWU7XG4gICAgaWYgKGFbcF0gPT09IHVuZGVmaW5lZClcbiAgICAgIGFbcF0gPSBiW3BdO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG4vLyBtZXRhIGZpcnN0LWxldmVsIGV4dGVuZHMgd2hlcmU6XG4vLyBhcnJheSArIGFycmF5IGFwcGVuZHNcbi8vIG9iamVjdCArIG9iamVjdCBleHRlbmRzXG4vLyBvdGhlciBwcm9wZXJ0aWVzIHJlcGxhY2VcbmZ1bmN0aW9uIGV4dGVuZE1ldGEgKGEsIGIsIF9wcmVwZW5kKSB7XG4gIGZvciAodmFyIHAgaW4gYikge1xuICAgIGlmICghT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpXG4gICAgICBjb250aW51ZTtcbiAgICB2YXIgdmFsID0gYltwXTtcbiAgICBpZiAoYVtwXSA9PT0gdW5kZWZpbmVkKVxuICAgICAgYVtwXSA9IHZhbDtcbiAgICBlbHNlIGlmICh2YWwgaW5zdGFuY2VvZiBBcnJheSAmJiBhW3BdIGluc3RhbmNlb2YgQXJyYXkpXG4gICAgICBhW3BdID0gW10uY29uY2F0KF9wcmVwZW5kID8gdmFsIDogYVtwXSkuY29uY2F0KF9wcmVwZW5kID8gYVtwXSA6IHZhbCk7XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbCA9PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGwgJiYgdHlwZW9mIGFbcF0gPT0gJ29iamVjdCcpXG4gICAgICBhW3BdID0gKF9wcmVwZW5kID8gcHJlcGVuZCA6IGV4dGVuZCkoZXh0ZW5kKHt9LCBhW3BdKSwgdmFsKTtcbiAgICBlbHNlIGlmICghX3ByZXBlbmQpXG4gICAgICBhW3BdID0gdmFsO1xuICB9XG59XG5cbnZhciBzdXBwb3J0c1ByZWxvYWQgPSBmYWxzZTtcbnZhciBzdXBwb3J0c1ByZWZldGNoID0gZmFsc2U7XG5pZiAoaXNCcm93c2VyKVxuICAoZnVuY3Rpb24gKCkge1xuICAgIHZhciByZWxMaXN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpLnJlbExpc3Q7XG4gICAgaWYgKHJlbExpc3QgJiYgcmVsTGlzdC5zdXBwb3J0cykge1xuICAgICAgc3VwcG9ydHNQcmVmZXRjaCA9IHRydWU7XG4gICAgICB0cnkge1xuICAgICAgICBzdXBwb3J0c1ByZWxvYWQgPSByZWxMaXN0LnN1cHBvcnRzKCdwcmVsb2FkJyk7XG4gICAgICB9XG4gICAgICBjYXRjaCAoZSkge31cbiAgICB9XG4gIH0pKCk7XG5cbmZ1bmN0aW9uIHByZWxvYWRTY3JpcHQgKHVybCkge1xuICAvLyBmYWxsYmFjayB0byBvbGQgZmFzaGlvbmVkIGltYWdlIHRlY2huaXF1ZSB3aGljaCBzdGlsbCB3b3JrcyBpbiBzYWZhcmlcbiAgaWYgKCFzdXBwb3J0c1ByZWxvYWQgJiYgIXN1cHBvcnRzUHJlZmV0Y2gpIHtcbiAgICB2YXIgcHJlbG9hZEltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgcHJlbG9hZEltYWdlLnNyYyA9IHVybDtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTtcbiAgaWYgKHN1cHBvcnRzUHJlbG9hZCkge1xuICAgIGxpbmsucmVsID0gJ3ByZWxvYWQnO1xuICAgIGxpbmsuYXMgPSAnc2NyaXB0JztcbiAgfVxuICBlbHNlIHtcbiAgICAvLyB0aGlzIHdvcmtzIGZvciBhbGwgZXhjZXB0IFNhZmFyaSAoZGV0ZWN0ZWQgYnkgcmVsTGlzdC5zdXBwb3J0cyBsYWNraW5nKVxuICAgIGxpbmsucmVsID0gJ3ByZWZldGNoJztcbiAgfVxuICBsaW5rLmhyZWYgPSB1cmw7XG4gIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQobGluayk7XG59XG5cbmZ1bmN0aW9uIHdvcmtlckltcG9ydCAoc3JjLCByZXNvbHZlLCByZWplY3QpIHtcbiAgdHJ5IHtcbiAgICBpbXBvcnRTY3JpcHRzKHNyYyk7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICByZWplY3QoZSk7XG4gIH1cbiAgcmVzb2x2ZSgpO1xufVxuXG5pZiAoaXNCcm93c2VyKSB7XG4gIHZhciBsb2FkaW5nU2NyaXB0cyA9IFtdO1xuICB2YXIgb25lcnJvciA9IHdpbmRvdy5vbmVycm9yO1xuICB3aW5kb3cub25lcnJvciA9IGZ1bmN0aW9uIGdsb2JhbE9uZXJyb3IgKG1zZywgc3JjKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2FkaW5nU2NyaXB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGxvYWRpbmdTY3JpcHRzW2ldLnNyYyAhPT0gc3JjKVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIGxvYWRpbmdTY3JpcHRzW2ldLmVycihtc2cpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAob25lcnJvcilcbiAgICAgIG9uZXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2NyaXB0TG9hZCAoc3JjLCBjcm9zc09yaWdpbiwgaW50ZWdyaXR5LCByZXNvbHZlLCByZWplY3QpIHtcbiAgLy8gcGVyY2VudCBlbmNvZGUganVzdCBcIiNcIiBmb3IgSFRUUCByZXF1ZXN0c1xuICBzcmMgPSBzcmMucmVwbGFjZSgvIy9nLCAnJTIzJyk7XG5cbiAgLy8gc3VicmVzb3VyY2UgaW50ZWdyaXR5IGlzIG5vdCBzdXBwb3J0ZWQgaW4gd2ViIHdvcmtlcnNcbiAgaWYgKGlzV29ya2VyKVxuICAgIHJldHVybiB3b3JrZXJJbXBvcnQoc3JjLCByZXNvbHZlLCByZWplY3QpO1xuXG4gIHZhciBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgc2NyaXB0LnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0JztcbiAgc2NyaXB0LmNoYXJzZXQgPSAndXRmLTgnO1xuICBzY3JpcHQuYXN5bmMgPSB0cnVlO1xuXG4gIGlmIChjcm9zc09yaWdpbilcbiAgICBzY3JpcHQuY3Jvc3NPcmlnaW4gPSBjcm9zc09yaWdpbjtcbiAgaWYgKGludGVncml0eSlcbiAgICBzY3JpcHQuaW50ZWdyaXR5ID0gaW50ZWdyaXR5O1xuXG4gIHNjcmlwdC5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgbG9hZCwgZmFsc2UpO1xuICBzY3JpcHQuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCBlcnJvciwgZmFsc2UpO1xuXG4gIHNjcmlwdC5zcmMgPSBzcmM7XG4gIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcblxuICBmdW5jdGlvbiBsb2FkICgpIHtcbiAgICByZXNvbHZlKCk7XG4gICAgY2xlYW51cCgpO1xuICB9XG5cbiAgLy8gbm90ZSB0aGlzIGRvZXMgbm90IGNhdGNoIGV4ZWN1dGlvbiBlcnJvcnNcbiAgZnVuY3Rpb24gZXJyb3IgKGVycikge1xuICAgIGNsZWFudXAoKTtcbiAgICByZWplY3QobmV3IEVycm9yKCdGZXRjaGluZyAnICsgc3JjKSk7XG4gIH1cblxuICBmdW5jdGlvbiBjbGVhbnVwICgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxvYWRpbmdTY3JpcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobG9hZGluZ1NjcmlwdHNbaV0uZXJyID09PSBlcnJvcikge1xuICAgICAgICBsb2FkaW5nU2NyaXB0cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBzY3JpcHQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbG9hZCcsIGxvYWQsIGZhbHNlKTtcbiAgICBzY3JpcHQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZXJyb3InLCBlcnJvciwgZmFsc2UpO1xuICAgIGRvY3VtZW50LmhlYWQucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZWFkTWVtYmVyRXhwcmVzc2lvbiAocCwgdmFsdWUpIHtcbiAgdmFyIHBQYXJ0cyA9IHAuc3BsaXQoJy4nKTtcbiAgd2hpbGUgKHBQYXJ0cy5sZW5ndGgpXG4gICAgdmFsdWUgPSB2YWx1ZVtwUGFydHMuc2hpZnQoKV07XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLy8gc2VwYXJhdGUgb3V0IHBhdGhzIGNhY2hlIGFzIGEgYmFzZVVSTCBsb2NrIHByb2Nlc3NcbmZ1bmN0aW9uIGFwcGx5UGF0aHMgKGJhc2VVUkwsIHBhdGhzLCBrZXkpIHtcbiAgdmFyIG1hcE1hdGNoID0gZ2V0TWFwTWF0Y2gocGF0aHMsIGtleSk7XG4gIGlmIChtYXBNYXRjaCkge1xuICAgIHZhciB0YXJnZXQgPSBwYXRoc1ttYXBNYXRjaF0gKyBrZXkuc3Vic3RyKG1hcE1hdGNoLmxlbmd0aCk7XG5cbiAgICB2YXIgcmVzb2x2ZWQgPSByZXNvbHZlSWZOb3RQbGFpbih0YXJnZXQsIGJhc2VVUkkpO1xuICAgIGlmIChyZXNvbHZlZCAhPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHJlc29sdmVkO1xuXG4gICAgcmV0dXJuIGJhc2VVUkwgKyB0YXJnZXQ7XG4gIH1cbiAgZWxzZSBpZiAoa2V5LmluZGV4T2YoJzonKSAhPT0gLTEpIHtcbiAgICByZXR1cm4ga2V5O1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiBiYXNlVVJMICsga2V5O1xuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrTWFwIChwKSB7XG4gIHZhciBuYW1lID0gdGhpcy5uYW1lO1xuICAvLyBjYW4gYWRkICc6JyBoZXJlIGlmIHdlIHdhbnQgcGF0aHMgdG8gbWF0Y2ggdGhlIGJlaGF2aW91ciBvZiBtYXBcbiAgaWYgKG5hbWUuc3Vic3RyKDAsIHAubGVuZ3RoKSA9PT0gcCAmJiAobmFtZS5sZW5ndGggPT09IHAubGVuZ3RoIHx8IG5hbWVbcC5sZW5ndGhdID09PSAnLycgfHwgcFtwLmxlbmd0aCAtIDFdID09PSAnLycgfHwgcFtwLmxlbmd0aCAtIDFdID09PSAnOicpKSB7XG4gICAgdmFyIGN1ckxlbiA9IHAuc3BsaXQoJy8nKS5sZW5ndGg7XG4gICAgaWYgKGN1ckxlbiA+IHRoaXMubGVuKSB7XG4gICAgICB0aGlzLm1hdGNoID0gcDtcbiAgICAgIHRoaXMubGVuID0gY3VyTGVuO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRNYXBNYXRjaCAobWFwLCBuYW1lKSB7XG4gIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtYXAsIG5hbWUpKVxuICAgIHJldHVybiBuYW1lO1xuXG4gIHZhciBiZXN0TWF0Y2ggPSB7XG4gICAgbmFtZTogbmFtZSxcbiAgICBtYXRjaDogdW5kZWZpbmVkLFxuICAgIGxlbjogMFxuICB9O1xuXG4gIE9iamVjdC5rZXlzKG1hcCkuZm9yRWFjaChjaGVja01hcCwgYmVzdE1hdGNoKTtcblxuICByZXR1cm4gYmVzdE1hdGNoLm1hdGNoO1xufVxuXG4vLyBSZWdFeCBhZGp1c3RlZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9qYnJhbnRseS95YWJibGUvYmxvYi9tYXN0ZXIvbGliL3lhYmJsZS5qcyNMMzM5XG52YXIgY2pzUmVxdWlyZVJlZ0V4ID0gLyg/Ol5cXHVGRUZGP3xbXiRfYS16QS1aXFx4QTAtXFx1RkZGRi5cIiddKXJlcXVpcmVcXHMqXFwoXFxzKihcIlteXCJcXFxcXSooPzpcXFxcLlteXCJcXFxcXSopKlwifCdbXidcXFxcXSooPzpcXFxcLlteJ1xcXFxdKikqJ3xgW15gXFxcXF0qKD86XFxcXC5bXmBcXFxcXSopKmApXFxzKlxcKS9nO1xuXG4vKlxuICogU291cmNlIGxvYWRpbmdcbiAqL1xuZnVuY3Rpb24gZmV0Y2hGZXRjaCAodXJsLCBhdXRob3JpemF0aW9uLCBpbnRlZ3JpdHksIGFzQnVmZmVyKSB7XG4gIC8vIGZldGNoIGRvZXNuJ3Qgc3VwcG9ydCBmaWxlOi8vLyB1cmxzXG4gIGlmICh1cmwuc3Vic3RyKDAsIDgpID09PSAnZmlsZTovLy8nKSB7XG4gICAgaWYgKGhhc1hocilcbiAgICAgIHJldHVybiB4aHJGZXRjaCh1cmwsIGF1dGhvcml6YXRpb24sIGludGVncml0eSwgYXNCdWZmZXIpO1xuICAgIGVsc2VcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZldGNoIGZpbGUgVVJMcyBpbiB0aGlzIGVudmlyb25tZW50LicpO1xuICB9XG5cbiAgLy8gcGVyY2VudCBlbmNvZGUganVzdCBcIiNcIiBmb3IgSFRUUCByZXF1ZXN0c1xuICB1cmwgPSB1cmwucmVwbGFjZSgvIy9nLCAnJTIzJyk7XG5cbiAgdmFyIG9wdHMgPSB7XG4gICAgLy8gTkIgZGVwcmVjYXRlXG4gICAgaGVhZGVyczogeyBBY2NlcHQ6ICdhcHBsaWNhdGlvbi94LWVzLW1vZHVsZSwgKi8qJyB9XG4gIH07XG5cbiAgaWYgKGludGVncml0eSlcbiAgICBvcHRzLmludGVncml0eSA9IGludGVncml0eTtcblxuICBpZiAoYXV0aG9yaXphdGlvbikge1xuICAgIGlmICh0eXBlb2YgYXV0aG9yaXphdGlvbiA9PSAnc3RyaW5nJylcbiAgICAgIG9wdHMuaGVhZGVyc1snQXV0aG9yaXphdGlvbiddID0gYXV0aG9yaXphdGlvbjtcbiAgICBvcHRzLmNyZWRlbnRpYWxzID0gJ2luY2x1ZGUnO1xuICB9XG5cbiAgcmV0dXJuIGZldGNoKHVybCwgb3B0cylcbiAgLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgaWYgKHJlcy5vaylcbiAgICAgIHJldHVybiBhc0J1ZmZlciA/IHJlcy5hcnJheUJ1ZmZlcigpIDogcmVzLnRleHQoKTtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZldGNoIGVycm9yOiAnICsgcmVzLnN0YXR1cyArICcgJyArIHJlcy5zdGF0dXNUZXh0KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHhockZldGNoICh1cmwsIGF1dGhvcml6YXRpb24sIGludGVncml0eSwgYXNCdWZmZXIpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAvLyBwZXJjZW50IGVuY29kZSBqdXN0IFwiI1wiIGZvciBIVFRQIHJlcXVlc3RzXG4gICAgdXJsID0gdXJsLnJlcGxhY2UoLyMvZywgJyUyMycpO1xuXG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIGlmIChhc0J1ZmZlcilcbiAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgIGZ1bmN0aW9uIGxvYWQoKSB7XG4gICAgICByZXNvbHZlKGFzQnVmZmVyID8geGhyLnJlc3BvbnNlIDogeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVycm9yKCkge1xuICAgICAgcmVqZWN0KG5ldyBFcnJvcignWEhSIGVycm9yOiAnICsgKHhoci5zdGF0dXMgPyAnICgnICsgeGhyLnN0YXR1cyArICh4aHIuc3RhdHVzVGV4dCA/ICcgJyArIHhoci5zdGF0dXNUZXh0ICA6ICcnKSArICcpJyA6ICcnKSArICcgbG9hZGluZyAnICsgdXJsKSk7XG4gICAgfVxuXG4gICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAvLyBpbiBDaHJvbWUgb24gZmlsZTovLy8gVVJMcywgc3RhdHVzIGlzIDBcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPT0gMCkge1xuICAgICAgICAgIGlmICh4aHIucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyB3aGVuIHJlc3BvbnNlVGV4dCBpcyBlbXB0eSwgd2FpdCBmb3IgbG9hZCBvciBlcnJvciBldmVudFxuICAgICAgICAgICAgLy8gdG8gaW5mb3JtIGlmIGl0IGlzIGEgNDA0IG9yIGVtcHR5IGZpbGVcbiAgICAgICAgICAgIHhoci5hZGRFdmVudExpc3RlbmVyKCdlcnJvcicsIGVycm9yKTtcbiAgICAgICAgICAgIHhoci5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgbG9hZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHhoci5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgIGxvYWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBlcnJvcigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgICB4aHIub3BlbihcIkdFVFwiLCB1cmwsIHRydWUpO1xuXG4gICAgaWYgKHhoci5zZXRSZXF1ZXN0SGVhZGVyKSB7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcignQWNjZXB0JywgJ2FwcGxpY2F0aW9uL3gtZXMtbW9kdWxlLCAqLyonKTtcbiAgICAgIC8vIGNhbiBzZXQgXCJhdXRob3JpemF0aW9uOiB0cnVlXCIgdG8gZW5hYmxlIHdpdGhDcmVkZW50aWFscyBvbmx5XG4gICAgICBpZiAoYXV0aG9yaXphdGlvbikge1xuICAgICAgICBpZiAodHlwZW9mIGF1dGhvcml6YXRpb24gPT0gJ3N0cmluZycpXG4gICAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0F1dGhvcml6YXRpb24nLCBhdXRob3JpemF0aW9uKTtcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgeGhyLnNlbmQobnVsbCk7XG4gIH0pO1xufVxuXG52YXIgZnM7XG5mdW5jdGlvbiBub2RlRmV0Y2ggKHVybCwgYXV0aG9yaXphdGlvbiwgaW50ZWdyaXR5LCBhc0J1ZmZlcikge1xuICBpZiAodXJsLnN1YnN0cigwLCA4KSAhPSAnZmlsZTovLy8nKVxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1VuYWJsZSB0byBmZXRjaCBcIicgKyB1cmwgKyAnXCIuIE9ubHkgZmlsZSBVUkxzIG9mIHRoZSBmb3JtIGZpbGU6Ly8vIHN1cHBvcnRlZCBydW5uaW5nIGluIE5vZGUuJykpO1xuXG4gIGZzID0gZnMgfHwgcmVxdWlyZSgnZnMnKTtcbiAgaWYgKGlzV2luZG93cylcbiAgICB1cmwgPSB1cmwucmVwbGFjZSgvXFwvL2csICdcXFxcJykuc3Vic3RyKDgpO1xuICBlbHNlXG4gICAgdXJsID0gdXJsLnN1YnN0cig3KTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGZzLnJlYWRGaWxlKHVybCwgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAoYXNCdWZmZXIpIHtcbiAgICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIC8vIFN0cmlwIEJ5dGUgT3JkZXIgTWFyayBvdXQgaWYgaXQncyB0aGUgbGVhZGluZyBjaGFyXG4gICAgICAgICAgdmFyIGRhdGFTdHJpbmcgPSBkYXRhICsgJyc7XG4gICAgICAgICAgaWYgKGRhdGFTdHJpbmdbMF0gPT09ICdcXHVmZWZmJylcbiAgICAgICAgICAgIGRhdGFTdHJpbmcgPSBkYXRhU3RyaW5nLnN1YnN0cigxKTtcblxuICAgICAgICAgIHJlc29sdmUoZGF0YVN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG5vRmV0Y2ggKCkge1xuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGZldGNoIG1ldGhvZCBpcyBkZWZpbmVkIGZvciB0aGlzIGVudmlyb25tZW50LicpO1xufVxuXG52YXIgZmV0Y2hGdW5jdGlvbjtcblxudmFyIGhhc1hociA9IHR5cGVvZiBYTUxIdHRwUmVxdWVzdCAhPT0gJ3VuZGVmaW5lZCc7XG5cbmlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlbGYuZmV0Y2ggIT09ICd1bmRlZmluZWQnKVxuIGZldGNoRnVuY3Rpb24gPSBmZXRjaEZldGNoO1xuZWxzZSBpZiAoaGFzWGhyKVxuICBmZXRjaEZ1bmN0aW9uID0geGhyRmV0Y2g7XG5lbHNlIGlmICh0eXBlb2YgcmVxdWlyZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnKVxuICBmZXRjaEZ1bmN0aW9uID0gbm9kZUZldGNoO1xuZWxzZVxuICBmZXRjaEZ1bmN0aW9uID0gbm9GZXRjaDtcblxudmFyIGZldGNoJDEgPSBmZXRjaEZ1bmN0aW9uO1xuXG5mdW5jdGlvbiBjcmVhdGVNZXRhZGF0YSAoKSB7XG4gIHJldHVybiB7XG4gICAgcGx1Z2luS2V5OiB1bmRlZmluZWQsXG4gICAgcGx1Z2luQXJndW1lbnQ6IHVuZGVmaW5lZCxcbiAgICBwbHVnaW5Nb2R1bGU6IHVuZGVmaW5lZCxcbiAgICBwYWNrYWdlS2V5OiB1bmRlZmluZWQsXG4gICAgcGFja2FnZUNvbmZpZzogdW5kZWZpbmVkLFxuICAgIGxvYWQ6IHVuZGVmaW5lZFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRQYXJlbnRNZXRhZGF0YSAobG9hZGVyLCBjb25maWcsIHBhcmVudEtleSkge1xuICB2YXIgcGFyZW50TWV0YWRhdGEgPSBjcmVhdGVNZXRhZGF0YSgpO1xuXG4gIGlmIChwYXJlbnRLZXkpIHtcbiAgICAvLyBkZXRlY3QgcGFyZW50IHBsdWdpblxuICAgIC8vIHdlIGp1c3QgbmVlZCBwbHVnaW5LZXkgdG8gYmUgdHJ1dGh5IGZvciBwYWNrYWdlIGNvbmZpZ3VyYXRpb25zXG4gICAgLy8gc28gd2UgZHVwbGljYXRlIGl0IGFzIHBsdWdpbkFyZ3VtZW50IC0gYWx0aG91Z2ggbm90IGNvcnJlY3QgaXRzIG5vdCB1c2VkXG4gICAgdmFyIHBhcmVudFBsdWdpbkluZGV4O1xuICAgIGlmIChjb25maWcucGx1Z2luRmlyc3QpIHtcbiAgICAgIGlmICgocGFyZW50UGx1Z2luSW5kZXggPSBwYXJlbnRLZXkubGFzdEluZGV4T2YoJyEnKSkgIT09IC0xKVxuICAgICAgICBwYXJlbnRNZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCA9IHBhcmVudE1ldGFkYXRhLnBsdWdpbktleSA9IHBhcmVudEtleS5zdWJzdHIoMCwgcGFyZW50UGx1Z2luSW5kZXgpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGlmICgocGFyZW50UGx1Z2luSW5kZXggPSBwYXJlbnRLZXkuaW5kZXhPZignIScpKSAhPT0gLTEpXG4gICAgICAgIHBhcmVudE1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50ID0gcGFyZW50TWV0YWRhdGEucGx1Z2luS2V5ID0gcGFyZW50S2V5LnN1YnN0cihwYXJlbnRQbHVnaW5JbmRleCArIDEpO1xuICAgIH1cblxuICAgIC8vIGRldGVjdCBwYXJlbnQgcGFja2FnZVxuICAgIHBhcmVudE1ldGFkYXRhLnBhY2thZ2VLZXkgPSBnZXRNYXBNYXRjaChjb25maWcucGFja2FnZXMsIHBhcmVudEtleSk7XG4gICAgaWYgKHBhcmVudE1ldGFkYXRhLnBhY2thZ2VLZXkpXG4gICAgICBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnID0gY29uZmlnLnBhY2thZ2VzW3BhcmVudE1ldGFkYXRhLnBhY2thZ2VLZXldO1xuICB9XG5cbiAgcmV0dXJuIHBhcmVudE1ldGFkYXRhO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemUgKGtleSwgcGFyZW50S2V5KSB7XG4gIHZhciBjb25maWcgPSB0aGlzW0NPTkZJR107XG5cbiAgdmFyIG1ldGFkYXRhID0gY3JlYXRlTWV0YWRhdGEoKTtcbiAgdmFyIHBhcmVudE1ldGFkYXRhID0gZ2V0UGFyZW50TWV0YWRhdGEodGhpcywgY29uZmlnLCBwYXJlbnRLZXkpO1xuXG4gIHZhciBsb2FkZXIgPSB0aGlzO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuXG4gIC8vIGJvb2xlYW4gY29uZGl0aW9uYWxcbiAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIC8vIGZpcnN0IHdlIG5vcm1hbGl6ZSB0aGUgY29uZGl0aW9uYWxcbiAgICB2YXIgYm9vbGVhbkluZGV4ID0ga2V5Lmxhc3RJbmRleE9mKCcjPycpO1xuXG4gICAgaWYgKGJvb2xlYW5JbmRleCA9PT0gLTEpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGtleSk7XG5cbiAgICB2YXIgY29uZGl0aW9uT2JqID0gcGFyc2VDb25kaXRpb24uY2FsbChsb2FkZXIsIGtleS5zdWJzdHIoYm9vbGVhbkluZGV4ICsgMikpO1xuXG4gICAgLy8gaW4gYnVpbGRzLCByZXR1cm4gbm9ybWFsaXplZCBjb25kaXRpb25hbFxuICAgIC8qaWYgKHRoaXMuYnVpbGRlcilcbiAgICAgIHJldHVybiB0aGlzLnJlc29sdmUoY29uZGl0aW9uT2JqLm1vZHVsZSwgcGFyZW50S2V5KVxuICAgICAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvbk1vZHVsZSkge1xuICAgICAgICBjb25kaXRpb25PYmoubW9kdWxlID0gY29uZGl0aW9uTW9kdWxlO1xuICAgICAgICByZXR1cm4ga2V5LnN1YnN0cigwLCBib29sZWFuSW5kZXgpICsgJyM/JyArIHNlcmlhbGl6ZUNvbmRpdGlvbihjb25kaXRpb25PYmopO1xuICAgICAgfSk7Ki9cblxuICAgIHJldHVybiByZXNvbHZlQ29uZGl0aW9uLmNhbGwobG9hZGVyLCBjb25kaXRpb25PYmosIHBhcmVudEtleSwgdHJ1ZSlcbiAgICAudGhlbihmdW5jdGlvbiAoY29uZGl0aW9uVmFsdWUpIHtcbiAgICAgIHJldHVybiBjb25kaXRpb25WYWx1ZSA/IGtleS5zdWJzdHIoMCwgYm9vbGVhbkluZGV4KSA6ICdAZW1wdHknO1xuICAgIH0pO1xuICB9KVxuXG4gIC8vIHBsdWdpblxuICAudGhlbihmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlUGx1Z2luKGNvbmZpZy5wbHVnaW5GaXJzdCwga2V5KTtcblxuICAgIGlmICghcGFyc2VkKVxuICAgICAgcmV0dXJuIHBhY2thZ2VSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIGtleSwgcGFyZW50TWV0YWRhdGEgJiYgcGFyZW50TWV0YWRhdGEucGx1Z2luQXJndW1lbnQgfHwgcGFyZW50S2V5LCBtZXRhZGF0YSwgcGFyZW50TWV0YWRhdGEsIGZhbHNlKTtcblxuICAgIG1ldGFkYXRhLnBsdWdpbktleSA9IHBhcnNlZC5wbHVnaW47XG5cbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoW1xuICAgICAgcGFja2FnZVJlc29sdmUuY2FsbChsb2FkZXIsIGNvbmZpZywgcGFyc2VkLmFyZ3VtZW50LCBwYXJlbnRNZXRhZGF0YSAmJiBwYXJlbnRNZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCB8fCBwYXJlbnRLZXksIG1ldGFkYXRhLCBwYXJlbnRNZXRhZGF0YSwgdHJ1ZSksXG4gICAgICBsb2FkZXIucmVzb2x2ZShwYXJzZWQucGx1Z2luLCBwYXJlbnRLZXkpXG4gICAgXSlcbiAgICAudGhlbihmdW5jdGlvbiAobm9ybWFsaXplZCkge1xuICAgICAgbWV0YWRhdGEucGx1Z2luQXJndW1lbnQgPSBub3JtYWxpemVkWzBdO1xuICAgICAgbWV0YWRhdGEucGx1Z2luS2V5ID0gbm9ybWFsaXplZFsxXTtcblxuICAgICAgLy8gZG9uJ3QgYWxsb3cgYSBwbHVnaW4gdG8gbG9hZCBpdHNlbGZcbiAgICAgIGlmIChtZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCA9PT0gbWV0YWRhdGEucGx1Z2luS2V5KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsdWdpbiAnICsgbWV0YWRhdGEucGx1Z2luQXJndW1lbnQgKyAnIGNhbm5vdCBsb2FkIGl0c2VsZiwgbWFrZSBzdXJlIGl0IGlzIGV4Y2x1ZGVkIGZyb20gYW55IHdpbGRjYXJkIG1ldGEgY29uZmlndXJhdGlvbiB2aWEgYSBjdXN0b20gbG9hZGVyOiBmYWxzZSBydWxlLicpO1xuXG4gICAgICByZXR1cm4gY29tYmluZVBsdWdpblBhcnRzKGNvbmZpZy5wbHVnaW5GaXJzdCwgbm9ybWFsaXplZFswXSwgbm9ybWFsaXplZFsxXSk7XG4gICAgfSk7XG4gIH0pXG4gIC50aGVuKGZ1bmN0aW9uIChub3JtYWxpemVkKSB7XG4gICAgcmV0dXJuIGludGVycG9sYXRlQ29uZGl0aW9uYWwuY2FsbChsb2FkZXIsIG5vcm1hbGl6ZWQsIHBhcmVudEtleSwgcGFyZW50TWV0YWRhdGEpO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAobm9ybWFsaXplZCkge1xuICAgIHNldE1ldGEuY2FsbChsb2FkZXIsIGNvbmZpZywgbm9ybWFsaXplZCwgbWV0YWRhdGEpO1xuXG4gICAgaWYgKG1ldGFkYXRhLnBsdWdpbktleSB8fCAhbWV0YWRhdGEubG9hZC5sb2FkZXIpXG4gICAgICByZXR1cm4gbm9ybWFsaXplZDtcblxuICAgIC8vIGxvYWRlciBieSBjb25maWd1cmF0aW9uXG4gICAgLy8gbm9ybWFsaXplcyB0byBwYXJlbnQgdG8gc3VwcG9ydCBwYWNrYWdlIGxvYWRlcnNcbiAgICByZXR1cm4gbG9hZGVyLnJlc29sdmUobWV0YWRhdGEubG9hZC5sb2FkZXIsIG5vcm1hbGl6ZWQpXG4gICAgLnRoZW4oZnVuY3Rpb24gKHBsdWdpbktleSkge1xuICAgICAgbWV0YWRhdGEucGx1Z2luS2V5ID0gcGx1Z2luS2V5O1xuICAgICAgbWV0YWRhdGEucGx1Z2luQXJndW1lbnQgPSBub3JtYWxpemVkO1xuICAgICAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG4gICAgfSk7XG4gIH0pXG4gIC50aGVuKGZ1bmN0aW9uIChub3JtYWxpemVkKSB7XG4gICAgbG9hZGVyW01FVEFEQVRBXVtub3JtYWxpemVkXSA9IG1ldGFkYXRhO1xuICAgIHJldHVybiBub3JtYWxpemVkO1xuICB9KTtcbn1cblxuLy8gbm9ybWFsaXphdGlvbiBmdW5jdGlvbiB1c2VkIGZvciByZWdpc3RyeSBrZXlzXG4vLyBqdXN0IGRvZXMgY29yZVJlc29sdmUgd2l0aG91dCBtYXBcbmZ1bmN0aW9uIGRlY2Fub25pY2FsaXplIChjb25maWcsIGtleSkge1xuICB2YXIgcGFyc2VkID0gcGFyc2VQbHVnaW4oY29uZmlnLnBsdWdpbkZpcnN0LCBrZXkpO1xuXG4gIC8vIHBsdWdpblxuICBpZiAocGFyc2VkKSB7XG4gICAgdmFyIHBsdWdpbktleSA9IGRlY2Fub25pY2FsaXplLmNhbGwodGhpcywgY29uZmlnLCBwYXJzZWQucGx1Z2luKTtcbiAgICByZXR1cm4gY29tYmluZVBsdWdpblBhcnRzKGNvbmZpZy5wbHVnaW5GaXJzdCwgY29yZVJlc29sdmUuY2FsbCh0aGlzLCBjb25maWcsIHBhcnNlZC5hcmd1bWVudCwgdW5kZWZpbmVkLCBmYWxzZSwgZmFsc2UpLCBwbHVnaW5LZXkpO1xuICB9XG5cbiAgcmV0dXJuIGNvcmVSZXNvbHZlLmNhbGwodGhpcywgY29uZmlnLCBrZXksIHVuZGVmaW5lZCwgZmFsc2UsIGZhbHNlKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplU3luYyAoa2V5LCBwYXJlbnRLZXkpIHtcbiAgdmFyIGNvbmZpZyA9IHRoaXNbQ09ORklHXTtcblxuICAvLyBub3JtYWxpemVTeW5jIGlzIG1ldGFkYXRhbGVzcywgc28gY3JlYXRlIG1ldGFkYXRhXG4gIHZhciBtZXRhZGF0YSA9IGNyZWF0ZU1ldGFkYXRhKCk7XG4gIHZhciBwYXJlbnRNZXRhZGF0YSA9IHBhcmVudE1ldGFkYXRhIHx8IGdldFBhcmVudE1ldGFkYXRhKHRoaXMsIGNvbmZpZywgcGFyZW50S2V5KTtcblxuICB2YXIgcGFyc2VkID0gcGFyc2VQbHVnaW4oY29uZmlnLnBsdWdpbkZpcnN0LCBrZXkpO1xuXG4gIC8vIHBsdWdpblxuICBpZiAocGFyc2VkKSB7XG4gICAgbWV0YWRhdGEucGx1Z2luS2V5ID0gbm9ybWFsaXplU3luYy5jYWxsKHRoaXMsIHBhcnNlZC5wbHVnaW4sIHBhcmVudEtleSk7XG4gICAgcmV0dXJuIGNvbWJpbmVQbHVnaW5QYXJ0cyhjb25maWcucGx1Z2luRmlyc3QsXG4gICAgICAgIHBhY2thZ2VSZXNvbHZlU3luYy5jYWxsKHRoaXMsIGNvbmZpZywgcGFyc2VkLmFyZ3VtZW50LCBwYXJlbnRNZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCB8fCBwYXJlbnRLZXksIG1ldGFkYXRhLCBwYXJlbnRNZXRhZGF0YSwgISFtZXRhZGF0YS5wbHVnaW5LZXkpLFxuICAgICAgICBtZXRhZGF0YS5wbHVnaW5LZXkpO1xuICB9XG5cbiAgcmV0dXJuIHBhY2thZ2VSZXNvbHZlU3luYy5jYWxsKHRoaXMsIGNvbmZpZywga2V5LCBwYXJlbnRNZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCB8fCBwYXJlbnRLZXksIG1ldGFkYXRhLCBwYXJlbnRNZXRhZGF0YSwgISFtZXRhZGF0YS5wbHVnaW5LZXkpO1xufVxuXG5mdW5jdGlvbiBjb3JlUmVzb2x2ZSAoY29uZmlnLCBrZXksIHBhcmVudEtleSwgZG9NYXAsIHBhY2thZ2VOYW1lKSB7XG4gIHZhciByZWxhdGl2ZVJlc29sdmVkID0gcmVzb2x2ZUlmTm90UGxhaW4oa2V5LCBwYXJlbnRLZXkgfHwgYmFzZVVSSSk7XG5cbiAgLy8gc3RhbmRhcmQgVVJMIHJlc29sdXRpb25cbiAgaWYgKHJlbGF0aXZlUmVzb2x2ZWQpXG4gICAgcmV0dXJuIGFwcGx5UGF0aHMoY29uZmlnLmJhc2VVUkwsIGNvbmZpZy5wYXRocywgcmVsYXRpdmVSZXNvbHZlZCk7XG5cbiAgLy8gcGxhaW4ga2V5cyBub3Qgc3RhcnRpbmcgd2l0aCAnLi8nLCAneDovLycgYW5kICcvJyBnbyB0aHJvdWdoIGN1c3RvbSByZXNvbHV0aW9uXG4gIGlmIChkb01hcCkge1xuICAgIHZhciBtYXBNYXRjaCA9IGdldE1hcE1hdGNoKGNvbmZpZy5tYXAsIGtleSk7XG5cbiAgICBpZiAobWFwTWF0Y2gpIHtcbiAgICAgIGtleSA9IGNvbmZpZy5tYXBbbWFwTWF0Y2hdICsga2V5LnN1YnN0cihtYXBNYXRjaC5sZW5ndGgpO1xuXG4gICAgICByZWxhdGl2ZVJlc29sdmVkID0gcmVzb2x2ZUlmTm90UGxhaW4oa2V5LCBiYXNlVVJJKTtcbiAgICAgIGlmIChyZWxhdGl2ZVJlc29sdmVkKVxuICAgICAgICByZXR1cm4gYXBwbHlQYXRocyhjb25maWcuYmFzZVVSTCwgY29uZmlnLnBhdGhzLCByZWxhdGl2ZVJlc29sdmVkKTtcbiAgICB9XG4gIH1cblxuICBpZiAodGhpcy5yZWdpc3RyeS5oYXMoa2V5KSlcbiAgICByZXR1cm4ga2V5O1xuXG4gIGlmIChrZXkuc3Vic3RyKDAsIDYpID09PSAnQG5vZGUvJylcbiAgICByZXR1cm4ga2V5O1xuXG4gIHZhciB0cmFpbGluZ1NsYXNoID0gcGFja2FnZU5hbWUgJiYga2V5W2tleS5sZW5ndGggLSAxXSAhPT0gJy8nO1xuICB2YXIgcmVzb2x2ZWQgPSBhcHBseVBhdGhzKGNvbmZpZy5iYXNlVVJMLCBjb25maWcucGF0aHMsIHRyYWlsaW5nU2xhc2ggPyBrZXkgKyAnLycgOiBrZXkpO1xuICBpZiAodHJhaWxpbmdTbGFzaClcbiAgICByZXR1cm4gcmVzb2x2ZWQuc3Vic3RyKDAsIHJlc29sdmVkLmxlbmd0aCAtIDEpO1xuICByZXR1cm4gcmVzb2x2ZWQ7XG59XG5cbmZ1bmN0aW9uIHBhY2thZ2VSZXNvbHZlU3luYyAoY29uZmlnLCBrZXksIHBhcmVudEtleSwgbWV0YWRhdGEsIHBhcmVudE1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucykge1xuICAvLyBpZ25vcmUgLiBzaW5jZSBpbnRlcm5hbCBtYXBzIGhhbmRsZWQgYnkgc3RhbmRhcmQgcGFja2FnZSByZXNvbHV0aW9uXG4gIGlmIChwYXJlbnRNZXRhZGF0YSAmJiBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnICYmIGtleVswXSAhPT0gJy4nKSB7XG4gICAgdmFyIHBhcmVudE1hcCA9IHBhcmVudE1ldGFkYXRhLnBhY2thZ2VDb25maWcubWFwO1xuICAgIHZhciBwYXJlbnRNYXBNYXRjaCA9IHBhcmVudE1hcCAmJiBnZXRNYXBNYXRjaChwYXJlbnRNYXAsIGtleSk7XG5cbiAgICBpZiAocGFyZW50TWFwTWF0Y2ggJiYgdHlwZW9mIHBhcmVudE1hcFtwYXJlbnRNYXBNYXRjaF0gPT09ICdzdHJpbmcnKSB7XG4gICAgICB2YXIgbWFwcGVkID0gZG9NYXBTeW5jKHRoaXMsIGNvbmZpZywgcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZywgcGFyZW50TWV0YWRhdGEucGFja2FnZUtleSwgcGFyZW50TWFwTWF0Y2gsIGtleSwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKTtcbiAgICAgIGlmIChtYXBwZWQpXG4gICAgICAgIHJldHVybiBtYXBwZWQ7XG4gICAgfVxuICB9XG5cbiAgdmFyIG5vcm1hbGl6ZWQgPSBjb3JlUmVzb2x2ZS5jYWxsKHRoaXMsIGNvbmZpZywga2V5LCBwYXJlbnRLZXksIHRydWUsIHRydWUpO1xuXG4gIHZhciBwa2dDb25maWdNYXRjaCA9IGdldFBhY2thZ2VDb25maWdNYXRjaChjb25maWcsIG5vcm1hbGl6ZWQpO1xuICBtZXRhZGF0YS5wYWNrYWdlS2V5ID0gcGtnQ29uZmlnTWF0Y2ggJiYgcGtnQ29uZmlnTWF0Y2gucGFja2FnZUtleSB8fCBnZXRNYXBNYXRjaChjb25maWcucGFja2FnZXMsIG5vcm1hbGl6ZWQpO1xuXG4gIGlmICghbWV0YWRhdGEucGFja2FnZUtleSlcbiAgICByZXR1cm4gbm9ybWFsaXplZDtcblxuICBpZiAoY29uZmlnLnBhY2thZ2VDb25maWdLZXlzLmluZGV4T2Yobm9ybWFsaXplZCkgIT09IC0xKSB7XG4gICAgbWV0YWRhdGEucGFja2FnZUtleSA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gbm9ybWFsaXplZDtcbiAgfVxuXG4gIG1ldGFkYXRhLnBhY2thZ2VDb25maWcgPSBjb25maWcucGFja2FnZXNbbWV0YWRhdGEucGFja2FnZUtleV0gfHwgKGNvbmZpZy5wYWNrYWdlc1ttZXRhZGF0YS5wYWNrYWdlS2V5XSA9IGNyZWF0ZVBhY2thZ2UoKSk7XG5cbiAgdmFyIHN1YlBhdGggPSBub3JtYWxpemVkLnN1YnN0cihtZXRhZGF0YS5wYWNrYWdlS2V5Lmxlbmd0aCArIDEpO1xuXG4gIHJldHVybiBhcHBseVBhY2thZ2VDb25maWdTeW5jKHRoaXMsIGNvbmZpZywgbWV0YWRhdGEucGFja2FnZUNvbmZpZywgbWV0YWRhdGEucGFja2FnZUtleSwgc3ViUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKTtcbn1cblxuZnVuY3Rpb24gcGFja2FnZVJlc29sdmUgKGNvbmZpZywga2V5LCBwYXJlbnRLZXksIG1ldGFkYXRhLCBwYXJlbnRNZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpIHtcbiAgdmFyIGxvYWRlciA9IHRoaXM7XG5cbiAgcmV0dXJuIHJlc29sdmVkUHJvbWlzZVxuICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgLy8gaWdub3JlIC4gc2luY2UgaW50ZXJuYWwgbWFwcyBoYW5kbGVkIGJ5IHN0YW5kYXJkIHBhY2thZ2UgcmVzb2x1dGlvblxuICAgIGlmIChwYXJlbnRNZXRhZGF0YSAmJiBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnICYmIGtleS5zdWJzdHIoMCwgMikgIT09ICcuLycpIHtcbiAgICAgIHZhciBwYXJlbnRNYXAgPSBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnLm1hcDtcbiAgICAgIHZhciBwYXJlbnRNYXBNYXRjaCA9IHBhcmVudE1hcCAmJiBnZXRNYXBNYXRjaChwYXJlbnRNYXAsIGtleSk7XG5cbiAgICAgIGlmIChwYXJlbnRNYXBNYXRjaClcbiAgICAgICAgcmV0dXJuIGRvTWFwKGxvYWRlciwgY29uZmlnLCBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnLCBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlS2V5LCBwYXJlbnRNYXBNYXRjaCwga2V5LCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpO1xuICAgIH1cblxuICAgIHJldHVybiByZXNvbHZlZFByb21pc2U7XG4gIH0pXG4gIC50aGVuKGZ1bmN0aW9uIChtYXBwZWQpIHtcbiAgICBpZiAobWFwcGVkKVxuICAgICAgcmV0dXJuIG1hcHBlZDtcblxuICAgIC8vIGFwcGx5IG1hcCwgY29yZSwgcGF0aHMsIGNvbnRleHR1YWwgcGFja2FnZSBtYXBcbiAgICB2YXIgbm9ybWFsaXplZCA9IGNvcmVSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIGtleSwgcGFyZW50S2V5LCB0cnVlLCB0cnVlKTtcblxuICAgIHZhciBwa2dDb25maWdNYXRjaCA9IGdldFBhY2thZ2VDb25maWdNYXRjaChjb25maWcsIG5vcm1hbGl6ZWQpO1xuICAgIG1ldGFkYXRhLnBhY2thZ2VLZXkgPSBwa2dDb25maWdNYXRjaCAmJiBwa2dDb25maWdNYXRjaC5wYWNrYWdlS2V5IHx8IGdldE1hcE1hdGNoKGNvbmZpZy5wYWNrYWdlcywgbm9ybWFsaXplZCk7XG5cbiAgICBpZiAoIW1ldGFkYXRhLnBhY2thZ2VLZXkpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5vcm1hbGl6ZWQpO1xuXG4gICAgaWYgKGNvbmZpZy5wYWNrYWdlQ29uZmlnS2V5cy5pbmRleE9mKG5vcm1hbGl6ZWQpICE9PSAtMSkge1xuICAgICAgbWV0YWRhdGEucGFja2FnZUtleSA9IHVuZGVmaW5lZDtcbiAgICAgIG1ldGFkYXRhLmxvYWQgPSBjcmVhdGVNZXRhKCk7XG4gICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdqc29uJztcbiAgICAgIC8vIGVuc3VyZSBubyBsb2FkZXJcbiAgICAgIG1ldGFkYXRhLmxvYWQubG9hZGVyID0gJyc7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5vcm1hbGl6ZWQpO1xuICAgIH1cblxuICAgIG1ldGFkYXRhLnBhY2thZ2VDb25maWcgPSBjb25maWcucGFja2FnZXNbbWV0YWRhdGEucGFja2FnZUtleV0gfHwgKGNvbmZpZy5wYWNrYWdlc1ttZXRhZGF0YS5wYWNrYWdlS2V5XSA9IGNyZWF0ZVBhY2thZ2UoKSk7XG5cbiAgICAvLyBsb2FkIGNvbmZpZ3VyYXRpb24gd2hlbiBpdCBtYXRjaGVzIHBhY2thZ2VDb25maWdQYXRocywgbm90IGFscmVhZHkgY29uZmlndXJlZCwgYW5kIG5vdCB0aGUgY29uZmlnIGl0c2VsZlxuICAgIHZhciBsb2FkQ29uZmlnID0gcGtnQ29uZmlnTWF0Y2ggJiYgIW1ldGFkYXRhLnBhY2thZ2VDb25maWcuY29uZmlndXJlZDtcblxuICAgIHJldHVybiAobG9hZENvbmZpZyA/IGxvYWRQYWNrYWdlQ29uZmlnUGF0aChsb2FkZXIsIGNvbmZpZywgcGtnQ29uZmlnTWF0Y2guY29uZmlnUGF0aCwgbWV0YWRhdGEpIDogcmVzb2x2ZWRQcm9taXNlKVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBzdWJQYXRoID0gbm9ybWFsaXplZC5zdWJzdHIobWV0YWRhdGEucGFja2FnZUtleS5sZW5ndGggKyAxKTtcblxuICAgICAgcmV0dXJuIGFwcGx5UGFja2FnZUNvbmZpZyhsb2FkZXIsIGNvbmZpZywgbWV0YWRhdGEucGFja2FnZUNvbmZpZywgbWV0YWRhdGEucGFja2FnZUtleSwgc3ViUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU1ldGEgKCkge1xuICByZXR1cm4ge1xuICAgIGV4dGVuc2lvbjogJycsXG4gICAgZGVwczogdW5kZWZpbmVkLFxuICAgIGZvcm1hdDogdW5kZWZpbmVkLFxuICAgIGxvYWRlcjogdW5kZWZpbmVkLFxuICAgIHNjcmlwdExvYWQ6IHVuZGVmaW5lZCxcbiAgICBnbG9iYWxzOiB1bmRlZmluZWQsXG4gICAgbm9uY2U6IHVuZGVmaW5lZCxcbiAgICBpbnRlZ3JpdHk6IHVuZGVmaW5lZCxcbiAgICBzb3VyY2VNYXA6IHVuZGVmaW5lZCxcbiAgICBleHBvcnRzOiB1bmRlZmluZWQsXG4gICAgZW5jYXBzdWxhdGVHbG9iYWw6IGZhbHNlLFxuICAgIGNyb3NzT3JpZ2luOiB1bmRlZmluZWQsXG4gICAgY2pzUmVxdWlyZURldGVjdGlvbjogdHJ1ZSxcbiAgICBjanNEZWZlckRlcHNFeGVjdXRlOiBmYWxzZSxcbiAgICBlc01vZHVsZTogZmFsc2VcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0TWV0YSAoY29uZmlnLCBrZXksIG1ldGFkYXRhKSB7XG4gIG1ldGFkYXRhLmxvYWQgPSBtZXRhZGF0YS5sb2FkIHx8IGNyZWF0ZU1ldGEoKTtcblxuICAvLyBhcHBseSB3aWxkY2FyZCBtZXRhc1xuICB2YXIgYmVzdERlcHRoID0gMDtcbiAgdmFyIHdpbGRjYXJkSW5kZXg7XG4gIGZvciAodmFyIG1vZHVsZSBpbiBjb25maWcubWV0YSkge1xuICAgIHdpbGRjYXJkSW5kZXggPSBtb2R1bGUuaW5kZXhPZignKicpO1xuICAgIGlmICh3aWxkY2FyZEluZGV4ID09PSAtMSlcbiAgICAgIGNvbnRpbnVlO1xuICAgIGlmIChtb2R1bGUuc3Vic3RyKDAsIHdpbGRjYXJkSW5kZXgpID09PSBrZXkuc3Vic3RyKDAsIHdpbGRjYXJkSW5kZXgpXG4gICAgICAgICYmIG1vZHVsZS5zdWJzdHIod2lsZGNhcmRJbmRleCArIDEpID09PSBrZXkuc3Vic3RyKGtleS5sZW5ndGggLSBtb2R1bGUubGVuZ3RoICsgd2lsZGNhcmRJbmRleCArIDEpKSB7XG4gICAgICB2YXIgZGVwdGggPSBtb2R1bGUuc3BsaXQoJy8nKS5sZW5ndGg7XG4gICAgICBpZiAoZGVwdGggPiBiZXN0RGVwdGgpXG4gICAgICAgIGJlc3REZXB0aCA9IGRlcHRoO1xuICAgICAgZXh0ZW5kTWV0YShtZXRhZGF0YS5sb2FkLCBjb25maWcubWV0YVttb2R1bGVdLCBiZXN0RGVwdGggIT09IGRlcHRoKTtcbiAgICB9XG4gIH1cblxuICAvLyBhcHBseSBleGFjdCBtZXRhXG4gIGlmIChjb25maWcubWV0YVtrZXldKVxuICAgIGV4dGVuZE1ldGEobWV0YWRhdGEubG9hZCwgY29uZmlnLm1ldGFba2V5XSwgZmFsc2UpO1xuXG4gIC8vIGFwcGx5IHBhY2thZ2UgbWV0YVxuICBpZiAobWV0YWRhdGEucGFja2FnZUtleSkge1xuICAgIHZhciBzdWJQYXRoID0ga2V5LnN1YnN0cihtZXRhZGF0YS5wYWNrYWdlS2V5Lmxlbmd0aCArIDEpO1xuXG4gICAgdmFyIG1ldGEgPSB7fTtcbiAgICBpZiAobWV0YWRhdGEucGFja2FnZUNvbmZpZy5tZXRhKSB7XG4gICAgICB2YXIgYmVzdERlcHRoID0gMDtcbiAgICAgIGdldE1ldGFNYXRjaGVzKG1ldGFkYXRhLnBhY2thZ2VDb25maWcubWV0YSwgc3ViUGF0aCwgZnVuY3Rpb24gKG1ldGFQYXR0ZXJuLCBtYXRjaE1ldGEsIG1hdGNoRGVwdGgpIHtcbiAgICAgICAgaWYgKG1hdGNoRGVwdGggPiBiZXN0RGVwdGgpXG4gICAgICAgICAgYmVzdERlcHRoID0gbWF0Y2hEZXB0aDtcbiAgICAgICAgZXh0ZW5kTWV0YShtZXRhLCBtYXRjaE1ldGEsIG1hdGNoRGVwdGggJiYgYmVzdERlcHRoID4gbWF0Y2hEZXB0aCk7XG4gICAgICB9KTtcblxuICAgICAgZXh0ZW5kTWV0YShtZXRhZGF0YS5sb2FkLCBtZXRhLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgLy8gZm9ybWF0XG4gICAgaWYgKG1ldGFkYXRhLnBhY2thZ2VDb25maWcuZm9ybWF0ICYmICFtZXRhZGF0YS5wbHVnaW5LZXkgJiYgIW1ldGFkYXRhLmxvYWQubG9hZGVyKVxuICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSBtZXRhZGF0YS5sb2FkLmZvcm1hdCB8fCBtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLmZvcm1hdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVBsdWdpbiAocGx1Z2luRmlyc3QsIGtleSkge1xuICB2YXIgYXJndW1lbnRLZXk7XG4gIHZhciBwbHVnaW5LZXk7XG5cbiAgdmFyIHBsdWdpbkluZGV4ID0gcGx1Z2luRmlyc3QgPyBrZXkuaW5kZXhPZignIScpIDoga2V5Lmxhc3RJbmRleE9mKCchJyk7XG5cbiAgaWYgKHBsdWdpbkluZGV4ID09PSAtMSlcbiAgICByZXR1cm47XG5cbiAgaWYgKHBsdWdpbkZpcnN0KSB7XG4gICAgYXJndW1lbnRLZXkgPSBrZXkuc3Vic3RyKHBsdWdpbkluZGV4ICsgMSk7XG4gICAgcGx1Z2luS2V5ID0ga2V5LnN1YnN0cigwLCBwbHVnaW5JbmRleCk7XG4gIH1cbiAgZWxzZSB7XG4gICAgYXJndW1lbnRLZXkgPSBrZXkuc3Vic3RyKDAsIHBsdWdpbkluZGV4KTtcbiAgICBwbHVnaW5LZXkgPSBrZXkuc3Vic3RyKHBsdWdpbkluZGV4ICsgMSkgfHwgYXJndW1lbnRLZXkuc3Vic3RyKGFyZ3VtZW50S2V5Lmxhc3RJbmRleE9mKCcuJykgKyAxKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYXJndW1lbnQ6IGFyZ3VtZW50S2V5LFxuICAgIHBsdWdpbjogcGx1Z2luS2V5XG4gIH07XG59XG5cbi8vIHB1dCBrZXkgYmFjayB0b2dldGhlciBhZnRlciBwYXJ0cyBoYXZlIGJlZW4gbm9ybWFsaXplZFxuZnVuY3Rpb24gY29tYmluZVBsdWdpblBhcnRzIChwbHVnaW5GaXJzdCwgYXJndW1lbnRLZXksIHBsdWdpbktleSkge1xuICBpZiAocGx1Z2luRmlyc3QpXG4gICAgcmV0dXJuIHBsdWdpbktleSArICchJyArIGFyZ3VtZW50S2V5O1xuICBlbHNlXG4gICAgcmV0dXJuIGFyZ3VtZW50S2V5ICsgJyEnICsgcGx1Z2luS2V5O1xufVxuXG4vKlxuICogUGFja2FnZSBDb25maWd1cmF0aW9uIEV4dGVuc2lvblxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogU3lzdGVtSlMucGFja2FnZXMgPSB7XG4gKiAgIGpxdWVyeToge1xuICogICAgIG1haW46ICdpbmRleC5qcycsIC8vIHdoZW4gbm90IHNldCwgcGFja2FnZSBrZXkgaXMgcmVxdWVzdGVkIGRpcmVjdGx5XG4gKiAgICAgZm9ybWF0OiAnYW1kJyxcbiAqICAgICBkZWZhdWx0RXh0ZW5zaW9uOiAndHMnLCAvLyBkZWZhdWx0cyB0byAnanMnLCBjYW4gYmUgc2V0IHRvIGZhbHNlXG4gKiAgICAgbW9kdWxlczoge1xuICogICAgICAgJyoudHMnOiB7XG4gKiAgICAgICAgIGxvYWRlcjogJ3R5cGVzY3JpcHQnXG4gKiAgICAgICB9LFxuICogICAgICAgJ3ZlbmRvci9zaXp6bGUuanMnOiB7XG4gKiAgICAgICAgIGZvcm1hdDogJ2dsb2JhbCdcbiAqICAgICAgIH1cbiAqICAgICB9LFxuICogICAgIG1hcDoge1xuICogICAgICAgIC8vIG1hcCBpbnRlcm5hbCByZXF1aXJlKCdzaXp6bGUnKSB0byBsb2NhbCByZXF1aXJlKCcuL3ZlbmRvci9zaXp6bGUnKVxuICogICAgICAgIHNpenpsZTogJy4vdmVuZG9yL3NpenpsZS5qcycsXG4gKiAgICAgICAgLy8gbWFwIGFueSBpbnRlcm5hbCBvciBleHRlcm5hbCByZXF1aXJlIG9mICdqcXVlcnkvdmVuZG9yL2Fub3RoZXInIHRvICdhbm90aGVyL2luZGV4LmpzJ1xuICogICAgICAgICcuL3ZlbmRvci9hbm90aGVyLmpzJzogJy4vYW5vdGhlci9pbmRleC5qcycsXG4gKiAgICAgICAgLy8gdGVzdC5qcyAvIHRlc3QgLT4gbGliL3Rlc3QuanNcbiAqICAgICAgICAnLi90ZXN0LmpzJzogJy4vbGliL3Rlc3QuanMnLFxuICpcbiAqICAgICAgICAvLyBlbnZpcm9ubWVudC1zcGVjaWZpYyBtYXAgY29uZmlndXJhdGlvbnNcbiAqICAgICAgICAnLi9pbmRleC5qcyc6IHtcbiAqICAgICAgICAgICd+YnJvd3Nlcic6ICcuL2luZGV4LW5vZGUuanMnLFxuICogICAgICAgICAgJy4vY3VzdG9tLWNvbmRpdGlvbi5qc3x+ZXhwb3J0JzogJy4vaW5kZXgtY3VzdG9tLmpzJ1xuICogICAgICAgIH1cbiAqICAgICB9LFxuICogICAgIC8vIGFsbG93cyBmb3Igc2V0dGluZyBwYWNrYWdlLXByZWZpeGVkIGRlcENhY2hlXG4gKiAgICAgLy8ga2V5cyBhcmUgbm9ybWFsaXplZCBtb2R1bGUga2V5cyByZWxhdGl2ZSB0byB0aGUgcGFja2FnZSBpdHNlbGZcbiAqICAgICBkZXBDYWNoZToge1xuICogICAgICAgLy8gaW1wb3J0ICdwYWNrYWdlL2luZGV4LmpzJyBsb2FkcyBpbiBwYXJhbGxlbCBwYWNrYWdlL2xpYi90ZXN0LmpzLHBhY2thZ2UvdmVuZG9yL3NpenpsZS5qc1xuICogICAgICAgJy4vaW5kZXguanMnOiBbJy4vdGVzdCddLFxuICogICAgICAgJy4vdGVzdC5qcyc6IFsnZXh0ZXJuYWwtZGVwJ10sXG4gKiAgICAgICAnZXh0ZXJuYWwtZGVwL3BhdGguanMnOiBbJy4vYW5vdGhlci5qcyddXG4gKiAgICAgfVxuICogICB9XG4gKiB9O1xuICpcbiAqIFRoZW46XG4gKiAgIGltcG9ydCAnanF1ZXJ5JyAgICAgICAgICAgICAgICAgICAgICAgLT4ganF1ZXJ5L2luZGV4LmpzXG4gKiAgIGltcG9ydCAnanF1ZXJ5L3N1Ym1vZHVsZScgICAgICAgICAgICAgLT4ganF1ZXJ5L3N1Ym1vZHVsZS5qc1xuICogICBpbXBvcnQgJ2pxdWVyeS9zdWJtb2R1bGUudHMnICAgICAgICAgIC0+IGpxdWVyeS9zdWJtb2R1bGUudHMgbG9hZGVkIGFzIHR5cGVzY3JpcHRcbiAqICAgaW1wb3J0ICdqcXVlcnkvdmVuZG9yL2Fub3RoZXInICAgICAgICAtPiBhbm90aGVyL2luZGV4LmpzXG4gKlxuICogRGV0YWlsZWQgQmVoYXZpb3Vyc1xuICogLSBtYWluIGNhbiBoYXZlIGEgbGVhZGluZyBcIi4vXCIgY2FuIGJlIGFkZGVkIG9wdGlvbmFsbHlcbiAqIC0gbWFwIGFuZCBkZWZhdWx0RXh0ZW5zaW9uIGFyZSBhcHBsaWVkIHRvIHRoZSBtYWluXG4gKiAtIGRlZmF1bHRFeHRlbnNpb24gYWRkcyB0aGUgZXh0ZW5zaW9uIG9ubHkgaWYgdGhlIGV4YWN0IGV4dGVuc2lvbiBpcyBub3QgcHJlc2VudFxuXG4gKiAtIGlmIGEgbWV0YSB2YWx1ZSBpcyBhdmFpbGFibGUgZm9yIGEgbW9kdWxlLCBtYXAgYW5kIGRlZmF1bHRFeHRlbnNpb24gYXJlIHNraXBwZWRcbiAqIC0gbGlrZSBnbG9iYWwgbWFwLCBwYWNrYWdlIG1hcCBhbHNvIGFwcGxpZXMgdG8gc3VicGF0aHMgKHNpenpsZS94LCAuL3ZlbmRvci9hbm90aGVyL3N1YilcbiAqIC0gY29uZGl0aW9uIG1vZHVsZSBtYXAgaXMgJ0BlbnYnIG1vZHVsZSBpbiBwYWNrYWdlIG9yICdAc3lzdGVtLWVudicgZ2xvYmFsbHlcbiAqIC0gbWFwIHRhcmdldHMgc3VwcG9ydCBjb25kaXRpb25hbCBpbnRlcnBvbGF0aW9uICgnLi94JzogJy4veC4je3xlbnZ9LmpzJylcbiAqIC0gaW50ZXJuYWwgcGFja2FnZSBtYXAgdGFyZ2V0cyBjYW5ub3QgdXNlIGJvb2xlYW4gY29uZGl0aW9uYWxzXG4gKlxuICogUGFja2FnZSBDb25maWd1cmF0aW9uIExvYWRpbmdcbiAqXG4gKiBOb3QgYWxsIHBhY2thZ2VzIG1heSBhbHJlYWR5IGhhdmUgdGhlaXIgY29uZmlndXJhdGlvbiBwcmVzZW50IGluIHRoZSBTeXN0ZW0gY29uZmlnXG4gKiBGb3IgdGhlc2UgY2FzZXMsIGEgbGlzdCBvZiBwYWNrYWdlQ29uZmlnUGF0aHMgY2FuIGJlIHByb3ZpZGVkLCB3aGljaCB3aGVuIG1hdGNoZWQgYWdhaW5zdFxuICogYSByZXF1ZXN0LCB3aWxsIGZpcnN0IHJlcXVlc3QgYSBcIi5qc29uXCIgZmlsZSBieSB0aGUgcGFja2FnZSBrZXkgdG8gZGVyaXZlIHRoZSBwYWNrYWdlXG4gKiBjb25maWd1cmF0aW9uIGZyb20uIFRoaXMgYWxsb3dzIGR5bmFtaWMgbG9hZGluZyBvZiBub24tcHJlZGV0ZXJtaW5lZCBjb2RlLCBhIGtleSB1c2VcbiAqIGNhc2UgaW4gU3lzdGVtSlMuXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiAgIFN5c3RlbUpTLnBhY2thZ2VDb25maWdQYXRocyA9IFsncGFja2FnZXMvdGVzdC9wYWNrYWdlLmpzb24nLCAncGFja2FnZXMvKi5qc29uJ107XG4gKlxuICogICAvLyB3aWxsIGZpcnN0IHJlcXVlc3QgJ3BhY2thZ2VzL25ldy1wYWNrYWdlL3BhY2thZ2UuanNvbicgZm9yIHRoZSBwYWNrYWdlIGNvbmZpZ1xuICogICAvLyBiZWZvcmUgY29tcGxldGluZyB0aGUgcGFja2FnZSByZXF1ZXN0IHRvICdwYWNrYWdlcy9uZXctcGFja2FnZS9wYXRoJ1xuICogICBTeXN0ZW1KUy5pbXBvcnQoJ3BhY2thZ2VzL25ldy1wYWNrYWdlL3BhdGgnKTtcbiAqXG4gKiAgIC8vIHdpbGwgZmlyc3QgcmVxdWVzdCAncGFja2FnZXMvdGVzdC9wYWNrYWdlLmpzb24nIGJlZm9yZSB0aGUgbWFpblxuICogICBTeXN0ZW1KUy5pbXBvcnQoJ3BhY2thZ2VzL3Rlc3QnKTtcbiAqXG4gKiBXaGVuIGEgcGFja2FnZSBtYXRjaGVzIHBhY2thZ2VDb25maWdQYXRocywgaXQgd2lsbCBhbHdheXMgc2VuZCBhIGNvbmZpZyByZXF1ZXN0IGZvclxuICogdGhlIHBhY2thZ2UgY29uZmlndXJhdGlvbi5cbiAqIFRoZSBwYWNrYWdlIGtleSBpdHNlbGYgaXMgdGFrZW4gdG8gYmUgdGhlIG1hdGNoIHVwIHRvIGFuZCBpbmNsdWRpbmcgdGhlIGxhc3Qgd2lsZGNhcmRcbiAqIG9yIHRyYWlsaW5nIHNsYXNoLlxuICogVGhlIG1vc3Qgc3BlY2lmaWMgcGFja2FnZSBjb25maWcgcGF0aCB3aWxsIGJlIHVzZWQuXG4gKiBBbnkgZXhpc3RpbmcgcGFja2FnZSBjb25maWd1cmF0aW9ucyBmb3IgdGhlIHBhY2thZ2Ugd2lsbCBkZWVwbHkgbWVyZ2Ugd2l0aCB0aGVcbiAqIHBhY2thZ2UgY29uZmlnLCB3aXRoIHRoZSBleGlzdGluZyBwYWNrYWdlIGNvbmZpZ3VyYXRpb25zIHRha2luZyBwcmVmZXJlbmNlLlxuICogVG8gb3B0LW91dCBvZiB0aGUgcGFja2FnZSBjb25maWd1cmF0aW9uIHJlcXVlc3QgZm9yIGEgcGFja2FnZSB0aGF0IG1hdGNoZXNcbiAqIHBhY2thZ2VDb25maWdQYXRocywgdXNlIHRoZSB7IGNvbmZpZ3VyZWQ6IHRydWUgfSBwYWNrYWdlIGNvbmZpZyBvcHRpb24uXG4gKlxuICovXG5cbmZ1bmN0aW9uIGFkZERlZmF1bHRFeHRlbnNpb24gKGNvbmZpZywgcGtnLCBwa2dLZXksIHN1YlBhdGgsIHNraXBFeHRlbnNpb25zKSB7XG4gIC8vIGRvbid0IGFwcGx5IGV4dGVuc2lvbnMgdG8gZm9sZGVycyBvciBpZiBkZWZhdWx0RXh0ZW5zaW9uID0gZmFsc2VcbiAgaWYgKCFzdWJQYXRoIHx8ICFwa2cuZGVmYXVsdEV4dGVuc2lvbiB8fCBzdWJQYXRoW3N1YlBhdGgubGVuZ3RoIC0gMV0gPT09ICcvJyB8fCBza2lwRXh0ZW5zaW9ucylcbiAgICByZXR1cm4gc3ViUGF0aDtcblxuICB2YXIgbWV0YU1hdGNoID0gZmFsc2U7XG5cbiAgLy8gZXhhY3QgbWV0YSBvciBtZXRhIHdpdGggYW55IGNvbnRlbnQgYWZ0ZXIgdGhlIGxhc3Qgd2lsZGNhcmQgc2tpcHMgZXh0ZW5zaW9uXG4gIGlmIChwa2cubWV0YSlcbiAgICBnZXRNZXRhTWF0Y2hlcyhwa2cubWV0YSwgc3ViUGF0aCwgZnVuY3Rpb24gKG1ldGFQYXR0ZXJuLCBtYXRjaE1ldGEsIG1hdGNoRGVwdGgpIHtcbiAgICAgIGlmIChtYXRjaERlcHRoID09PSAwIHx8IG1ldGFQYXR0ZXJuLmxhc3RJbmRleE9mKCcqJykgIT09IG1ldGFQYXR0ZXJuLmxlbmd0aCAtIDEpXG4gICAgICAgIHJldHVybiBtZXRhTWF0Y2ggPSB0cnVlO1xuICAgIH0pO1xuXG4gIC8vIGV4YWN0IGdsb2JhbCBtZXRhIG9yIG1ldGEgd2l0aCBhbnkgY29udGVudCBhZnRlciB0aGUgbGFzdCB3aWxkY2FyZCBza2lwcyBleHRlbnNpb25cbiAgaWYgKCFtZXRhTWF0Y2ggJiYgY29uZmlnLm1ldGEpXG4gICAgZ2V0TWV0YU1hdGNoZXMoY29uZmlnLm1ldGEsIHBrZ0tleSArICcvJyArIHN1YlBhdGgsIGZ1bmN0aW9uIChtZXRhUGF0dGVybiwgbWF0Y2hNZXRhLCBtYXRjaERlcHRoKSB7XG4gICAgICBpZiAobWF0Y2hEZXB0aCA9PT0gMCB8fCBtZXRhUGF0dGVybi5sYXN0SW5kZXhPZignKicpICE9PSBtZXRhUGF0dGVybi5sZW5ndGggLSAxKVxuICAgICAgICByZXR1cm4gbWV0YU1hdGNoID0gdHJ1ZTtcbiAgICB9KTtcblxuICBpZiAobWV0YU1hdGNoKVxuICAgIHJldHVybiBzdWJQYXRoO1xuXG4gIC8vIHdvcmsgb3V0IHdoYXQgdGhlIGRlZmF1bHRFeHRlbnNpb24gaXMgYW5kIGFkZCBpZiBub3QgdGhlcmUgYWxyZWFkeVxuICB2YXIgZGVmYXVsdEV4dGVuc2lvbiA9ICcuJyArIHBrZy5kZWZhdWx0RXh0ZW5zaW9uO1xuICBpZiAoc3ViUGF0aC5zdWJzdHIoc3ViUGF0aC5sZW5ndGggLSBkZWZhdWx0RXh0ZW5zaW9uLmxlbmd0aCkgIT09IGRlZmF1bHRFeHRlbnNpb24pXG4gICAgcmV0dXJuIHN1YlBhdGggKyBkZWZhdWx0RXh0ZW5zaW9uO1xuICBlbHNlXG4gICAgcmV0dXJuIHN1YlBhdGg7XG59XG5cbmZ1bmN0aW9uIGFwcGx5UGFja2FnZUNvbmZpZ1N5bmMgKGxvYWRlciwgY29uZmlnLCBwa2csIHBrZ0tleSwgc3ViUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKSB7XG4gIC8vIG1haW5cbiAgaWYgKCFzdWJQYXRoKSB7XG4gICAgaWYgKHBrZy5tYWluKVxuICAgICAgc3ViUGF0aCA9IHBrZy5tYWluLnN1YnN0cigwLCAyKSA9PT0gJy4vJyA/IHBrZy5tYWluLnN1YnN0cigyKSA6IHBrZy5tYWluO1xuICAgIGVsc2VcbiAgICAgIC8vIGFsc28gbm8gc3VibWFwIGlmIGtleSBpcyBwYWNrYWdlIGl0c2VsZiAoaW1wb3J0ICdwa2cnIC0+ICdwYXRoL3RvL3BrZy5qcycpXG4gICAgICAvLyBOQiBjYW4gYWRkIGEgZGVmYXVsdCBwYWNrYWdlIG1haW4gY29udmVudGlvbiBoZXJlXG4gICAgICAvLyBpZiBpdCBiZWNvbWVzIGludGVybmFsIHRvIHRoZSBwYWNrYWdlIHRoZW4gaXQgd291bGQgbm8gbG9uZ2VyIGJlIGFuIGV4aXQgcGF0aFxuICAgICAgcmV0dXJuIHBrZ0tleTtcbiAgfVxuXG4gIC8vIG1hcCBjb25maWcgY2hlY2tpbmcgd2l0aG91dCB0aGVuIHdpdGggZXh0ZW5zaW9uc1xuICBpZiAocGtnLm1hcCkge1xuICAgIHZhciBtYXBQYXRoID0gJy4vJyArIHN1YlBhdGg7XG5cbiAgICB2YXIgbWFwTWF0Y2ggPSBnZXRNYXBNYXRjaChwa2cubWFwLCBtYXBQYXRoKTtcblxuICAgIC8vIHdlIHRoZW4gY2hlY2sgbWFwIHdpdGggdGhlIGRlZmF1bHQgZXh0ZW5zaW9uIGFkZGluZ1xuICAgIGlmICghbWFwTWF0Y2gpIHtcbiAgICAgIG1hcFBhdGggPSAnLi8nICsgYWRkRGVmYXVsdEV4dGVuc2lvbihjb25maWcsIHBrZywgcGtnS2V5LCBzdWJQYXRoLCBza2lwRXh0ZW5zaW9ucyk7XG4gICAgICBpZiAobWFwUGF0aCAhPT0gJy4vJyArIHN1YlBhdGgpXG4gICAgICAgIG1hcE1hdGNoID0gZ2V0TWFwTWF0Y2gocGtnLm1hcCwgbWFwUGF0aCk7XG4gICAgfVxuICAgIGlmIChtYXBNYXRjaCkge1xuICAgICAgdmFyIG1hcHBlZCA9IGRvTWFwU3luYyhsb2FkZXIsIGNvbmZpZywgcGtnLCBwa2dLZXksIG1hcE1hdGNoLCBtYXBQYXRoLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpO1xuICAgICAgaWYgKG1hcHBlZClcbiAgICAgICAgcmV0dXJuIG1hcHBlZDtcbiAgICB9XG4gIH1cblxuICAvLyBub3JtYWwgcGFja2FnZSByZXNvbHV0aW9uXG4gIHJldHVybiBwa2dLZXkgKyAnLycgKyBhZGREZWZhdWx0RXh0ZW5zaW9uKGNvbmZpZywgcGtnLCBwa2dLZXksIHN1YlBhdGgsIHNraXBFeHRlbnNpb25zKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRNYXBwaW5nIChtYXBNYXRjaCwgbWFwcGVkLCBwYXRoKSB7XG4gIC8vIGFsbG93IGludGVybmFsIC4veCAtPiAuL3gveSBvciAuL3gvIC0+IC4veC95IHJlY3Vyc2l2ZSBtYXBzXG4gIC8vIGJ1dCBvbmx5IGlmIHRoZSBwYXRoIGlzIGV4YWN0bHkgLi94IGFuZCBub3QgLi94L3pcbiAgaWYgKG1hcHBlZC5zdWJzdHIoMCwgbWFwTWF0Y2gubGVuZ3RoKSA9PT0gbWFwTWF0Y2ggJiYgcGF0aC5sZW5ndGggPiBtYXBNYXRjaC5sZW5ndGgpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBkb01hcFN5bmMgKGxvYWRlciwgY29uZmlnLCBwa2csIHBrZ0tleSwgbWFwTWF0Y2gsIHBhdGgsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucykge1xuICBpZiAocGF0aFtwYXRoLmxlbmd0aCAtIDFdID09PSAnLycpXG4gICAgcGF0aCA9IHBhdGguc3Vic3RyKDAsIHBhdGgubGVuZ3RoIC0gMSk7XG4gIHZhciBtYXBwZWQgPSBwa2cubWFwW21hcE1hdGNoXTtcblxuICBpZiAodHlwZW9mIG1hcHBlZCA9PT0gJ29iamVjdCcpXG4gICAgdGhyb3cgbmV3IEVycm9yKCdTeW5jaHJvbm91cyBjb25kaXRpb25hbCBub3JtYWxpemF0aW9uIG5vdCBzdXBwb3J0ZWQgc3luYyBub3JtYWxpemluZyAnICsgbWFwTWF0Y2ggKyAnIGluICcgKyBwa2dLZXkpO1xuXG4gIGlmICghdmFsaWRNYXBwaW5nKG1hcE1hdGNoLCBtYXBwZWQsIHBhdGgpIHx8IHR5cGVvZiBtYXBwZWQgIT09ICdzdHJpbmcnKVxuICAgIHJldHVybjtcblxuICByZXR1cm4gcGFja2FnZVJlc29sdmVTeW5jLmNhbGwobG9hZGVyLCBjb25maWcsIG1hcHBlZCArIHBhdGguc3Vic3RyKG1hcE1hdGNoLmxlbmd0aCksIHBrZ0tleSArICcvJywgbWV0YWRhdGEsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucyk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5UGFja2FnZUNvbmZpZyAobG9hZGVyLCBjb25maWcsIHBrZywgcGtnS2V5LCBzdWJQYXRoLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpIHtcbiAgLy8gbWFpblxuICBpZiAoIXN1YlBhdGgpIHtcbiAgICBpZiAocGtnLm1haW4pXG4gICAgICBzdWJQYXRoID0gcGtnLm1haW4uc3Vic3RyKDAsIDIpID09PSAnLi8nID8gcGtnLm1haW4uc3Vic3RyKDIpIDogcGtnLm1haW47XG4gICAgLy8gYWxzbyBubyBzdWJtYXAgaWYga2V5IGlzIHBhY2thZ2UgaXRzZWxmIChpbXBvcnQgJ3BrZycgLT4gJ3BhdGgvdG8vcGtnLmpzJylcbiAgICBlbHNlXG4gICAgICAvLyBOQiBjYW4gYWRkIGEgZGVmYXVsdCBwYWNrYWdlIG1haW4gY29udmVudGlvbiBoZXJlXG4gICAgICAvLyBpZiBpdCBiZWNvbWVzIGludGVybmFsIHRvIHRoZSBwYWNrYWdlIHRoZW4gaXQgd291bGQgbm8gbG9uZ2VyIGJlIGFuIGV4aXQgcGF0aFxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwa2dLZXkpO1xuICB9XG5cbiAgLy8gbWFwIGNvbmZpZyBjaGVja2luZyB3aXRob3V0IHRoZW4gd2l0aCBleHRlbnNpb25zXG4gIHZhciBtYXBQYXRoLCBtYXBNYXRjaDtcblxuICBpZiAocGtnLm1hcCkge1xuICAgIG1hcFBhdGggPSAnLi8nICsgc3ViUGF0aDtcbiAgICBtYXBNYXRjaCA9IGdldE1hcE1hdGNoKHBrZy5tYXAsIG1hcFBhdGgpO1xuXG4gICAgLy8gd2UgdGhlbiBjaGVjayBtYXAgd2l0aCB0aGUgZGVmYXVsdCBleHRlbnNpb24gYWRkaW5nXG4gICAgaWYgKCFtYXBNYXRjaCkge1xuICAgICAgbWFwUGF0aCA9ICcuLycgKyBhZGREZWZhdWx0RXh0ZW5zaW9uKGNvbmZpZywgcGtnLCBwa2dLZXksIHN1YlBhdGgsIHNraXBFeHRlbnNpb25zKTtcbiAgICAgIGlmIChtYXBQYXRoICE9PSAnLi8nICsgc3ViUGF0aClcbiAgICAgICAgbWFwTWF0Y2ggPSBnZXRNYXBNYXRjaChwa2cubWFwLCBtYXBQYXRoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gKG1hcE1hdGNoID8gZG9NYXAobG9hZGVyLCBjb25maWcsIHBrZywgcGtnS2V5LCBtYXBNYXRjaCwgbWFwUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKSA6IHJlc29sdmVkUHJvbWlzZSlcbiAgLnRoZW4oZnVuY3Rpb24gKG1hcHBlZCkge1xuICAgIGlmIChtYXBwZWQpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG1hcHBlZCk7XG5cbiAgICAvLyBub3JtYWwgcGFja2FnZSByZXNvbHV0aW9uIC8gZmFsbGJhY2sgcmVzb2x1dGlvbiBmb3Igbm8gY29uZGl0aW9uYWwgbWF0Y2hcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHBrZ0tleSArICcvJyArIGFkZERlZmF1bHRFeHRlbnNpb24oY29uZmlnLCBwa2csIHBrZ0tleSwgc3ViUGF0aCwgc2tpcEV4dGVuc2lvbnMpKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGRvTWFwIChsb2FkZXIsIGNvbmZpZywgcGtnLCBwa2dLZXksIG1hcE1hdGNoLCBwYXRoLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpIHtcbiAgaWYgKHBhdGhbcGF0aC5sZW5ndGggLSAxXSA9PT0gJy8nKVxuICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBwYXRoLmxlbmd0aCAtIDEpO1xuXG4gIHZhciBtYXBwZWQgPSBwa2cubWFwW21hcE1hdGNoXTtcblxuICBpZiAodHlwZW9mIG1hcHBlZCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAoIXZhbGlkTWFwcGluZyhtYXBNYXRjaCwgbWFwcGVkLCBwYXRoKSlcbiAgICAgIHJldHVybiByZXNvbHZlZFByb21pc2U7XG4gICAgcmV0dXJuIHBhY2thZ2VSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIG1hcHBlZCArIHBhdGguc3Vic3RyKG1hcE1hdGNoLmxlbmd0aCksIHBrZ0tleSArICcvJywgbWV0YWRhdGEsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucylcbiAgICAudGhlbihmdW5jdGlvbiAobm9ybWFsaXplZCkge1xuICAgICAgcmV0dXJuIGludGVycG9sYXRlQ29uZGl0aW9uYWwuY2FsbChsb2FkZXIsIG5vcm1hbGl6ZWQsIHBrZ0tleSArICcvJywgbWV0YWRhdGEpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gd2UgdXNlIGEgc3BlY2lhbCBjb25kaXRpb25hbCBzeW50YXggdG8gYWxsb3cgdGhlIGJ1aWxkZXIgdG8gaGFuZGxlIGNvbmRpdGlvbmFsIGJyYW5jaCBwb2ludHMgZnVydGhlclxuICAvKmlmIChsb2FkZXIuYnVpbGRlcilcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHBrZ0tleSArICcvIzonICsgcGF0aCk7Ki9cblxuICAvLyB3ZSBsb2FkIGFsbCBjb25kaXRpb25zIHVwZnJvbnRcbiAgdmFyIGNvbmRpdGlvblByb21pc2VzID0gW107XG4gIHZhciBjb25kaXRpb25zID0gW107XG4gIGZvciAodmFyIGUgaW4gbWFwcGVkKSB7XG4gICAgdmFyIGMgPSBwYXJzZUNvbmRpdGlvbihlKTtcbiAgICBjb25kaXRpb25zLnB1c2goe1xuICAgICAgY29uZGl0aW9uOiBjLFxuICAgICAgbWFwOiBtYXBwZWRbZV1cbiAgICB9KTtcbiAgICBjb25kaXRpb25Qcm9taXNlcy5wdXNoKFJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlLmltcG9ydC5jYWxsKGxvYWRlciwgYy5tb2R1bGUsIHBrZ0tleSkpO1xuICB9XG5cbiAgLy8gbWFwIG9iamVjdCAtPiBjb25kaXRpb25hbCBtYXBcbiAgcmV0dXJuIFByb21pc2UuYWxsKGNvbmRpdGlvblByb21pc2VzKVxuICAudGhlbihmdW5jdGlvbiAoY29uZGl0aW9uVmFsdWVzKSB7XG4gICAgLy8gZmlyc3QgbWFwIGNvbmRpdGlvbiB0byBtYXRjaCBpcyB1c2VkXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25kaXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgYyA9IGNvbmRpdGlvbnNbaV0uY29uZGl0aW9uO1xuICAgICAgdmFyIHZhbHVlID0gcmVhZE1lbWJlckV4cHJlc3Npb24oYy5wcm9wLCAnX191c2VEZWZhdWx0JyBpbiBjb25kaXRpb25WYWx1ZXNbaV0gPyBjb25kaXRpb25WYWx1ZXNbaV0uX191c2VEZWZhdWx0IDogY29uZGl0aW9uVmFsdWVzW2ldKTtcbiAgICAgIGlmICghYy5uZWdhdGUgJiYgdmFsdWUgfHwgYy5uZWdhdGUgJiYgIXZhbHVlKVxuICAgICAgICByZXR1cm4gY29uZGl0aW9uc1tpXS5tYXA7XG4gICAgfVxuICB9KVxuICAudGhlbihmdW5jdGlvbiAobWFwcGVkKSB7XG4gICAgaWYgKG1hcHBlZCkge1xuICAgICAgaWYgKCF2YWxpZE1hcHBpbmcobWFwTWF0Y2gsIG1hcHBlZCwgcGF0aCkpXG4gICAgICAgIHJldHVybiByZXNvbHZlZFByb21pc2U7XG4gICAgICByZXR1cm4gcGFja2FnZVJlc29sdmUuY2FsbChsb2FkZXIsIGNvbmZpZywgbWFwcGVkICsgcGF0aC5zdWJzdHIobWFwTWF0Y2gubGVuZ3RoKSwgcGtnS2V5ICsgJy8nLCBtZXRhZGF0YSwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKVxuICAgICAgLnRoZW4oZnVuY3Rpb24gKG5vcm1hbGl6ZWQpIHtcbiAgICAgICAgcmV0dXJuIGludGVycG9sYXRlQ29uZGl0aW9uYWwuY2FsbChsb2FkZXIsIG5vcm1hbGl6ZWQsIHBrZ0tleSArICcvJywgbWV0YWRhdGEpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gbm8gZW52aXJvbm1lbnQgbWF0Y2ggLT4gZmFsbGJhY2sgdG8gb3JpZ2luYWwgc3ViUGF0aCBieSByZXR1cm5pbmcgdW5kZWZpbmVkXG4gIH0pO1xufVxuXG4vLyBjaGVjayBpZiB0aGUgZ2l2ZW4gbm9ybWFsaXplZCBrZXkgbWF0Y2hlcyBhIHBhY2thZ2VDb25maWdQYXRoXG4vLyBpZiBzbywgbG9hZHMgdGhlIGNvbmZpZ1xudmFyIHBhY2thZ2VDb25maWdQYXRocyA9IHt9O1xuXG4vLyBkYXRhIG9iamVjdCBmb3IgcXVpY2sgY2hlY2tzIGFnYWluc3QgcGFja2FnZSBwYXRoc1xuZnVuY3Rpb24gY3JlYXRlUGtnQ29uZmlnUGF0aE9iaiAocGF0aCkge1xuICB2YXIgbGFzdFdpbGRjYXJkID0gcGF0aC5sYXN0SW5kZXhPZignKicpO1xuICB2YXIgbGVuZ3RoID0gTWF0aC5tYXgobGFzdFdpbGRjYXJkICsgMSwgcGF0aC5sYXN0SW5kZXhPZignLycpKTtcbiAgcmV0dXJuIHtcbiAgICBsZW5ndGg6IGxlbmd0aCxcbiAgICByZWdFeDogbmV3IFJlZ0V4cCgnXignICsgcGF0aC5zdWJzdHIoMCwgbGVuZ3RoKS5yZXBsYWNlKC9bLis/XiR7fSgpfFtcXF1cXFxcXS9nLCAnXFxcXCQmJykucmVwbGFjZSgvXFwqL2csICdbXlxcXFwvXSsnKSArICcpKFxcXFwvfCQpJyksXG4gICAgd2lsZGNhcmQ6IGxhc3RXaWxkY2FyZCAhPT0gLTFcbiAgfTtcbn1cblxuLy8gbW9zdCBzcGVjaWZpYyBtYXRjaCB3aW5zXG5mdW5jdGlvbiBnZXRQYWNrYWdlQ29uZmlnTWF0Y2ggKGNvbmZpZywgbm9ybWFsaXplZCkge1xuICB2YXIgcGtnS2V5LCBleGFjdE1hdGNoID0gZmFsc2UsIGNvbmZpZ1BhdGg7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY29uZmlnLnBhY2thZ2VDb25maWdQYXRocy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYWNrYWdlQ29uZmlnUGF0aCA9IGNvbmZpZy5wYWNrYWdlQ29uZmlnUGF0aHNbaV07XG4gICAgdmFyIHAgPSBwYWNrYWdlQ29uZmlnUGF0aHNbcGFja2FnZUNvbmZpZ1BhdGhdIHx8IChwYWNrYWdlQ29uZmlnUGF0aHNbcGFja2FnZUNvbmZpZ1BhdGhdID0gY3JlYXRlUGtnQ29uZmlnUGF0aE9iaihwYWNrYWdlQ29uZmlnUGF0aCkpO1xuICAgIGlmIChub3JtYWxpemVkLmxlbmd0aCA8IHAubGVuZ3RoKVxuICAgICAgY29udGludWU7XG4gICAgdmFyIG1hdGNoID0gbm9ybWFsaXplZC5tYXRjaChwLnJlZ0V4KTtcbiAgICBpZiAobWF0Y2ggJiYgKCFwa2dLZXkgfHwgKCEoZXhhY3RNYXRjaCAmJiBwLndpbGRjYXJkKSAmJiBwa2dLZXkubGVuZ3RoIDwgbWF0Y2hbMV0ubGVuZ3RoKSkpIHtcbiAgICAgIHBrZ0tleSA9IG1hdGNoWzFdO1xuICAgICAgZXhhY3RNYXRjaCA9ICFwLndpbGRjYXJkO1xuICAgICAgY29uZmlnUGF0aCA9IHBrZ0tleSArIHBhY2thZ2VDb25maWdQYXRoLnN1YnN0cihwLmxlbmd0aCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFwa2dLZXkpXG4gICAgcmV0dXJuO1xuXG4gIHJldHVybiB7XG4gICAgcGFja2FnZUtleTogcGtnS2V5LFxuICAgIGNvbmZpZ1BhdGg6IGNvbmZpZ1BhdGhcbiAgfTtcbn1cblxuZnVuY3Rpb24gbG9hZFBhY2thZ2VDb25maWdQYXRoIChsb2FkZXIsIGNvbmZpZywgcGtnQ29uZmlnUGF0aCwgbWV0YWRhdGEsIG5vcm1hbGl6ZWQpIHtcbiAgdmFyIGNvbmZpZ0xvYWRlciA9IGxvYWRlci5wbHVnaW5Mb2FkZXIgfHwgbG9hZGVyO1xuXG4gIC8vIGVuc3VyZSB3ZSBub3RlIHRoaXMgaXMgYSBwYWNrYWdlIGNvbmZpZyBmaWxlIHBhdGhcbiAgLy8gaXQgd2lsbCB0aGVuIGJlIHNraXBwZWQgZnJvbSBnZXR0aW5nIG90aGVyIG5vcm1hbGl6YXRpb25zIGl0c2VsZiB0byBlbnN1cmUgaWRlbXBvdGVuY3lcbiAgaWYgKGNvbmZpZy5wYWNrYWdlQ29uZmlnS2V5cy5pbmRleE9mKHBrZ0NvbmZpZ1BhdGgpID09PSAtMSlcbiAgICBjb25maWcucGFja2FnZUNvbmZpZ0tleXMucHVzaChwa2dDb25maWdQYXRoKTtcblxuICByZXR1cm4gY29uZmlnTG9hZGVyLmltcG9ydChwa2dDb25maWdQYXRoKVxuICAudGhlbihmdW5jdGlvbiAocGtnQ29uZmlnKSB7XG4gICAgc2V0UGtnQ29uZmlnKG1ldGFkYXRhLnBhY2thZ2VDb25maWcsIHBrZ0NvbmZpZywgbWV0YWRhdGEucGFja2FnZUtleSwgdHJ1ZSwgY29uZmlnKTtcbiAgICBtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLmNvbmZpZ3VyZWQgPSB0cnVlO1xuICB9KVxuICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgIHRocm93IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnVW5hYmxlIHRvIGZldGNoIHBhY2thZ2UgY29uZmlndXJhdGlvbiBmaWxlICcgKyBwa2dDb25maWdQYXRoKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldE1ldGFNYXRjaGVzIChwa2dNZXRhLCBzdWJQYXRoLCBtYXRjaEZuKSB7XG4gIC8vIHdpbGRjYXJkIG1ldGFcbiAgdmFyIHdpbGRjYXJkSW5kZXg7XG4gIGZvciAodmFyIG1vZHVsZSBpbiBwa2dNZXRhKSB7XG4gICAgLy8gYWxsb3cgbWV0YSB0byBzdGFydCB3aXRoIC4vIGZvciBmbGV4aWJpbGl0eVxuICAgIHZhciBkb3RSZWwgPSBtb2R1bGUuc3Vic3RyKDAsIDIpID09PSAnLi8nID8gJy4vJyA6ICcnO1xuICAgIGlmIChkb3RSZWwpXG4gICAgICBtb2R1bGUgPSBtb2R1bGUuc3Vic3RyKDIpO1xuXG4gICAgd2lsZGNhcmRJbmRleCA9IG1vZHVsZS5pbmRleE9mKCcqJyk7XG4gICAgaWYgKHdpbGRjYXJkSW5kZXggPT09IC0xKVxuICAgICAgY29udGludWU7XG5cbiAgICBpZiAobW9kdWxlLnN1YnN0cigwLCB3aWxkY2FyZEluZGV4KSA9PT0gc3ViUGF0aC5zdWJzdHIoMCwgd2lsZGNhcmRJbmRleClcbiAgICAgICAgJiYgbW9kdWxlLnN1YnN0cih3aWxkY2FyZEluZGV4ICsgMSkgPT09IHN1YlBhdGguc3Vic3RyKHN1YlBhdGgubGVuZ3RoIC0gbW9kdWxlLmxlbmd0aCArIHdpbGRjYXJkSW5kZXggKyAxKSkge1xuICAgICAgLy8gYWxvdyBtYXRjaCBmdW5jdGlvbiB0byByZXR1cm4gdHJ1ZSBmb3IgYW4gZXhpdCBwYXRoXG4gICAgICBpZiAobWF0Y2hGbihtb2R1bGUsIHBrZ01ldGFbZG90UmVsICsgbW9kdWxlXSwgbW9kdWxlLnNwbGl0KCcvJykubGVuZ3RoKSlcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuICAvLyBleGFjdCBtZXRhXG4gIHZhciBleGFjdE1ldGEgPSBwa2dNZXRhW3N1YlBhdGhdICYmIE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKHBrZ01ldGEsIHN1YlBhdGgpID8gcGtnTWV0YVtzdWJQYXRoXSA6IHBrZ01ldGFbJy4vJyArIHN1YlBhdGhdO1xuICBpZiAoZXhhY3RNZXRhKVxuICAgIG1hdGNoRm4oZXhhY3RNZXRhLCBleGFjdE1ldGEsIDApO1xufVxuXG5cbi8qXG4gKiBDb25kaXRpb25zIEV4dGVuc2lvblxuICpcbiAqICAgQWxsb3dzIGEgY29uZGl0aW9uIG1vZHVsZSB0byBhbHRlciB0aGUgcmVzb2x1dGlvbiBvZiBhbiBpbXBvcnQgdmlhIHN5bnRheDpcbiAqXG4gKiAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5LyN7YnJvd3Nlcn0nO1xuICpcbiAqICAgV2lsbCBmaXJzdCBsb2FkIHRoZSBtb2R1bGUgJ2Jyb3dzZXInIHZpYSBgU3lzdGVtSlMuaW1wb3J0KCdicm93c2VyJylgIGFuZFxuICogICB0YWtlIHRoZSBkZWZhdWx0IGV4cG9ydCBvZiB0aGF0IG1vZHVsZS5cbiAqICAgSWYgdGhlIGRlZmF1bHQgZXhwb3J0IGlzIG5vdCBhIHN0cmluZywgYW4gZXJyb3IgaXMgdGhyb3duLlxuICpcbiAqICAgV2UgdGhlbiBzdWJzdGl0dXRlIHRoZSBzdHJpbmcgaW50byB0aGUgcmVxdWlyZSB0byBnZXQgdGhlIGNvbmRpdGlvbmFsIHJlc29sdXRpb25cbiAqICAgZW5hYmxpbmcgZW52aXJvbm1lbnQtc3BlY2lmaWMgdmFyaWF0aW9ucyBsaWtlOlxuICpcbiAqICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnkvaWUnXG4gKiAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5L2ZpcmVmb3gnXG4gKiAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5L2Nocm9tZSdcbiAqICAgICBpbXBvcnQgJCBmcm9tICdqcXVlcnkvc2FmYXJpJ1xuICpcbiAqICAgSXQgY2FuIGJlIHVzZWZ1bCBmb3IgYSBjb25kaXRpb24gbW9kdWxlIHRvIGRlZmluZSBtdWx0aXBsZSBjb25kaXRpb25zLlxuICogICBUaGlzIGNhbiBiZSBkb25lIHZpYSB0aGUgYHxgIG1vZGlmaWVyIHRvIHNwZWNpZnkgYW4gZXhwb3J0IG1lbWJlciBleHByZXNzaW9uOlxuICpcbiAqICAgICBpbXBvcnQgJ2pxdWVyeS8jey4vYnJvd3Nlci5qc3xncmFkZS52ZXJzaW9ufSdcbiAqXG4gKiAgIFdoZXJlIHRoZSBgZ3JhZGVgIGV4cG9ydCBgdmVyc2lvbmAgbWVtYmVyIGluIHRoZSBgYnJvd3Nlci5qc2AgbW9kdWxlICBpcyBzdWJzdGl0dXRlZC5cbiAqXG4gKlxuICogQm9vbGVhbiBDb25kaXRpb25hbHNcbiAqXG4gKiAgIEZvciBwb2x5ZmlsbCBtb2R1bGVzLCB0aGF0IGFyZSB1c2VkIGFzIGltcG9ydHMgYnV0IGhhdmUgbm8gbW9kdWxlIHZhbHVlLFxuICogICBhIGJpbmFyeSBjb25kaXRpb25hbCBhbGxvd3MgYSBtb2R1bGUgbm90IHRvIGJlIGxvYWRlZCBhdCBhbGwgaWYgbm90IG5lZWRlZDpcbiAqXG4gKiAgICAgaW1wb3J0ICdlczUtc2hpbSM/Li9jb25kaXRpb25zLmpzfG5lZWRzLWVzNXNoaW0nXG4gKlxuICogICBUaGVzZSBjb25kaXRpb25zIGNhbiBhbHNvIGJlIG5lZ2F0ZWQgdmlhOlxuICpcbiAqICAgICBpbXBvcnQgJ2VzNS1zaGltIz8uL2NvbmRpdGlvbnMuanN8fmVzNidcbiAqXG4gKi9cblxudmFyIHN5c0NvbmRpdGlvbnMgPSBbJ2Jyb3dzZXInLCAnbm9kZScsICdkZXYnLCAnYnVpbGQnLCAncHJvZHVjdGlvbicsICdkZWZhdWx0J107XG5cbmZ1bmN0aW9uIHBhcnNlQ29uZGl0aW9uIChjb25kaXRpb24pIHtcbiAgdmFyIGNvbmRpdGlvbkV4cG9ydCwgY29uZGl0aW9uTW9kdWxlLCBuZWdhdGlvbjtcblxuICB2YXIgbmVnYXRpb247XG4gIHZhciBjb25kaXRpb25FeHBvcnRJbmRleCA9IGNvbmRpdGlvbi5sYXN0SW5kZXhPZignfCcpO1xuICBpZiAoY29uZGl0aW9uRXhwb3J0SW5kZXggIT09IC0xKSB7XG4gICAgY29uZGl0aW9uRXhwb3J0ID0gY29uZGl0aW9uLnN1YnN0cihjb25kaXRpb25FeHBvcnRJbmRleCArIDEpO1xuICAgIGNvbmRpdGlvbk1vZHVsZSA9IGNvbmRpdGlvbi5zdWJzdHIoMCwgY29uZGl0aW9uRXhwb3J0SW5kZXgpO1xuXG4gICAgaWYgKGNvbmRpdGlvbkV4cG9ydFswXSA9PT0gJ34nKSB7XG4gICAgICBuZWdhdGlvbiA9IHRydWU7XG4gICAgICBjb25kaXRpb25FeHBvcnQgPSBjb25kaXRpb25FeHBvcnQuc3Vic3RyKDEpO1xuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICBuZWdhdGlvbiA9IGNvbmRpdGlvblswXSA9PT0gJ34nO1xuICAgIGNvbmRpdGlvbkV4cG9ydCA9ICdkZWZhdWx0JztcbiAgICBjb25kaXRpb25Nb2R1bGUgPSBjb25kaXRpb24uc3Vic3RyKG5lZ2F0aW9uKTtcbiAgICBpZiAoc3lzQ29uZGl0aW9ucy5pbmRleE9mKGNvbmRpdGlvbk1vZHVsZSkgIT09IC0xKSB7XG4gICAgICBjb25kaXRpb25FeHBvcnQgPSBjb25kaXRpb25Nb2R1bGU7XG4gICAgICBjb25kaXRpb25Nb2R1bGUgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbW9kdWxlOiBjb25kaXRpb25Nb2R1bGUgfHwgJ0BzeXN0ZW0tZW52JyxcbiAgICBwcm9wOiBjb25kaXRpb25FeHBvcnQsXG4gICAgbmVnYXRlOiBuZWdhdGlvblxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ29uZGl0aW9uIChjb25kaXRpb25PYmosIHBhcmVudEtleSwgYm9vbCkge1xuICAvLyBpbXBvcnQgd2l0aG91dCBfX3VzZURlZmF1bHQgaGFuZGxpbmcgaGVyZVxuICByZXR1cm4gUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUuaW1wb3J0LmNhbGwodGhpcywgY29uZGl0aW9uT2JqLm1vZHVsZSwgcGFyZW50S2V5KVxuICAudGhlbihmdW5jdGlvbiAoY29uZGl0aW9uKSB7XG4gICAgdmFyIG0gPSByZWFkTWVtYmVyRXhwcmVzc2lvbihjb25kaXRpb25PYmoucHJvcCwgY29uZGl0aW9uKTtcblxuICAgIGlmIChib29sICYmIHR5cGVvZiBtICE9PSAnYm9vbGVhbicpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDb25kaXRpb24gZGlkIG5vdCByZXNvbHZlIHRvIGEgYm9vbGVhbi4nKTtcblxuICAgIHJldHVybiBjb25kaXRpb25PYmoubmVnYXRlID8gIW0gOiBtO1xuICB9KTtcbn1cblxudmFyIGludGVycG9sYXRpb25SZWdFeCA9IC8jXFx7W15cXH1dK1xcfS87XG5mdW5jdGlvbiBpbnRlcnBvbGF0ZUNvbmRpdGlvbmFsIChrZXksIHBhcmVudEtleSwgcGFyZW50TWV0YWRhdGEpIHtcbiAgLy8gZmlyc3Qgd2Ugbm9ybWFsaXplIHRoZSBjb25kaXRpb25hbFxuICB2YXIgY29uZGl0aW9uYWxNYXRjaCA9IGtleS5tYXRjaChpbnRlcnBvbGF0aW9uUmVnRXgpO1xuXG4gIGlmICghY29uZGl0aW9uYWxNYXRjaClcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGtleSk7XG5cbiAgdmFyIGNvbmRpdGlvbk9iaiA9IHBhcnNlQ29uZGl0aW9uLmNhbGwodGhpcywgY29uZGl0aW9uYWxNYXRjaFswXS5zdWJzdHIoMiwgY29uZGl0aW9uYWxNYXRjaFswXS5sZW5ndGggLSAzKSk7XG5cbiAgLy8gaW4gYnVpbGRzLCByZXR1cm4gbm9ybWFsaXplZCBjb25kaXRpb25hbFxuICAvKmlmICh0aGlzLmJ1aWxkZXIpXG4gICAgcmV0dXJuIHRoaXMubm9ybWFsaXplKGNvbmRpdGlvbk9iai5tb2R1bGUsIHBhcmVudEtleSwgY3JlYXRlTWV0YWRhdGEoKSwgcGFyZW50TWV0YWRhdGEpXG4gICAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvbk1vZHVsZSkge1xuICAgICAgY29uZGl0aW9uT2JqLm1vZHVsZSA9IGNvbmRpdGlvbk1vZHVsZTtcbiAgICAgIHJldHVybiBrZXkucmVwbGFjZShpbnRlcnBvbGF0aW9uUmVnRXgsICcjeycgKyBzZXJpYWxpemVDb25kaXRpb24oY29uZGl0aW9uT2JqKSArICd9Jyk7XG4gICAgfSk7Ki9cblxuICByZXR1cm4gcmVzb2x2ZUNvbmRpdGlvbi5jYWxsKHRoaXMsIGNvbmRpdGlvbk9iaiwgcGFyZW50S2V5LCBmYWxzZSlcbiAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvblZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiBjb25kaXRpb25WYWx1ZSAhPT0gJ3N0cmluZycpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgY29uZGl0aW9uIHZhbHVlIGZvciAnICsga2V5ICsgJyBkb2VzblxcJ3QgcmVzb2x2ZSB0byBhIHN0cmluZy4nKTtcblxuICAgIGlmIChjb25kaXRpb25WYWx1ZS5pbmRleE9mKCcvJykgIT09IC0xKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5hYmxlZCB0byBpbnRlcnBvbGF0ZSBjb25kaXRpb25hbCAnICsga2V5ICsgKHBhcmVudEtleSA/ICcgaW4gJyArIHBhcmVudEtleSA6ICcnKSArICdcXG5cXHRUaGUgY29uZGl0aW9uIHZhbHVlICcgKyBjb25kaXRpb25WYWx1ZSArICcgY2Fubm90IGNvbnRhaW4gYSBcIi9cIiBzZXBhcmF0b3IuJyk7XG5cbiAgICByZXR1cm4ga2V5LnJlcGxhY2UoaW50ZXJwb2xhdGlvblJlZ0V4LCBjb25kaXRpb25WYWx1ZSk7XG4gIH0pO1xufVxuXG4vKlxuIEV4dGVuZCBjb25maWcgbWVyZ2luZyBvbmUgZGVlcCBvbmx5XG5cbiAgbG9hZGVyLmNvbmZpZyh7XG4gICAgc29tZTogJ3JhbmRvbScsXG4gICAgY29uZmlnOiAnaGVyZScsXG4gICAgZGVlcDoge1xuICAgICAgY29uZmlnOiB7IHRvbzogJ3RvbycgfVxuICAgIH1cbiAgfSk7XG5cbiAgPD0+XG5cbiAgbG9hZGVyLnNvbWUgPSAncmFuZG9tJztcbiAgbG9hZGVyLmNvbmZpZyA9ICdoZXJlJ1xuICBsb2FkZXIuZGVlcCA9IGxvYWRlci5kZWVwIHx8IHt9O1xuICBsb2FkZXIuZGVlcC5jb25maWcgPSB7IHRvbzogJ3RvbycgfTtcblxuXG4gIE5vcm1hbGl6ZXMgbWV0YSBhbmQgcGFja2FnZSBjb25maWdzIGFsbG93aW5nIGZvcjpcblxuICBTeXN0ZW1KUy5jb25maWcoe1xuICAgIG1ldGE6IHtcbiAgICAgICcuL2luZGV4LmpzJzoge31cbiAgICB9XG4gIH0pO1xuXG4gIFRvIGJlY29tZVxuXG4gIFN5c3RlbUpTLm1ldGFbJ2h0dHBzOi8vdGhpc3NpdGUuY29tL2luZGV4LmpzJ10gPSB7fTtcblxuICBGb3IgZWFzeSBub3JtYWxpemF0aW9uIGNhbm9uaWNhbGl6YXRpb24gd2l0aCBsYXRlc3QgVVJMIHN1cHBvcnQuXG5cbiovXG52YXIgZW52Q29uZmlnTmFtZXMgPSBbJ2Jyb3dzZXJDb25maWcnLCAnbm9kZUNvbmZpZycsICdkZXZDb25maWcnLCAnYnVpbGRDb25maWcnLCAncHJvZHVjdGlvbkNvbmZpZyddO1xuZnVuY3Rpb24gZW52U2V0KGxvYWRlciwgY2ZnLCBlbnZDYWxsYmFjaykge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGVudkNvbmZpZ05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGVudkNvbmZpZyA9IGVudkNvbmZpZ05hbWVzW2ldO1xuICAgIGlmIChjZmdbZW52Q29uZmlnXSAmJiBlbnZNb2R1bGVbZW52Q29uZmlnLnN1YnN0cigwLCBlbnZDb25maWcubGVuZ3RoIC0gNildKVxuICAgICAgZW52Q2FsbGJhY2soY2ZnW2VudkNvbmZpZ10pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNsb25lT2JqIChvYmosIG1heERlcHRoKSB7XG4gIHZhciBjbG9uZSA9IHt9O1xuICBmb3IgKHZhciBwIGluIG9iaikge1xuICAgIHZhciBwcm9wID0gb2JqW3BdO1xuICAgIGlmIChtYXhEZXB0aCA+IDEpIHtcbiAgICAgIGlmIChwcm9wIGluc3RhbmNlb2YgQXJyYXkpXG4gICAgICAgIGNsb25lW3BdID0gW10uY29uY2F0KHByb3ApO1xuICAgICAgZWxzZSBpZiAodHlwZW9mIHByb3AgPT09ICdvYmplY3QnKVxuICAgICAgICBjbG9uZVtwXSA9IGNsb25lT2JqKHByb3AsIG1heERlcHRoIC0gMSk7XG4gICAgICBlbHNlIGlmIChwICE9PSAncGFja2FnZUNvbmZpZycpXG4gICAgICAgIGNsb25lW3BdID0gcHJvcDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBjbG9uZVtwXSA9IHByb3A7XG4gICAgfVxuICB9XG4gIHJldHVybiBjbG9uZTtcbn1cblxuZnVuY3Rpb24gZ2V0Q29uZmlnSXRlbSAoY29uZmlnLCBwKSB7XG4gIHZhciBjZmdJdGVtID0gY29uZmlnW3BdO1xuXG4gIC8vIGdldENvbmZpZyBtdXN0IHJldHVybiBhbiB1bm1vZGlmaWFibGUgY2xvbmUgb2YgdGhlIGNvbmZpZ3VyYXRpb25cbiAgaWYgKGNmZ0l0ZW0gaW5zdGFuY2VvZiBBcnJheSlcbiAgICByZXR1cm4gY29uZmlnW3BdLmNvbmNhdChbXSk7XG4gIGVsc2UgaWYgKHR5cGVvZiBjZmdJdGVtID09PSAnb2JqZWN0JylcbiAgICByZXR1cm4gY2xvbmVPYmooY2ZnSXRlbSwgMylcbiAgZWxzZVxuICAgIHJldHVybiBjb25maWdbcF07XG59XG5cbmZ1bmN0aW9uIGdldENvbmZpZyAoY29uZmlnTmFtZSkge1xuICBpZiAoY29uZmlnTmFtZSkge1xuICAgIGlmIChjb25maWdOYW1lcy5pbmRleE9mKGNvbmZpZ05hbWUpICE9PSAtMSlcbiAgICAgIHJldHVybiBnZXRDb25maWdJdGVtKHRoaXNbQ09ORklHXSwgY29uZmlnTmFtZSk7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdcIicgKyBjb25maWdOYW1lICsgJ1wiIGlzIG5vdCBhIHZhbGlkIGNvbmZpZ3VyYXRpb24gbmFtZS4gTXVzdCBiZSBvbmUgb2YgJyArIGNvbmZpZ05hbWVzLmpvaW4oJywgJykgKyAnLicpO1xuICB9XG5cbiAgdmFyIGNmZyA9IHt9O1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbmZpZ05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHAgPSBjb25maWdOYW1lc1tpXTtcbiAgICB2YXIgY29uZmlnSXRlbSA9IGdldENvbmZpZ0l0ZW0odGhpc1tDT05GSUddLCBwKTtcbiAgICBpZiAoY29uZmlnSXRlbSAhPT0gdW5kZWZpbmVkKVxuICAgICAgY2ZnW3BdID0gY29uZmlnSXRlbTtcbiAgfVxuICByZXR1cm4gY2ZnO1xufVxuXG5mdW5jdGlvbiBzZXRDb25maWcgKGNmZywgaXNFbnZDb25maWcpIHtcbiAgdmFyIGxvYWRlciA9IHRoaXM7XG4gIHZhciBjb25maWcgPSB0aGlzW0NPTkZJR107XG5cbiAgaWYgKCd3YXJuaW5ncycgaW4gY2ZnKVxuICAgIGNvbmZpZy53YXJuaW5ncyA9IGNmZy53YXJuaW5ncztcblxuICBpZiAoJ3dhc20nIGluIGNmZylcbiAgICBjb25maWcud2FzbSA9IHR5cGVvZiBXZWJBc3NlbWJseSAhPT0gJ3VuZGVmaW5lZCcgJiYgY2ZnLndhc207XG5cbiAgaWYgKCdwcm9kdWN0aW9uJyBpbiBjZmcgfHwgJ2J1aWxkJyBpbiBjZmcpXG4gICAgc2V0UHJvZHVjdGlvbi5jYWxsKGxvYWRlciwgISFjZmcucHJvZHVjdGlvbiwgISEoY2ZnLmJ1aWxkIHx8IGVudk1vZHVsZSAmJiBlbnZNb2R1bGUuYnVpbGQpKTtcblxuICBpZiAoIWlzRW52Q29uZmlnKSB7XG4gICAgLy8gaWYgdXNpbmcgbm9kZUNvbmZpZyAvIGJyb3dzZXJDb25maWcgLyBwcm9kdWN0aW9uQ29uZmlnLCB0YWtlIGJhc2VVUkwgZnJvbSB0aGVyZVxuICAgIC8vIHRoZXNlIGV4Y2VwdGlvbnMgd2lsbCBiZSB1bm5lY2Vzc2FyeSB3aGVuIHdlIGNhbiBwcm9wZXJseSBpbXBsZW1lbnQgY29uZmlnIHF1ZXVpbmdzXG4gICAgdmFyIGJhc2VVUkw7XG4gICAgZW52U2V0KGxvYWRlciwgY2ZnLCBmdW5jdGlvbihjZmcpIHtcbiAgICAgIGJhc2VVUkwgPSBiYXNlVVJMIHx8IGNmZy5iYXNlVVJMO1xuICAgIH0pO1xuICAgIGJhc2VVUkwgPSBiYXNlVVJMIHx8IGNmZy5iYXNlVVJMO1xuXG4gICAgLy8gYWx3YXlzIGNvbmZpZ3VyZSBiYXNlVVJMIGZpcnN0XG4gICAgaWYgKGJhc2VVUkwpIHtcbiAgICAgIGNvbmZpZy5iYXNlVVJMID0gcmVzb2x2ZUlmTm90UGxhaW4oYmFzZVVSTCwgYmFzZVVSSSkgfHwgcmVzb2x2ZUlmTm90UGxhaW4oJy4vJyArIGJhc2VVUkwsIGJhc2VVUkkpO1xuICAgICAgaWYgKGNvbmZpZy5iYXNlVVJMW2NvbmZpZy5iYXNlVVJMLmxlbmd0aCAtIDFdICE9PSAnLycpXG4gICAgICAgIGNvbmZpZy5iYXNlVVJMICs9ICcvJztcbiAgICB9XG5cbiAgICBpZiAoY2ZnLnBhdGhzKVxuICAgICAgZXh0ZW5kKGNvbmZpZy5wYXRocywgY2ZnLnBhdGhzKTtcblxuICAgIGVudlNldChsb2FkZXIsIGNmZywgZnVuY3Rpb24oY2ZnKSB7XG4gICAgICBpZiAoY2ZnLnBhdGhzKVxuICAgICAgICBleHRlbmQoY29uZmlnLnBhdGhzLCBjZmcucGF0aHMpO1xuICAgIH0pO1xuXG4gICAgZm9yICh2YXIgcCBpbiBjb25maWcucGF0aHMpIHtcbiAgICAgIGlmIChjb25maWcucGF0aHNbcF0uaW5kZXhPZignKicpID09PSAtMSlcbiAgICAgICAgY29udGludWU7XG4gICAgICB3YXJuLmNhbGwoY29uZmlnLCAnUGF0aCBjb25maWcgJyArIHAgKyAnIC0+ICcgKyBjb25maWcucGF0aHNbcF0gKyAnIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYXMgd2lsZGNhcmRzIGFyZSBkZXByZWNhdGVkLicpO1xuICAgICAgZGVsZXRlIGNvbmZpZy5wYXRoc1twXTtcbiAgICB9XG4gIH1cblxuICBpZiAoY2ZnLmRlZmF1bHRKU0V4dGVuc2lvbnMpXG4gICAgd2Fybi5jYWxsKGNvbmZpZywgJ1RoZSBkZWZhdWx0SlNFeHRlbnNpb25zIGNvbmZpZ3VyYXRpb24gb3B0aW9uIGlzIGRlcHJlY2F0ZWQuXFxuICBVc2UgcGFja2FnZXMgZGVmYXVsdEV4dGVuc2lvbiBpbnN0ZWFkLicsIHRydWUpO1xuXG4gIGlmICh0eXBlb2YgY2ZnLnBsdWdpbkZpcnN0ID09PSAnYm9vbGVhbicpXG4gICAgY29uZmlnLnBsdWdpbkZpcnN0ID0gY2ZnLnBsdWdpbkZpcnN0O1xuXG4gIGlmIChjZmcubWFwKSB7XG4gICAgZm9yICh2YXIgcCBpbiBjZmcubWFwKSB7XG4gICAgICB2YXIgdiA9IGNmZy5tYXBbcF07XG5cbiAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIG1hcHBlZCA9IGNvcmVSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIHYsIHVuZGVmaW5lZCwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgaWYgKG1hcHBlZFttYXBwZWQubGVuZ3RoIC0xXSA9PT0gJy8nICYmIHBbcC5sZW5ndGggLSAxXSAhPT0gJzonICYmIHBbcC5sZW5ndGggLSAxXSAhPT0gJy8nKVxuICAgICAgICAgIG1hcHBlZCA9IG1hcHBlZC5zdWJzdHIoMCwgbWFwcGVkLmxlbmd0aCAtIDEpO1xuICAgICAgICBjb25maWcubWFwW3BdID0gbWFwcGVkO1xuICAgICAgfVxuXG4gICAgICAvLyBvYmplY3QgbWFwXG4gICAgICBlbHNlIHtcbiAgICAgICAgdmFyIHBrZ05hbWUgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBwW3AubGVuZ3RoIC0gMV0gIT09ICcvJyA/IHAgKyAnLycgOiBwLCB1bmRlZmluZWQsIHRydWUsIHRydWUpO1xuICAgICAgICBwa2dOYW1lID0gcGtnTmFtZS5zdWJzdHIoMCwgcGtnTmFtZS5sZW5ndGggLSAxKTtcblxuICAgICAgICB2YXIgcGtnID0gY29uZmlnLnBhY2thZ2VzW3BrZ05hbWVdO1xuICAgICAgICBpZiAoIXBrZykge1xuICAgICAgICAgIHBrZyA9IGNvbmZpZy5wYWNrYWdlc1twa2dOYW1lXSA9IGNyZWF0ZVBhY2thZ2UoKTtcbiAgICAgICAgICAvLyB1c2UgJycgaW5zdGVhZCBvZiBmYWxzZSB0byBrZWVwIHR5cGUgY29uc2lzdGVudFxuICAgICAgICAgIHBrZy5kZWZhdWx0RXh0ZW5zaW9uID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgc2V0UGtnQ29uZmlnKHBrZywgeyBtYXA6IHYgfSwgcGtnTmFtZSwgZmFsc2UsIGNvbmZpZyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKGNmZy5wYWNrYWdlQ29uZmlnUGF0aHMpIHtcbiAgICB2YXIgcGFja2FnZUNvbmZpZ1BhdGhzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjZmcucGFja2FnZUNvbmZpZ1BhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcGF0aCA9IGNmZy5wYWNrYWdlQ29uZmlnUGF0aHNbaV07XG4gICAgICB2YXIgcGFja2FnZUxlbmd0aCA9IE1hdGgubWF4KHBhdGgubGFzdEluZGV4T2YoJyonKSArIDEsIHBhdGgubGFzdEluZGV4T2YoJy8nKSk7XG4gICAgICB2YXIgbm9ybWFsaXplZCA9IGNvcmVSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIHBhdGguc3Vic3RyKDAsIHBhY2thZ2VMZW5ndGgpLCB1bmRlZmluZWQsIGZhbHNlLCBmYWxzZSk7XG4gICAgICBwYWNrYWdlQ29uZmlnUGF0aHNbaV0gPSBub3JtYWxpemVkICsgcGF0aC5zdWJzdHIocGFja2FnZUxlbmd0aCk7XG4gICAgfVxuICAgIGNvbmZpZy5wYWNrYWdlQ29uZmlnUGF0aHMgPSBwYWNrYWdlQ29uZmlnUGF0aHM7XG4gIH1cblxuICBpZiAoY2ZnLmJ1bmRsZXMpIHtcbiAgICBmb3IgKHZhciBwIGluIGNmZy5idW5kbGVzKSB7XG4gICAgICB2YXIgYnVuZGxlID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNmZy5idW5kbGVzW3BdLmxlbmd0aDsgaSsrKVxuICAgICAgICBidW5kbGUucHVzaChsb2FkZXIubm9ybWFsaXplU3luYyhjZmcuYnVuZGxlc1twXVtpXSkpO1xuICAgICAgY29uZmlnLmJ1bmRsZXNbcF0gPSBidW5kbGU7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNmZy5wYWNrYWdlcykge1xuICAgIGZvciAodmFyIHAgaW4gY2ZnLnBhY2thZ2VzKSB7XG4gICAgICBpZiAocC5tYXRjaCgvXihbXlxcL10rOik/XFwvXFwvJC8pKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIicgKyBwICsgJ1wiIGlzIG5vdCBhIHZhbGlkIHBhY2thZ2UgbmFtZS4nKTtcblxuICAgICAgdmFyIHBrZ05hbWUgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBwW3AubGVuZ3RoIC0gMV0gIT09ICcvJyA/IHAgKyAnLycgOiBwLCB1bmRlZmluZWQsIHRydWUsIHRydWUpO1xuICAgICAgcGtnTmFtZSA9IHBrZ05hbWUuc3Vic3RyKDAsIHBrZ05hbWUubGVuZ3RoIC0gMSk7XG5cbiAgICAgIHNldFBrZ0NvbmZpZyhjb25maWcucGFja2FnZXNbcGtnTmFtZV0gPSBjb25maWcucGFja2FnZXNbcGtnTmFtZV0gfHwgY3JlYXRlUGFja2FnZSgpLCBjZmcucGFja2FnZXNbcF0sIHBrZ05hbWUsIGZhbHNlLCBjb25maWcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjZmcuZGVwQ2FjaGUpIHtcbiAgICBmb3IgKHZhciBwIGluIGNmZy5kZXBDYWNoZSlcbiAgICAgIGNvbmZpZy5kZXBDYWNoZVtsb2FkZXIubm9ybWFsaXplU3luYyhwKV0gPSBbXS5jb25jYXQoY2ZnLmRlcENhY2hlW3BdKTtcbiAgfVxuXG4gIGlmIChjZmcubWV0YSkge1xuICAgIGZvciAodmFyIHAgaW4gY2ZnLm1ldGEpIHtcbiAgICAgIC8vIGJhc2Ugd2lsZGNhcmQgc3RheXMgYmFzZVxuICAgICAgaWYgKHBbMF0gPT09ICcqJykge1xuICAgICAgICBleHRlbmQoY29uZmlnLm1ldGFbcF0gPSBjb25maWcubWV0YVtwXSB8fCB7fSwgY2ZnLm1ldGFbcF0pO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHZhciByZXNvbHZlZCA9IGNvcmVSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIHAsIHVuZGVmaW5lZCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgIGV4dGVuZChjb25maWcubWV0YVtyZXNvbHZlZF0gPSBjb25maWcubWV0YVtyZXNvbHZlZF0gfHwge30sIGNmZy5tZXRhW3BdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoJ3RyYW5zcGlsZXInIGluIGNmZylcbiAgICBjb25maWcudHJhbnNwaWxlciA9IGNmZy50cmFuc3BpbGVyO1xuXG5cbiAgLy8gY29weSBhbnkgcmVtYWluaW5nIG5vbi1zdGFuZGFyZCBjb25maWd1cmF0aW9uIHByb3BlcnRpZXNcbiAgZm9yICh2YXIgYyBpbiBjZmcpIHtcbiAgICBpZiAoY29uZmlnTmFtZXMuaW5kZXhPZihjKSAhPT0gLTEpXG4gICAgICBjb250aW51ZTtcbiAgICBpZiAoZW52Q29uZmlnTmFtZXMuaW5kZXhPZihjKSAhPT0gLTEpXG4gICAgICBjb250aW51ZTtcblxuICAgIC8vIHdhcm4uY2FsbChjb25maWcsICdTZXR0aW5nIGN1c3RvbSBjb25maWcgb3B0aW9uIGBTeXN0ZW0uY29uZmlnKHsgJyArIGMgKyAnOiAuLi4gfSlgIGlzIGRlcHJlY2F0ZWQuIEF2b2lkIGN1c3RvbSBjb25maWcgb3B0aW9ucyBvciBzZXQgU3lzdGVtSlMuJyArIGMgKyAnID0gLi4uIGRpcmVjdGx5LicpO1xuICAgIGxvYWRlcltjXSA9IGNmZ1tjXTtcbiAgfVxuXG4gIGVudlNldChsb2FkZXIsIGNmZywgZnVuY3Rpb24oY2ZnKSB7XG4gICAgbG9hZGVyLmNvbmZpZyhjZmcsIHRydWUpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlUGFja2FnZSAoKSB7XG4gIHJldHVybiB7XG4gICAgZGVmYXVsdEV4dGVuc2lvbjogdW5kZWZpbmVkLFxuICAgIG1haW46IHVuZGVmaW5lZCxcbiAgICBmb3JtYXQ6IHVuZGVmaW5lZCxcbiAgICBtZXRhOiB1bmRlZmluZWQsXG4gICAgbWFwOiB1bmRlZmluZWQsXG4gICAgcGFja2FnZUNvbmZpZzogdW5kZWZpbmVkLFxuICAgIGNvbmZpZ3VyZWQ6IGZhbHNlXG4gIH07XG59XG5cbi8vIGRlZXBseS1tZXJnZSAodG8gZmlyc3QgbGV2ZWwpIGNvbmZpZyB3aXRoIGFueSBleGlzdGluZyBwYWNrYWdlIGNvbmZpZ1xuZnVuY3Rpb24gc2V0UGtnQ29uZmlnIChwa2csIGNmZywgcGtnTmFtZSwgcHJlcGVuZENvbmZpZywgY29uZmlnKSB7XG4gIGZvciAodmFyIHByb3AgaW4gY2ZnKSB7XG4gICAgaWYgKHByb3AgPT09ICdtYWluJyB8fCBwcm9wID09PSAnZm9ybWF0JyB8fCBwcm9wID09PSAnZGVmYXVsdEV4dGVuc2lvbicgfHwgcHJvcCA9PT0gJ2NvbmZpZ3VyZWQnKSB7XG4gICAgICBpZiAoIXByZXBlbmRDb25maWcgfHwgcGtnW3Byb3BdID09PSB1bmRlZmluZWQpXG4gICAgICAgIHBrZ1twcm9wXSA9IGNmZ1twcm9wXTtcbiAgICB9XG4gICAgZWxzZSBpZiAocHJvcCA9PT0gJ21hcCcpIHtcbiAgICAgIChwcmVwZW5kQ29uZmlnID8gcHJlcGVuZCA6IGV4dGVuZCkocGtnLm1hcCA9IHBrZy5tYXAgfHwge30sIGNmZy5tYXApO1xuICAgIH1cbiAgICBlbHNlIGlmIChwcm9wID09PSAnbWV0YScpIHtcbiAgICAgIChwcmVwZW5kQ29uZmlnID8gcHJlcGVuZCA6IGV4dGVuZCkocGtnLm1ldGEgPSBwa2cubWV0YSB8fCB7fSwgY2ZnLm1ldGEpO1xuICAgIH1cbiAgICBlbHNlIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChjZmcsIHByb3ApKSB7XG4gICAgICB3YXJuLmNhbGwoY29uZmlnLCAnXCInICsgcHJvcCArICdcIiBpcyBub3QgYSB2YWxpZCBwYWNrYWdlIGNvbmZpZ3VyYXRpb24gb3B0aW9uIGluIHBhY2thZ2UgJyArIHBrZ05hbWUpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGRlZmF1bHQgZGVmYXVsdEV4dGVuc2lvbiBmb3IgcGFja2FnZXMgb25seVxuICBpZiAocGtnLmRlZmF1bHRFeHRlbnNpb24gPT09IHVuZGVmaW5lZClcbiAgICBwa2cuZGVmYXVsdEV4dGVuc2lvbiA9ICdqcyc7XG5cbiAgaWYgKHBrZy5tYWluID09PSB1bmRlZmluZWQgJiYgcGtnLm1hcCAmJiBwa2cubWFwWycuJ10pIHtcbiAgICBwa2cubWFpbiA9IHBrZy5tYXBbJy4nXTtcbiAgICBkZWxldGUgcGtnLm1hcFsnLiddO1xuICB9XG4gIC8vIG1haW4gb2JqZWN0IGJlY29tZXMgbWFpbiBtYXBcbiAgZWxzZSBpZiAodHlwZW9mIHBrZy5tYWluID09PSAnb2JqZWN0Jykge1xuICAgIHBrZy5tYXAgPSBwa2cubWFwIHx8IHt9O1xuICAgIHBrZy5tYXBbJy4vQG1haW4nXSA9IHBrZy5tYWluO1xuICAgIHBrZy5tYWluWydkZWZhdWx0J10gPSBwa2cubWFpblsnZGVmYXVsdCddIHx8ICcuLyc7XG4gICAgcGtnLm1haW4gPSAnQG1haW4nO1xuICB9XG5cbiAgcmV0dXJuIHBrZztcbn1cblxudmFyIGhhc0J1ZmZlciA9IHR5cGVvZiBCdWZmZXIgIT09ICd1bmRlZmluZWQnO1xudHJ5IHtcbiAgaWYgKGhhc0J1ZmZlciAmJiBuZXcgQnVmZmVyKCdhJykudG9TdHJpbmcoJ2Jhc2U2NCcpICE9PSAnWVE9PScpXG4gICAgaGFzQnVmZmVyID0gZmFsc2U7XG59XG5jYXRjaCAoZSkge1xuICBoYXNCdWZmZXIgPSBmYWxzZTtcbn1cblxudmFyIHNvdXJjZU1hcFByZWZpeCA9ICdcXG4vLyMgc291cmNlTWFwcGluZycgKyAnVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsJztcbmZ1bmN0aW9uIGlubGluZVNvdXJjZU1hcCAoc291cmNlTWFwU3RyaW5nKSB7XG4gIGlmIChoYXNCdWZmZXIpXG4gICAgcmV0dXJuIHNvdXJjZU1hcFByZWZpeCArIG5ldyBCdWZmZXIoc291cmNlTWFwU3RyaW5nKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gIGVsc2UgaWYgKHR5cGVvZiBidG9hICE9PSAndW5kZWZpbmVkJylcbiAgICByZXR1cm4gc291cmNlTWFwUHJlZml4ICsgYnRvYSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoc291cmNlTWFwU3RyaW5nKSkpO1xuICBlbHNlXG4gICAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBnZXRTb3VyY2Uoc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsIHdyYXApIHtcbiAgdmFyIGxhc3RMaW5lSW5kZXggPSBzb3VyY2UubGFzdEluZGV4T2YoJ1xcbicpO1xuXG4gIGlmIChzb3VyY2VNYXApIHtcbiAgICBpZiAodHlwZW9mIHNvdXJjZU1hcCAhPSAnb2JqZWN0JylcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xvYWQubWV0YWRhdGEuc291cmNlTWFwIG11c3QgYmUgc2V0IHRvIGFuIG9iamVjdC4nKTtcblxuICAgIHNvdXJjZU1hcCA9IEpTT04uc3RyaW5naWZ5KHNvdXJjZU1hcCk7XG4gIH1cblxuICByZXR1cm4gKHdyYXAgPyAnKGZ1bmN0aW9uKFN5c3RlbSwgU3lzdGVtSlMpIHsnIDogJycpICsgc291cmNlICsgKHdyYXAgPyAnXFxufSkoU3lzdGVtLCBTeXN0ZW0pOycgOiAnJylcbiAgICAgIC8vIGFkZHMgdGhlIHNvdXJjZVVSTCBjb21tZW50IGlmIG5vdCBhbHJlYWR5IHByZXNlbnRcbiAgICAgICsgKHNvdXJjZS5zdWJzdHIobGFzdExpbmVJbmRleCwgMTUpICE9ICdcXG4vLyMgc291cmNlVVJMPSdcbiAgICAgICAgPyAnXFxuLy8jIHNvdXJjZVVSTD0nICsgYWRkcmVzcyArIChzb3VyY2VNYXAgPyAnIXRyYW5zcGlsZWQnIDogJycpIDogJycpXG4gICAgICAvLyBhZGQgc291cmNlTWFwcGluZ1VSTCBpZiBsb2FkLm1ldGFkYXRhLnNvdXJjZU1hcCBpcyBzZXRcbiAgICAgICsgKHNvdXJjZU1hcCAmJiBpbmxpbmVTb3VyY2VNYXAoc291cmNlTWFwKSB8fCAnJyk7XG59XG5cbi8vIHNjcmlwdCBleGVjdXRpb24gdmlhIGluamVjdGluZyBhIHNjcmlwdCB0YWcgaW50byB0aGUgcGFnZVxuLy8gdGhpcyBhbGxvd3MgQ1NQIG5vbmNlIHRvIGJlIHNldCBmb3IgQ1NQIGVudmlyb25tZW50c1xudmFyIGhlYWQ7XG5mdW5jdGlvbiBzY3JpcHRFeGVjKGxvYWRlciwgc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsIG5vbmNlKSB7XG4gIGlmICghaGVhZClcbiAgICBoZWFkID0gZG9jdW1lbnQuaGVhZCB8fCBkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuICB2YXIgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gIHNjcmlwdC50ZXh0ID0gZ2V0U291cmNlKHNvdXJjZSwgc291cmNlTWFwLCBhZGRyZXNzLCBmYWxzZSk7XG4gIHZhciBvbmVycm9yID0gd2luZG93Lm9uZXJyb3I7XG4gIHZhciBlO1xuICB3aW5kb3cub25lcnJvciA9IGZ1bmN0aW9uKF9lKSB7XG4gICAgZSA9IGFkZFRvRXJyb3IoX2UsICdFdmFsdWF0aW5nICcgKyBhZGRyZXNzKTtcbiAgICBpZiAob25lcnJvcilcbiAgICAgIG9uZXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfTtcbiAgcHJlRXhlYyhsb2FkZXIpO1xuXG4gIGlmIChub25jZSlcbiAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCdub25jZScsIG5vbmNlKTtcblxuICBoZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gIGhlYWQucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcbiAgcG9zdEV4ZWMoKTtcbiAgd2luZG93Lm9uZXJyb3IgPSBvbmVycm9yO1xuICBpZiAoZSlcbiAgICByZXR1cm4gZTtcbn1cblxudmFyIHZtO1xudmFyIHVzZVZtO1xuXG52YXIgY3VyU3lzdGVtO1xuXG52YXIgY2FsbENvdW50ZXIgPSAwO1xuZnVuY3Rpb24gcHJlRXhlYyAobG9hZGVyKSB7XG4gIGlmIChjYWxsQ291bnRlcisrID09IDApXG4gICAgY3VyU3lzdGVtID0gZW52R2xvYmFsLlN5c3RlbTtcbiAgZW52R2xvYmFsLlN5c3RlbSA9IGVudkdsb2JhbC5TeXN0ZW1KUyA9IGxvYWRlcjtcbn1cbmZ1bmN0aW9uIHBvc3RFeGVjICgpIHtcbiAgaWYgKC0tY2FsbENvdW50ZXIgPT0gMClcbiAgICBlbnZHbG9iYWwuU3lzdGVtID0gZW52R2xvYmFsLlN5c3RlbUpTID0gY3VyU3lzdGVtO1xufVxuXG52YXIgc3VwcG9ydHNTY3JpcHRFeGVjID0gZmFsc2U7XG5pZiAoaXNCcm93c2VyICYmIHR5cGVvZiBkb2N1bWVudCAhPSAndW5kZWZpbmVkJyAmJiBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSkge1xuICBpZiAoISh3aW5kb3cuY2hyb21lICYmIHdpbmRvdy5jaHJvbWUuZXh0ZW5zaW9uIHx8IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL15Ob2RlXFwuanMvKSkpXG4gICAgc3VwcG9ydHNTY3JpcHRFeGVjID0gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZXZhbHVhdGUgKGxvYWRlciwgc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsIGludGVncml0eSwgbm9uY2UsIG5vV3JhcCkge1xuICBpZiAoIXNvdXJjZSlcbiAgICByZXR1cm47XG4gIGlmIChub25jZSAmJiBzdXBwb3J0c1NjcmlwdEV4ZWMpXG4gICAgcmV0dXJuIHNjcmlwdEV4ZWMobG9hZGVyLCBzb3VyY2UsIHNvdXJjZU1hcCwgYWRkcmVzcywgbm9uY2UpO1xuICB0cnkge1xuICAgIHByZUV4ZWMobG9hZGVyKTtcbiAgICAvLyBnbG9iYWwgc2NvcGVkIGV2YWwgZm9yIG5vZGUgKGF2b2lkcyByZXF1aXJlIHNjb3BlIGxlYWspXG4gICAgaWYgKCF2bSAmJiBsb2FkZXIuX25vZGVSZXF1aXJlKSB7XG4gICAgICB2bSA9IGxvYWRlci5fbm9kZVJlcXVpcmUoJ3ZtJyk7XG4gICAgICB1c2VWbSA9IHZtLnJ1bkluVGhpc0NvbnRleHQoXCJ0eXBlb2YgU3lzdGVtICE9PSAndW5kZWZpbmVkJyAmJiBTeXN0ZW1cIikgPT09IGxvYWRlcjtcbiAgICB9XG4gICAgaWYgKHVzZVZtKVxuICAgICAgdm0ucnVuSW5UaGlzQ29udGV4dChnZXRTb3VyY2Uoc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsICFub1dyYXApLCB7IGZpbGVuYW1lOiBhZGRyZXNzICsgKHNvdXJjZU1hcCA/ICchdHJhbnNwaWxlZCcgOiAnJykgfSk7XG4gICAgZWxzZVxuICAgICAgKDAsIGV2YWwpKGdldFNvdXJjZShzb3VyY2UsIHNvdXJjZU1hcCwgYWRkcmVzcywgIW5vV3JhcCkpO1xuICAgIHBvc3RFeGVjKCk7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICBwb3N0RXhlYygpO1xuICAgIHJldHVybiBlO1xuICB9XG59XG5cbnZhciBmb3JtYXRIZWxwZXJzID0gZnVuY3Rpb24gKGxvYWRlcikge1xuICBsb2FkZXIuc2V0KCdAQGNqcy1oZWxwZXJzJywgbG9hZGVyLm5ld01vZHVsZSh7XG4gICAgcmVxdWlyZVJlc29sdmU6IHJlcXVpcmVSZXNvbHZlLmJpbmQobG9hZGVyKSxcbiAgICBnZXRQYXRoVmFyczogZ2V0UGF0aFZhcnNcbiAgfSkpO1xuXG4gIGxvYWRlci5zZXQoJ0BAZ2xvYmFsLWhlbHBlcnMnLCBsb2FkZXIubmV3TW9kdWxlKHtcbiAgICBwcmVwYXJlR2xvYmFsOiBwcmVwYXJlR2xvYmFsXG4gIH0pKTtcblxuICAvKlxuICAgIEFNRC1jb21wYXRpYmxlIHJlcXVpcmVcbiAgICBUbyBjb3B5IFJlcXVpcmVKUywgc2V0IHdpbmRvdy5yZXF1aXJlID0gd2luZG93LnJlcXVpcmVqcyA9IGxvYWRlci5hbWRSZXF1aXJlXG4gICovXG4gIGZ1bmN0aW9uIHJlcXVpcmUgKG5hbWVzLCBjYWxsYmFjaywgZXJyYmFjaywgcmVmZXJlcikge1xuICAgIC8vIGluIGFtZCwgZmlyc3QgYXJnIGNhbiBiZSBhIGNvbmZpZyBvYmplY3QuLi4gd2UganVzdCBpZ25vcmVcbiAgICBpZiAodHlwZW9mIG5hbWVzID09PSAnb2JqZWN0JyAmJiAhKG5hbWVzIGluc3RhbmNlb2YgQXJyYXkpKVxuICAgICAgcmV0dXJuIHJlcXVpcmUuYXBwbHkobnVsbCwgQXJyYXkucHJvdG90eXBlLnNwbGljZS5jYWxsKGFyZ3VtZW50cywgMSwgYXJndW1lbnRzLmxlbmd0aCAtIDEpKTtcblxuICAgIC8vIGFtZCByZXF1aXJlXG4gICAgaWYgKHR5cGVvZiBuYW1lcyA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKVxuICAgICAgbmFtZXMgPSBbbmFtZXNdO1xuICAgIGlmIChuYW1lcyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICB2YXIgZHluYW1pY1JlcXVpcmVzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzLmxlbmd0aDsgaSsrKVxuICAgICAgICBkeW5hbWljUmVxdWlyZXMucHVzaChsb2FkZXIuaW1wb3J0KG5hbWVzW2ldLCByZWZlcmVyKSk7XG4gICAgICBQcm9taXNlLmFsbChkeW5hbWljUmVxdWlyZXMpLnRoZW4oZnVuY3Rpb24gKG1vZHVsZXMpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKVxuICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIG1vZHVsZXMpO1xuICAgICAgfSwgZXJyYmFjayk7XG4gICAgfVxuXG4gICAgLy8gY29tbW9uanMgcmVxdWlyZVxuICAgIGVsc2UgaWYgKHR5cGVvZiBuYW1lcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHZhciBub3JtYWxpemVkID0gbG9hZGVyLmRlY2Fub25pY2FsaXplKG5hbWVzLCByZWZlcmVyKTtcbiAgICAgIHZhciBtb2R1bGUgPSBsb2FkZXIuZ2V0KG5vcm1hbGl6ZWQpO1xuICAgICAgaWYgKCFtb2R1bGUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTW9kdWxlIG5vdCBhbHJlYWR5IGxvYWRlZCBsb2FkaW5nIFwiJyArIG5hbWVzICsgJ1wiIGFzICcgKyBub3JtYWxpemVkICsgKHJlZmVyZXIgPyAnIGZyb20gXCInICsgcmVmZXJlciArICdcIi4nIDogJy4nKSk7XG4gICAgICByZXR1cm4gJ19fdXNlRGVmYXVsdCcgaW4gbW9kdWxlID8gbW9kdWxlLl9fdXNlRGVmYXVsdCA6IG1vZHVsZTtcbiAgICB9XG5cbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIHJlcXVpcmUnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlZmluZSAobmFtZSwgZGVwcywgZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGZhY3RvcnkgPSBkZXBzO1xuICAgICAgZGVwcyA9IG5hbWU7XG4gICAgICBuYW1lID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoIShkZXBzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICBmYWN0b3J5ID0gZGVwcztcbiAgICAgIGRlcHMgPSBbJ3JlcXVpcmUnLCAnZXhwb3J0cycsICdtb2R1bGUnXS5zcGxpY2UoMCwgZmFjdG9yeS5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZmFjdG9yeSAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgIGZhY3RvcnkgPSAoZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyByZXR1cm4gZmFjdG9yeTsgfVxuICAgICAgfSkoZmFjdG9yeSk7XG5cbiAgICBpZiAoIW5hbWUpIHtcbiAgICAgIGlmIChjdXJNZXRhRGVwcykge1xuICAgICAgICBkZXBzID0gZGVwcy5jb25jYXQoY3VyTWV0YURlcHMpO1xuICAgICAgICBjdXJNZXRhRGVwcyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZW1vdmUgc3lzdGVtIGRlcGVuZGVuY2llc1xuICAgIHZhciByZXF1aXJlSW5kZXgsIGV4cG9ydHNJbmRleCwgbW9kdWxlSW5kZXg7XG5cbiAgICBpZiAoKHJlcXVpcmVJbmRleCA9IGRlcHMuaW5kZXhPZigncmVxdWlyZScpKSAhPT0gLTEpIHtcblxuICAgICAgZGVwcy5zcGxpY2UocmVxdWlyZUluZGV4LCAxKTtcblxuICAgICAgLy8gb25seSB0cmFjZSBjanMgcmVxdWlyZXMgZm9yIG5vbi1uYW1lZFxuICAgICAgLy8gbmFtZWQgZGVmaW5lcyBhc3N1bWUgdGhlIHRyYWNlIGhhcyBhbHJlYWR5IGJlZW4gZG9uZVxuICAgICAgaWYgKCFuYW1lKVxuICAgICAgICBkZXBzID0gZGVwcy5jb25jYXQoYW1kR2V0Q0pTRGVwcyhmYWN0b3J5LnRvU3RyaW5nKCksIHJlcXVpcmVJbmRleCkpO1xuICAgIH1cblxuICAgIGlmICgoZXhwb3J0c0luZGV4ID0gZGVwcy5pbmRleE9mKCdleHBvcnRzJykpICE9PSAtMSlcbiAgICAgIGRlcHMuc3BsaWNlKGV4cG9ydHNJbmRleCwgMSk7XG5cbiAgICBpZiAoKG1vZHVsZUluZGV4ID0gZGVwcy5pbmRleE9mKCdtb2R1bGUnKSkgIT09IC0xKVxuICAgICAgZGVwcy5zcGxpY2UobW9kdWxlSW5kZXgsIDEpO1xuXG4gICAgZnVuY3Rpb24gZXhlY3V0ZSAocmVxLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgIHZhciBkZXBWYWx1ZXMgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKylcbiAgICAgICAgZGVwVmFsdWVzLnB1c2gocmVxKGRlcHNbaV0pKTtcblxuICAgICAgbW9kdWxlLnVyaSA9IG1vZHVsZS5pZDtcblxuICAgICAgbW9kdWxlLmNvbmZpZyA9IG5vb3A7XG5cbiAgICAgIC8vIGFkZCBiYWNrIGluIHN5c3RlbSBkZXBlbmRlbmNpZXNcbiAgICAgIGlmIChtb2R1bGVJbmRleCAhPT0gLTEpXG4gICAgICAgIGRlcFZhbHVlcy5zcGxpY2UobW9kdWxlSW5kZXgsIDAsIG1vZHVsZSk7XG5cbiAgICAgIGlmIChleHBvcnRzSW5kZXggIT09IC0xKVxuICAgICAgICBkZXBWYWx1ZXMuc3BsaWNlKGV4cG9ydHNJbmRleCwgMCwgZXhwb3J0cyk7XG5cbiAgICAgIGlmIChyZXF1aXJlSW5kZXggIT09IC0xKSB7XG4gICAgICAgIHZhciBjb250ZXh0dWFsUmVxdWlyZSA9IGZ1bmN0aW9uIChuYW1lcywgY2FsbGJhY2ssIGVycmJhY2spIHtcbiAgICAgICAgICBpZiAodHlwZW9mIG5hbWVzID09PSAnc3RyaW5nJyAmJiB0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICByZXR1cm4gcmVxKG5hbWVzKTtcbiAgICAgICAgICByZXR1cm4gcmVxdWlyZS5jYWxsKGxvYWRlciwgbmFtZXMsIGNhbGxiYWNrLCBlcnJiYWNrLCBtb2R1bGUuaWQpO1xuICAgICAgICB9O1xuICAgICAgICBjb250ZXh0dWFsUmVxdWlyZS50b1VybCA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgcmV0dXJuIGxvYWRlci5ub3JtYWxpemVTeW5jKG5hbWUsIG1vZHVsZS5pZCk7XG4gICAgICAgIH07XG4gICAgICAgIGRlcFZhbHVlcy5zcGxpY2UocmVxdWlyZUluZGV4LCAwLCBjb250ZXh0dWFsUmVxdWlyZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIHNldCBnbG9iYWwgcmVxdWlyZSB0byBBTUQgcmVxdWlyZVxuICAgICAgdmFyIGN1clJlcXVpcmUgPSBlbnZHbG9iYWwucmVxdWlyZTtcbiAgICAgIGVudkdsb2JhbC5yZXF1aXJlID0gcmVxdWlyZTtcblxuICAgICAgdmFyIG91dHB1dCA9IGZhY3RvcnkuYXBwbHkoZXhwb3J0c0luZGV4ID09PSAtMSA/IGVudkdsb2JhbCA6IGV4cG9ydHMsIGRlcFZhbHVlcyk7XG5cbiAgICAgIGVudkdsb2JhbC5yZXF1aXJlID0gY3VyUmVxdWlyZTtcblxuICAgICAgaWYgKHR5cGVvZiBvdXRwdXQgIT09ICd1bmRlZmluZWQnKVxuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG91dHB1dDtcbiAgICB9XG5cbiAgICAvLyBhbm9ueW1vdXMgZGVmaW5lXG4gICAgaWYgKCFuYW1lKSB7XG4gICAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKGRlcHMsIGZhbHNlLCBjdXJFc01vZHVsZSA/IHdyYXBFc01vZHVsZUV4ZWN1dGUoZXhlY3V0ZSkgOiBleGVjdXRlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKG5hbWUsIGRlcHMsIGZhbHNlLCBleGVjdXRlKTtcblxuICAgICAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhbnkgb3RoZXIgZGVmaW5lcyxcbiAgICAgIC8vIHRoZW4gbGV0IHRoaXMgYmUgYW4gYW5vbnltb3VzIGRlZmluZVxuICAgICAgLy8gdGhpcyBpcyBqdXN0IHRvIHN1cHBvcnQgc2luZ2xlIG1vZHVsZXMgb2YgdGhlIGZvcm06XG4gICAgICAvLyBkZWZpbmUoJ2pxdWVyeScpXG4gICAgICAvLyBzdGlsbCBsb2FkaW5nIGFub255bW91c2x5XG4gICAgICAvLyBiZWNhdXNlIGl0IGlzIGRvbmUgd2lkZWx5IGVub3VnaCB0byBiZSB1c2VmdWxcbiAgICAgIC8vIGFzIHNvb24gYXMgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBkZWZpbmUsIHRoaXMgZ2V0cyByZW1vdmVkIHRob3VnaFxuICAgICAgaWYgKGxhc3ROYW1lZERlZmluZSkge1xuICAgICAgICBsYXN0TmFtZWREZWZpbmUgPSB1bmRlZmluZWQ7XG4gICAgICAgIG11bHRpcGxlTmFtZWREZWZpbmVzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKCFtdWx0aXBsZU5hbWVkRGVmaW5lcykge1xuICAgICAgICBsYXN0TmFtZWREZWZpbmUgPSBbZGVwcywgZXhlY3V0ZV07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGRlZmluZS5hbWQgPSB7fTtcblxuICBsb2FkZXIuYW1kRGVmaW5lID0gZGVmaW5lO1xuICBsb2FkZXIuYW1kUmVxdWlyZSA9IHJlcXVpcmU7XG59O1xuXG4vLyBDSlNcbnZhciB3aW5kb3dPcmlnaW47XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cubG9jYXRpb24pXG4gIHdpbmRvd09yaWdpbiA9IGxvY2F0aW9uLnByb3RvY29sICsgJy8vJyArIGxvY2F0aW9uLmhvc3RuYW1lICsgKGxvY2F0aW9uLnBvcnQgPyAnOicgKyBsb2NhdGlvbi5wb3J0IDogJycpO1xuXG5mdW5jdGlvbiBzdHJpcE9yaWdpbihwYXRoKSB7XG4gIGlmIChwYXRoLnN1YnN0cigwLCA4KSA9PT0gJ2ZpbGU6Ly8vJylcbiAgICByZXR1cm4gcGF0aC5zdWJzdHIoNyArICEhaXNXaW5kb3dzKTtcblxuICBpZiAod2luZG93T3JpZ2luICYmIHBhdGguc3Vic3RyKDAsIHdpbmRvd09yaWdpbi5sZW5ndGgpID09PSB3aW5kb3dPcmlnaW4pXG4gICAgcmV0dXJuIHBhdGguc3Vic3RyKHdpbmRvd09yaWdpbi5sZW5ndGgpO1xuXG4gIHJldHVybiBwYXRoO1xufVxuXG5mdW5jdGlvbiByZXF1aXJlUmVzb2x2ZSAocmVxdWVzdCwgcGFyZW50SWQpIHtcbiAgcmV0dXJuIHN0cmlwT3JpZ2luKHRoaXMubm9ybWFsaXplU3luYyhyZXF1ZXN0LCBwYXJlbnRJZCkpO1xufVxuXG5mdW5jdGlvbiBnZXRQYXRoVmFycyAobW9kdWxlSWQpIHtcbiAgLy8gcmVtb3ZlIGFueSBwbHVnaW4gc3ludGF4XG4gIHZhciBwbHVnaW5JbmRleCA9IG1vZHVsZUlkLmxhc3RJbmRleE9mKCchJyk7XG4gIHZhciBmaWxlbmFtZTtcbiAgaWYgKHBsdWdpbkluZGV4ICE9PSAtMSlcbiAgICBmaWxlbmFtZSA9IG1vZHVsZUlkLnN1YnN0cigwLCBwbHVnaW5JbmRleCk7XG4gIGVsc2VcbiAgICBmaWxlbmFtZSA9IG1vZHVsZUlkO1xuXG4gIHZhciBkaXJuYW1lID0gZmlsZW5hbWUuc3BsaXQoJy8nKTtcbiAgZGlybmFtZS5wb3AoKTtcbiAgZGlybmFtZSA9IGRpcm5hbWUuam9pbignLycpO1xuXG4gIHJldHVybiB7XG4gICAgZmlsZW5hbWU6IHN0cmlwT3JpZ2luKGZpbGVuYW1lKSxcbiAgICBkaXJuYW1lOiBzdHJpcE9yaWdpbihkaXJuYW1lKVxuICB9O1xufVxuXG52YXIgY29tbWVudFJlZ0V4JDEgPSAvKF58W15cXFxcXSkoXFwvXFwqKFtcXHNcXFNdKj8pXFwqXFwvfChbXjpdfF4pXFwvXFwvKC4qKSQpL21nO1xudmFyIHN0cmluZ1JlZ0V4JDEgPSAvKFwiW15cIlxcXFxcXG5cXHJdKihcXFxcLlteXCJcXFxcXFxuXFxyXSopKlwifCdbXidcXFxcXFxuXFxyXSooXFxcXC5bXidcXFxcXFxuXFxyXSopKicpL2c7XG5cbi8vIGV4dHJhY3QgQ0pTIGRlcGVuZGVuY2llcyBmcm9tIHNvdXJjZSB0ZXh0IHZpYSByZWdleCBzdGF0aWMgYW5hbHlzaXNcbi8vIHJlYWQgcmVxdWlyZSgneCcpIHN0YXRlbWVudHMgbm90IGluIGNvbW1lbnRzIG9yIHN0cmluZ3NcbmZ1bmN0aW9uIGdldENKU0RlcHMgKHNvdXJjZSkge1xuICBjanNSZXF1aXJlUmVnRXgubGFzdEluZGV4ID0gY29tbWVudFJlZ0V4JDEubGFzdEluZGV4ID0gc3RyaW5nUmVnRXgkMS5sYXN0SW5kZXggPSAwO1xuXG4gIHZhciBkZXBzID0gW107XG5cbiAgdmFyIG1hdGNoO1xuXG4gIC8vIHRyYWNrIHN0cmluZyBhbmQgY29tbWVudCBsb2NhdGlvbnMgZm9yIHVubWluaWZpZWQgc291cmNlXG4gIHZhciBzdHJpbmdMb2NhdGlvbnMgPSBbXSwgY29tbWVudExvY2F0aW9ucyA9IFtdO1xuXG4gIGZ1bmN0aW9uIGluTG9jYXRpb24gKGxvY2F0aW9ucywgbWF0Y2gpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxvY2F0aW9ucy5sZW5ndGg7IGkrKylcbiAgICAgIGlmIChsb2NhdGlvbnNbaV1bMF0gPCBtYXRjaC5pbmRleCAmJiBsb2NhdGlvbnNbaV1bMV0gPiBtYXRjaC5pbmRleClcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKHNvdXJjZS5sZW5ndGggLyBzb3VyY2Uuc3BsaXQoJ1xcbicpLmxlbmd0aCA8IDIwMCkge1xuICAgIHdoaWxlIChtYXRjaCA9IHN0cmluZ1JlZ0V4JDEuZXhlYyhzb3VyY2UpKVxuICAgICAgc3RyaW5nTG9jYXRpb25zLnB1c2goW21hdGNoLmluZGV4LCBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aF0pO1xuXG4gICAgLy8gVE9ETzogdHJhY2sgdGVtcGxhdGUgbGl0ZXJhbHMgaGVyZSBiZWZvcmUgY29tbWVudHNcblxuICAgIHdoaWxlIChtYXRjaCA9IGNvbW1lbnRSZWdFeCQxLmV4ZWMoc291cmNlKSkge1xuICAgICAgLy8gb25seSB0cmFjayBjb21tZW50cyBub3Qgc3RhcnRpbmcgaW4gc3RyaW5nc1xuICAgICAgaWYgKCFpbkxvY2F0aW9uKHN0cmluZ0xvY2F0aW9ucywgbWF0Y2gpKVxuICAgICAgICBjb21tZW50TG9jYXRpb25zLnB1c2goW21hdGNoLmluZGV4ICsgbWF0Y2hbMV0ubGVuZ3RoLCBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aCAtIDFdKTtcbiAgICB9XG4gIH1cblxuICB3aGlsZSAobWF0Y2ggPSBjanNSZXF1aXJlUmVnRXguZXhlYyhzb3VyY2UpKSB7XG4gICAgLy8gZW5zdXJlIHdlJ3JlIG5vdCB3aXRoaW4gYSBzdHJpbmcgb3IgY29tbWVudCBsb2NhdGlvblxuICAgIGlmICghaW5Mb2NhdGlvbihzdHJpbmdMb2NhdGlvbnMsIG1hdGNoKSAmJiAhaW5Mb2NhdGlvbihjb21tZW50TG9jYXRpb25zLCBtYXRjaCkpIHtcbiAgICAgIHZhciBkZXAgPSBtYXRjaFsxXS5zdWJzdHIoMSwgbWF0Y2hbMV0ubGVuZ3RoIC0gMik7XG4gICAgICAvLyBza2lwIGNhc2VzIGxpa2UgcmVxdWlyZSgnXCIgKyBmaWxlICsgXCInKVxuICAgICAgaWYgKGRlcC5tYXRjaCgvXCJ8Jy8pKVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIGRlcHMucHVzaChkZXApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkZXBzO1xufVxuXG4vLyBHbG9iYWxcbi8vIGJhcmUgbWluaW11bSBpZ25vcmVzXG52YXIgaWdub3JlZEdsb2JhbFByb3BzID0gWydfZycsICdzZXNzaW9uU3RvcmFnZScsICdsb2NhbFN0b3JhZ2UnLCAnY2xpcGJvYXJkRGF0YScsICdmcmFtZXMnLCAnZnJhbWVFbGVtZW50JywgJ2V4dGVybmFsJyxcbiAgJ21vekFuaW1hdGlvblN0YXJ0VGltZScsICd3ZWJraXRTdG9yYWdlSW5mbycsICd3ZWJraXRJbmRleGVkREInLCAnbW96SW5uZXJTY3JlZW5ZJywgJ21veklubmVyU2NyZWVuWCddO1xuXG52YXIgZ2xvYmFsU25hcHNob3Q7XG5mdW5jdGlvbiBnbG9iYWxJdGVyYXRvciAoZ2xvYmFsTmFtZSkge1xuICBpZiAoaWdub3JlZEdsb2JhbFByb3BzLmluZGV4T2YoZ2xvYmFsTmFtZSkgIT09IC0xKVxuICAgIHJldHVybjtcbiAgdHJ5IHtcbiAgICB2YXIgdmFsdWUgPSBlbnZHbG9iYWxbZ2xvYmFsTmFtZV07XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICBpZ25vcmVkR2xvYmFsUHJvcHMucHVzaChnbG9iYWxOYW1lKTtcbiAgfVxuICB0aGlzKGdsb2JhbE5hbWUsIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gZ2V0R2xvYmFsVmFsdWUgKGV4cG9ydHMpIHtcbiAgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnc3RyaW5nJylcbiAgICByZXR1cm4gcmVhZE1lbWJlckV4cHJlc3Npb24oZXhwb3J0cywgZW52R2xvYmFsKTtcblxuICBpZiAoIShleHBvcnRzIGluc3RhbmNlb2YgQXJyYXkpKVxuICAgIHRocm93IG5ldyBFcnJvcignR2xvYmFsIGV4cG9ydHMgbXVzdCBiZSBhIHN0cmluZyBvciBhcnJheS4nKTtcblxuICB2YXIgZ2xvYmFsVmFsdWUgPSB7fTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHBvcnRzLmxlbmd0aDsgaSsrKVxuICAgIGdsb2JhbFZhbHVlW2V4cG9ydHNbaV0uc3BsaXQoJy4nKS5wb3AoKV0gPSByZWFkTWVtYmVyRXhwcmVzc2lvbihleHBvcnRzW2ldLCBlbnZHbG9iYWwpO1xuICByZXR1cm4gZ2xvYmFsVmFsdWU7XG59XG5cbmZ1bmN0aW9uIHByZXBhcmVHbG9iYWwgKG1vZHVsZU5hbWUsIGV4cG9ydHMsIGdsb2JhbHMsIGVuY2Fwc3VsYXRlKSB7XG4gIC8vIGRpc2FibGUgbW9kdWxlIGRldGVjdGlvblxuICB2YXIgY3VyRGVmaW5lID0gZW52R2xvYmFsLmRlZmluZTtcblxuICBlbnZHbG9iYWwuZGVmaW5lID0gdW5kZWZpbmVkO1xuXG4gIC8vIHNldCBnbG9iYWxzXG4gIHZhciBvbGRHbG9iYWxzO1xuICBpZiAoZ2xvYmFscykge1xuICAgIG9sZEdsb2JhbHMgPSB7fTtcbiAgICBmb3IgKHZhciBnIGluIGdsb2JhbHMpIHtcbiAgICAgIG9sZEdsb2JhbHNbZ10gPSBlbnZHbG9iYWxbZ107XG4gICAgICBlbnZHbG9iYWxbZ10gPSBnbG9iYWxzW2ddO1xuICAgIH1cbiAgfVxuXG4gIC8vIHN0b3JlIGEgY29tcGxldGUgY29weSBvZiB0aGUgZ2xvYmFsIG9iamVjdCBpbiBvcmRlciB0byBkZXRlY3QgY2hhbmdlc1xuICBpZiAoIWV4cG9ydHMpIHtcbiAgICBnbG9iYWxTbmFwc2hvdCA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoZW52R2xvYmFsKS5mb3JFYWNoKGdsb2JhbEl0ZXJhdG9yLCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgIGdsb2JhbFNuYXBzaG90W25hbWVdID0gdmFsdWU7XG4gICAgfSk7XG4gIH1cblxuICAvLyByZXR1cm4gZnVuY3Rpb24gdG8gcmV0cmlldmUgZ2xvYmFsXG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGdsb2JhbFZhbHVlID0gZXhwb3J0cyA/IGdldEdsb2JhbFZhbHVlKGV4cG9ydHMpIDoge307XG5cbiAgICB2YXIgc2luZ2xlR2xvYmFsO1xuICAgIHZhciBtdWx0aXBsZUV4cG9ydHMgPSAhIWV4cG9ydHM7XG5cbiAgICBpZiAoIWV4cG9ydHMgfHwgZW5jYXBzdWxhdGUpXG4gICAgICBPYmplY3Qua2V5cyhlbnZHbG9iYWwpLmZvckVhY2goZ2xvYmFsSXRlcmF0b3IsIGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSkge1xuICAgICAgICBpZiAoZ2xvYmFsU25hcHNob3RbbmFtZV0gPT09IHZhbHVlKVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIC8vIGFsbG93IGdsb2JhbCBlbmNhcHN1bGF0aW9uIHdoZXJlIGdsb2JhbHMgYXJlIHJlbW92ZWRcbiAgICAgICAgaWYgKGVuY2Fwc3VsYXRlKVxuICAgICAgICAgIGVudkdsb2JhbFtuYW1lXSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAoIWV4cG9ydHMpIHtcbiAgICAgICAgICBnbG9iYWxWYWx1ZVtuYW1lXSA9IHZhbHVlO1xuXG4gICAgICAgICAgaWYgKHNpbmdsZUdsb2JhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAoIW11bHRpcGxlRXhwb3J0cyAmJiBzaW5nbGVHbG9iYWwgIT09IHZhbHVlKVxuICAgICAgICAgICAgICBtdWx0aXBsZUV4cG9ydHMgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNpbmdsZUdsb2JhbCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBnbG9iYWxWYWx1ZSA9IG11bHRpcGxlRXhwb3J0cyA/IGdsb2JhbFZhbHVlIDogc2luZ2xlR2xvYmFsO1xuXG4gICAgLy8gcmV2ZXJ0IGdsb2JhbHNcbiAgICBpZiAob2xkR2xvYmFscykge1xuICAgICAgZm9yICh2YXIgZyBpbiBvbGRHbG9iYWxzKVxuICAgICAgICBlbnZHbG9iYWxbZ10gPSBvbGRHbG9iYWxzW2ddO1xuICAgIH1cbiAgICBlbnZHbG9iYWwuZGVmaW5lID0gY3VyRGVmaW5lO1xuXG4gICAgcmV0dXJuIGdsb2JhbFZhbHVlO1xuICB9O1xufVxuXG4vLyBBTURcbnZhciBjanNSZXF1aXJlUHJlID0gXCIoPzpefFteJF9hLXpBLVpcXFxceEEwLVxcXFx1RkZGRi5dKVwiO1xudmFyIGNqc1JlcXVpcmVQb3N0ID0gXCJcXFxccypcXFxcKFxcXFxzKihcXFwiKFteXFxcIl0rKVxcXCJ8JyhbXiddKyknKVxcXFxzKlxcXFwpXCI7XG52YXIgZm5CcmFja2V0UmVnRXggPSAvXFwoKFteXFwpXSopXFwpLztcbnZhciB3c1JlZ0V4ID0gL15cXHMrfFxccyskL2c7XG5cbnZhciByZXF1aXJlUmVnRXhzID0ge307XG5cbmZ1bmN0aW9uIGFtZEdldENKU0RlcHMoc291cmNlLCByZXF1aXJlSW5kZXgpIHtcblxuICAvLyByZW1vdmUgY29tbWVudHNcbiAgc291cmNlID0gc291cmNlLnJlcGxhY2UoY29tbWVudFJlZ0V4JDEsICcnKTtcblxuICAvLyBkZXRlcm1pbmUgdGhlIHJlcXVpcmUgYWxpYXNcbiAgdmFyIHBhcmFtcyA9IHNvdXJjZS5tYXRjaChmbkJyYWNrZXRSZWdFeCk7XG4gIHZhciByZXF1aXJlQWxpYXMgPSAocGFyYW1zWzFdLnNwbGl0KCcsJylbcmVxdWlyZUluZGV4XSB8fCAncmVxdWlyZScpLnJlcGxhY2Uod3NSZWdFeCwgJycpO1xuXG4gIC8vIGZpbmQgb3IgZ2VuZXJhdGUgdGhlIHJlZ2V4IGZvciB0aGlzIHJlcXVpcmVBbGlhc1xuICB2YXIgcmVxdWlyZVJlZ0V4ID0gcmVxdWlyZVJlZ0V4c1tyZXF1aXJlQWxpYXNdIHx8IChyZXF1aXJlUmVnRXhzW3JlcXVpcmVBbGlhc10gPSBuZXcgUmVnRXhwKGNqc1JlcXVpcmVQcmUgKyByZXF1aXJlQWxpYXMgKyBjanNSZXF1aXJlUG9zdCwgJ2cnKSk7XG5cbiAgcmVxdWlyZVJlZ0V4Lmxhc3RJbmRleCA9IDA7XG5cbiAgdmFyIGRlcHMgPSBbXTtcblxuICB2YXIgbWF0Y2g7XG4gIHdoaWxlIChtYXRjaCA9IHJlcXVpcmVSZWdFeC5leGVjKHNvdXJjZSkpXG4gICAgZGVwcy5wdXNoKG1hdGNoWzJdIHx8IG1hdGNoWzNdKTtcblxuICByZXR1cm4gZGVwcztcbn1cblxuZnVuY3Rpb24gd3JhcEVzTW9kdWxlRXhlY3V0ZSAoZXhlY3V0ZSkge1xuICByZXR1cm4gZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgIGV4ZWN1dGUocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKTtcbiAgICBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHM7XG4gICAgaWYgKCh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGV4cG9ydHMgPT09ICdmdW5jdGlvbicpICYmICEoJ19fZXNNb2R1bGUnIGluIGV4cG9ydHMpKVxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZS5leHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgICAgICAgdmFsdWU6IHRydWVcbiAgICAgIH0pO1xuICB9O1xufVxuXG4vLyBnZW5lcmF0ZSBhbm9ueW1vdXMgZGVmaW5lIGZyb20gc2luZ3VsYXIgbmFtZWQgZGVmaW5lXG52YXIgbXVsdGlwbGVOYW1lZERlZmluZXMgPSBmYWxzZTtcbnZhciBsYXN0TmFtZWREZWZpbmU7XG52YXIgY3VyTWV0YURlcHM7XG52YXIgY3VyRXNNb2R1bGUgPSBmYWxzZTtcbmZ1bmN0aW9uIGNsZWFyTGFzdERlZmluZSAobWV0YURlcHMsIGVzTW9kdWxlKSB7XG4gIGN1ck1ldGFEZXBzID0gbWV0YURlcHM7XG4gIGN1ckVzTW9kdWxlID0gZXNNb2R1bGU7XG4gIGxhc3ROYW1lZERlZmluZSA9IHVuZGVmaW5lZDtcbiAgbXVsdGlwbGVOYW1lZERlZmluZXMgPSBmYWxzZTtcbn1cbmZ1bmN0aW9uIHJlZ2lzdGVyTGFzdERlZmluZSAobG9hZGVyKSB7XG4gIGlmIChsYXN0TmFtZWREZWZpbmUpXG4gICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhjdXJNZXRhRGVwcyA/IGxhc3ROYW1lZERlZmluZVswXS5jb25jYXQoY3VyTWV0YURlcHMpIDogbGFzdE5hbWVkRGVmaW5lWzBdLFxuICAgICAgICBmYWxzZSwgY3VyRXNNb2R1bGUgPyB3cmFwRXNNb2R1bGVFeGVjdXRlKGxhc3ROYW1lZERlZmluZVsxXSkgOiBsYXN0TmFtZWREZWZpbmVbMV0pO1xuXG4gIC8vIGJ1bmRsZXMgYXJlIGFuIGVtcHR5IG1vZHVsZVxuICBlbHNlIGlmIChtdWx0aXBsZU5hbWVkRGVmaW5lcylcbiAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKFtdLCBmYWxzZSwgbm9vcCk7XG59XG5cbnZhciBzdXBwb3J0c1NjcmlwdExvYWQgPSAoaXNCcm93c2VyIHx8IGlzV29ya2VyKSAmJiB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IudXNlckFnZW50ICYmICFuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9NU0lFICg5fDEwKS4wLyk7XG5cbi8vIGluY2x1ZGUgdGhlIG5vZGUgcmVxdWlyZSBzaW5jZSB3ZSdyZSBvdmVycmlkaW5nIGl0XG52YXIgbm9kZVJlcXVpcmU7XG5pZiAodHlwZW9mIHJlcXVpcmUgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiAhcHJvY2Vzcy5icm93c2VyKVxuICBub2RlUmVxdWlyZSA9IHJlcXVpcmU7XG5cbmZ1bmN0aW9uIHNldE1ldGFFc01vZHVsZSAobWV0YWRhdGEsIG1vZHVsZVZhbHVlKSB7XG4gIGlmIChtZXRhZGF0YS5sb2FkLmVzTW9kdWxlICYmICh0eXBlb2YgbW9kdWxlVmFsdWUgPT09ICdvYmplY3QnIHx8IHR5cGVvZiBtb2R1bGVWYWx1ZSA9PT0gJ2Z1bmN0aW9uJykgJiZcbiAgICAgICEoJ19fZXNNb2R1bGUnIGluIG1vZHVsZVZhbHVlKSlcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kdWxlVmFsdWUsICdfX2VzTW9kdWxlJywge1xuICAgICAgdmFsdWU6IHRydWVcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5zdGFudGlhdGUkMSAoa2V5LCBwcm9jZXNzQW5vblJlZ2lzdGVyKSB7XG4gIHZhciBsb2FkZXIgPSB0aGlzO1xuICB2YXIgY29uZmlnID0gdGhpc1tDT05GSUddO1xuICAvLyBmaXJzdCBkbyBidW5kbGVzIGFuZCBkZXBDYWNoZVxuICByZXR1cm4gKGxvYWRCdW5kbGVzQW5kRGVwQ2FjaGUoY29uZmlnLCB0aGlzLCBrZXkpIHx8IHJlc29sdmVkUHJvbWlzZSlcbiAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIGlmIChwcm9jZXNzQW5vblJlZ2lzdGVyKCkpXG4gICAgICByZXR1cm47XG5cbiAgICB2YXIgbWV0YWRhdGEgPSBsb2FkZXJbTUVUQURBVEFdW2tleV07XG5cbiAgICAvLyBub2RlIG1vZHVsZSBsb2FkaW5nXG4gICAgaWYgKGtleS5zdWJzdHIoMCwgNikgPT09ICdAbm9kZS8nKSB7XG4gICAgICBpZiAoIWxvYWRlci5fbm9kZVJlcXVpcmUpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Vycm9yIGxvYWRpbmcgJyArIGtleSArICcuIENhbiBvbmx5IGxvYWQgbm9kZSBjb3JlIG1vZHVsZXMgaW4gTm9kZS4nKTtcbiAgICAgIGxvYWRlci5yZWdpc3RlckR5bmFtaWMoW10sIGZhbHNlLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBsb2FkTm9kZU1vZHVsZS5jYWxsKGxvYWRlciwga2V5LnN1YnN0cig2KSwgbG9hZGVyLmJhc2VVUkwpO1xuICAgICAgfSk7XG4gICAgICBwcm9jZXNzQW5vblJlZ2lzdGVyKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG1ldGFkYXRhLmxvYWQuc2NyaXB0TG9hZCApIHtcbiAgICAgIGlmIChtZXRhZGF0YS5sb2FkLnBsdWdpbktleSB8fCAhc3VwcG9ydHNTY3JpcHRMb2FkKSB7XG4gICAgICAgIG1ldGFkYXRhLmxvYWQuc2NyaXB0TG9hZCA9IGZhbHNlO1xuICAgICAgICB3YXJuLmNhbGwoY29uZmlnLCAnc2NyaXB0TG9hZCBub3Qgc3VwcG9ydGVkIGZvciBcIicgKyBrZXkgKyAnXCInKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAobWV0YWRhdGEubG9hZC5zY3JpcHRMb2FkICE9PSBmYWxzZSAmJiAhbWV0YWRhdGEubG9hZC5wbHVnaW5LZXkgJiYgc3VwcG9ydHNTY3JpcHRMb2FkKSB7XG4gICAgICAvLyBhdXRvIHNjcmlwdCBsb2FkIEFNRCwgZ2xvYmFsIHdpdGhvdXQgZGVwc1xuICAgICAgaWYgKCFtZXRhZGF0YS5sb2FkLmRlcHMgJiYgIW1ldGFkYXRhLmxvYWQuZ2xvYmFscyAmJlxuICAgICAgICAgIChtZXRhZGF0YS5sb2FkLmZvcm1hdCA9PT0gJ3N5c3RlbScgfHwgbWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdyZWdpc3RlcicgfHwgbWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdnbG9iYWwnICYmIG1ldGFkYXRhLmxvYWQuZXhwb3J0cykpXG4gICAgICAgIG1ldGFkYXRhLmxvYWQuc2NyaXB0TG9hZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gZmV0Y2ggLyB0cmFuc2xhdGUgLyBpbnN0YW50aWF0ZSBwaXBlbGluZVxuICAgIGlmICghbWV0YWRhdGEubG9hZC5zY3JpcHRMb2FkKVxuICAgICAgcmV0dXJuIGluaXRpYWxpemVQbHVnaW4obG9hZGVyLCBrZXksIG1ldGFkYXRhKVxuICAgICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcnVuRmV0Y2hQaXBlbGluZShsb2FkZXIsIGtleSwgbWV0YWRhdGEsIHByb2Nlc3NBbm9uUmVnaXN0ZXIsIGNvbmZpZy53YXNtKTtcbiAgICAgIH0pXG5cbiAgICAvLyBqdXN0IHNjcmlwdCBsb2FkaW5nXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmIChtZXRhZGF0YS5sb2FkLmZvcm1hdCA9PT0gJ2FtZCcgJiYgZW52R2xvYmFsLmRlZmluZSAhPT0gbG9hZGVyLmFtZERlZmluZSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2FkaW5nIEFNRCB3aXRoIHNjcmlwdExvYWQgcmVxdWlyZXMgc2V0dGluZyB0aGUgZ2xvYmFsIGAnICsgZ2xvYmFsTmFtZSArICcuZGVmaW5lID0gU3lzdGVtSlMuYW1kRGVmaW5lYCcpO1xuXG4gICAgICBzY3JpcHRMb2FkKGtleSwgbWV0YWRhdGEubG9hZC5jcm9zc09yaWdpbiwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFwcm9jZXNzQW5vblJlZ2lzdGVyKCkpIHtcbiAgICAgICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdnbG9iYWwnO1xuICAgICAgICAgIHZhciBnbG9iYWxWYWx1ZSA9IG1ldGFkYXRhLmxvYWQuZXhwb3J0cyAmJiBnZXRHbG9iYWxWYWx1ZShtZXRhZGF0YS5sb2FkLmV4cG9ydHMpO1xuICAgICAgICAgIGxvYWRlci5yZWdpc3RlckR5bmFtaWMoW10sIGZhbHNlLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZXRNZXRhRXNNb2R1bGUobWV0YWRhdGEsIGdsb2JhbFZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBnbG9iYWxWYWx1ZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBwcm9jZXNzQW5vblJlZ2lzdGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9LCByZWplY3QpO1xuICAgIH0pO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAoaW5zdGFudGlhdGVkKSB7XG4gICAgZGVsZXRlIGxvYWRlcltNRVRBREFUQV1ba2V5XTtcbiAgICByZXR1cm4gaW5zdGFudGlhdGVkO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVBsdWdpbiAobG9hZGVyLCBrZXksIG1ldGFkYXRhKSB7XG4gIGlmICghbWV0YWRhdGEucGx1Z2luS2V5KVxuICAgIHJldHVybiByZXNvbHZlZFByb21pc2U7XG5cbiAgcmV0dXJuIGxvYWRlci5pbXBvcnQobWV0YWRhdGEucGx1Z2luS2V5KS50aGVuKGZ1bmN0aW9uIChwbHVnaW4pIHtcbiAgICBtZXRhZGF0YS5wbHVnaW5Nb2R1bGUgPSBwbHVnaW47XG4gICAgbWV0YWRhdGEucGx1Z2luTG9hZCA9IHtcbiAgICAgIG5hbWU6IGtleSxcbiAgICAgIGFkZHJlc3M6IG1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50LFxuICAgICAgc291cmNlOiB1bmRlZmluZWQsXG4gICAgICBtZXRhZGF0YTogbWV0YWRhdGEubG9hZFxuICAgIH07XG4gICAgbWV0YWRhdGEubG9hZC5kZXBzID0gbWV0YWRhdGEubG9hZC5kZXBzIHx8IFtdO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gbG9hZEJ1bmRsZXNBbmREZXBDYWNoZSAoY29uZmlnLCBsb2FkZXIsIGtleSkge1xuICAvLyBsb2FkIGRpcmVjdCBkZXBzLCBpbiB0dXJuIHdpbGwgcGljayB1cCB0aGVpciB0cmFjZSB0cmVlc1xuICB2YXIgZGVwcyA9IGNvbmZpZy5kZXBDYWNoZVtrZXldO1xuICBpZiAoZGVwcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGVwcy5sZW5ndGg7IGkrKylcbiAgICAgIGxvYWRlci5ub3JtYWxpemUoZGVwc1tpXSwga2V5KS50aGVuKHByZWxvYWRTY3JpcHQpO1xuICB9XG4gIGVsc2Uge1xuICAgIHZhciBtYXRjaGVkID0gZmFsc2U7XG4gICAgZm9yICh2YXIgYiBpbiBjb25maWcuYnVuZGxlcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25maWcuYnVuZGxlc1tiXS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY3VyTW9kdWxlID0gY29uZmlnLmJ1bmRsZXNbYl1baV07XG5cbiAgICAgICAgaWYgKGN1ck1vZHVsZSA9PT0ga2V5KSB7XG4gICAgICAgICAgbWF0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB3aWxkY2FyZCBpbiBidW5kbGVzIGluY2x1ZGVzIC8gYm91bmRhcmllc1xuICAgICAgICBpZiAoY3VyTW9kdWxlLmluZGV4T2YoJyonKSAhPT0gLTEpIHtcbiAgICAgICAgICB2YXIgcGFydHMgPSBjdXJNb2R1bGUuc3BsaXQoJyonKTtcbiAgICAgICAgICBpZiAocGFydHMubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgICBjb25maWcuYnVuZGxlc1tiXS5zcGxpY2UoaS0tLCAxKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChrZXkuc3Vic3RyKDAsIHBhcnRzWzBdLmxlbmd0aCkgPT09IHBhcnRzWzBdICYmXG4gICAgICAgICAgICAgIGtleS5zdWJzdHIoa2V5Lmxlbmd0aCAtIHBhcnRzWzFdLmxlbmd0aCwgcGFydHNbMV0ubGVuZ3RoKSA9PT0gcGFydHNbMV0pIHtcbiAgICAgICAgICAgIG1hdGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXRjaGVkKVxuICAgICAgICByZXR1cm4gbG9hZGVyLmltcG9ydChiKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcnVuRmV0Y2hQaXBlbGluZSAobG9hZGVyLCBrZXksIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyLCB3YXNtKSB7XG4gIGlmIChtZXRhZGF0YS5sb2FkLmV4cG9ydHMgJiYgIW1ldGFkYXRhLmxvYWQuZm9ybWF0KVxuICAgIG1ldGFkYXRhLmxvYWQuZm9ybWF0ID0gJ2dsb2JhbCc7XG5cbiAgcmV0dXJuIHJlc29sdmVkUHJvbWlzZVxuXG4gIC8vIGxvY2F0ZVxuICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUgfHwgIW1ldGFkYXRhLnBsdWdpbk1vZHVsZS5sb2NhdGUpXG4gICAgICByZXR1cm47XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG1ldGFkYXRhLnBsdWdpbk1vZHVsZS5sb2NhdGUuY2FsbChsb2FkZXIsIG1ldGFkYXRhLnBsdWdpbkxvYWQpKVxuICAgIC50aGVuKGZ1bmN0aW9uIChhZGRyZXNzKSB7XG4gICAgICBpZiAoYWRkcmVzcylcbiAgICAgICAgbWV0YWRhdGEucGx1Z2luTG9hZC5hZGRyZXNzID0gYWRkcmVzcztcbiAgICB9KTtcbiAgfSlcblxuICAvLyBmZXRjaFxuICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUpXG4gICAgICByZXR1cm4gZmV0Y2gkMShrZXksIG1ldGFkYXRhLmxvYWQuYXV0aG9yaXphdGlvbiwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIHdhc20pO1xuXG4gICAgd2FzbSA9IGZhbHNlO1xuXG4gICAgaWYgKCFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUuZmV0Y2gpXG4gICAgICByZXR1cm4gZmV0Y2gkMShtZXRhZGF0YS5wbHVnaW5Mb2FkLmFkZHJlc3MsIG1ldGFkYXRhLmxvYWQuYXV0aG9yaXphdGlvbiwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIGZhbHNlKTtcblxuICAgIHJldHVybiBtZXRhZGF0YS5wbHVnaW5Nb2R1bGUuZmV0Y2guY2FsbChsb2FkZXIsIG1ldGFkYXRhLnBsdWdpbkxvYWQsIGZ1bmN0aW9uIChsb2FkKSB7XG4gICAgICByZXR1cm4gZmV0Y2gkMShsb2FkLmFkZHJlc3MsIG1ldGFkYXRhLmxvYWQuYXV0aG9yaXphdGlvbiwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIGZhbHNlKTtcbiAgICB9KTtcbiAgfSlcblxuICAudGhlbihmdW5jdGlvbiAoZmV0Y2hlZCkge1xuICAgIC8vIGZldGNoIGlzIGFscmVhZHkgYSB1dGYtOCBzdHJpbmcgaWYgbm90IGRvaW5nIHdhc20gZGV0ZWN0aW9uXG4gICAgaWYgKCF3YXNtIHx8IHR5cGVvZiBmZXRjaGVkID09PSAnc3RyaW5nJylcbiAgICAgIHJldHVybiB0cmFuc2xhdGVBbmRJbnN0YW50aWF0ZShsb2FkZXIsIGtleSwgZmV0Y2hlZCwgbWV0YWRhdGEsIHByb2Nlc3NBbm9uUmVnaXN0ZXIpO1xuXG4gICAgcmV0dXJuIGNoZWNrSW5zdGFudGlhdGVXYXNtKGxvYWRlciwgZmV0Y2hlZCwgcHJvY2Vzc0Fub25SZWdpc3RlcilcbiAgICAudGhlbihmdW5jdGlvbiAod2FzbUluc3RhbnRpYXRlZCkge1xuICAgICAgaWYgKHdhc21JbnN0YW50aWF0ZWQpXG4gICAgICAgIHJldHVybjtcblxuICAgICAgLy8gbm90IHdhc20gLT4gY29udmVydCBidWZmZXIgaW50byB1dGYtOCBzdHJpbmcgdG8gZXhlY3V0ZSBhcyBhIG1vZHVsZVxuICAgICAgLy8gVGV4dERlY29kZXIgY29tcGF0aWJpbGl0eSBtYXRjaGVzIFdBU00gY3VycmVudGx5LiBOZWVkIHRvIGtlZXAgY2hlY2tpbmcgdGhpcy5cbiAgICAgIC8vIFRoZSBUZXh0RGVjb2RlciBpbnRlcmZhY2UgaXMgZG9jdW1lbnRlZCBhdCBodHRwOi8vZW5jb2Rpbmcuc3BlYy53aGF0d2cub3JnLyNpbnRlcmZhY2UtdGV4dGRlY29kZXJcbiAgICAgIHZhciBzdHJpbmdTb3VyY2UgPSBpc0Jyb3dzZXIgPyBuZXcgVGV4dERlY29kZXIoJ3V0Zi04JykuZGVjb2RlKG5ldyBVaW50OEFycmF5KGZldGNoZWQpKSA6IGZldGNoZWQudG9TdHJpbmcoKTtcbiAgICAgIHJldHVybiB0cmFuc2xhdGVBbmRJbnN0YW50aWF0ZShsb2FkZXIsIGtleSwgc3RyaW5nU291cmNlLCBtZXRhZGF0YSwgcHJvY2Vzc0Fub25SZWdpc3Rlcik7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB0cmFuc2xhdGVBbmRJbnN0YW50aWF0ZSAobG9hZGVyLCBrZXksIHNvdXJjZSwgbWV0YWRhdGEsIHByb2Nlc3NBbm9uUmVnaXN0ZXIpIHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzb3VyY2UpXG4gIC8vIHRyYW5zbGF0ZVxuICAudGhlbihmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgaWYgKG1ldGFkYXRhLmxvYWQuZm9ybWF0ID09PSAnZGV0ZWN0JylcbiAgICAgIG1ldGFkYXRhLmxvYWQuZm9ybWF0ID0gdW5kZWZpbmVkO1xuXG4gICAgcmVhZE1ldGFTeW50YXgoc291cmNlLCBtZXRhZGF0YSk7XG5cbiAgICBpZiAoIW1ldGFkYXRhLnBsdWdpbk1vZHVsZSlcbiAgICAgIHJldHVybiBzb3VyY2U7XG5cbiAgICBtZXRhZGF0YS5wbHVnaW5Mb2FkLnNvdXJjZSA9IHNvdXJjZTtcblxuICAgIGlmICghbWV0YWRhdGEucGx1Z2luTW9kdWxlLnRyYW5zbGF0ZSlcbiAgICAgIHJldHVybiBzb3VyY2U7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG1ldGFkYXRhLnBsdWdpbk1vZHVsZS50cmFuc2xhdGUuY2FsbChsb2FkZXIsIG1ldGFkYXRhLnBsdWdpbkxvYWQsIG1ldGFkYXRhLnRyYWNlT3B0cykpXG4gICAgLnRoZW4oZnVuY3Rpb24gKHRyYW5zbGF0ZWQpIHtcbiAgICAgIGlmIChtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCkge1xuICAgICAgICBpZiAodHlwZW9mIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwICE9PSAnb2JqZWN0JylcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21ldGFkYXRhLmxvYWQuc291cmNlTWFwIG11c3QgYmUgc2V0IHRvIGFuIG9iamVjdC4nKTtcbiAgICAgICAgc2FuaXRpemVTb3VyY2VNYXAobWV0YWRhdGEucGx1Z2luTG9hZC5hZGRyZXNzLCBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgdHJhbnNsYXRlZCA9PT0gJ3N0cmluZycpXG4gICAgICAgIHJldHVybiB0cmFuc2xhdGVkO1xuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gbWV0YWRhdGEucGx1Z2luTG9hZC5zb3VyY2U7XG4gICAgfSk7XG4gIH0pXG4gIC50aGVuKGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICBpZiAoIW1ldGFkYXRhLmxvYWQuZm9ybWF0ICYmIHNvdXJjZS5zdWJzdHJpbmcoMCwgOCkgPT09ICdcImJ1bmRsZVwiJykge1xuICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSAnc3lzdGVtJztcbiAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfVxuXG4gICAgaWYgKG1ldGFkYXRhLmxvYWQuZm9ybWF0ID09PSAncmVnaXN0ZXInIHx8ICFtZXRhZGF0YS5sb2FkLmZvcm1hdCAmJiBkZXRlY3RSZWdpc3RlckZvcm1hdChzb3VyY2UpKSB7XG4gICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdyZWdpc3Rlcic7XG4gICAgICByZXR1cm4gc291cmNlO1xuICAgIH1cblxuICAgIGlmIChtZXRhZGF0YS5sb2FkLmZvcm1hdCAhPT0gJ2VzbScgJiYgKG1ldGFkYXRhLmxvYWQuZm9ybWF0IHx8ICFzb3VyY2UubWF0Y2goZXNtUmVnRXgpKSkge1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG5cbiAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdlc20nO1xuICAgIHJldHVybiB0cmFuc3BpbGUobG9hZGVyLCBzb3VyY2UsIGtleSwgbWV0YWRhdGEsIHByb2Nlc3NBbm9uUmVnaXN0ZXIpO1xuICB9KVxuXG4gIC8vIGluc3RhbnRpYXRlXG4gIC50aGVuKGZ1bmN0aW9uICh0cmFuc2xhdGVkKSB7XG4gICAgaWYgKHR5cGVvZiB0cmFuc2xhdGVkICE9PSAnc3RyaW5nJyB8fCAhbWV0YWRhdGEucGx1Z2luTW9kdWxlIHx8ICFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUuaW5zdGFudGlhdGUpXG4gICAgICByZXR1cm4gdHJhbnNsYXRlZDtcblxuICAgIHZhciBjYWxsZWRJbnN0YW50aWF0ZSA9IGZhbHNlO1xuICAgIG1ldGFkYXRhLnBsdWdpbkxvYWQuc291cmNlID0gdHJhbnNsYXRlZDtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG1ldGFkYXRhLnBsdWdpbk1vZHVsZS5pbnN0YW50aWF0ZS5jYWxsKGxvYWRlciwgbWV0YWRhdGEucGx1Z2luTG9hZCwgZnVuY3Rpb24gKGxvYWQpIHtcbiAgICAgIHRyYW5zbGF0ZWQgPSBsb2FkLnNvdXJjZTtcbiAgICAgIG1ldGFkYXRhLmxvYWQgPSBsb2FkLm1ldGFkYXRhO1xuICAgICAgaWYgKGNhbGxlZEluc3RhbnRpYXRlKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luc3RhbnRpYXRlIG11c3Qgb25seSBiZSBjYWxsZWQgb25jZS4nKTtcbiAgICAgIGNhbGxlZEluc3RhbnRpYXRlID0gdHJ1ZTtcbiAgICB9KSlcbiAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICBpZiAoY2FsbGVkSW5zdGFudGlhdGUpXG4gICAgICAgIHJldHVybiB0cmFuc2xhdGVkO1xuICAgICAgcmV0dXJuIHByb3RlY3RlZENyZWF0ZU5hbWVzcGFjZShyZXN1bHQpO1xuICAgIH0pO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgLy8gcGx1Z2luIGluc3RhbnRpYXRlIHJlc3VsdCBjYXNlXG4gICAgaWYgKHR5cGVvZiBzb3VyY2UgIT09ICdzdHJpbmcnKVxuICAgICAgcmV0dXJuIHNvdXJjZTtcblxuICAgIGlmICghbWV0YWRhdGEubG9hZC5mb3JtYXQpXG4gICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9IGRldGVjdExlZ2FjeUZvcm1hdChzb3VyY2UpO1xuXG4gICAgdmFyIHJlZ2lzdGVyZWQgPSBmYWxzZTtcblxuICAgIHN3aXRjaCAobWV0YWRhdGEubG9hZC5mb3JtYXQpIHtcbiAgICAgIGNhc2UgJ2VzbSc6XG4gICAgICBjYXNlICdyZWdpc3Rlcic6XG4gICAgICBjYXNlICdzeXN0ZW0nOlxuICAgICAgICB2YXIgZXJyID0gZXZhbHVhdGUobG9hZGVyLCBzb3VyY2UsIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwLCBrZXksIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBtZXRhZGF0YS5sb2FkLm5vbmNlLCBmYWxzZSk7XG4gICAgICAgIGlmIChlcnIpXG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICBpZiAoIXByb2Nlc3NBbm9uUmVnaXN0ZXIoKSlcbiAgICAgICAgICByZXR1cm4gZW1wdHlNb2R1bGU7XG4gICAgICAgIHJldHVybjtcbiAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdqc29uJzpcbiAgICAgICAgLy8gd2Fybi5jYWxsKGNvbmZpZywgJ1wianNvblwiIG1vZHVsZSBmb3JtYXQgaXMgZGVwcmVjYXRlZC4nKTtcbiAgICAgICAgdmFyIHBhcnNlZCA9IEpTT04ucGFyc2Uoc291cmNlKTtcbiAgICAgICAgcmV0dXJuIGxvYWRlci5uZXdNb2R1bGUoeyBkZWZhdWx0OiBwYXJzZWQsIF9fdXNlRGVmYXVsdDogcGFyc2VkIH0pO1xuXG4gICAgICBjYXNlICdhbWQnOlxuICAgICAgICB2YXIgY3VyRGVmaW5lID0gZW52R2xvYmFsLmRlZmluZTtcbiAgICAgICAgZW52R2xvYmFsLmRlZmluZSA9IGxvYWRlci5hbWREZWZpbmU7XG5cbiAgICAgICAgY2xlYXJMYXN0RGVmaW5lKG1ldGFkYXRhLmxvYWQuZGVwcywgbWV0YWRhdGEubG9hZC5lc01vZHVsZSk7XG5cbiAgICAgICAgdmFyIGVyciA9IGV2YWx1YXRlKGxvYWRlciwgc291cmNlLCBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCwga2V5LCBtZXRhZGF0YS5sb2FkLmludGVncml0eSwgbWV0YWRhdGEubG9hZC5ub25jZSwgZmFsc2UpO1xuXG4gICAgICAgIC8vIGlmIGRpZG4ndCByZWdpc3RlciBhbm9ueW1vdXNseSwgdXNlIHRoZSBsYXN0IG5hbWVkIGRlZmluZSBpZiBvbmx5IG9uZVxuICAgICAgICByZWdpc3RlcmVkID0gcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgICBpZiAoIXJlZ2lzdGVyZWQpIHtcbiAgICAgICAgICByZWdpc3Rlckxhc3REZWZpbmUobG9hZGVyKTtcbiAgICAgICAgICByZWdpc3RlcmVkID0gcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgZW52R2xvYmFsLmRlZmluZSA9IGN1ckRlZmluZTtcblxuICAgICAgICBpZiAoZXJyKVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdjanMnOlxuICAgICAgICB2YXIgbWV0YURlcHMgPSBtZXRhZGF0YS5sb2FkLmRlcHM7XG4gICAgICAgIHZhciBkZXBzID0gKG1ldGFkYXRhLmxvYWQuZGVwcyB8fCBbXSkuY29uY2F0KG1ldGFkYXRhLmxvYWQuY2pzUmVxdWlyZURldGVjdGlvbiA/IGdldENKU0RlcHMoc291cmNlKSA6IFtdKTtcblxuICAgICAgICBmb3IgKHZhciBnIGluIG1ldGFkYXRhLmxvYWQuZ2xvYmFscylcbiAgICAgICAgICBpZiAobWV0YWRhdGEubG9hZC5nbG9iYWxzW2ddKVxuICAgICAgICAgICAgZGVwcy5wdXNoKG1ldGFkYXRhLmxvYWQuZ2xvYmFsc1tnXSk7XG5cbiAgICAgICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhkZXBzLCB0cnVlLCBmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgICAgcmVxdWlyZS5yZXNvbHZlID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlcXVpcmVSZXNvbHZlLmNhbGwobG9hZGVyLCBrZXksIG1vZHVsZS5pZCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBzdXBwb3J0IG1vZHVsZS5wYXRocyBpc2hcbiAgICAgICAgICBtb2R1bGUucGF0aHMgPSBbXTtcbiAgICAgICAgICBtb2R1bGUucmVxdWlyZSA9IHJlcXVpcmU7XG5cbiAgICAgICAgICAvLyBlbnN1cmUgbWV0YSBkZXBzIGV4ZWN1dGUgZmlyc3RcbiAgICAgICAgICBpZiAoIW1ldGFkYXRhLmxvYWQuY2pzRGVmZXJEZXBzRXhlY3V0ZSAmJiBtZXRhRGVwcylcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWV0YURlcHMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgICAgIHJlcXVpcmUobWV0YURlcHNbaV0pO1xuXG4gICAgICAgICAgdmFyIHBhdGhWYXJzID0gZ2V0UGF0aFZhcnMobW9kdWxlLmlkKTtcbiAgICAgICAgICB2YXIgX19janNXcmFwcGVyID0ge1xuICAgICAgICAgICAgZXhwb3J0czogZXhwb3J0cyxcbiAgICAgICAgICAgIGFyZ3M6IFtyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUsIHBhdGhWYXJzLmZpbGVuYW1lLCBwYXRoVmFycy5kaXJuYW1lLCBlbnZHbG9iYWwsIGVudkdsb2JhbF1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgdmFyIGNqc1dyYXBwZXIgPSBcIihmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlLCBfX2ZpbGVuYW1lLCBfX2Rpcm5hbWUsIGdsb2JhbCwgR0xPQkFMXCI7XG5cbiAgICAgICAgICAvLyBhZGQgbWV0YWRhdGEuZ2xvYmFscyB0byB0aGUgd3JhcHBlciBhcmd1bWVudHNcbiAgICAgICAgICBpZiAobWV0YWRhdGEubG9hZC5nbG9iYWxzKVxuICAgICAgICAgICAgZm9yICh2YXIgZyBpbiBtZXRhZGF0YS5sb2FkLmdsb2JhbHMpIHtcbiAgICAgICAgICAgICAgX19janNXcmFwcGVyLmFyZ3MucHVzaChyZXF1aXJlKG1ldGFkYXRhLmxvYWQuZ2xvYmFsc1tnXSkpO1xuICAgICAgICAgICAgICBjanNXcmFwcGVyICs9IFwiLCBcIiArIGc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBkaXNhYmxlIEFNRCBkZXRlY3Rpb25cbiAgICAgICAgICB2YXIgZGVmaW5lID0gZW52R2xvYmFsLmRlZmluZTtcbiAgICAgICAgICBlbnZHbG9iYWwuZGVmaW5lID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGVudkdsb2JhbC5fX2Nqc1dyYXBwZXIgPSBfX2Nqc1dyYXBwZXI7XG5cbiAgICAgICAgICBzb3VyY2UgPSBjanNXcmFwcGVyICsgXCIpIHtcIiArIHNvdXJjZS5yZXBsYWNlKGhhc2hCYW5nUmVnRXgsICcnKSArIFwiXFxufSkuYXBwbHkoX19janNXcmFwcGVyLmV4cG9ydHMsIF9fY2pzV3JhcHBlci5hcmdzKTtcIjtcblxuICAgICAgICAgIHZhciBlcnIgPSBldmFsdWF0ZShsb2FkZXIsIHNvdXJjZSwgbWV0YWRhdGEubG9hZC5zb3VyY2VNYXAsIGtleSwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIG1ldGFkYXRhLmxvYWQubm9uY2UsIGZhbHNlKTtcbiAgICAgICAgICBpZiAoZXJyKVxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuXG4gICAgICAgICAgc2V0TWV0YUVzTW9kdWxlKG1ldGFkYXRhLCBleHBvcnRzKTtcblxuICAgICAgICAgIGVudkdsb2JhbC5fX2Nqc1dyYXBwZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgZW52R2xvYmFsLmRlZmluZSA9IGRlZmluZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlZ2lzdGVyZWQgPSBwcm9jZXNzQW5vblJlZ2lzdGVyKCk7XG4gICAgICBicmVhaztcblxuICAgICAgY2FzZSAnZ2xvYmFsJzpcbiAgICAgICAgdmFyIGRlcHMgPSBtZXRhZGF0YS5sb2FkLmRlcHMgfHwgW107XG4gICAgICAgIGZvciAodmFyIGcgaW4gbWV0YWRhdGEubG9hZC5nbG9iYWxzKSB7XG4gICAgICAgICAgdmFyIGdsID0gbWV0YWRhdGEubG9hZC5nbG9iYWxzW2ddO1xuICAgICAgICAgIGlmIChnbClcbiAgICAgICAgICAgIGRlcHMucHVzaChnbCk7XG4gICAgICAgIH1cblxuICAgICAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKGRlcHMsIGZhbHNlLCBmdW5jdGlvbiAocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgICAgdmFyIGdsb2JhbHM7XG4gICAgICAgICAgaWYgKG1ldGFkYXRhLmxvYWQuZ2xvYmFscykge1xuICAgICAgICAgICAgZ2xvYmFscyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgZyBpbiBtZXRhZGF0YS5sb2FkLmdsb2JhbHMpXG4gICAgICAgICAgICAgIGlmIChtZXRhZGF0YS5sb2FkLmdsb2JhbHNbZ10pXG4gICAgICAgICAgICAgICAgZ2xvYmFsc1tnXSA9IHJlcXVpcmUobWV0YWRhdGEubG9hZC5nbG9iYWxzW2ddKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgZXhwb3J0TmFtZSA9IG1ldGFkYXRhLmxvYWQuZXhwb3J0cztcblxuICAgICAgICAgIGlmIChleHBvcnROYW1lKVxuICAgICAgICAgICAgc291cmNlICs9ICdcXG4nICsgZ2xvYmFsTmFtZSArICdbXCInICsgZXhwb3J0TmFtZSArICdcIl0gPSAnICsgZXhwb3J0TmFtZSArICc7JztcblxuICAgICAgICAgIHZhciByZXRyaWV2ZUdsb2JhbCA9IHByZXBhcmVHbG9iYWwobW9kdWxlLmlkLCBleHBvcnROYW1lLCBnbG9iYWxzLCBtZXRhZGF0YS5sb2FkLmVuY2Fwc3VsYXRlR2xvYmFsKTtcbiAgICAgICAgICB2YXIgZXJyID0gZXZhbHVhdGUobG9hZGVyLCBzb3VyY2UsIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwLCBrZXksIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBtZXRhZGF0YS5sb2FkLm5vbmNlLCB0cnVlKTtcblxuICAgICAgICAgIGlmIChlcnIpXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG5cbiAgICAgICAgICB2YXIgb3V0cHV0ID0gcmV0cmlldmVHbG9iYWwoKTtcbiAgICAgICAgICBzZXRNZXRhRXNNb2R1bGUobWV0YWRhdGEsIG91dHB1dCk7XG4gICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlZ2lzdGVyZWQgPSBwcm9jZXNzQW5vblJlZ2lzdGVyKCk7XG4gICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBtb2R1bGUgZm9ybWF0IFwiJyArIG1ldGFkYXRhLmxvYWQuZm9ybWF0ICsgJ1wiIGZvciBcIicgKyBrZXkgKyAnXCIuJyArIChtZXRhZGF0YS5sb2FkLmZvcm1hdCA9PT0gJ2VzNicgPyAnIFVzZSBcImVzbVwiIGluc3RlYWQgaGVyZS4nIDogJycpKTtcbiAgICB9XG5cbiAgICBpZiAoIXJlZ2lzdGVyZWQpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vZHVsZSAnICsga2V5ICsgJyBkZXRlY3RlZCBhcyAnICsgbWV0YWRhdGEubG9hZC5mb3JtYXQgKyAnIGJ1dCBkaWRuXFwndCBleGVjdXRlIGNvcnJlY3RseS4nKTtcbiAgfSk7XG59XG5cbnZhciBnbG9iYWxOYW1lID0gdHlwZW9mIHNlbGYgIT0gJ3VuZGVmaW5lZCcgPyAnc2VsZicgOiAnZ2xvYmFsJztcblxuLy8gZ29vZCBlbm91Z2ggRVM2IG1vZHVsZSBkZXRlY3Rpb24gcmVnZXggLSBmb3JtYXQgZGV0ZWN0aW9ucyBub3QgZGVzaWduZWQgdG8gYmUgYWNjdXJhdGUsIGJ1dCB0byBoYW5kbGUgdGhlIDk5JSB1c2UgY2FzZVxudmFyIGVzbVJlZ0V4ID0gLyheXFxzKnxbfVxcKTtcXG5dXFxzKikoaW1wb3J0XFxzKihbJ1wiXXwoXFwqXFxzK2FzXFxzKyk/KD8hdHlwZSkoW15cIidcXChcXClcXG47IF0rKVxccypmcm9tXFxzKlsnXCJdfFxceyl8ZXhwb3J0XFxzK1xcKlxccytmcm9tXFxzK1tcIiddfGV4cG9ydFxccyooXFx7fGRlZmF1bHR8ZnVuY3Rpb258Y2xhc3N8dmFyfGNvbnN0fGxldHxhc3luY1xccytmdW5jdGlvbikpLztcblxudmFyIGxlYWRpbmdDb21tZW50QW5kTWV0YVJlZ0V4ID0gL14oXFxzKlxcL1xcKlteXFwqXSooXFwqKD8hXFwvKVteXFwqXSopKlxcKlxcL3xcXHMqXFwvXFwvW15cXG5dKnxcXHMqXCJbXlwiXStcIlxccyo7P3xcXHMqJ1teJ10rJ1xccyo7PykqXFxzKi87XG5mdW5jdGlvbiBkZXRlY3RSZWdpc3RlckZvcm1hdChzb3VyY2UpIHtcbiAgdmFyIGxlYWRpbmdDb21tZW50QW5kTWV0YSA9IHNvdXJjZS5tYXRjaChsZWFkaW5nQ29tbWVudEFuZE1ldGFSZWdFeCk7XG4gIHJldHVybiBsZWFkaW5nQ29tbWVudEFuZE1ldGEgJiYgc291cmNlLnN1YnN0cihsZWFkaW5nQ29tbWVudEFuZE1ldGFbMF0ubGVuZ3RoLCAxNSkgPT09ICdTeXN0ZW0ucmVnaXN0ZXInO1xufVxuXG4vLyBBTUQgTW9kdWxlIEZvcm1hdCBEZXRlY3Rpb24gUmVnRXhcbi8vIGRlZmluZShbLi4sIC4uLCAuLl0sIC4uLilcbi8vIGRlZmluZSh2YXJOYW1lKTsgfHwgZGVmaW5lKGZ1bmN0aW9uKHJlcXVpcmUsIGV4cG9ydHMpIHt9KTsgfHwgZGVmaW5lKHt9KVxudmFyIGFtZFJlZ0V4ID0gLyg/Ol5cXHVGRUZGP3xbXiRfYS16QS1aXFx4QTAtXFx1RkZGRi5dKWRlZmluZVxccypcXChcXHMqKFwiW15cIl0rXCJcXHMqLFxccyp8J1teJ10rJ1xccyosXFxzKik/XFxzKihcXFsoXFxzKigoXCJbXlwiXStcInwnW14nXSsnKVxccyosfFxcL1xcLy4qXFxyP1xcbnxcXC9cXCooLnxcXHMpKj9cXCpcXC8pKSooXFxzKihcIlteXCJdK1wifCdbXiddKycpXFxzKiw/KT8oXFxzKihcXC9cXC8uKlxccj9cXG58XFwvXFwqKC58XFxzKSo/XFwqXFwvKSkqXFxzKlxcXXxmdW5jdGlvblxccyp8e3xbXyRhLXpBLVpcXHhBMC1cXHVGRkZGXVtfJGEtekEtWjAtOVxceEEwLVxcdUZGRkZdKlxcKSkvO1xuXG4vLy8gcmVxdWlyZSgnLi4uJykgfHwgZXhwb3J0c1snJ10gPSAuLi4gfHwgZXhwb3J0cy5hc2QgPSAuLi4gfHwgbW9kdWxlLmV4cG9ydHMgPSAuLi5cbnZhciBjanNFeHBvcnRzUmVnRXggPSAvKD86XlxcdUZFRkY/fFteJF9hLXpBLVpcXHhBMC1cXHVGRkZGLl0pKGV4cG9ydHNcXHMqKFxcW1snXCJdfFxcLil8bW9kdWxlKFxcLmV4cG9ydHN8XFxbJ2V4cG9ydHMnXFxdfFxcW1wiZXhwb3J0c1wiXFxdKVxccyooXFxbWydcIl18Wz0sXFwuXSkpLztcbi8vIHVzZWQgdG8gc3VwcG9ydCBsZWFkaW5nICMhL3Vzci9iaW4vZW52IGluIHNjcmlwdHMgYXMgc3VwcG9ydGVkIGluIE5vZGVcbnZhciBoYXNoQmFuZ1JlZ0V4ID0gL15cXCNcXCEuKi87XG5cbmZ1bmN0aW9uIGRldGVjdExlZ2FjeUZvcm1hdCAoc291cmNlKSB7XG4gIGlmIChzb3VyY2UubWF0Y2goYW1kUmVnRXgpKVxuICAgIHJldHVybiAnYW1kJztcblxuICBjanNFeHBvcnRzUmVnRXgubGFzdEluZGV4ID0gMDtcbiAgY2pzUmVxdWlyZVJlZ0V4Lmxhc3RJbmRleCA9IDA7XG4gIGlmIChjanNSZXF1aXJlUmVnRXguZXhlYyhzb3VyY2UpIHx8IGNqc0V4cG9ydHNSZWdFeC5leGVjKHNvdXJjZSkpXG4gICAgcmV0dXJuICdjanMnO1xuXG4gIC8vIGdsb2JhbCBpcyB0aGUgZmFsbGJhY2sgZm9ybWF0XG4gIHJldHVybiAnZ2xvYmFsJztcbn1cblxuZnVuY3Rpb24gc2FuaXRpemVTb3VyY2VNYXAgKGFkZHJlc3MsIHNvdXJjZU1hcCkge1xuICB2YXIgb3JpZ2luYWxOYW1lID0gYWRkcmVzcy5zcGxpdCgnIScpWzBdO1xuXG4gIC8vIGZvcmNlIHNldCB0aGUgZmlsZW5hbWUgb2YgdGhlIG9yaWdpbmFsIGZpbGVcbiAgaWYgKCFzb3VyY2VNYXAuZmlsZSB8fCBzb3VyY2VNYXAuZmlsZSA9PSBhZGRyZXNzKVxuICAgIHNvdXJjZU1hcC5maWxlID0gb3JpZ2luYWxOYW1lICsgJyF0cmFuc3BpbGVkJztcblxuICAvLyBmb3JjZSBzZXQgdGhlIHNvdXJjZXMgbGlzdCBpZiBvbmx5IG9uZSBzb3VyY2VcbiAgaWYgKCFzb3VyY2VNYXAuc291cmNlcyB8fCBzb3VyY2VNYXAuc291cmNlcy5sZW5ndGggPD0gMSAmJiAoIXNvdXJjZU1hcC5zb3VyY2VzWzBdIHx8IHNvdXJjZU1hcC5zb3VyY2VzWzBdID09PSBhZGRyZXNzKSlcbiAgICBzb3VyY2VNYXAuc291cmNlcyA9IFtvcmlnaW5hbE5hbWVdO1xufVxuXG5mdW5jdGlvbiB0cmFuc3BpbGUgKGxvYWRlciwgc291cmNlLCBrZXksIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyKSB7XG4gIGlmICghbG9hZGVyLnRyYW5zcGlsZXIpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5hYmxlIHRvIGR5bmFtaWNhbGx5IHRyYW5zcGlsZSBFUyBtb2R1bGVcXG4gICBBIGxvYWRlciBwbHVnaW4gbmVlZHMgdG8gYmUgY29uZmlndXJlZCB2aWEgYFN5c3RlbUpTLmNvbmZpZyh7IHRyYW5zcGlsZXI6IFxcJ3RyYW5zcGlsZXItbW9kdWxlXFwnIH0pYC4nKTtcblxuICAvLyBkZXBzIHN1cHBvcnQgZm9yIGVzIHRyYW5zcGlsZVxuICBpZiAobWV0YWRhdGEubG9hZC5kZXBzKSB7XG4gICAgdmFyIGRlcHNQcmVmaXggPSAnJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1ldGFkYXRhLmxvYWQuZGVwcy5sZW5ndGg7IGkrKylcbiAgICAgIGRlcHNQcmVmaXggKz0gJ2ltcG9ydCBcIicgKyBtZXRhZGF0YS5sb2FkLmRlcHNbaV0gKyAnXCI7ICc7XG4gICAgc291cmNlID0gZGVwc1ByZWZpeCArIHNvdXJjZTtcbiAgfVxuXG4gIC8vIGRvIHRyYW5zcGlsYXRpb25cbiAgcmV0dXJuIGxvYWRlci5pbXBvcnQuY2FsbChsb2FkZXIsIGxvYWRlci50cmFuc3BpbGVyKVxuICAudGhlbihmdW5jdGlvbiAodHJhbnNwaWxlcikge1xuICAgIHRyYW5zcGlsZXIgPSB0cmFuc3BpbGVyLl9fdXNlRGVmYXVsdCB8fCB0cmFuc3BpbGVyO1xuXG4gICAgLy8gdHJhbnNsYXRlIGhvb2tzIG1lYW5zIHRoaXMgaXMgYSB0cmFuc3BpbGVyIHBsdWdpbiBpbnN0ZWFkIG9mIGEgcmF3IGltcGxlbWVudGF0aW9uXG4gICAgaWYgKCF0cmFuc3BpbGVyLnRyYW5zbGF0ZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihsb2FkZXIudHJhbnNwaWxlciArICcgaXMgbm90IGEgdmFsaWQgdHJhbnNwaWxlciBwbHVnaW4uJyk7XG5cbiAgICAvLyBpZiB0cmFuc3BpbGVyIGlzIHRoZSBzYW1lIGFzIHRoZSBwbHVnaW4gbG9hZGVyLCB0aGVuIGRvbid0IHJ1biB0d2ljZVxuICAgIGlmICh0cmFuc3BpbGVyID09PSBtZXRhZGF0YS5wbHVnaW5Nb2R1bGUpXG4gICAgICByZXR1cm4gc291cmNlO1xuXG4gICAgLy8gY29udmVydCB0aGUgc291cmNlIG1hcCBpbnRvIGFuIG9iamVjdCBmb3IgdHJhbnNwaWxhdGlvbiBjaGFpbmluZ1xuICAgIGlmICh0eXBlb2YgbWV0YWRhdGEubG9hZC5zb3VyY2VNYXAgPT09ICdzdHJpbmcnKVxuICAgICAgbWV0YWRhdGEubG9hZC5zb3VyY2VNYXAgPSBKU09OLnBhcnNlKG1ldGFkYXRhLmxvYWQuc291cmNlTWFwKTtcblxuICAgIG1ldGFkYXRhLnBsdWdpbkxvYWQgPSBtZXRhZGF0YS5wbHVnaW5Mb2FkIHx8IHtcbiAgICAgIG5hbWU6IGtleSxcbiAgICAgIGFkZHJlc3M6IGtleSxcbiAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLmxvYWRcbiAgICB9O1xuICAgIG1ldGFkYXRhLmxvYWQuZGVwcyA9IG1ldGFkYXRhLmxvYWQuZGVwcyB8fCBbXTtcblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJhbnNwaWxlci50cmFuc2xhdGUuY2FsbChsb2FkZXIsIG1ldGFkYXRhLnBsdWdpbkxvYWQsIG1ldGFkYXRhLnRyYWNlT3B0cykpXG4gICAgLnRoZW4oZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgICAgLy8gc2FuaXRpemUgc291cmNlTWFwIGlmIGFuIG9iamVjdCBub3QgYSBKU09OIHN0cmluZ1xuICAgICAgdmFyIHNvdXJjZU1hcCA9IG1ldGFkYXRhLmxvYWQuc291cmNlTWFwO1xuICAgICAgaWYgKHNvdXJjZU1hcCAmJiB0eXBlb2Ygc291cmNlTWFwID09PSAnb2JqZWN0JylcbiAgICAgICAgc2FuaXRpemVTb3VyY2VNYXAoa2V5LCBzb3VyY2VNYXApO1xuXG4gICAgICBpZiAobWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdlc20nICYmIGRldGVjdFJlZ2lzdGVyRm9ybWF0KHNvdXJjZSkpXG4gICAgICAgIG1ldGFkYXRhLmxvYWQuZm9ybWF0ID0gJ3JlZ2lzdGVyJztcblxuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9KTtcbiAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgIHRocm93IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnVW5hYmxlIHRvIGxvYWQgdHJhbnNwaWxlciB0byB0cmFuc3BpbGUgJyArIGtleSk7XG4gIH0pO1xufVxuXG4vLyBkZXRlY3QgYW55IG1ldGEgaGVhZGVyIHN5bnRheFxuLy8gb25seSBzZXQgaWYgbm90IGFscmVhZHkgc2V0XG52YXIgbWV0YVJlZ0V4ID0gL14oXFxzKlxcL1xcKlteXFwqXSooXFwqKD8hXFwvKVteXFwqXSopKlxcKlxcL3xcXHMqXFwvXFwvW15cXG5dKnxcXHMqXCJbXlwiXStcIlxccyo7P3xcXHMqJ1teJ10rJ1xccyo7PykrLztcbnZhciBtZXRhUGFydFJlZ0V4ID0gL1xcL1xcKlteXFwqXSooXFwqKD8hXFwvKVteXFwqXSopKlxcKlxcL3xcXC9cXC9bXlxcbl0qfFwiW15cIl0rXCJcXHMqOz98J1teJ10rJ1xccyo7Py9nO1xuXG5mdW5jdGlvbiBzZXRNZXRhUHJvcGVydHkodGFyZ2V0LCBwLCB2YWx1ZSkge1xuICB2YXIgcFBhcnRzID0gcC5zcGxpdCgnLicpO1xuICB2YXIgY3VyUGFydDtcbiAgd2hpbGUgKHBQYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgY3VyUGFydCA9IHBQYXJ0cy5zaGlmdCgpO1xuICAgIHRhcmdldCA9IHRhcmdldFtjdXJQYXJ0XSA9IHRhcmdldFtjdXJQYXJ0XSB8fCB7fTtcbiAgfVxuICBjdXJQYXJ0ID0gcFBhcnRzLnNoaWZ0KCk7XG4gIGlmICh0YXJnZXRbY3VyUGFydF0gPT09IHVuZGVmaW5lZClcbiAgICB0YXJnZXRbY3VyUGFydF0gPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gcmVhZE1ldGFTeW50YXggKHNvdXJjZSwgbWV0YWRhdGEpIHtcbiAgdmFyIG1ldGEgPSBzb3VyY2UubWF0Y2gobWV0YVJlZ0V4KTtcbiAgaWYgKCFtZXRhKVxuICAgIHJldHVybjtcblxuICB2YXIgbWV0YVBhcnRzID0gbWV0YVswXS5tYXRjaChtZXRhUGFydFJlZ0V4KTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG1ldGFQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBjdXJQYXJ0ID0gbWV0YVBhcnRzW2ldO1xuICAgIHZhciBsZW4gPSBjdXJQYXJ0Lmxlbmd0aDtcblxuICAgIHZhciBmaXJzdENoYXIgPSBjdXJQYXJ0LnN1YnN0cigwLCAxKTtcbiAgICBpZiAoY3VyUGFydC5zdWJzdHIobGVuIC0gMSwgMSkgPT0gJzsnKVxuICAgICAgbGVuLS07XG5cbiAgICBpZiAoZmlyc3RDaGFyICE9ICdcIicgJiYgZmlyc3RDaGFyICE9IFwiJ1wiKVxuICAgICAgY29udGludWU7XG5cbiAgICB2YXIgbWV0YVN0cmluZyA9IGN1clBhcnQuc3Vic3RyKDEsIGN1clBhcnQubGVuZ3RoIC0gMyk7XG4gICAgdmFyIG1ldGFOYW1lID0gbWV0YVN0cmluZy5zdWJzdHIoMCwgbWV0YVN0cmluZy5pbmRleE9mKCcgJykpO1xuXG4gICAgaWYgKG1ldGFOYW1lKSB7XG4gICAgICB2YXIgbWV0YVZhbHVlID0gbWV0YVN0cmluZy5zdWJzdHIobWV0YU5hbWUubGVuZ3RoICsgMSwgbWV0YVN0cmluZy5sZW5ndGggLSBtZXRhTmFtZS5sZW5ndGggLSAxKTtcblxuICAgICAgaWYgKG1ldGFOYW1lID09PSAnZGVwcycpXG4gICAgICAgIG1ldGFOYW1lID0gJ2RlcHNbXSc7XG5cbiAgICAgIGlmIChtZXRhTmFtZS5zdWJzdHIobWV0YU5hbWUubGVuZ3RoIC0gMiwgMikgPT09ICdbXScpIHtcbiAgICAgICAgbWV0YU5hbWUgPSBtZXRhTmFtZS5zdWJzdHIoMCwgbWV0YU5hbWUubGVuZ3RoIC0gMik7XG4gICAgICAgIG1ldGFkYXRhLmxvYWRbbWV0YU5hbWVdID0gbWV0YWRhdGEubG9hZFttZXRhTmFtZV0gfHwgW107XG4gICAgICAgIG1ldGFkYXRhLmxvYWRbbWV0YU5hbWVdLnB1c2gobWV0YVZhbHVlKTtcbiAgICAgIH1cbiAgICAgIC8vIFwidXNlIHN0cmljdFwiIGlzIG5vdCBtZXRhXG4gICAgICBlbHNlIGlmIChtZXRhTmFtZSAhPT0gJ3VzZScpIHtcbiAgICAgICAgc2V0TWV0YVByb3BlcnR5KG1ldGFkYXRhLmxvYWQsIG1ldGFOYW1lLCBtZXRhVmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIG1ldGFkYXRhLmxvYWRbbWV0YVN0cmluZ10gPSB0cnVlO1xuICAgIH1cbiAgfVxufVxuXG52YXIgc2NyaXB0U3JjO1xuXG4vLyBQcm9taXNlIGRldGVjdGlvbiBhbmQgZXJyb3IgbWVzc2FnZVxuaWYgKHR5cGVvZiBQcm9taXNlID09PSAndW5kZWZpbmVkJylcbiAgdGhyb3cgbmV3IEVycm9yKCdTeXN0ZW1KUyBuZWVkcyBhIFByb21pc2UgcG9seWZpbGwuJyk7XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gIHZhciBzY3JpcHRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3NjcmlwdCcpO1xuICB2YXIgY3VyU2NyaXB0ID0gc2NyaXB0c1tzY3JpcHRzLmxlbmd0aCAtIDFdO1xuICBpZiAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCAmJiAoY3VyU2NyaXB0LmRlZmVyIHx8IGN1clNjcmlwdC5hc3luYykpXG4gICAgY3VyU2NyaXB0ID0gZG9jdW1lbnQuY3VycmVudFNjcmlwdDtcblxuICBzY3JpcHRTcmMgPSBjdXJTY3JpcHQgJiYgY3VyU2NyaXB0LnNyYztcbn1cbi8vIHdvcmtlclxuZWxzZSBpZiAodHlwZW9mIGltcG9ydFNjcmlwdHMgIT09ICd1bmRlZmluZWQnKSB7XG4gIHRyeSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdfJyk7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICBlLnN0YWNrLnJlcGxhY2UoLyg/OmF0fEApLiooaHR0cC4rKTpbXFxkXSs6W1xcZF0rLywgZnVuY3Rpb24obSwgdXJsKSB7XG4gICAgICBzY3JpcHRTcmMgPSB1cmw7XG4gICAgfSk7XG4gIH1cbn1cbi8vIG5vZGVcbmVsc2UgaWYgKHR5cGVvZiBfX2ZpbGVuYW1lICE9PSAndW5kZWZpbmVkJykge1xuICBzY3JpcHRTcmMgPSBfX2ZpbGVuYW1lO1xufVxuXG5mdW5jdGlvbiBTeXN0ZW1KU0xvYWRlciQxICgpIHtcbiAgUmVnaXN0ZXJMb2FkZXIkMS5jYWxsKHRoaXMpO1xuXG4gIC8vIE5CIGRlcHJlY2F0ZVxuICB0aGlzLl9sb2FkZXIgPSB7fTtcblxuICAvLyBpbnRlcm5hbCBtZXRhZGF0YSBzdG9yZVxuICB0aGlzW01FVEFEQVRBXSA9IHt9O1xuXG4gIC8vIGludGVybmFsIGNvbmZpZ3VyYXRpb25cbiAgdGhpc1tDT05GSUddID0ge1xuICAgIGJhc2VVUkw6IGJhc2VVUkksXG4gICAgcGF0aHM6IHt9LFxuXG4gICAgcGFja2FnZUNvbmZpZ1BhdGhzOiBbXSxcbiAgICBwYWNrYWdlQ29uZmlnS2V5czogW10sXG4gICAgbWFwOiB7fSxcbiAgICBwYWNrYWdlczoge30sXG4gICAgZGVwQ2FjaGU6IHt9LFxuICAgIG1ldGE6IHt9LFxuICAgIGJ1bmRsZXM6IHt9LFxuXG4gICAgcHJvZHVjdGlvbjogZmFsc2UsXG5cbiAgICB0cmFuc3BpbGVyOiB1bmRlZmluZWQsXG4gICAgbG9hZGVkQnVuZGxlczoge30sXG5cbiAgICAvLyBnbG9iYWwgYmVoYXZpb3VyIGZsYWdzXG4gICAgd2FybmluZ3M6IGZhbHNlLFxuICAgIHBsdWdpbkZpcnN0OiBmYWxzZSxcblxuICAgIC8vIGVuYWJsZSB3YXNtIGxvYWRpbmcgYW5kIGRldGVjdGlvbiB3aGVuIHN1cHBvcnRlZFxuICAgIHdhc206IGZhbHNlXG4gIH07XG5cbiAgLy8gbWFrZSB0aGUgbG9jYXRpb24gb2YgdGhlIHN5c3RlbS5qcyBzY3JpcHQgYWNjZXNzaWJsZSAoaWYgYW55KVxuICB0aGlzLnNjcmlwdFNyYyA9IHNjcmlwdFNyYztcblxuICB0aGlzLl9ub2RlUmVxdWlyZSA9IG5vZGVSZXF1aXJlO1xuXG4gIC8vIHN1cHBvcnQgdGhlIGVtcHR5IG1vZHVsZSwgYXMgYSBjb25jZXB0XG4gIHRoaXMucmVnaXN0cnkuc2V0KCdAZW1wdHknLCBlbXB0eU1vZHVsZSk7XG5cbiAgc2V0UHJvZHVjdGlvbi5jYWxsKHRoaXMsIGZhbHNlLCBmYWxzZSk7XG5cbiAgLy8gYWRkIG1vZHVsZSBmb3JtYXQgaGVscGVyc1xuICBmb3JtYXRIZWxwZXJzKHRoaXMpO1xufVxuXG52YXIgZW52TW9kdWxlO1xuZnVuY3Rpb24gc2V0UHJvZHVjdGlvbiAoaXNQcm9kdWN0aW9uLCBpc0J1aWxkZXIpIHtcbiAgdGhpc1tDT05GSUddLnByb2R1Y3Rpb24gPSBpc1Byb2R1Y3Rpb247XG4gIHRoaXMucmVnaXN0cnkuc2V0KCdAc3lzdGVtLWVudicsIGVudk1vZHVsZSA9IHRoaXMubmV3TW9kdWxlKHtcbiAgICBicm93c2VyOiBpc0Jyb3dzZXIsXG4gICAgbm9kZTogISF0aGlzLl9ub2RlUmVxdWlyZSxcbiAgICBwcm9kdWN0aW9uOiAhaXNCdWlsZGVyICYmIGlzUHJvZHVjdGlvbixcbiAgICBkZXY6IGlzQnVpbGRlciB8fCAhaXNQcm9kdWN0aW9uLFxuICAgIGJ1aWxkOiBpc0J1aWxkZXIsXG4gICAgJ2RlZmF1bHQnOiB0cnVlXG4gIH0pKTtcbn1cblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlKTtcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBTeXN0ZW1KU0xvYWRlciQxO1xuXG4vLyBOQiBkZXByZWNhdGUgbm9ybWFsaXplXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZVtTeXN0ZW1KU0xvYWRlciQxLnJlc29sdmUgPSBSZWdpc3RlckxvYWRlciQxLnJlc29sdmVdID0gU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUubm9ybWFsaXplID0gbm9ybWFsaXplO1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKGtleSwgcGFyZW50S2V5KSB7XG4gIHdhcm4uY2FsbCh0aGlzW0NPTkZJR10sICdTeXN0ZW0ubG9hZCBpcyBkZXByZWNhdGVkLicpO1xuICByZXR1cm4gdGhpcy5pbXBvcnQoa2V5LCBwYXJlbnRLZXkpO1xufTtcblxuLy8gTkIgZGVwcmVjYXRlIGRlY2Fub25pY2FsaXplLCBub3JtYWxpemVTeW5jXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5kZWNhbm9uaWNhbGl6ZSA9IFN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLm5vcm1hbGl6ZVN5bmMgPSBTeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5yZXNvbHZlU3luYyA9IG5vcm1hbGl6ZVN5bmM7XG5cblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlW1N5c3RlbUpTTG9hZGVyJDEuaW5zdGFudGlhdGUgPSBSZWdpc3RlckxvYWRlciQxLmluc3RhbnRpYXRlXSA9IGluc3RhbnRpYXRlJDE7XG5cblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmNvbmZpZyA9IHNldENvbmZpZztcblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmdldENvbmZpZyA9IGdldENvbmZpZztcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuZ2xvYmFsID0gZW52R2xvYmFsO1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5pbXBvcnQgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBSZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5pbXBvcnQuYXBwbHkodGhpcywgYXJndW1lbnRzKVxuICAudGhlbihmdW5jdGlvbiAobSkge1xuICAgIHJldHVybiAnX191c2VEZWZhdWx0JyBpbiBtID8gbS5fX3VzZURlZmF1bHQgOiBtO1xuICB9KTtcbn07XG5cbnZhciBjb25maWdOYW1lcyA9IFsnYmFzZVVSTCcsICdtYXAnLCAncGF0aHMnLCAncGFja2FnZXMnLCAncGFja2FnZUNvbmZpZ1BhdGhzJywgJ2RlcENhY2hlJywgJ21ldGEnLCAnYnVuZGxlcycsICd0cmFuc3BpbGVyJywgJ3dhcm5pbmdzJywgJ3BsdWdpbkZpcnN0JywgJ3Byb2R1Y3Rpb24nLCAnd2FzbSddO1xuXG52YXIgaGFzUHJveHkgPSB0eXBlb2YgUHJveHkgIT09ICd1bmRlZmluZWQnO1xuZm9yICh2YXIgaSA9IDA7IGkgPCBjb25maWdOYW1lcy5sZW5ndGg7IGkrKykgKGZ1bmN0aW9uIChjb25maWdOYW1lKSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZSwgY29uZmlnTmFtZSwge1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGNmZyA9IGdldENvbmZpZ0l0ZW0odGhpc1tDT05GSUddLCBjb25maWdOYW1lKTtcblxuICAgICAgaWYgKGhhc1Byb3h5ICYmIHR5cGVvZiBjZmcgPT09ICdvYmplY3QnKVxuICAgICAgICBjZmcgPSBuZXcgUHJveHkoY2ZnLCB7XG4gICAgICAgICAgc2V0OiBmdW5jdGlvbiAodGFyZ2V0LCBvcHRpb24pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHNldCBTeXN0ZW1KUy4nICsgY29uZmlnTmFtZSArICdbXCInICsgb3B0aW9uICsgJ1wiXSBkaXJlY3RseS4gVXNlIFN5c3RlbUpTLmNvbmZpZyh7ICcgKyBjb25maWdOYW1lICsgJzogeyBcIicgKyBvcHRpb24gKyAnXCI6IC4uLiB9IH0pIHJhdGhlci4nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAvL2lmICh0eXBlb2YgY2ZnID09PSAnb2JqZWN0JylcbiAgICAgIC8vICB3YXJuLmNhbGwodGhpc1tDT05GSUddLCAnUmVmZXJlbmNpbmcgYFN5c3RlbUpTLicgKyBjb25maWdOYW1lICsgJ2AgaXMgZGVwcmVjYXRlZC4gVXNlIHRoZSBjb25maWcgZ2V0dGVyIGBTeXN0ZW1KUy5nZXRDb25maWcoXFwnJyArIGNvbmZpZ05hbWUgKyAnXFwnKWAnKTtcbiAgICAgIHJldHVybiBjZmc7XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NldHRpbmcgYFN5c3RlbUpTLicgKyBjb25maWdOYW1lICsgJ2AgZGlyZWN0bHkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gVXNlIGBTeXN0ZW1KUy5jb25maWcoeyAnICsgY29uZmlnTmFtZSArICc6IC4uLiB9KWAuJyk7XG4gICAgfVxuICB9KTtcbn0pKGNvbmZpZ05hbWVzW2ldKTtcblxuLypcbiAqIEJhY2t3YXJkcy1jb21wYXRpYmxlIHJlZ2lzdHJ5IEFQSSwgdG8gYmUgZGVwcmVjYXRlZFxuICovXG5mdW5jdGlvbiByZWdpc3RyeVdhcm4obG9hZGVyLCBtZXRob2QpIHtcbiAgd2Fybi5jYWxsKGxvYWRlcltDT05GSUddLCAnU3lzdGVtSlMuJyArIG1ldGhvZCArICcgaXMgZGVwcmVjYXRlZCBmb3IgU3lzdGVtSlMucmVnaXN0cnkuJyArIG1ldGhvZCk7XG59XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5kZWxldGUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJlZ2lzdHJ5V2Fybih0aGlzLCAnZGVsZXRlJyk7XG4gIHJldHVybiB0aGlzLnJlZ2lzdHJ5LmRlbGV0ZShrZXkpO1xufTtcblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmVnaXN0cnlXYXJuKHRoaXMsICdnZXQnKTtcbiAgcmV0dXJuIHRoaXMucmVnaXN0cnkuZ2V0KGtleSk7XG59O1xuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24gKGtleSkge1xuICByZWdpc3RyeVdhcm4odGhpcywgJ2hhcycpO1xuICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXMoa2V5KTtcbn07XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCBtb2R1bGUpIHtcbiAgcmVnaXN0cnlXYXJuKHRoaXMsICdzZXQnKTtcbiAgcmV0dXJuIHRoaXMucmVnaXN0cnkuc2V0KGtleSwgbW9kdWxlKTtcbn07XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5uZXdNb2R1bGUgPSBmdW5jdGlvbiAoYmluZGluZ3MpIHtcbiAgcmV0dXJuIG5ldyBNb2R1bGVOYW1lc3BhY2UoYmluZGluZ3MpO1xufTtcblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmlzTW9kdWxlID0gaXNNb2R1bGU7XG5cbi8vIGVuc3VyZSBTeXN0ZW0ucmVnaXN0ZXIgYW5kIFN5c3RlbS5yZWdpc3RlckR5bmFtaWMgZGVjYW5vbmljYWxpemVcblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLnJlZ2lzdGVyID0gZnVuY3Rpb24gKGtleSwgZGVwcywgZGVjbGFyZSkge1xuICBpZiAodHlwZW9mIGtleSA9PT0gJ3N0cmluZycpXG4gICAga2V5ID0gZGVjYW5vbmljYWxpemUuY2FsbCh0aGlzLCB0aGlzW0NPTkZJR10sIGtleSk7XG4gIHJldHVybiBSZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5yZWdpc3Rlci5jYWxsKHRoaXMsIGtleSwgZGVwcywgZGVjbGFyZSk7XG59O1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5yZWdpc3RlckR5bmFtaWMgPSBmdW5jdGlvbiAoa2V5LCBkZXBzLCBleGVjdXRpbmdSZXF1aXJlLCBleGVjdXRlKSB7XG4gIGlmICh0eXBlb2Yga2V5ID09PSAnc3RyaW5nJylcbiAgICBrZXkgPSBkZWNhbm9uaWNhbGl6ZS5jYWxsKHRoaXMsIHRoaXNbQ09ORklHXSwga2V5KTtcbiAgcmV0dXJuIFJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlLnJlZ2lzdGVyRHluYW1pYy5jYWxsKHRoaXMsIGtleSwgZGVwcywgZXhlY3V0aW5nUmVxdWlyZSwgZXhlY3V0ZSk7XG59O1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS52ZXJzaW9uID0gXCIwLjIwLjE5IERldlwiO1xuXG52YXIgU3lzdGVtID0gbmV3IFN5c3RlbUpTTG9hZGVyJDEoKTtcblxuLy8gb25seSBzZXQgdGhlIGdsb2JhbCBTeXN0ZW0gb24gdGhlIGdsb2JhbCBpbiBicm93c2Vyc1xuaWYgKGlzQnJvd3NlciB8fCBpc1dvcmtlcilcbiAgZW52R2xvYmFsLlN5c3RlbUpTID0gZW52R2xvYmFsLlN5c3RlbSA9IFN5c3RlbTtcblxuaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKVxuICBtb2R1bGUuZXhwb3J0cyA9IFN5c3RlbTtcblxufSgpKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN5c3RlbS5zcmMuanMubWFwXG4iLCIoZnVuY3Rpb24oc2VsZikge1xuICAndXNlIHN0cmljdCc7XG5cbiAgaWYgKHNlbGYuZmV0Y2gpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBzdXBwb3J0ID0ge1xuICAgIHNlYXJjaFBhcmFtczogJ1VSTFNlYXJjaFBhcmFtcycgaW4gc2VsZixcbiAgICBpdGVyYWJsZTogJ1N5bWJvbCcgaW4gc2VsZiAmJiAnaXRlcmF0b3InIGluIFN5bWJvbCxcbiAgICBibG9iOiAnRmlsZVJlYWRlcicgaW4gc2VsZiAmJiAnQmxvYicgaW4gc2VsZiAmJiAoZnVuY3Rpb24oKSB7XG4gICAgICB0cnkge1xuICAgICAgICBuZXcgQmxvYigpXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfSkoKSxcbiAgICBmb3JtRGF0YTogJ0Zvcm1EYXRhJyBpbiBzZWxmLFxuICAgIGFycmF5QnVmZmVyOiAnQXJyYXlCdWZmZXInIGluIHNlbGZcbiAgfVxuXG4gIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyKSB7XG4gICAgdmFyIHZpZXdDbGFzc2VzID0gW1xuICAgICAgJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgICAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgICAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICAgICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICAgICdbb2JqZWN0IFVpbnQzMkFycmF5XScsXG4gICAgICAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICAgICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nXG4gICAgXVxuXG4gICAgdmFyIGlzRGF0YVZpZXcgPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogJiYgRGF0YVZpZXcucHJvdG90eXBlLmlzUHJvdG90eXBlT2Yob2JqKVxuICAgIH1cblxuICAgIHZhciBpc0FycmF5QnVmZmVyVmlldyA9IEFycmF5QnVmZmVyLmlzVmlldyB8fCBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogJiYgdmlld0NsYXNzZXMuaW5kZXhPZihPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSkgPiAtMVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZU5hbWUobmFtZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIG5hbWUgPSBTdHJpbmcobmFtZSlcbiAgICB9XG4gICAgaWYgKC9bXmEtejAtOVxcLSMkJSYnKisuXFxeX2B8fl0vaS50ZXN0KG5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGNoYXJhY3RlciBpbiBoZWFkZXIgZmllbGQgbmFtZScpXG4gICAgfVxuICAgIHJldHVybiBuYW1lLnRvTG93ZXJDYXNlKClcbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZVZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHZhbHVlID0gU3RyaW5nKHZhbHVlKVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIC8vIEJ1aWxkIGEgZGVzdHJ1Y3RpdmUgaXRlcmF0b3IgZm9yIHRoZSB2YWx1ZSBsaXN0XG4gIGZ1bmN0aW9uIGl0ZXJhdG9yRm9yKGl0ZW1zKSB7XG4gICAgdmFyIGl0ZXJhdG9yID0ge1xuICAgICAgbmV4dDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGl0ZW1zLnNoaWZ0KClcbiAgICAgICAgcmV0dXJuIHtkb25lOiB2YWx1ZSA9PT0gdW5kZWZpbmVkLCB2YWx1ZTogdmFsdWV9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgICAgIGl0ZXJhdG9yW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGl0ZXJhdG9yXG4gIH1cblxuICBmdW5jdGlvbiBIZWFkZXJzKGhlYWRlcnMpIHtcbiAgICB0aGlzLm1hcCA9IHt9XG5cbiAgICBpZiAoaGVhZGVycyBpbnN0YW5jZW9mIEhlYWRlcnMpIHtcbiAgICAgIGhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgICB0aGlzLmFwcGVuZChuYW1lLCB2YWx1ZSlcbiAgICAgIH0sIHRoaXMpXG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGhlYWRlcnMpKSB7XG4gICAgICBoZWFkZXJzLmZvckVhY2goZnVuY3Rpb24oaGVhZGVyKSB7XG4gICAgICAgIHRoaXMuYXBwZW5kKGhlYWRlclswXSwgaGVhZGVyWzFdKVxuICAgICAgfSwgdGhpcylcbiAgICB9IGVsc2UgaWYgKGhlYWRlcnMpIHtcbiAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGhlYWRlcnMpLmZvckVhY2goZnVuY3Rpb24obmFtZSkge1xuICAgICAgICB0aGlzLmFwcGVuZChuYW1lLCBoZWFkZXJzW25hbWVdKVxuICAgICAgfSwgdGhpcylcbiAgICB9XG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5hcHBlbmQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gICAgdmFsdWUgPSBub3JtYWxpemVWYWx1ZSh2YWx1ZSlcbiAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLm1hcFtuYW1lXVxuICAgIHRoaXMubWFwW25hbWVdID0gb2xkVmFsdWUgPyBvbGRWYWx1ZSsnLCcrdmFsdWUgOiB2YWx1ZVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGVbJ2RlbGV0ZSddID0gZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24obmFtZSkge1xuICAgIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gICAgcmV0dXJuIHRoaXMuaGFzKG5hbWUpID8gdGhpcy5tYXBbbmFtZV0gOiBudWxsXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmhhc093blByb3BlcnR5KG5vcm1hbGl6ZU5hbWUobmFtZSkpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIHRoaXMubWFwW25vcm1hbGl6ZU5hbWUobmFtZSldID0gbm9ybWFsaXplVmFsdWUodmFsdWUpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMubWFwKSB7XG4gICAgICBpZiAodGhpcy5tYXAuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgY2FsbGJhY2suY2FsbCh0aGlzQXJnLCB0aGlzLm1hcFtuYW1lXSwgbmFtZSwgdGhpcylcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS5rZXlzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGl0ZW1zID0gW11cbiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHsgaXRlbXMucHVzaChuYW1lKSB9KVxuICAgIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlLnZhbHVlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7IGl0ZW1zLnB1c2godmFsdWUpIH0pXG4gICAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZW50cmllcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7IGl0ZW1zLnB1c2goW25hbWUsIHZhbHVlXSkgfSlcbiAgICByZXR1cm4gaXRlcmF0b3JGb3IoaXRlbXMpXG4gIH1cblxuICBpZiAoc3VwcG9ydC5pdGVyYWJsZSkge1xuICAgIEhlYWRlcnMucHJvdG90eXBlW1N5bWJvbC5pdGVyYXRvcl0gPSBIZWFkZXJzLnByb3RvdHlwZS5lbnRyaWVzXG4gIH1cblxuICBmdW5jdGlvbiBjb25zdW1lZChib2R5KSB7XG4gICAgaWYgKGJvZHkuYm9keVVzZWQpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKCdBbHJlYWR5IHJlYWQnKSlcbiAgICB9XG4gICAgYm9keS5ib2R5VXNlZCA9IHRydWVcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlc29sdmUocmVhZGVyLnJlc3VsdClcbiAgICAgIH1cbiAgICAgIHJlYWRlci5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChyZWFkZXIuZXJyb3IpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRCbG9iQXNBcnJheUJ1ZmZlcihibG9iKSB7XG4gICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgICB2YXIgcHJvbWlzZSA9IGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpXG4gICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGJsb2IpXG4gICAgcmV0dXJuIHByb21pc2VcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRCbG9iQXNUZXh0KGJsb2IpIHtcbiAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKVxuICAgIHZhciBwcm9taXNlID0gZmlsZVJlYWRlclJlYWR5KHJlYWRlcilcbiAgICByZWFkZXIucmVhZEFzVGV4dChibG9iKVxuICAgIHJldHVybiBwcm9taXNlXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQXJyYXlCdWZmZXJBc1RleHQoYnVmKSB7XG4gICAgdmFyIHZpZXcgPSBuZXcgVWludDhBcnJheShidWYpXG4gICAgdmFyIGNoYXJzID0gbmV3IEFycmF5KHZpZXcubGVuZ3RoKVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2aWV3Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjaGFyc1tpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUodmlld1tpXSlcbiAgICB9XG4gICAgcmV0dXJuIGNoYXJzLmpvaW4oJycpXG4gIH1cblxuICBmdW5jdGlvbiBidWZmZXJDbG9uZShidWYpIHtcbiAgICBpZiAoYnVmLnNsaWNlKSB7XG4gICAgICByZXR1cm4gYnVmLnNsaWNlKDApXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmLmJ5dGVMZW5ndGgpXG4gICAgICB2aWV3LnNldChuZXcgVWludDhBcnJheShidWYpKVxuICAgICAgcmV0dXJuIHZpZXcuYnVmZmVyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gQm9keSgpIHtcbiAgICB0aGlzLmJvZHlVc2VkID0gZmFsc2VcblxuICAgIHRoaXMuX2luaXRCb2R5ID0gZnVuY3Rpb24oYm9keSkge1xuICAgICAgdGhpcy5fYm9keUluaXQgPSBib2R5XG4gICAgICBpZiAoIWJvZHkpIHtcbiAgICAgICAgdGhpcy5fYm9keVRleHQgPSAnJ1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5fYm9keVRleHQgPSBib2R5XG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYmxvYiAmJiBCbG9iLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlCbG9iID0gYm9keVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmZvcm1EYXRhICYmIEZvcm1EYXRhLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlGb3JtRGF0YSA9IGJvZHlcbiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5zZWFyY2hQYXJhbXMgJiYgVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keS50b1N0cmluZygpXG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYXJyYXlCdWZmZXIgJiYgc3VwcG9ydC5ibG9iICYmIGlzRGF0YVZpZXcoYm9keSkpIHtcbiAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyID0gYnVmZmVyQ2xvbmUoYm9keS5idWZmZXIpXG4gICAgICAgIC8vIElFIDEwLTExIGNhbid0IGhhbmRsZSBhIERhdGFWaWV3IGJvZHkuXG4gICAgICAgIHRoaXMuX2JvZHlJbml0ID0gbmV3IEJsb2IoW3RoaXMuX2JvZHlBcnJheUJ1ZmZlcl0pXG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYXJyYXlCdWZmZXIgJiYgKEFycmF5QnVmZmVyLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpIHx8IGlzQXJyYXlCdWZmZXJWaWV3KGJvZHkpKSkge1xuICAgICAgICB0aGlzLl9ib2R5QXJyYXlCdWZmZXIgPSBidWZmZXJDbG9uZShib2R5KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnN1cHBvcnRlZCBCb2R5SW5pdCB0eXBlJylcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLmhlYWRlcnMuZ2V0KCdjb250ZW50LXR5cGUnKSkge1xuICAgICAgICBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ3RleHQvcGxhaW47Y2hhcnNldD1VVEYtOCcpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUJsb2IgJiYgdGhpcy5fYm9keUJsb2IudHlwZSkge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsIHRoaXMuX2JvZHlCbG9iLnR5cGUpXG4gICAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5zZWFyY2hQYXJhbXMgJiYgVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDtjaGFyc2V0PVVURi04JylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdXBwb3J0LmJsb2IpIHtcbiAgICAgIHRoaXMuYmxvYiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmVqZWN0ZWQgPSBjb25zdW1lZCh0aGlzKVxuICAgICAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9ib2R5QmxvYikge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUJsb2IpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgQmxvYihbdGhpcy5fYm9keUFycmF5QnVmZmVyXSkpXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcmVhZCBGb3JtRGF0YSBib2R5IGFzIGJsb2InKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEJsb2IoW3RoaXMuX2JvZHlUZXh0XSkpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5hcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnN1bWVkKHRoaXMpIHx8IFByb21pc2UucmVzb2x2ZSh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYmxvYigpLnRoZW4ocmVhZEJsb2JBc0FycmF5QnVmZmVyKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVqZWN0ZWQgPSBjb25zdW1lZCh0aGlzKVxuICAgICAgaWYgKHJlamVjdGVkKSB7XG4gICAgICAgIHJldHVybiByZWplY3RlZFxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fYm9keUJsb2IpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRCbG9iQXNUZXh0KHRoaXMuX2JvZHlCbG9iKVxuICAgICAgfSBlbHNlIGlmICh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZWFkQXJyYXlCdWZmZXJBc1RleHQodGhpcy5fYm9keUFycmF5QnVmZmVyKSlcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgRm9ybURhdGEgYm9keSBhcyB0ZXh0JylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keVRleHQpXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN1cHBvcnQuZm9ybURhdGEpIHtcbiAgICAgIHRoaXMuZm9ybURhdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oZGVjb2RlKVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuanNvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oSlNPTi5wYXJzZSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gSFRUUCBtZXRob2RzIHdob3NlIGNhcGl0YWxpemF0aW9uIHNob3VsZCBiZSBub3JtYWxpemVkXG4gIHZhciBtZXRob2RzID0gWydERUxFVEUnLCAnR0VUJywgJ0hFQUQnLCAnT1BUSU9OUycsICdQT1NUJywgJ1BVVCddXG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplTWV0aG9kKG1ldGhvZCkge1xuICAgIHZhciB1cGNhc2VkID0gbWV0aG9kLnRvVXBwZXJDYXNlKClcbiAgICByZXR1cm4gKG1ldGhvZHMuaW5kZXhPZih1cGNhc2VkKSA+IC0xKSA/IHVwY2FzZWQgOiBtZXRob2RcbiAgfVxuXG4gIGZ1bmN0aW9uIFJlcXVlc3QoaW5wdXQsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgIHZhciBib2R5ID0gb3B0aW9ucy5ib2R5XG5cbiAgICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBSZXF1ZXN0KSB7XG4gICAgICBpZiAoaW5wdXQuYm9keVVzZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQWxyZWFkeSByZWFkJylcbiAgICAgIH1cbiAgICAgIHRoaXMudXJsID0gaW5wdXQudXJsXG4gICAgICB0aGlzLmNyZWRlbnRpYWxzID0gaW5wdXQuY3JlZGVudGlhbHNcbiAgICAgIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyBIZWFkZXJzKGlucHV0LmhlYWRlcnMpXG4gICAgICB9XG4gICAgICB0aGlzLm1ldGhvZCA9IGlucHV0Lm1ldGhvZFxuICAgICAgdGhpcy5tb2RlID0gaW5wdXQubW9kZVxuICAgICAgaWYgKCFib2R5ICYmIGlucHV0Ll9ib2R5SW5pdCAhPSBudWxsKSB7XG4gICAgICAgIGJvZHkgPSBpbnB1dC5fYm9keUluaXRcbiAgICAgICAgaW5wdXQuYm9keVVzZWQgPSB0cnVlXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudXJsID0gU3RyaW5nKGlucHV0KVxuICAgIH1cblxuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBvcHRpb25zLmNyZWRlbnRpYWxzIHx8IHRoaXMuY3JlZGVudGlhbHMgfHwgJ29taXQnXG4gICAgaWYgKG9wdGlvbnMuaGVhZGVycyB8fCAhdGhpcy5oZWFkZXJzKSB7XG4gICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhvcHRpb25zLmhlYWRlcnMpXG4gICAgfVxuICAgIHRoaXMubWV0aG9kID0gbm9ybWFsaXplTWV0aG9kKG9wdGlvbnMubWV0aG9kIHx8IHRoaXMubWV0aG9kIHx8ICdHRVQnKVxuICAgIHRoaXMubW9kZSA9IG9wdGlvbnMubW9kZSB8fCB0aGlzLm1vZGUgfHwgbnVsbFxuICAgIHRoaXMucmVmZXJyZXIgPSBudWxsXG5cbiAgICBpZiAoKHRoaXMubWV0aG9kID09PSAnR0VUJyB8fCB0aGlzLm1ldGhvZCA9PT0gJ0hFQUQnKSAmJiBib2R5KSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb2R5IG5vdCBhbGxvd2VkIGZvciBHRVQgb3IgSEVBRCByZXF1ZXN0cycpXG4gICAgfVxuICAgIHRoaXMuX2luaXRCb2R5KGJvZHkpXG4gIH1cblxuICBSZXF1ZXN0LnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgUmVxdWVzdCh0aGlzLCB7IGJvZHk6IHRoaXMuX2JvZHlJbml0IH0pXG4gIH1cblxuICBmdW5jdGlvbiBkZWNvZGUoYm9keSkge1xuICAgIHZhciBmb3JtID0gbmV3IEZvcm1EYXRhKClcbiAgICBib2R5LnRyaW0oKS5zcGxpdCgnJicpLmZvckVhY2goZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAgIGlmIChieXRlcykge1xuICAgICAgICB2YXIgc3BsaXQgPSBieXRlcy5zcGxpdCgnPScpXG4gICAgICAgIHZhciBuYW1lID0gc3BsaXQuc2hpZnQoKS5yZXBsYWNlKC9cXCsvZywgJyAnKVxuICAgICAgICB2YXIgdmFsdWUgPSBzcGxpdC5qb2luKCc9JykucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgZm9ybS5hcHBlbmQoZGVjb2RlVVJJQ29tcG9uZW50KG5hbWUpLCBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIGZvcm1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlSGVhZGVycyhyYXdIZWFkZXJzKSB7XG4gICAgdmFyIGhlYWRlcnMgPSBuZXcgSGVhZGVycygpXG4gICAgLy8gUmVwbGFjZSBpbnN0YW5jZXMgb2YgXFxyXFxuIGFuZCBcXG4gZm9sbG93ZWQgYnkgYXQgbGVhc3Qgb25lIHNwYWNlIG9yIGhvcml6b250YWwgdGFiIHdpdGggYSBzcGFjZVxuICAgIC8vIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3MjMwI3NlY3Rpb24tMy4yXG4gICAgdmFyIHByZVByb2Nlc3NlZEhlYWRlcnMgPSByYXdIZWFkZXJzLnJlcGxhY2UoL1xccj9cXG5bXFx0IF0rL2csICcgJylcbiAgICBwcmVQcm9jZXNzZWRIZWFkZXJzLnNwbGl0KC9cXHI/XFxuLykuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICB2YXIgcGFydHMgPSBsaW5lLnNwbGl0KCc6JylcbiAgICAgIHZhciBrZXkgPSBwYXJ0cy5zaGlmdCgpLnRyaW0oKVxuICAgICAgaWYgKGtleSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBwYXJ0cy5qb2luKCc6JykudHJpbSgpXG4gICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gaGVhZGVyc1xuICB9XG5cbiAgQm9keS5jYWxsKFJlcXVlc3QucHJvdG90eXBlKVxuXG4gIGZ1bmN0aW9uIFJlc3BvbnNlKGJvZHlJbml0LCBvcHRpb25zKSB7XG4gICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICBvcHRpb25zID0ge31cbiAgICB9XG5cbiAgICB0aGlzLnR5cGUgPSAnZGVmYXVsdCdcbiAgICB0aGlzLnN0YXR1cyA9IG9wdGlvbnMuc3RhdHVzID09PSB1bmRlZmluZWQgPyAyMDAgOiBvcHRpb25zLnN0YXR1c1xuICAgIHRoaXMub2sgPSB0aGlzLnN0YXR1cyA+PSAyMDAgJiYgdGhpcy5zdGF0dXMgPCAzMDBcbiAgICB0aGlzLnN0YXR1c1RleHQgPSAnc3RhdHVzVGV4dCcgaW4gb3B0aW9ucyA/IG9wdGlvbnMuc3RhdHVzVGV4dCA6ICdPSydcbiAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhvcHRpb25zLmhlYWRlcnMpXG4gICAgdGhpcy51cmwgPSBvcHRpb25zLnVybCB8fCAnJ1xuICAgIHRoaXMuX2luaXRCb2R5KGJvZHlJbml0KVxuICB9XG5cbiAgQm9keS5jYWxsKFJlc3BvbnNlLnByb3RvdHlwZSlcblxuICBSZXNwb25zZS5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKHRoaXMuX2JvZHlJbml0LCB7XG4gICAgICBzdGF0dXM6IHRoaXMuc3RhdHVzLFxuICAgICAgc3RhdHVzVGV4dDogdGhpcy5zdGF0dXNUZXh0LFxuICAgICAgaGVhZGVyczogbmV3IEhlYWRlcnModGhpcy5oZWFkZXJzKSxcbiAgICAgIHVybDogdGhpcy51cmxcbiAgICB9KVxuICB9XG5cbiAgUmVzcG9uc2UuZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwge3N0YXR1czogMCwgc3RhdHVzVGV4dDogJyd9KVxuICAgIHJlc3BvbnNlLnR5cGUgPSAnZXJyb3InXG4gICAgcmV0dXJuIHJlc3BvbnNlXG4gIH1cblxuICB2YXIgcmVkaXJlY3RTdGF0dXNlcyA9IFszMDEsIDMwMiwgMzAzLCAzMDcsIDMwOF1cblxuICBSZXNwb25zZS5yZWRpcmVjdCA9IGZ1bmN0aW9uKHVybCwgc3RhdHVzKSB7XG4gICAgaWYgKHJlZGlyZWN0U3RhdHVzZXMuaW5kZXhPZihzdGF0dXMpID09PSAtMSkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0ludmFsaWQgc3RhdHVzIGNvZGUnKVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUmVzcG9uc2UobnVsbCwge3N0YXR1czogc3RhdHVzLCBoZWFkZXJzOiB7bG9jYXRpb246IHVybH19KVxuICB9XG5cbiAgc2VsZi5IZWFkZXJzID0gSGVhZGVyc1xuICBzZWxmLlJlcXVlc3QgPSBSZXF1ZXN0XG4gIHNlbGYuUmVzcG9uc2UgPSBSZXNwb25zZVxuXG4gIHNlbGYuZmV0Y2ggPSBmdW5jdGlvbihpbnB1dCwgaW5pdCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHZhciByZXF1ZXN0ID0gbmV3IFJlcXVlc3QoaW5wdXQsIGluaXQpXG4gICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KClcblxuICAgICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgICAgICBzdGF0dXM6IHhoci5zdGF0dXMsXG4gICAgICAgICAgc3RhdHVzVGV4dDogeGhyLnN0YXR1c1RleHQsXG4gICAgICAgICAgaGVhZGVyczogcGFyc2VIZWFkZXJzKHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSB8fCAnJylcbiAgICAgICAgfVxuICAgICAgICBvcHRpb25zLnVybCA9ICdyZXNwb25zZVVSTCcgaW4geGhyID8geGhyLnJlc3BvbnNlVVJMIDogb3B0aW9ucy5oZWFkZXJzLmdldCgnWC1SZXF1ZXN0LVVSTCcpXG4gICAgICAgIHZhciBib2R5ID0gJ3Jlc3BvbnNlJyBpbiB4aHIgPyB4aHIucmVzcG9uc2UgOiB4aHIucmVzcG9uc2VUZXh0XG4gICAgICAgIHJlc29sdmUobmV3IFJlc3BvbnNlKGJvZHksIG9wdGlvbnMpKVxuICAgICAgfVxuXG4gICAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QobmV3IFR5cGVFcnJvcignTmV0d29yayByZXF1ZXN0IGZhaWxlZCcpKVxuICAgICAgfVxuXG4gICAgICB4aHIub250aW1lb3V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChuZXcgVHlwZUVycm9yKCdOZXR3b3JrIHJlcXVlc3QgZmFpbGVkJykpXG4gICAgICB9XG5cbiAgICAgIHhoci5vcGVuKHJlcXVlc3QubWV0aG9kLCByZXF1ZXN0LnVybCwgdHJ1ZSlcblxuICAgICAgaWYgKHJlcXVlc3QuY3JlZGVudGlhbHMgPT09ICdpbmNsdWRlJykge1xuICAgICAgICB4aHIud2l0aENyZWRlbnRpYWxzID0gdHJ1ZVxuICAgICAgfSBlbHNlIGlmIChyZXF1ZXN0LmNyZWRlbnRpYWxzID09PSAnb21pdCcpIHtcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IGZhbHNlXG4gICAgICB9XG5cbiAgICAgIGlmICgncmVzcG9uc2VUeXBlJyBpbiB4aHIgJiYgc3VwcG9ydC5ibG9iKSB7XG4gICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYmxvYidcbiAgICAgIH1cblxuICAgICAgcmVxdWVzdC5oZWFkZXJzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIobmFtZSwgdmFsdWUpXG4gICAgICB9KVxuXG4gICAgICB4aHIuc2VuZCh0eXBlb2YgcmVxdWVzdC5fYm9keUluaXQgPT09ICd1bmRlZmluZWQnID8gbnVsbCA6IHJlcXVlc3QuX2JvZHlJbml0KVxuICAgIH0pXG4gIH1cbiAgc2VsZi5mZXRjaC5wb2x5ZmlsbCA9IHRydWVcbn0pKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/IHNlbGYgOiB0aGlzKTtcbiIsIihmdW5jdGlvbigpeyd1c2Ugc3RyaWN0Jzt2YXIgaz10aGlzO1xuZnVuY3Rpb24gYWEoYSl7dmFyIGI9dHlwZW9mIGE7aWYoXCJvYmplY3RcIj09YilpZihhKXtpZihhIGluc3RhbmNlb2YgQXJyYXkpcmV0dXJuXCJhcnJheVwiO2lmKGEgaW5zdGFuY2VvZiBPYmplY3QpcmV0dXJuIGI7dmFyIGM9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGEpO2lmKFwiW29iamVjdCBXaW5kb3ddXCI9PWMpcmV0dXJuXCJvYmplY3RcIjtpZihcIltvYmplY3QgQXJyYXldXCI9PWN8fFwibnVtYmVyXCI9PXR5cGVvZiBhLmxlbmd0aCYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEuc3BsaWNlJiZcInVuZGVmaW5lZFwiIT10eXBlb2YgYS5wcm9wZXJ0eUlzRW51bWVyYWJsZSYmIWEucHJvcGVydHlJc0VudW1lcmFibGUoXCJzcGxpY2VcIikpcmV0dXJuXCJhcnJheVwiO2lmKFwiW29iamVjdCBGdW5jdGlvbl1cIj09Y3x8XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEuY2FsbCYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEucHJvcGVydHlJc0VudW1lcmFibGUmJiFhLnByb3BlcnR5SXNFbnVtZXJhYmxlKFwiY2FsbFwiKSlyZXR1cm5cImZ1bmN0aW9uXCJ9ZWxzZSByZXR1cm5cIm51bGxcIjtlbHNlIGlmKFwiZnVuY3Rpb25cIj09XG5iJiZcInVuZGVmaW5lZFwiPT10eXBlb2YgYS5jYWxsKXJldHVyblwib2JqZWN0XCI7cmV0dXJuIGJ9ZnVuY3Rpb24gbChhKXtyZXR1cm5cInN0cmluZ1wiPT10eXBlb2YgYX1mdW5jdGlvbiBiYShhLGIsYyl7cmV0dXJuIGEuY2FsbC5hcHBseShhLmJpbmQsYXJndW1lbnRzKX1mdW5jdGlvbiBjYShhLGIsYyl7aWYoIWEpdGhyb3cgRXJyb3IoKTtpZigyPGFyZ3VtZW50cy5sZW5ndGgpe3ZhciBkPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywyKTtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgYz1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO0FycmF5LnByb3RvdHlwZS51bnNoaWZ0LmFwcGx5KGMsZCk7cmV0dXJuIGEuYXBwbHkoYixjKX19cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGEuYXBwbHkoYixhcmd1bWVudHMpfX1cbmZ1bmN0aW9uIGRhKGEsYixjKXtkYT1GdW5jdGlvbi5wcm90b3R5cGUuYmluZCYmLTEhPUZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kLnRvU3RyaW5nKCkuaW5kZXhPZihcIm5hdGl2ZSBjb2RlXCIpP2JhOmNhO3JldHVybiBkYS5hcHBseShudWxsLGFyZ3VtZW50cyl9ZnVuY3Rpb24gZWEoYSxiKXt2YXIgYz1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsMSk7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIGI9Yy5zbGljZSgpO2IucHVzaC5hcHBseShiLGFyZ3VtZW50cyk7cmV0dXJuIGEuYXBwbHkodGhpcyxiKX19XG5mdW5jdGlvbiBtKGEpe3ZhciBiPW47ZnVuY3Rpb24gYygpe31jLnByb3RvdHlwZT1iLnByb3RvdHlwZTthLkc9Yi5wcm90b3R5cGU7YS5wcm90b3R5cGU9bmV3IGM7YS5wcm90b3R5cGUuY29uc3RydWN0b3I9YTthLkY9ZnVuY3Rpb24oYSxjLGYpe2Zvcih2YXIgZz1BcnJheShhcmd1bWVudHMubGVuZ3RoLTIpLGg9MjtoPGFyZ3VtZW50cy5sZW5ndGg7aCsrKWdbaC0yXT1hcmd1bWVudHNbaF07cmV0dXJuIGIucHJvdG90eXBlW2NdLmFwcGx5KGEsZyl9fTsvKlxuXG4gVGhlIE1JVCBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMDcgQ3lib3p1IExhYnMsIEluYy5cbiBDb3B5cmlnaHQgKGMpIDIwMTIgR29vZ2xlIEluYy5cblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4gc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuXG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4gSU4gVEhFIFNPRlRXQVJFLlxuKi9cbnZhciBmYT1TdHJpbmcucHJvdG90eXBlLnRyaW0/ZnVuY3Rpb24oYSl7cmV0dXJuIGEudHJpbSgpfTpmdW5jdGlvbihhKXtyZXR1cm4gYS5yZXBsYWNlKC9eW1xcc1xceGEwXSt8W1xcc1xceGEwXSskL2csXCJcIil9O2Z1bmN0aW9uIHEoYSxiKXtyZXR1cm4tMSE9YS5pbmRleE9mKGIpfWZ1bmN0aW9uIGdhKGEsYil7cmV0dXJuIGE8Yj8tMTphPmI/MTowfTt2YXIgaGE9QXJyYXkucHJvdG90eXBlLmluZGV4T2Y/ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2M9bnVsbD09Yz8wOjA+Yz9NYXRoLm1heCgwLGEubGVuZ3RoK2MpOmM7aWYobChhKSlyZXR1cm4gbChiKSYmMT09Yi5sZW5ndGg/YS5pbmRleE9mKGIsYyk6LTE7Zm9yKDtjPGEubGVuZ3RoO2MrKylpZihjIGluIGEmJmFbY109PT1iKXJldHVybiBjO3JldHVybi0xfSxyPUFycmF5LnByb3RvdHlwZS5mb3JFYWNoP2Z1bmN0aW9uKGEsYixjKXtBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD1hLmxlbmd0aCxlPWwoYSk/YS5zcGxpdChcIlwiKTphLGY9MDtmPGQ7ZisrKWYgaW4gZSYmYi5jYWxsKGMsZVtmXSxmLGEpfSxpYT1BcnJheS5wcm90b3R5cGUuZmlsdGVyP2Z1bmN0aW9uKGEsYixjKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmZpbHRlci5jYWxsKGEsXG5iLGMpfTpmdW5jdGlvbihhLGIsYyl7Zm9yKHZhciBkPWEubGVuZ3RoLGU9W10sZj0wLGc9bChhKT9hLnNwbGl0KFwiXCIpOmEsaD0wO2g8ZDtoKyspaWYoaCBpbiBnKXt2YXIgcD1nW2hdO2IuY2FsbChjLHAsaCxhKSYmKGVbZisrXT1wKX1yZXR1cm4gZX0sdD1BcnJheS5wcm90b3R5cGUucmVkdWNlP2Z1bmN0aW9uKGEsYixjLGQpe2QmJihiPWRhKGIsZCkpO3JldHVybiBBcnJheS5wcm90b3R5cGUucmVkdWNlLmNhbGwoYSxiLGMpfTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgZT1jO3IoYSxmdW5jdGlvbihjLGcpe2U9Yi5jYWxsKGQsZSxjLGcsYSl9KTtyZXR1cm4gZX0samE9QXJyYXkucHJvdG90eXBlLnNvbWU/ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBBcnJheS5wcm90b3R5cGUuc29tZS5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD1hLmxlbmd0aCxlPWwoYSk/YS5zcGxpdChcIlwiKTphLGY9MDtmPGQ7ZisrKWlmKGYgaW4gZSYmYi5jYWxsKGMsZVtmXSxmLGEpKXJldHVybiEwO1xucmV0dXJuITF9O2Z1bmN0aW9uIGthKGEsYil7dmFyIGM7YTp7Yz1hLmxlbmd0aDtmb3IodmFyIGQ9bChhKT9hLnNwbGl0KFwiXCIpOmEsZT0wO2U8YztlKyspaWYoZSBpbiBkJiZiLmNhbGwodm9pZCAwLGRbZV0sZSxhKSl7Yz1lO2JyZWFrIGF9Yz0tMX1yZXR1cm4gMD5jP251bGw6bChhKT9hLmNoYXJBdChjKTphW2NdfWZ1bmN0aW9uIGxhKGEpe3JldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KEFycmF5LnByb3RvdHlwZSxhcmd1bWVudHMpfWZ1bmN0aW9uIG1hKGEsYixjKXtyZXR1cm4gMj49YXJndW1lbnRzLmxlbmd0aD9BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhLGIpOkFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGEsYixjKX07dmFyIHU7YTp7dmFyIG5hPWsubmF2aWdhdG9yO2lmKG5hKXt2YXIgb2E9bmEudXNlckFnZW50O2lmKG9hKXt1PW9hO2JyZWFrIGF9fXU9XCJcIn07dmFyIHBhPXEodSxcIk9wZXJhXCIpfHxxKHUsXCJPUFJcIiksdj1xKHUsXCJUcmlkZW50XCIpfHxxKHUsXCJNU0lFXCIpLHFhPXEodSxcIkVkZ2VcIikscmE9cSh1LFwiR2Vja29cIikmJiEocSh1LnRvTG93ZXJDYXNlKCksXCJ3ZWJraXRcIikmJiFxKHUsXCJFZGdlXCIpKSYmIShxKHUsXCJUcmlkZW50XCIpfHxxKHUsXCJNU0lFXCIpKSYmIXEodSxcIkVkZ2VcIiksc2E9cSh1LnRvTG93ZXJDYXNlKCksXCJ3ZWJraXRcIikmJiFxKHUsXCJFZGdlXCIpO2Z1bmN0aW9uIHRhKCl7dmFyIGE9ay5kb2N1bWVudDtyZXR1cm4gYT9hLmRvY3VtZW50TW9kZTp2b2lkIDB9dmFyIHVhO1xuYTp7dmFyIHZhPVwiXCIsd2E9ZnVuY3Rpb24oKXt2YXIgYT11O2lmKHJhKXJldHVybi9ydlxcOihbXlxcKTtdKykoXFwpfDspLy5leGVjKGEpO2lmKHFhKXJldHVybi9FZGdlXFwvKFtcXGRcXC5dKykvLmV4ZWMoYSk7aWYodilyZXR1cm4vXFxiKD86TVNJRXxydilbOiBdKFteXFwpO10rKShcXCl8OykvLmV4ZWMoYSk7aWYoc2EpcmV0dXJuL1dlYktpdFxcLyhcXFMrKS8uZXhlYyhhKTtpZihwYSlyZXR1cm4vKD86VmVyc2lvbilbIFxcL10/KFxcUyspLy5leGVjKGEpfSgpO3dhJiYodmE9d2E/d2FbMV06XCJcIik7aWYodil7dmFyIHhhPXRhKCk7aWYobnVsbCE9eGEmJnhhPnBhcnNlRmxvYXQodmEpKXt1YT1TdHJpbmcoeGEpO2JyZWFrIGF9fXVhPXZhfXZhciB5YT17fTtcbmZ1bmN0aW9uIHphKGEpe2lmKCF5YVthXSl7Zm9yKHZhciBiPTAsYz1mYShTdHJpbmcodWEpKS5zcGxpdChcIi5cIiksZD1mYShTdHJpbmcoYSkpLnNwbGl0KFwiLlwiKSxlPU1hdGgubWF4KGMubGVuZ3RoLGQubGVuZ3RoKSxmPTA7MD09YiYmZjxlO2YrKyl7dmFyIGc9Y1tmXXx8XCJcIixoPWRbZl18fFwiXCIscD0vKFxcZCopKFxcRCopL2cseT0vKFxcZCopKFxcRCopL2c7ZG97dmFyIEQ9cC5leGVjKGcpfHxbXCJcIixcIlwiLFwiXCJdLFg9eS5leGVjKGgpfHxbXCJcIixcIlwiLFwiXCJdO2lmKDA9PURbMF0ubGVuZ3RoJiYwPT1YWzBdLmxlbmd0aClicmVhaztiPWdhKDA9PURbMV0ubGVuZ3RoPzA6cGFyc2VJbnQoRFsxXSwxMCksMD09WFsxXS5sZW5ndGg/MDpwYXJzZUludChYWzFdLDEwKSl8fGdhKDA9PURbMl0ubGVuZ3RoLDA9PVhbMl0ubGVuZ3RoKXx8Z2EoRFsyXSxYWzJdKX13aGlsZSgwPT1iKX15YVthXT0wPD1ifX1cbnZhciBBYT1rLmRvY3VtZW50LEJhPUFhJiZ2P3RhKCl8fChcIkNTUzFDb21wYXRcIj09QWEuY29tcGF0TW9kZT9wYXJzZUludCh1YSwxMCk6NSk6dm9pZCAwO3ZhciB3PXYmJiEoOTw9TnVtYmVyKEJhKSksQ2E9diYmISg4PD1OdW1iZXIoQmEpKTtmdW5jdGlvbiB4KGEsYixjLGQpe3RoaXMuYT1hO3RoaXMubm9kZU5hbWU9Yzt0aGlzLm5vZGVWYWx1ZT1kO3RoaXMubm9kZVR5cGU9Mjt0aGlzLnBhcmVudE5vZGU9dGhpcy5vd25lckVsZW1lbnQ9Yn1mdW5jdGlvbiBEYShhLGIpe3ZhciBjPUNhJiZcImhyZWZcIj09Yi5ub2RlTmFtZT9hLmdldEF0dHJpYnV0ZShiLm5vZGVOYW1lLDIpOmIubm9kZVZhbHVlO3JldHVybiBuZXcgeChiLGEsYi5ub2RlTmFtZSxjKX07ZnVuY3Rpb24geihhKXt2YXIgYj1udWxsLGM9YS5ub2RlVHlwZTsxPT1jJiYoYj1hLnRleHRDb250ZW50LGI9dm9pZCAwPT1ifHxudWxsPT1iP2EuaW5uZXJUZXh0OmIsYj12b2lkIDA9PWJ8fG51bGw9PWI/XCJcIjpiKTtpZihcInN0cmluZ1wiIT10eXBlb2YgYilpZih3JiZcInRpdGxlXCI9PWEubm9kZU5hbWUudG9Mb3dlckNhc2UoKSYmMT09YyliPWEudGV4dDtlbHNlIGlmKDk9PWN8fDE9PWMpe2E9OT09Yz9hLmRvY3VtZW50RWxlbWVudDphLmZpcnN0Q2hpbGQ7Zm9yKHZhciBjPTAsZD1bXSxiPVwiXCI7YTspe2RvIDEhPWEubm9kZVR5cGUmJihiKz1hLm5vZGVWYWx1ZSksdyYmXCJ0aXRsZVwiPT1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkmJihiKz1hLnRleHQpLGRbYysrXT1hO3doaWxlKGE9YS5maXJzdENoaWxkKTtmb3IoO2MmJiEoYT1kWy0tY10ubmV4dFNpYmxpbmcpOyk7fX1lbHNlIGI9YS5ub2RlVmFsdWU7cmV0dXJuXCJcIitifVxuZnVuY3Rpb24gQShhLGIsYyl7aWYobnVsbD09PWIpcmV0dXJuITA7dHJ5e2lmKCFhLmdldEF0dHJpYnV0ZSlyZXR1cm4hMX1jYXRjaChkKXtyZXR1cm4hMX1DYSYmXCJjbGFzc1wiPT1iJiYoYj1cImNsYXNzTmFtZVwiKTtyZXR1cm4gbnVsbD09Yz8hIWEuZ2V0QXR0cmlidXRlKGIpOmEuZ2V0QXR0cmlidXRlKGIsMik9PWN9ZnVuY3Rpb24gQihhLGIsYyxkLGUpe3JldHVybih3P0VhOkZhKS5jYWxsKG51bGwsYSxiLGwoYyk/YzpudWxsLGwoZCk/ZDpudWxsLGV8fG5ldyBDKX1cbmZ1bmN0aW9uIEVhKGEsYixjLGQsZSl7aWYoYSBpbnN0YW5jZW9mIEV8fDg9PWEuYnx8YyYmbnVsbD09PWEuYil7dmFyIGY9Yi5hbGw7aWYoIWYpcmV0dXJuIGU7YT1HYShhKTtpZihcIipcIiE9YSYmKGY9Yi5nZXRFbGVtZW50c0J5VGFnTmFtZShhKSwhZikpcmV0dXJuIGU7aWYoYyl7Zm9yKHZhciBnPVtdLGg9MDtiPWZbaCsrXTspQShiLGMsZCkmJmcucHVzaChiKTtmPWd9Zm9yKGg9MDtiPWZbaCsrXTspXCIqXCI9PWEmJlwiIVwiPT1iLnRhZ05hbWV8fEYoZSxiKTtyZXR1cm4gZX1IYShhLGIsYyxkLGUpO3JldHVybiBlfVxuZnVuY3Rpb24gRmEoYSxiLGMsZCxlKXtiLmdldEVsZW1lbnRzQnlOYW1lJiZkJiZcIm5hbWVcIj09YyYmIXY/KGI9Yi5nZXRFbGVtZW50c0J5TmFtZShkKSxyKGIsZnVuY3Rpb24oYil7YS5hKGIpJiZGKGUsYil9KSk6Yi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lJiZkJiZcImNsYXNzXCI9PWM/KGI9Yi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGQpLHIoYixmdW5jdGlvbihiKXtiLmNsYXNzTmFtZT09ZCYmYS5hKGIpJiZGKGUsYil9KSk6YSBpbnN0YW5jZW9mIEc/SGEoYSxiLGMsZCxlKTpiLmdldEVsZW1lbnRzQnlUYWdOYW1lJiYoYj1iLmdldEVsZW1lbnRzQnlUYWdOYW1lKGEuZigpKSxyKGIsZnVuY3Rpb24oYSl7QShhLGMsZCkmJkYoZSxhKX0pKTtyZXR1cm4gZX1cbmZ1bmN0aW9uIElhKGEsYixjLGQsZSl7dmFyIGY7aWYoKGEgaW5zdGFuY2VvZiBFfHw4PT1hLmJ8fGMmJm51bGw9PT1hLmIpJiYoZj1iLmNoaWxkTm9kZXMpKXt2YXIgZz1HYShhKTtpZihcIipcIiE9ZyYmKGY9aWEoZixmdW5jdGlvbihhKXtyZXR1cm4gYS50YWdOYW1lJiZhLnRhZ05hbWUudG9Mb3dlckNhc2UoKT09Z30pLCFmKSlyZXR1cm4gZTtjJiYoZj1pYShmLGZ1bmN0aW9uKGEpe3JldHVybiBBKGEsYyxkKX0pKTtyKGYsZnVuY3Rpb24oYSl7XCIqXCI9PWcmJihcIiFcIj09YS50YWdOYW1lfHxcIipcIj09ZyYmMSE9YS5ub2RlVHlwZSl8fEYoZSxhKX0pO3JldHVybiBlfXJldHVybiBKYShhLGIsYyxkLGUpfWZ1bmN0aW9uIEphKGEsYixjLGQsZSl7Zm9yKGI9Yi5maXJzdENoaWxkO2I7Yj1iLm5leHRTaWJsaW5nKUEoYixjLGQpJiZhLmEoYikmJkYoZSxiKTtyZXR1cm4gZX1cbmZ1bmN0aW9uIEhhKGEsYixjLGQsZSl7Zm9yKGI9Yi5maXJzdENoaWxkO2I7Yj1iLm5leHRTaWJsaW5nKUEoYixjLGQpJiZhLmEoYikmJkYoZSxiKSxIYShhLGIsYyxkLGUpfWZ1bmN0aW9uIEdhKGEpe2lmKGEgaW5zdGFuY2VvZiBHKXtpZig4PT1hLmIpcmV0dXJuXCIhXCI7aWYobnVsbD09PWEuYilyZXR1cm5cIipcIn1yZXR1cm4gYS5mKCl9OyFyYSYmIXZ8fHYmJjk8PU51bWJlcihCYSl8fHJhJiZ6YShcIjEuOS4xXCIpO3YmJnphKFwiOVwiKTtmdW5jdGlvbiBLYShhLGIpe2lmKCFhfHwhYilyZXR1cm4hMTtpZihhLmNvbnRhaW5zJiYxPT1iLm5vZGVUeXBlKXJldHVybiBhPT1ifHxhLmNvbnRhaW5zKGIpO2lmKFwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKXJldHVybiBhPT1ifHwhIShhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGIpJjE2KTtmb3IoO2ImJmEhPWI7KWI9Yi5wYXJlbnROb2RlO3JldHVybiBiPT1hfVxuZnVuY3Rpb24gTGEoYSxiKXtpZihhPT1iKXJldHVybiAwO2lmKGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24pcmV0dXJuIGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oYikmMj8xOi0xO2lmKHYmJiEoOTw9TnVtYmVyKEJhKSkpe2lmKDk9PWEubm9kZVR5cGUpcmV0dXJuLTE7aWYoOT09Yi5ub2RlVHlwZSlyZXR1cm4gMX1pZihcInNvdXJjZUluZGV4XCJpbiBhfHxhLnBhcmVudE5vZGUmJlwic291cmNlSW5kZXhcImluIGEucGFyZW50Tm9kZSl7dmFyIGM9MT09YS5ub2RlVHlwZSxkPTE9PWIubm9kZVR5cGU7aWYoYyYmZClyZXR1cm4gYS5zb3VyY2VJbmRleC1iLnNvdXJjZUluZGV4O3ZhciBlPWEucGFyZW50Tm9kZSxmPWIucGFyZW50Tm9kZTtyZXR1cm4gZT09Zj9NYShhLGIpOiFjJiZLYShlLGIpPy0xKk5hKGEsYik6IWQmJkthKGYsYSk/TmEoYixhKTooYz9hLnNvdXJjZUluZGV4OmUuc291cmNlSW5kZXgpLShkP2Iuc291cmNlSW5kZXg6Zi5zb3VyY2VJbmRleCl9ZD05PT1hLm5vZGVUeXBlP1xuYTphLm93bmVyRG9jdW1lbnR8fGEuZG9jdW1lbnQ7Yz1kLmNyZWF0ZVJhbmdlKCk7Yy5zZWxlY3ROb2RlKGEpO2MuY29sbGFwc2UoITApO2Q9ZC5jcmVhdGVSYW5nZSgpO2Quc2VsZWN0Tm9kZShiKTtkLmNvbGxhcHNlKCEwKTtyZXR1cm4gYy5jb21wYXJlQm91bmRhcnlQb2ludHMoay5SYW5nZS5TVEFSVF9UT19FTkQsZCl9ZnVuY3Rpb24gTmEoYSxiKXt2YXIgYz1hLnBhcmVudE5vZGU7aWYoYz09YilyZXR1cm4tMTtmb3IodmFyIGQ9YjtkLnBhcmVudE5vZGUhPWM7KWQ9ZC5wYXJlbnROb2RlO3JldHVybiBNYShkLGEpfWZ1bmN0aW9uIE1hKGEsYil7Zm9yKHZhciBjPWI7Yz1jLnByZXZpb3VzU2libGluZzspaWYoYz09YSlyZXR1cm4tMTtyZXR1cm4gMX07ZnVuY3Rpb24gQygpe3RoaXMuYj10aGlzLmE9bnVsbDt0aGlzLmw9MH1mdW5jdGlvbiBPYShhKXt0aGlzLm5vZGU9YTt0aGlzLmE9dGhpcy5iPW51bGx9ZnVuY3Rpb24gUGEoYSxiKXtpZighYS5hKXJldHVybiBiO2lmKCFiLmEpcmV0dXJuIGE7Zm9yKHZhciBjPWEuYSxkPWIuYSxlPW51bGwsZj1udWxsLGc9MDtjJiZkOyl7dmFyIGY9Yy5ub2RlLGg9ZC5ub2RlO2Y9PWh8fGYgaW5zdGFuY2VvZiB4JiZoIGluc3RhbmNlb2YgeCYmZi5hPT1oLmE/KGY9YyxjPWMuYSxkPWQuYSk6MDxMYShjLm5vZGUsZC5ub2RlKT8oZj1kLGQ9ZC5hKTooZj1jLGM9Yy5hKTsoZi5iPWUpP2UuYT1mOmEuYT1mO2U9ZjtnKyt9Zm9yKGY9Y3x8ZDtmOylmLmI9ZSxlPWUuYT1mLGcrKyxmPWYuYTthLmI9ZTthLmw9ZztyZXR1cm4gYX1mdW5jdGlvbiBRYShhLGIpe3ZhciBjPW5ldyBPYShiKTtjLmE9YS5hO2EuYj9hLmEuYj1jOmEuYT1hLmI9YzthLmE9YzthLmwrK31cbmZ1bmN0aW9uIEYoYSxiKXt2YXIgYz1uZXcgT2EoYik7Yy5iPWEuYjthLmE/YS5iLmE9YzphLmE9YS5iPWM7YS5iPWM7YS5sKyt9ZnVuY3Rpb24gUmEoYSl7cmV0dXJuKGE9YS5hKT9hLm5vZGU6bnVsbH1mdW5jdGlvbiBTYShhKXtyZXR1cm4oYT1SYShhKSk/eihhKTpcIlwifWZ1bmN0aW9uIEgoYSxiKXtyZXR1cm4gbmV3IFRhKGEsISFiKX1mdW5jdGlvbiBUYShhLGIpe3RoaXMuZj1hO3RoaXMuYj0odGhpcy5jPWIpP2EuYjphLmE7dGhpcy5hPW51bGx9ZnVuY3Rpb24gSShhKXt2YXIgYj1hLmI7aWYobnVsbD09YilyZXR1cm4gbnVsbDt2YXIgYz1hLmE9YjthLmI9YS5jP2IuYjpiLmE7cmV0dXJuIGMubm9kZX07ZnVuY3Rpb24gbihhKXt0aGlzLmk9YTt0aGlzLmI9dGhpcy5nPSExO3RoaXMuZj1udWxsfWZ1bmN0aW9uIEooYSl7cmV0dXJuXCJcXG4gIFwiK2EudG9TdHJpbmcoKS5zcGxpdChcIlxcblwiKS5qb2luKFwiXFxuICBcIil9ZnVuY3Rpb24gVWEoYSxiKXthLmc9Yn1mdW5jdGlvbiBWYShhLGIpe2EuYj1ifWZ1bmN0aW9uIEsoYSxiKXt2YXIgYz1hLmEoYik7cmV0dXJuIGMgaW5zdGFuY2VvZiBDPytTYShjKTorY31mdW5jdGlvbiBMKGEsYil7dmFyIGM9YS5hKGIpO3JldHVybiBjIGluc3RhbmNlb2YgQz9TYShjKTpcIlwiK2N9ZnVuY3Rpb24gTShhLGIpe3ZhciBjPWEuYShiKTtyZXR1cm4gYyBpbnN0YW5jZW9mIEM/ISFjLmw6ISFjfTtmdW5jdGlvbiBOKGEsYixjKXtuLmNhbGwodGhpcyxhLmkpO3RoaXMuYz1hO3RoaXMuaD1iO3RoaXMubz1jO3RoaXMuZz1iLmd8fGMuZzt0aGlzLmI9Yi5ifHxjLmI7dGhpcy5jPT1XYSYmKGMuYnx8Yy5nfHw0PT1jLml8fDA9PWMuaXx8IWIuZj9iLmJ8fGIuZ3x8ND09Yi5pfHwwPT1iLml8fCFjLmZ8fCh0aGlzLmY9e25hbWU6Yy5mLm5hbWUsczpifSk6dGhpcy5mPXtuYW1lOmIuZi5uYW1lLHM6Y30pfW0oTik7XG5mdW5jdGlvbiBPKGEsYixjLGQsZSl7Yj1iLmEoZCk7Yz1jLmEoZCk7dmFyIGY7aWYoYiBpbnN0YW5jZW9mIEMmJmMgaW5zdGFuY2VvZiBDKXtiPUgoYik7Zm9yKGQ9SShiKTtkO2Q9SShiKSlmb3IoZT1IKGMpLGY9SShlKTtmO2Y9SShlKSlpZihhKHooZCkseihmKSkpcmV0dXJuITA7cmV0dXJuITF9aWYoYiBpbnN0YW5jZW9mIEN8fGMgaW5zdGFuY2VvZiBDKXtiIGluc3RhbmNlb2YgQz8oZT1iLGQ9Yyk6KGU9YyxkPWIpO2Y9SChlKTtmb3IodmFyIGc9dHlwZW9mIGQsaD1JKGYpO2g7aD1JKGYpKXtzd2l0Y2goZyl7Y2FzZSBcIm51bWJlclwiOmg9K3ooaCk7YnJlYWs7Y2FzZSBcImJvb2xlYW5cIjpoPSEheihoKTticmVhaztjYXNlIFwic3RyaW5nXCI6aD16KGgpO2JyZWFrO2RlZmF1bHQ6dGhyb3cgRXJyb3IoXCJJbGxlZ2FsIHByaW1pdGl2ZSB0eXBlIGZvciBjb21wYXJpc29uLlwiKTt9aWYoZT09YiYmYShoLGQpfHxlPT1jJiZhKGQsaCkpcmV0dXJuITB9cmV0dXJuITF9cmV0dXJuIGU/XCJib29sZWFuXCI9PVxudHlwZW9mIGJ8fFwiYm9vbGVhblwiPT10eXBlb2YgYz9hKCEhYiwhIWMpOlwibnVtYmVyXCI9PXR5cGVvZiBifHxcIm51bWJlclwiPT10eXBlb2YgYz9hKCtiLCtjKTphKGIsYyk6YSgrYiwrYyl9Ti5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5jLm0odGhpcy5oLHRoaXMubyxhKX07Ti5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYT1cIkJpbmFyeSBFeHByZXNzaW9uOiBcIit0aGlzLmMsYT1hK0oodGhpcy5oKTtyZXR1cm4gYSs9Sih0aGlzLm8pfTtmdW5jdGlvbiBYYShhLGIsYyxkKXt0aGlzLmE9YTt0aGlzLnc9Yjt0aGlzLmk9Yzt0aGlzLm09ZH1YYS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfTt2YXIgWWE9e307XG5mdW5jdGlvbiBQKGEsYixjLGQpe2lmKFlhLmhhc093blByb3BlcnR5KGEpKXRocm93IEVycm9yKFwiQmluYXJ5IG9wZXJhdG9yIGFscmVhZHkgY3JlYXRlZDogXCIrYSk7YT1uZXcgWGEoYSxiLGMsZCk7cmV0dXJuIFlhW2EudG9TdHJpbmcoKV09YX1QKFwiZGl2XCIsNiwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpL0soYixjKX0pO1AoXCJtb2RcIiw2LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYyklSyhiLGMpfSk7UChcIipcIiw2LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYykqSyhiLGMpfSk7UChcIitcIiw1LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYykrSyhiLGMpfSk7UChcIi1cIiw1LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYyktSyhiLGMpfSk7UChcIjxcIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE8Yn0sYSxiLGMpfSk7XG5QKFwiPlwiLDQsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE8oZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT5ifSxhLGIsYyl9KTtQKFwiPD1cIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE8PWJ9LGEsYixjKX0pO1AoXCI+PVwiLDQsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE8oZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT49Yn0sYSxiLGMpfSk7dmFyIFdhPVAoXCI9XCIsMywyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTyhmdW5jdGlvbihhLGIpe3JldHVybiBhPT1ifSxhLGIsYywhMCl9KTtQKFwiIT1cIiwzLDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGEhPWJ9LGEsYixjLCEwKX0pO1AoXCJhbmRcIiwyLDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBNKGEsYykmJk0oYixjKX0pO1AoXCJvclwiLDEsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE0oYSxjKXx8TShiLGMpfSk7ZnVuY3Rpb24gUShhLGIsYyl7dGhpcy5hPWE7dGhpcy5iPWJ8fDE7dGhpcy5mPWN8fDF9O2Z1bmN0aW9uIFphKGEsYil7aWYoYi5hLmxlbmd0aCYmNCE9YS5pKXRocm93IEVycm9yKFwiUHJpbWFyeSBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gbm9kZXNldCBpZiBmaWx0ZXIgaGFzIHByZWRpY2F0ZShzKS5cIik7bi5jYWxsKHRoaXMsYS5pKTt0aGlzLmM9YTt0aGlzLmg9Yjt0aGlzLmc9YS5nO3RoaXMuYj1hLmJ9bShaYSk7WmEucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7YT10aGlzLmMuYShhKTtyZXR1cm4gJGEodGhpcy5oLGEpfTtaYS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYTthPVwiRmlsdGVyOlwiK0oodGhpcy5jKTtyZXR1cm4gYSs9Sih0aGlzLmgpfTtmdW5jdGlvbiBhYihhLGIpe2lmKGIubGVuZ3RoPGEuQSl0aHJvdyBFcnJvcihcIkZ1bmN0aW9uIFwiK2EuaitcIiBleHBlY3RzIGF0IGxlYXN0XCIrYS5BK1wiIGFyZ3VtZW50cywgXCIrYi5sZW5ndGgrXCIgZ2l2ZW5cIik7aWYobnVsbCE9PWEudiYmYi5sZW5ndGg+YS52KXRocm93IEVycm9yKFwiRnVuY3Rpb24gXCIrYS5qK1wiIGV4cGVjdHMgYXQgbW9zdCBcIithLnYrXCIgYXJndW1lbnRzLCBcIitiLmxlbmd0aCtcIiBnaXZlblwiKTthLkImJnIoYixmdW5jdGlvbihiLGQpe2lmKDQhPWIuaSl0aHJvdyBFcnJvcihcIkFyZ3VtZW50IFwiK2QrXCIgdG8gZnVuY3Rpb24gXCIrYS5qK1wiIGlzIG5vdCBvZiB0eXBlIE5vZGVzZXQ6IFwiK2IpO30pO24uY2FsbCh0aGlzLGEuaSk7dGhpcy5oPWE7dGhpcy5jPWI7VWEodGhpcyxhLmd8fGphKGIsZnVuY3Rpb24oYSl7cmV0dXJuIGEuZ30pKTtWYSh0aGlzLGEuRCYmIWIubGVuZ3RofHxhLkMmJiEhYi5sZW5ndGh8fGphKGIsZnVuY3Rpb24oYSl7cmV0dXJuIGEuYn0pKX1tKGFiKTtcbmFiLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmgubS5hcHBseShudWxsLGxhKGEsdGhpcy5jKSl9O2FiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhPVwiRnVuY3Rpb246IFwiK3RoaXMuaDtpZih0aGlzLmMubGVuZ3RoKXZhciBiPXQodGhpcy5jLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGErSihiKX0sXCJBcmd1bWVudHM6XCIpLGE9YStKKGIpO3JldHVybiBhfTtmdW5jdGlvbiBiYihhLGIsYyxkLGUsZixnLGgscCl7dGhpcy5qPWE7dGhpcy5pPWI7dGhpcy5nPWM7dGhpcy5EPWQ7dGhpcy5DPWU7dGhpcy5tPWY7dGhpcy5BPWc7dGhpcy52PXZvaWQgMCE9PWg/aDpnO3RoaXMuQj0hIXB9YmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07dmFyIGNiPXt9O1xuZnVuY3Rpb24gUihhLGIsYyxkLGUsZixnLGgpe2lmKGNiLmhhc093blByb3BlcnR5KGEpKXRocm93IEVycm9yKFwiRnVuY3Rpb24gYWxyZWFkeSBjcmVhdGVkOiBcIithK1wiLlwiKTtjYlthXT1uZXcgYmIoYSxiLGMsZCwhMSxlLGYsZyxoKX1SKFwiYm9vbGVhblwiLDIsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTShiLGEpfSwxKTtSKFwiY2VpbGluZ1wiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTWF0aC5jZWlsKEsoYixhKSl9LDEpO1IoXCJjb25jYXRcIiwzLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIHQobWEoYXJndW1lbnRzLDEpLGZ1bmN0aW9uKGIsZCl7cmV0dXJuIGIrTChkLGEpfSxcIlwiKX0sMixudWxsKTtSKFwiY29udGFpbnNcIiwyLCExLCExLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gcShMKGIsYSksTChjLGEpKX0sMik7UihcImNvdW50XCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiBiLmEoYSkubH0sMSwxLCEwKTtcblIoXCJmYWxzZVwiLDIsITEsITEsZnVuY3Rpb24oKXtyZXR1cm4hMX0sMCk7UihcImZsb29yXCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiBNYXRoLmZsb29yKEsoYixhKSl9LDEpO1IoXCJpZFwiLDQsITEsITEsZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEpe2lmKHcpe3ZhciBiPWUuYWxsW2FdO2lmKGIpe2lmKGIubm9kZVR5cGUmJmE9PWIuaWQpcmV0dXJuIGI7aWYoYi5sZW5ndGgpcmV0dXJuIGthKGIsZnVuY3Rpb24oYil7cmV0dXJuIGE9PWIuaWR9KX1yZXR1cm4gbnVsbH1yZXR1cm4gZS5nZXRFbGVtZW50QnlJZChhKX12YXIgZD1hLmEsZT05PT1kLm5vZGVUeXBlP2Q6ZC5vd25lckRvY3VtZW50LGQ9TChiLGEpLnNwbGl0KC9cXHMrLyksZj1bXTtyKGQsZnVuY3Rpb24oYSl7YT1jKGEpOyFhfHwwPD1oYShmLGEpfHxmLnB1c2goYSl9KTtmLnNvcnQoTGEpO3ZhciBnPW5ldyBDO3IoZixmdW5jdGlvbihhKXtGKGcsYSl9KTtyZXR1cm4gZ30sMSk7XG5SKFwibGFuZ1wiLDIsITEsITEsZnVuY3Rpb24oKXtyZXR1cm4hMX0sMSk7UihcImxhc3RcIiwxLCEwLCExLGZ1bmN0aW9uKGEpe2lmKDEhPWFyZ3VtZW50cy5sZW5ndGgpdGhyb3cgRXJyb3IoXCJGdW5jdGlvbiBsYXN0IGV4cGVjdHMgKClcIik7cmV0dXJuIGEuZn0sMCk7UihcImxvY2FsLW5hbWVcIiwzLCExLCEwLGZ1bmN0aW9uKGEsYil7dmFyIGM9Yj9SYShiLmEoYSkpOmEuYTtyZXR1cm4gYz9jLmxvY2FsTmFtZXx8Yy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOlwiXCJ9LDAsMSwhMCk7UihcIm5hbWVcIiwzLCExLCEwLGZ1bmN0aW9uKGEsYil7dmFyIGM9Yj9SYShiLmEoYSkpOmEuYTtyZXR1cm4gYz9jLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk6XCJcIn0sMCwxLCEwKTtSKFwibmFtZXNwYWNlLXVyaVwiLDMsITAsITEsZnVuY3Rpb24oKXtyZXR1cm5cIlwifSwwLDEsITApO1xuUihcIm5vcm1hbGl6ZS1zcGFjZVwiLDMsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4oYj9MKGIsYSk6eihhLmEpKS5yZXBsYWNlKC9bXFxzXFx4YTBdKy9nLFwiIFwiKS5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLFwiXCIpfSwwLDEpO1IoXCJub3RcIiwyLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIU0oYixhKX0sMSk7UihcIm51bWJlclwiLDEsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj9LKGIsYSk6K3ooYS5hKX0sMCwxKTtSKFwicG9zaXRpb25cIiwxLCEwLCExLGZ1bmN0aW9uKGEpe3JldHVybiBhLmJ9LDApO1IoXCJyb3VuZFwiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTWF0aC5yb3VuZChLKGIsYSkpfSwxKTtSKFwic3RhcnRzLXdpdGhcIiwyLCExLCExLGZ1bmN0aW9uKGEsYixjKXtiPUwoYixhKTthPUwoYyxhKTtyZXR1cm4gMD09Yi5sYXN0SW5kZXhPZihhLDApfSwyKTtSKFwic3RyaW5nXCIsMywhMSwhMCxmdW5jdGlvbihhLGIpe3JldHVybiBiP0woYixhKTp6KGEuYSl9LDAsMSk7XG5SKFwic3RyaW5nLWxlbmd0aFwiLDEsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4oYj9MKGIsYSk6eihhLmEpKS5sZW5ndGh9LDAsMSk7UihcInN1YnN0cmluZ1wiLDMsITEsITEsZnVuY3Rpb24oYSxiLGMsZCl7Yz1LKGMsYSk7aWYoaXNOYU4oYyl8fEluZmluaXR5PT1jfHwtSW5maW5pdHk9PWMpcmV0dXJuXCJcIjtkPWQ/SyhkLGEpOkluZmluaXR5O2lmKGlzTmFOKGQpfHwtSW5maW5pdHk9PT1kKXJldHVyblwiXCI7Yz1NYXRoLnJvdW5kKGMpLTE7dmFyIGU9TWF0aC5tYXgoYywwKTthPUwoYixhKTtyZXR1cm4gSW5maW5pdHk9PWQ/YS5zdWJzdHJpbmcoZSk6YS5zdWJzdHJpbmcoZSxjK01hdGgucm91bmQoZCkpfSwyLDMpO1IoXCJzdWJzdHJpbmctYWZ0ZXJcIiwzLCExLCExLGZ1bmN0aW9uKGEsYixjKXtiPUwoYixhKTthPUwoYyxhKTtjPWIuaW5kZXhPZihhKTtyZXR1cm4tMT09Yz9cIlwiOmIuc3Vic3RyaW5nKGMrYS5sZW5ndGgpfSwyKTtcblIoXCJzdWJzdHJpbmctYmVmb3JlXCIsMywhMSwhMSxmdW5jdGlvbihhLGIsYyl7Yj1MKGIsYSk7YT1MKGMsYSk7YT1iLmluZGV4T2YoYSk7cmV0dXJuLTE9PWE/XCJcIjpiLnN1YnN0cmluZygwLGEpfSwyKTtSKFwic3VtXCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz1IKGIuYShhKSksZD0wLGU9SShjKTtlO2U9SShjKSlkKz0reihlKTtyZXR1cm4gZH0sMSwxLCEwKTtSKFwidHJhbnNsYXRlXCIsMywhMSwhMSxmdW5jdGlvbihhLGIsYyxkKXtiPUwoYixhKTtjPUwoYyxhKTt2YXIgZT1MKGQsYSk7YT17fTtmb3IoZD0wO2Q8Yy5sZW5ndGg7ZCsrKXt2YXIgZj1jLmNoYXJBdChkKTtmIGluIGF8fChhW2ZdPWUuY2hhckF0KGQpKX1jPVwiXCI7Zm9yKGQ9MDtkPGIubGVuZ3RoO2QrKylmPWIuY2hhckF0KGQpLGMrPWYgaW4gYT9hW2ZdOmY7cmV0dXJuIGN9LDMpO1IoXCJ0cnVlXCIsMiwhMSwhMSxmdW5jdGlvbigpe3JldHVybiEwfSwwKTtmdW5jdGlvbiBHKGEsYil7dGhpcy5oPWE7dGhpcy5jPXZvaWQgMCE9PWI/YjpudWxsO3RoaXMuYj1udWxsO3N3aXRjaChhKXtjYXNlIFwiY29tbWVudFwiOnRoaXMuYj04O2JyZWFrO2Nhc2UgXCJ0ZXh0XCI6dGhpcy5iPTM7YnJlYWs7Y2FzZSBcInByb2Nlc3NpbmctaW5zdHJ1Y3Rpb25cIjp0aGlzLmI9NzticmVhaztjYXNlIFwibm9kZVwiOmJyZWFrO2RlZmF1bHQ6dGhyb3cgRXJyb3IoXCJVbmV4cGVjdGVkIGFyZ3VtZW50XCIpO319ZnVuY3Rpb24gZGIoYSl7cmV0dXJuXCJjb21tZW50XCI9PWF8fFwidGV4dFwiPT1hfHxcInByb2Nlc3NpbmctaW5zdHJ1Y3Rpb25cIj09YXx8XCJub2RlXCI9PWF9Ry5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4gbnVsbD09PXRoaXMuYnx8dGhpcy5iPT1hLm5vZGVUeXBlfTtHLnByb3RvdHlwZS5mPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuaH07XG5HLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhPVwiS2luZCBUZXN0OiBcIit0aGlzLmg7bnVsbD09PXRoaXMuY3x8KGErPUoodGhpcy5jKSk7cmV0dXJuIGF9O2Z1bmN0aW9uIGViKGEpe3RoaXMuYj1hO3RoaXMuYT0wfWZ1bmN0aW9uIGZiKGEpe2E9YS5tYXRjaChnYik7Zm9yKHZhciBiPTA7YjxhLmxlbmd0aDtiKyspaGIudGVzdChhW2JdKSYmYS5zcGxpY2UoYiwxKTtyZXR1cm4gbmV3IGViKGEpfXZhciBnYj0vXFwkPyg/Oig/IVswLTktXFwuXSkoPzpcXCp8W1xcdy1cXC5dKyk6KT8oPyFbMC05LVxcLl0pKD86XFwqfFtcXHctXFwuXSspfFxcL1xcL3xcXC5cXC58Ojp8XFxkKyg/OlxcLlxcZCopP3xcXC5cXGQrfFwiW15cIl0qXCJ8J1teJ10qJ3xbITw+XT18XFxzK3wuL2csaGI9L15cXHMvO2Z1bmN0aW9uIFMoYSxiKXtyZXR1cm4gYS5iW2EuYSsoYnx8MCldfWZ1bmN0aW9uIFQoYSl7cmV0dXJuIGEuYlthLmErK119ZnVuY3Rpb24gaWIoYSl7cmV0dXJuIGEuYi5sZW5ndGg8PWEuYX07ZnVuY3Rpb24gamIoYSl7bi5jYWxsKHRoaXMsMyk7dGhpcy5jPWEuc3Vic3RyaW5nKDEsYS5sZW5ndGgtMSl9bShqYik7amIucHJvdG90eXBlLmE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jfTtqYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIkxpdGVyYWw6IFwiK3RoaXMuY307ZnVuY3Rpb24gRShhLGIpe3RoaXMuaj1hLnRvTG93ZXJDYXNlKCk7dmFyIGM7Yz1cIipcIj09dGhpcy5qP1wiKlwiOlwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiO3RoaXMuYz1iP2IudG9Mb3dlckNhc2UoKTpjfUUucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9YS5ub2RlVHlwZTtpZigxIT1iJiYyIT1iKXJldHVybiExO2I9dm9pZCAwIT09YS5sb2NhbE5hbWU/YS5sb2NhbE5hbWU6YS5ub2RlTmFtZTtyZXR1cm5cIipcIiE9dGhpcy5qJiZ0aGlzLmohPWIudG9Mb3dlckNhc2UoKT8hMTpcIipcIj09dGhpcy5jPyEwOnRoaXMuYz09KGEubmFtZXNwYWNlVVJJP2EubmFtZXNwYWNlVVJJLnRvTG93ZXJDYXNlKCk6XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCIpfTtFLnByb3RvdHlwZS5mPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07XG5FLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiTmFtZSBUZXN0OiBcIisoXCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCI9PXRoaXMuYz9cIlwiOnRoaXMuYytcIjpcIikrdGhpcy5qfTtmdW5jdGlvbiBrYihhLGIpe24uY2FsbCh0aGlzLGEuaSk7dGhpcy5oPWE7dGhpcy5jPWI7dGhpcy5nPWEuZzt0aGlzLmI9YS5iO2lmKDE9PXRoaXMuYy5sZW5ndGgpe3ZhciBjPXRoaXMuY1swXTtjLnV8fGMuYyE9bGJ8fChjPWMubyxcIipcIiE9Yy5mKCkmJih0aGlzLmY9e25hbWU6Yy5mKCksczpudWxsfSkpfX1tKGtiKTtmdW5jdGlvbiBtYigpe24uY2FsbCh0aGlzLDQpfW0obWIpO21iLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBDO2E9YS5hOzk9PWEubm9kZVR5cGU/RihiLGEpOkYoYixhLm93bmVyRG9jdW1lbnQpO3JldHVybiBifTttYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIlJvb3QgSGVscGVyIEV4cHJlc3Npb25cIn07ZnVuY3Rpb24gbmIoKXtuLmNhbGwodGhpcyw0KX1tKG5iKTtuYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj1uZXcgQztGKGIsYS5hKTtyZXR1cm4gYn07bmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJDb250ZXh0IEhlbHBlciBFeHByZXNzaW9uXCJ9O1xuZnVuY3Rpb24gb2IoYSl7cmV0dXJuXCIvXCI9PWF8fFwiLy9cIj09YX1rYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmguYShhKTtpZighKGIgaW5zdGFuY2VvZiBDKSl0aHJvdyBFcnJvcihcIkZpbHRlciBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gbm9kZXNldC5cIik7YT10aGlzLmM7Zm9yKHZhciBjPTAsZD1hLmxlbmd0aDtjPGQmJmIubDtjKyspe3ZhciBlPWFbY10sZj1IKGIsZS5jLmEpLGc7aWYoZS5nfHxlLmMhPXBiKWlmKGUuZ3x8ZS5jIT1xYilmb3IoZz1JKGYpLGI9ZS5hKG5ldyBRKGcpKTtudWxsIT0oZz1JKGYpKTspZz1lLmEobmV3IFEoZykpLGI9UGEoYixnKTtlbHNlIGc9SShmKSxiPWUuYShuZXcgUShnKSk7ZWxzZXtmb3IoZz1JKGYpOyhiPUkoZikpJiYoIWcuY29udGFpbnN8fGcuY29udGFpbnMoYikpJiZiLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGcpJjg7Zz1iKTtiPWUuYShuZXcgUShnKSl9fXJldHVybiBifTtcbmtiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhO2E9XCJQYXRoIEV4cHJlc3Npb246XCIrSih0aGlzLmgpO2lmKHRoaXMuYy5sZW5ndGgpe3ZhciBiPXQodGhpcy5jLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGErSihiKX0sXCJTdGVwczpcIik7YSs9SihiKX1yZXR1cm4gYX07ZnVuY3Rpb24gcmIoYSl7bi5jYWxsKHRoaXMsNCk7dGhpcy5jPWE7VWEodGhpcyxqYSh0aGlzLmMsZnVuY3Rpb24oYSl7cmV0dXJuIGEuZ30pKTtWYSh0aGlzLGphKHRoaXMuYyxmdW5jdGlvbihhKXtyZXR1cm4gYS5ifSkpfW0ocmIpO3JiLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBDO3IodGhpcy5jLGZ1bmN0aW9uKGMpe2M9Yy5hKGEpO2lmKCEoYyBpbnN0YW5jZW9mIEMpKXRocm93IEVycm9yKFwiUGF0aCBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gTm9kZVNldC5cIik7Yj1QYShiLGMpfSk7cmV0dXJuIGJ9O3JiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0KHRoaXMuYyxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiVW5pb24gRXhwcmVzc2lvbjpcIil9O2Z1bmN0aW9uIHNiKGEsYil7dGhpcy5hPWE7dGhpcy5iPSEhYn1cbmZ1bmN0aW9uICRhKGEsYixjKXtmb3IoYz1jfHwwO2M8YS5hLmxlbmd0aDtjKyspZm9yKHZhciBkPWEuYVtjXSxlPUgoYiksZj1iLmwsZyxoPTA7Zz1JKGUpO2grKyl7dmFyIHA9YS5iP2YtaDpoKzE7Zz1kLmEobmV3IFEoZyxwLGYpKTtpZihcIm51bWJlclwiPT10eXBlb2YgZylwPXA9PWc7ZWxzZSBpZihcInN0cmluZ1wiPT10eXBlb2YgZ3x8XCJib29sZWFuXCI9PXR5cGVvZiBnKXA9ISFnO2Vsc2UgaWYoZyBpbnN0YW5jZW9mIEMpcD0wPGcubDtlbHNlIHRocm93IEVycm9yKFwiUHJlZGljYXRlLmV2YWx1YXRlIHJldHVybmVkIGFuIHVuZXhwZWN0ZWQgdHlwZS5cIik7aWYoIXApe3A9ZTtnPXAuZjt2YXIgeT1wLmE7aWYoIXkpdGhyb3cgRXJyb3IoXCJOZXh0IG11c3QgYmUgY2FsbGVkIGF0IGxlYXN0IG9uY2UgYmVmb3JlIHJlbW92ZS5cIik7dmFyIEQ9eS5iLHk9eS5hO0Q/RC5hPXk6Zy5hPXk7eT95LmI9RDpnLmI9RDtnLmwtLTtwLmE9bnVsbH19cmV0dXJuIGJ9XG5zYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdCh0aGlzLmEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStKKGIpfSxcIlByZWRpY2F0ZXM6XCIpfTtmdW5jdGlvbiBVKGEsYixjLGQpe24uY2FsbCh0aGlzLDQpO3RoaXMuYz1hO3RoaXMubz1iO3RoaXMuaD1jfHxuZXcgc2IoW10pO3RoaXMudT0hIWQ7Yj10aGlzLmg7Yj0wPGIuYS5sZW5ndGg/Yi5hWzBdLmY6bnVsbDthLmImJmImJihhPWIubmFtZSxhPXc/YS50b0xvd2VyQ2FzZSgpOmEsdGhpcy5mPXtuYW1lOmEsczpiLnN9KTthOnthPXRoaXMuaDtmb3IoYj0wO2I8YS5hLmxlbmd0aDtiKyspaWYoYz1hLmFbYl0sYy5nfHwxPT1jLml8fDA9PWMuaSl7YT0hMDticmVhayBhfWE9ITF9dGhpcy5nPWF9bShVKTtcblUucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9YS5hLGM9bnVsbCxjPXRoaXMuZixkPW51bGwsZT1udWxsLGY9MDtjJiYoZD1jLm5hbWUsZT1jLnM/TChjLnMsYSk6bnVsbCxmPTEpO2lmKHRoaXMudSlpZih0aGlzLmd8fHRoaXMuYyE9dGIpaWYoYT1IKChuZXcgVSh1YixuZXcgRyhcIm5vZGVcIikpKS5hKGEpKSxiPUkoYSkpZm9yKGM9dGhpcy5tKGIsZCxlLGYpO251bGwhPShiPUkoYSkpOyljPVBhKGMsdGhpcy5tKGIsZCxlLGYpKTtlbHNlIGM9bmV3IEM7ZWxzZSBjPUIodGhpcy5vLGIsZCxlKSxjPSRhKHRoaXMuaCxjLGYpO2Vsc2UgYz10aGlzLm0oYS5hLGQsZSxmKTtyZXR1cm4gY307VS5wcm90b3R5cGUubT1mdW5jdGlvbihhLGIsYyxkKXthPXRoaXMuYy5mKHRoaXMubyxhLGIsYyk7cmV0dXJuIGE9JGEodGhpcy5oLGEsZCl9O1xuVS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYTthPVwiU3RlcDpcIitKKFwiT3BlcmF0b3I6IFwiKyh0aGlzLnU/XCIvL1wiOlwiL1wiKSk7dGhpcy5jLmomJihhKz1KKFwiQXhpczogXCIrdGhpcy5jKSk7YSs9Sih0aGlzLm8pO2lmKHRoaXMuaC5hLmxlbmd0aCl7dmFyIGI9dCh0aGlzLmguYSxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiUHJlZGljYXRlczpcIik7YSs9SihiKX1yZXR1cm4gYX07ZnVuY3Rpb24gdmIoYSxiLGMsZCl7dGhpcy5qPWE7dGhpcy5mPWI7dGhpcy5hPWM7dGhpcy5iPWR9dmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07dmFyIHdiPXt9O2Z1bmN0aW9uIFYoYSxiLGMsZCl7aWYod2IuaGFzT3duUHJvcGVydHkoYSkpdGhyb3cgRXJyb3IoXCJBeGlzIGFscmVhZHkgY3JlYXRlZDogXCIrYSk7Yj1uZXcgdmIoYSxiLGMsISFkKTtyZXR1cm4gd2JbYV09Yn1cblYoXCJhbmNlc3RvclwiLGZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPW5ldyBDLGQ9YjtkPWQucGFyZW50Tm9kZTspYS5hKGQpJiZRYShjLGQpO3JldHVybiBjfSwhMCk7VihcImFuY2VzdG9yLW9yLXNlbGZcIixmdW5jdGlvbihhLGIpe3ZhciBjPW5ldyBDLGQ9YjtkbyBhLmEoZCkmJlFhKGMsZCk7d2hpbGUoZD1kLnBhcmVudE5vZGUpO3JldHVybiBjfSwhMCk7XG52YXIgbGI9VihcImF0dHJpYnV0ZVwiLGZ1bmN0aW9uKGEsYil7dmFyIGM9bmV3IEMsZD1hLmYoKTtpZihcInN0eWxlXCI9PWQmJncmJmIuc3R5bGUpcmV0dXJuIEYoYyxuZXcgeChiLnN0eWxlLGIsXCJzdHlsZVwiLGIuc3R5bGUuY3NzVGV4dCkpLGM7dmFyIGU9Yi5hdHRyaWJ1dGVzO2lmKGUpaWYoYSBpbnN0YW5jZW9mIEcmJm51bGw9PT1hLmJ8fFwiKlwiPT1kKWZvcih2YXIgZD0wLGY7Zj1lW2RdO2QrKyl3P2Yubm9kZVZhbHVlJiZGKGMsRGEoYixmKSk6RihjLGYpO2Vsc2UoZj1lLmdldE5hbWVkSXRlbShkKSkmJih3P2Yubm9kZVZhbHVlJiZGKGMsRGEoYixmKSk6RihjLGYpKTtyZXR1cm4gY30sITEpLHRiPVYoXCJjaGlsZFwiLGZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0dXJuKHc/SWE6SmEpLmNhbGwobnVsbCxhLGIsbChjKT9jOm51bGwsbChkKT9kOm51bGwsZXx8bmV3IEMpfSwhMSwhMCk7VihcImRlc2NlbmRhbnRcIixCLCExLCEwKTtcbnZhciB1Yj1WKFwiZGVzY2VuZGFudC1vci1zZWxmXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEM7QShiLGMsZCkmJmEuYShiKSYmRihlLGIpO3JldHVybiBCKGEsYixjLGQsZSl9LCExLCEwKSxwYj1WKFwiZm9sbG93aW5nXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEM7ZG8gZm9yKHZhciBmPWI7Zj1mLm5leHRTaWJsaW5nOylBKGYsYyxkKSYmYS5hKGYpJiZGKGUsZiksZT1CKGEsZixjLGQsZSk7d2hpbGUoYj1iLnBhcmVudE5vZGUpO3JldHVybiBlfSwhMSwhMCk7VihcImZvbGxvd2luZy1zaWJsaW5nXCIsZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9bmV3IEMsZD1iO2Q9ZC5uZXh0U2libGluZzspYS5hKGQpJiZGKGMsZCk7cmV0dXJuIGN9LCExKTtWKFwibmFtZXNwYWNlXCIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEN9LCExKTtcbnZhciB4Yj1WKFwicGFyZW50XCIsZnVuY3Rpb24oYSxiKXt2YXIgYz1uZXcgQztpZig5PT1iLm5vZGVUeXBlKXJldHVybiBjO2lmKDI9PWIubm9kZVR5cGUpcmV0dXJuIEYoYyxiLm93bmVyRWxlbWVudCksYzt2YXIgZD1iLnBhcmVudE5vZGU7YS5hKGQpJiZGKGMsZCk7cmV0dXJuIGN9LCExKSxxYj1WKFwicHJlY2VkaW5nXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEMsZj1bXTtkbyBmLnVuc2hpZnQoYik7d2hpbGUoYj1iLnBhcmVudE5vZGUpO2Zvcih2YXIgZz0xLGg9Zi5sZW5ndGg7ZzxoO2crKyl7dmFyIHA9W107Zm9yKGI9ZltnXTtiPWIucHJldmlvdXNTaWJsaW5nOylwLnVuc2hpZnQoYik7Zm9yKHZhciB5PTAsRD1wLmxlbmd0aDt5PEQ7eSsrKWI9cFt5XSxBKGIsYyxkKSYmYS5hKGIpJiZGKGUsYiksZT1CKGEsYixjLGQsZSl9cmV0dXJuIGV9LCEwLCEwKTtcblYoXCJwcmVjZWRpbmctc2libGluZ1wiLGZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPW5ldyBDLGQ9YjtkPWQucHJldmlvdXNTaWJsaW5nOylhLmEoZCkmJlFhKGMsZCk7cmV0dXJuIGN9LCEwKTt2YXIgeWI9VihcInNlbGZcIixmdW5jdGlvbihhLGIpe3ZhciBjPW5ldyBDO2EuYShiKSYmRihjLGIpO3JldHVybiBjfSwhMSk7ZnVuY3Rpb24gemIoYSl7bi5jYWxsKHRoaXMsMSk7dGhpcy5jPWE7dGhpcy5nPWEuZzt0aGlzLmI9YS5ifW0oemIpO3piLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3JldHVybi1LKHRoaXMuYyxhKX07emIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJVbmFyeSBFeHByZXNzaW9uOiAtXCIrSih0aGlzLmMpfTtmdW5jdGlvbiBBYihhKXtuLmNhbGwodGhpcywxKTt0aGlzLmM9YX1tKEFiKTtBYi5wcm90b3R5cGUuYT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN9O0FiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiTnVtYmVyOiBcIit0aGlzLmN9O2Z1bmN0aW9uIEJiKGEsYil7dGhpcy5hPWE7dGhpcy5iPWJ9ZnVuY3Rpb24gQ2IoYSl7Zm9yKHZhciBiLGM9W107Oyl7VyhhLFwiTWlzc2luZyByaWdodCBoYW5kIHNpZGUgb2YgYmluYXJ5IGV4cHJlc3Npb24uXCIpO2I9RGIoYSk7dmFyIGQ9VChhLmEpO2lmKCFkKWJyZWFrO3ZhciBlPShkPVlhW2RdfHxudWxsKSYmZC53O2lmKCFlKXthLmEuYS0tO2JyZWFrfWZvcig7Yy5sZW5ndGgmJmU8PWNbYy5sZW5ndGgtMV0udzspYj1uZXcgTihjLnBvcCgpLGMucG9wKCksYik7Yy5wdXNoKGIsZCl9Zm9yKDtjLmxlbmd0aDspYj1uZXcgTihjLnBvcCgpLGMucG9wKCksYik7cmV0dXJuIGJ9ZnVuY3Rpb24gVyhhLGIpe2lmKGliKGEuYSkpdGhyb3cgRXJyb3IoYik7fWZ1bmN0aW9uIEViKGEsYil7dmFyIGM9VChhLmEpO2lmKGMhPWIpdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW4sIGV4cGVjdGVkOiBcIitiK1wiIGdvdDogXCIrYyk7fVxuZnVuY3Rpb24gRmIoYSl7YT1UKGEuYSk7aWYoXCIpXCIhPWEpdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW46IFwiK2EpO31mdW5jdGlvbiBHYihhKXthPVQoYS5hKTtpZigyPmEubGVuZ3RoKXRocm93IEVycm9yKFwiVW5jbG9zZWQgbGl0ZXJhbCBzdHJpbmdcIik7cmV0dXJuIG5ldyBqYihhKX1cbmZ1bmN0aW9uIEhiKGEpe3ZhciBiLGM9W10sZDtpZihvYihTKGEuYSkpKXtiPVQoYS5hKTtkPVMoYS5hKTtpZihcIi9cIj09YiYmKGliKGEuYSl8fFwiLlwiIT1kJiZcIi4uXCIhPWQmJlwiQFwiIT1kJiZcIipcIiE9ZCYmIS8oPyFbMC05XSlbXFx3XS8udGVzdChkKSkpcmV0dXJuIG5ldyBtYjtkPW5ldyBtYjtXKGEsXCJNaXNzaW5nIG5leHQgbG9jYXRpb24gc3RlcC5cIik7Yj1JYihhLGIpO2MucHVzaChiKX1lbHNle2E6e2I9UyhhLmEpO2Q9Yi5jaGFyQXQoMCk7c3dpdGNoKGQpe2Nhc2UgXCIkXCI6dGhyb3cgRXJyb3IoXCJWYXJpYWJsZSByZWZlcmVuY2Ugbm90IGFsbG93ZWQgaW4gSFRNTCBYUGF0aFwiKTtjYXNlIFwiKFwiOlQoYS5hKTtiPUNiKGEpO1coYSwndW5jbG9zZWQgXCIoXCInKTtFYihhLFwiKVwiKTticmVhaztjYXNlICdcIic6Y2FzZSBcIidcIjpiPUdiKGEpO2JyZWFrO2RlZmF1bHQ6aWYoaXNOYU4oK2IpKWlmKCFkYihiKSYmLyg/IVswLTldKVtcXHddLy50ZXN0KGQpJiZcIihcIj09UyhhLmEsMSkpe2I9VChhLmEpO1xuYj1jYltiXXx8bnVsbDtUKGEuYSk7Zm9yKGQ9W107XCIpXCIhPVMoYS5hKTspe1coYSxcIk1pc3NpbmcgZnVuY3Rpb24gYXJndW1lbnQgbGlzdC5cIik7ZC5wdXNoKENiKGEpKTtpZihcIixcIiE9UyhhLmEpKWJyZWFrO1QoYS5hKX1XKGEsXCJVbmNsb3NlZCBmdW5jdGlvbiBhcmd1bWVudCBsaXN0LlwiKTtGYihhKTtiPW5ldyBhYihiLGQpfWVsc2V7Yj1udWxsO2JyZWFrIGF9ZWxzZSBiPW5ldyBBYigrVChhLmEpKX1cIltcIj09UyhhLmEpJiYoZD1uZXcgc2IoSmIoYSkpLGI9bmV3IFphKGIsZCkpfWlmKGIpaWYob2IoUyhhLmEpKSlkPWI7ZWxzZSByZXR1cm4gYjtlbHNlIGI9SWIoYSxcIi9cIiksZD1uZXcgbmIsYy5wdXNoKGIpfWZvcig7b2IoUyhhLmEpKTspYj1UKGEuYSksVyhhLFwiTWlzc2luZyBuZXh0IGxvY2F0aW9uIHN0ZXAuXCIpLGI9SWIoYSxiKSxjLnB1c2goYik7cmV0dXJuIG5ldyBrYihkLGMpfVxuZnVuY3Rpb24gSWIoYSxiKXt2YXIgYyxkLGU7aWYoXCIvXCIhPWImJlwiLy9cIiE9Yil0aHJvdyBFcnJvcignU3RlcCBvcCBzaG91bGQgYmUgXCIvXCIgb3IgXCIvL1wiJyk7aWYoXCIuXCI9PVMoYS5hKSlyZXR1cm4gZD1uZXcgVSh5YixuZXcgRyhcIm5vZGVcIikpLFQoYS5hKSxkO2lmKFwiLi5cIj09UyhhLmEpKXJldHVybiBkPW5ldyBVKHhiLG5ldyBHKFwibm9kZVwiKSksVChhLmEpLGQ7dmFyIGY7aWYoXCJAXCI9PVMoYS5hKSlmPWxiLFQoYS5hKSxXKGEsXCJNaXNzaW5nIGF0dHJpYnV0ZSBuYW1lXCIpO2Vsc2UgaWYoXCI6OlwiPT1TKGEuYSwxKSl7aWYoIS8oPyFbMC05XSlbXFx3XS8udGVzdChTKGEuYSkuY2hhckF0KDApKSl0aHJvdyBFcnJvcihcIkJhZCB0b2tlbjogXCIrVChhLmEpKTtjPVQoYS5hKTtmPXdiW2NdfHxudWxsO2lmKCFmKXRocm93IEVycm9yKFwiTm8gYXhpcyB3aXRoIG5hbWU6IFwiK2MpO1QoYS5hKTtXKGEsXCJNaXNzaW5nIG5vZGUgbmFtZVwiKX1lbHNlIGY9dGI7Yz1TKGEuYSk7aWYoLyg/IVswLTldKVtcXHdcXCpdLy50ZXN0KGMuY2hhckF0KDApKSlpZihcIihcIj09XG5TKGEuYSwxKSl7aWYoIWRiKGMpKXRocm93IEVycm9yKFwiSW52YWxpZCBub2RlIHR5cGU6IFwiK2MpO2M9VChhLmEpO2lmKCFkYihjKSl0aHJvdyBFcnJvcihcIkludmFsaWQgdHlwZSBuYW1lOiBcIitjKTtFYihhLFwiKFwiKTtXKGEsXCJCYWQgbm9kZXR5cGVcIik7ZT1TKGEuYSkuY2hhckF0KDApO3ZhciBnPW51bGw7aWYoJ1wiJz09ZXx8XCInXCI9PWUpZz1HYihhKTtXKGEsXCJCYWQgbm9kZXR5cGVcIik7RmIoYSk7Yz1uZXcgRyhjLGcpfWVsc2UgaWYoYz1UKGEuYSksZT1jLmluZGV4T2YoXCI6XCIpLC0xPT1lKWM9bmV3IEUoYyk7ZWxzZXt2YXIgZz1jLnN1YnN0cmluZygwLGUpLGg7aWYoXCIqXCI9PWcpaD1cIipcIjtlbHNlIGlmKGg9YS5iKGcpLCFoKXRocm93IEVycm9yKFwiTmFtZXNwYWNlIHByZWZpeCBub3QgZGVjbGFyZWQ6IFwiK2cpO2M9Yy5zdWJzdHIoZSsxKTtjPW5ldyBFKGMsaCl9ZWxzZSB0aHJvdyBFcnJvcihcIkJhZCB0b2tlbjogXCIrVChhLmEpKTtlPW5ldyBzYihKYihhKSxmLmEpO3JldHVybiBkfHxcbm5ldyBVKGYsYyxlLFwiLy9cIj09Yil9ZnVuY3Rpb24gSmIoYSl7Zm9yKHZhciBiPVtdO1wiW1wiPT1TKGEuYSk7KXtUKGEuYSk7VyhhLFwiTWlzc2luZyBwcmVkaWNhdGUgZXhwcmVzc2lvbi5cIik7dmFyIGM9Q2IoYSk7Yi5wdXNoKGMpO1coYSxcIlVuY2xvc2VkIHByZWRpY2F0ZSBleHByZXNzaW9uLlwiKTtFYihhLFwiXVwiKX1yZXR1cm4gYn1mdW5jdGlvbiBEYihhKXtpZihcIi1cIj09UyhhLmEpKXJldHVybiBUKGEuYSksbmV3IHpiKERiKGEpKTt2YXIgYj1IYihhKTtpZihcInxcIiE9UyhhLmEpKWE9YjtlbHNle2ZvcihiPVtiXTtcInxcIj09VChhLmEpOylXKGEsXCJNaXNzaW5nIG5leHQgdW5pb24gbG9jYXRpb24gcGF0aC5cIiksYi5wdXNoKEhiKGEpKTthLmEuYS0tO2E9bmV3IHJiKGIpfXJldHVybiBhfTtmdW5jdGlvbiBLYihhKXtzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOnJldHVybiBlYShMYixhKTtjYXNlIDk6cmV0dXJuIEtiKGEuZG9jdW1lbnRFbGVtZW50KTtjYXNlIDExOmNhc2UgMTA6Y2FzZSA2OmNhc2UgMTI6cmV0dXJuIE1iO2RlZmF1bHQ6cmV0dXJuIGEucGFyZW50Tm9kZT9LYihhLnBhcmVudE5vZGUpOk1ifX1mdW5jdGlvbiBNYigpe3JldHVybiBudWxsfWZ1bmN0aW9uIExiKGEsYil7aWYoYS5wcmVmaXg9PWIpcmV0dXJuIGEubmFtZXNwYWNlVVJJfHxcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjt2YXIgYz1hLmdldEF0dHJpYnV0ZU5vZGUoXCJ4bWxuczpcIitiKTtyZXR1cm4gYyYmYy5zcGVjaWZpZWQ/Yy52YWx1ZXx8bnVsbDphLnBhcmVudE5vZGUmJjkhPWEucGFyZW50Tm9kZS5ub2RlVHlwZT9MYihhLnBhcmVudE5vZGUsYik6bnVsbH07ZnVuY3Rpb24gTmIoYSxiKXtpZighYS5sZW5ndGgpdGhyb3cgRXJyb3IoXCJFbXB0eSBYUGF0aCBleHByZXNzaW9uLlwiKTt2YXIgYz1mYihhKTtpZihpYihjKSl0aHJvdyBFcnJvcihcIkludmFsaWQgWFBhdGggZXhwcmVzc2lvbi5cIik7Yj9cImZ1bmN0aW9uXCI9PWFhKGIpfHwoYj1kYShiLmxvb2t1cE5hbWVzcGFjZVVSSSxiKSk6Yj1mdW5jdGlvbigpe3JldHVybiBudWxsfTt2YXIgZD1DYihuZXcgQmIoYyxiKSk7aWYoIWliKGMpKXRocm93IEVycm9yKFwiQmFkIHRva2VuOiBcIitUKGMpKTt0aGlzLmV2YWx1YXRlPWZ1bmN0aW9uKGEsYil7dmFyIGM9ZC5hKG5ldyBRKGEpKTtyZXR1cm4gbmV3IFkoYyxiKX19XG5mdW5jdGlvbiBZKGEsYil7aWYoMD09YilpZihhIGluc3RhbmNlb2YgQyliPTQ7ZWxzZSBpZihcInN0cmluZ1wiPT10eXBlb2YgYSliPTI7ZWxzZSBpZihcIm51bWJlclwiPT10eXBlb2YgYSliPTE7ZWxzZSBpZihcImJvb2xlYW5cIj09dHlwZW9mIGEpYj0zO2Vsc2UgdGhyb3cgRXJyb3IoXCJVbmV4cGVjdGVkIGV2YWx1YXRpb24gcmVzdWx0LlwiKTtpZigyIT1iJiYxIT1iJiYzIT1iJiYhKGEgaW5zdGFuY2VvZiBDKSl0aHJvdyBFcnJvcihcInZhbHVlIGNvdWxkIG5vdCBiZSBjb252ZXJ0ZWQgdG8gdGhlIHNwZWNpZmllZCB0eXBlXCIpO3RoaXMucmVzdWx0VHlwZT1iO3ZhciBjO3N3aXRjaChiKXtjYXNlIDI6dGhpcy5zdHJpbmdWYWx1ZT1hIGluc3RhbmNlb2YgQz9TYShhKTpcIlwiK2E7YnJlYWs7Y2FzZSAxOnRoaXMubnVtYmVyVmFsdWU9YSBpbnN0YW5jZW9mIEM/K1NhKGEpOithO2JyZWFrO2Nhc2UgMzp0aGlzLmJvb2xlYW5WYWx1ZT1hIGluc3RhbmNlb2YgQz8wPGEubDohIWE7YnJlYWs7Y2FzZSA0OmNhc2UgNTpjYXNlIDY6Y2FzZSA3OnZhciBkPVxuSChhKTtjPVtdO2Zvcih2YXIgZT1JKGQpO2U7ZT1JKGQpKWMucHVzaChlIGluc3RhbmNlb2YgeD9lLmE6ZSk7dGhpcy5zbmFwc2hvdExlbmd0aD1hLmw7dGhpcy5pbnZhbGlkSXRlcmF0b3JTdGF0ZT0hMTticmVhaztjYXNlIDg6Y2FzZSA5OmQ9UmEoYSk7dGhpcy5zaW5nbGVOb2RlVmFsdWU9ZCBpbnN0YW5jZW9mIHg/ZC5hOmQ7YnJlYWs7ZGVmYXVsdDp0aHJvdyBFcnJvcihcIlVua25vd24gWFBhdGhSZXN1bHQgdHlwZS5cIik7fXZhciBmPTA7dGhpcy5pdGVyYXRlTmV4dD1mdW5jdGlvbigpe2lmKDQhPWImJjUhPWIpdGhyb3cgRXJyb3IoXCJpdGVyYXRlTmV4dCBjYWxsZWQgd2l0aCB3cm9uZyByZXN1bHQgdHlwZVwiKTtyZXR1cm4gZj49Yy5sZW5ndGg/bnVsbDpjW2YrK119O3RoaXMuc25hcHNob3RJdGVtPWZ1bmN0aW9uKGEpe2lmKDYhPWImJjchPWIpdGhyb3cgRXJyb3IoXCJzbmFwc2hvdEl0ZW0gY2FsbGVkIHdpdGggd3JvbmcgcmVzdWx0IHR5cGVcIik7cmV0dXJuIGE+PWMubGVuZ3RofHxcbjA+YT9udWxsOmNbYV19fVkuQU5ZX1RZUEU9MDtZLk5VTUJFUl9UWVBFPTE7WS5TVFJJTkdfVFlQRT0yO1kuQk9PTEVBTl9UWVBFPTM7WS5VTk9SREVSRURfTk9ERV9JVEVSQVRPUl9UWVBFPTQ7WS5PUkRFUkVEX05PREVfSVRFUkFUT1JfVFlQRT01O1kuVU5PUkRFUkVEX05PREVfU05BUFNIT1RfVFlQRT02O1kuT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEU9NztZLkFOWV9VTk9SREVSRURfTk9ERV9UWVBFPTg7WS5GSVJTVF9PUkRFUkVEX05PREVfVFlQRT05O2Z1bmN0aW9uIE9iKGEpe3RoaXMubG9va3VwTmFtZXNwYWNlVVJJPUtiKGEpfVxuZnVuY3Rpb24gUGIoYSxiKXt2YXIgYz1hfHxrLGQ9Yy5Eb2N1bWVudCYmYy5Eb2N1bWVudC5wcm90b3R5cGV8fGMuZG9jdW1lbnQ7aWYoIWQuZXZhbHVhdGV8fGIpYy5YUGF0aFJlc3VsdD1ZLGQuZXZhbHVhdGU9ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuKG5ldyBOYihhLGMpKS5ldmFsdWF0ZShiLGQpfSxkLmNyZWF0ZUV4cHJlc3Npb249ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IE5iKGEsYil9LGQuY3JlYXRlTlNSZXNvbHZlcj1mdW5jdGlvbihhKXtyZXR1cm4gbmV3IE9iKGEpfX12YXIgUWI9W1wid2d4cGF0aFwiLFwiaW5zdGFsbFwiXSxaPWs7UWJbMF1pbiBafHwhWi5leGVjU2NyaXB0fHxaLmV4ZWNTY3JpcHQoXCJ2YXIgXCIrUWJbMF0pO2Zvcih2YXIgUmI7UWIubGVuZ3RoJiYoUmI9UWIuc2hpZnQoKSk7KVFiLmxlbmd0aHx8dm9pZCAwPT09UGI/WltSYl0/Wj1aW1JiXTpaPVpbUmJdPXt9OlpbUmJdPVBiO21vZHVsZS5leHBvcnRzLmluc3RhbGw9UGI7bW9kdWxlLmV4cG9ydHMuWFBhdGhSZXN1bHRUeXBlPXtBTllfVFlQRTowLE5VTUJFUl9UWVBFOjEsU1RSSU5HX1RZUEU6MixCT09MRUFOX1RZUEU6MyxVTk9SREVSRURfTk9ERV9JVEVSQVRPUl9UWVBFOjQsT1JERVJFRF9OT0RFX0lURVJBVE9SX1RZUEU6NSxVTk9SREVSRURfTk9ERV9TTkFQU0hPVF9UWVBFOjYsT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEU6NyxBTllfVU5PUkRFUkVEX05PREVfVFlQRTo4LEZJUlNUX09SREVSRURfTk9ERV9UWVBFOjl9O30pLmNhbGwoZ2xvYmFsKVxuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4vLyBCYWNrd2FyZCBDb21wYXQgVGFibGVcbid1c2Ugc3RyaWN0JztcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQob2JqKSB7IGlmIChvYmogJiYgb2JqLl9fZXNNb2R1bGUpIHsgcmV0dXJuIG9iajsgfSBlbHNlIHsgdmFyIG5ld09iaiA9IHt9OyBpZiAob2JqICE9IG51bGwpIHsgZm9yICh2YXIga2V5IGluIG9iaikgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkgbmV3T2JqW2tleV0gPSBvYmpba2V5XTsgfSB9IG5ld09ialsnZGVmYXVsdCddID0gb2JqOyByZXR1cm4gbmV3T2JqOyB9IH1cblxudmFyIF9odHRwUHlkaW9Vc2Vyc0FwaSA9IHJlcXVpcmUoJy4vaHR0cC9QeWRpb1VzZXJzQXBpJyk7XG5cbnZhciBVc2Vyc0FwaSA9IF9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkKF9odHRwUHlkaW9Vc2Vyc0FwaSk7XG5cbnZhciBDb25uZXhpb24gPSByZXF1aXJlKCcuL2h0dHAvQ29ubmV4aW9uJyksXG4gICAgTWV0YUNhY2hlU2VydmljZSA9IHJlcXVpcmUoJy4vaHR0cC9NZXRhQ2FjaGVTZXJ2aWNlJyksXG4gICAgUHlkaW9BcGkgPSByZXF1aXJlKCcuL2h0dHAvUHlkaW9BcGknKSxcbiAgICBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi9odHRwL1Jlc291cmNlc01hbmFnZXInKSxcbiAgICBMb2dnZXIgPSByZXF1aXJlKCcuL2xhbmcvTG9nZ2VyJyksXG4gICAgT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4vbGFuZy9PYnNlcnZhYmxlJyksXG4gICAgQWN0aW9uID0gcmVxdWlyZSgnLi9tb2RlbC9BY3Rpb24nKSxcbiAgICBBanhwTm9kZSA9IHJlcXVpcmUoJy4vbW9kZWwvQWp4cE5vZGUnKSxcbiAgICBDb250cm9sbGVyID0gcmVxdWlyZSgnLi9tb2RlbC9Db250cm9sbGVyJyksXG4gICAgRW1wdHlOb2RlUHJvdmlkZXIgPSByZXF1aXJlKCcuL21vZGVsL0VtcHR5Tm9kZVByb3ZpZGVyJyksXG4gICAgUHlkaW9EYXRhTW9kZWwgPSByZXF1aXJlKCcuL21vZGVsL1B5ZGlvRGF0YU1vZGVsJyksXG4gICAgUmVnaXN0cnkgPSByZXF1aXJlKCcuL21vZGVsL1JlZ2lzdHJ5JyksXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyID0gcmVxdWlyZSgnLi9tb2RlbC9SZW1vdGVOb2RlUHJvdmlkZXInKSxcbiAgICBSZXBvc2l0b3J5ID0gcmVxdWlyZSgnLi9tb2RlbC9SZXBvc2l0b3J5JyksXG4gICAgVXNlciA9IHJlcXVpcmUoJy4vbW9kZWwvVXNlcicpLFxuICAgIENvbnRleHRNZW51ID0gcmVxdWlyZSgnLi9tb2RlbC9Db250ZXh0TWVudScpLFxuICAgIENvb2tpZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi91dGlsL0Nvb2tpZXNNYW5hZ2VyJyksXG4gICAgRE9NVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvRE9NVXRpbHMnKSxcbiAgICBGdW5jVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvRnVuY1V0aWxzJyksXG4gICAgSGFzaGVyVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvSGFzaGVyVXRpbHMnKSxcbiAgICBMYW5nVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvTGFuZ1V0aWxzJyksXG4gICAgUGFzc1V0aWxzID0gcmVxdWlyZSgnLi91dGlsL1Bhc3NVdGlscycpLFxuICAgIFBhdGhVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9QYXRoVXRpbHMnKSxcbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIgPSByZXF1aXJlKCcuL3V0aWwvUGVyaW9kaWNhbEV4ZWN1dGVyJyksXG4gICAgQWN0aXZpdHlNb25pdG9yID0gcmVxdWlyZSgnLi91dGlsL0FjdGl2aXR5TW9uaXRvcicpLFxuICAgIFhNTFV0aWxzID0gcmVxdWlyZSgnLi91dGlsL1hNTFV0aWxzJyksXG4gICAgUHlkaW8gPSByZXF1aXJlKCcuL1B5ZGlvJyk7XG5cbnZhciBQeWRpb1VzZXJzID0ge1xuICAgIENsaWVudDogVXNlcnNBcGkuVXNlcnNBcGksXG4gICAgVXNlcjogVXNlcnNBcGkuVXNlclxufTtcblxudmFyIG5hbWVzcGFjZSA9IHtcbiAgICBDb25uZXhpb246IENvbm5leGlvbixcbiAgICBNZXRhQ2FjaGVTZXJ2aWNlOiBNZXRhQ2FjaGVTZXJ2aWNlLFxuICAgIFB5ZGlvQXBpOiBQeWRpb0FwaSxcbiAgICBQeWRpb1VzZXJzOiBQeWRpb1VzZXJzLFxuICAgIFJlc291cmNlc01hbmFnZXI6IFJlc291cmNlc01hbmFnZXIsXG4gICAgTG9nZ2VyOiBMb2dnZXIsXG4gICAgT2JzZXJ2YWJsZTogT2JzZXJ2YWJsZSxcbiAgICBBY3Rpb246IEFjdGlvbixcbiAgICBBanhwTm9kZTogQWp4cE5vZGUsXG4gICAgQ29udHJvbGxlcjogQ29udHJvbGxlcixcbiAgICBFbXB0eU5vZGVQcm92aWRlcjogRW1wdHlOb2RlUHJvdmlkZXIsXG4gICAgUHlkaW9EYXRhTW9kZWw6IFB5ZGlvRGF0YU1vZGVsLFxuICAgIFJlZ2lzdHJ5OiBSZWdpc3RyeSxcbiAgICBSZW1vdGVOb2RlUHJvdmlkZXI6IFJlbW90ZU5vZGVQcm92aWRlcixcbiAgICBSZXBvc2l0b3J5OiBSZXBvc2l0b3J5LFxuICAgIFVzZXI6IFVzZXIsXG4gICAgQ29udGV4dE1lbnU6IENvbnRleHRNZW51LFxuICAgIENvb2tpZXNNYW5hZ2VyOiBDb29raWVzTWFuYWdlcixcbiAgICBET01VdGlsczogRE9NVXRpbHMsXG4gICAgRnVuY1V0aWxzOiBGdW5jVXRpbHMsXG4gICAgSGFzaGVyVXRpbHM6IEhhc2hlclV0aWxzLFxuICAgIExhbmdVdGlsczogTGFuZ1V0aWxzLFxuICAgIFBhc3NVdGlsczogUGFzc1V0aWxzLFxuICAgIFBhdGhVdGlsczogUGF0aFV0aWxzLFxuICAgIFBlcmlvZGljYWxFeGVjdXRlcjogUGVyaW9kaWNhbEV4ZWN1dGVyLFxuICAgIEFjdGl2aXR5TW9uaXRvcjogQWN0aXZpdHlNb25pdG9yLFxuICAgIFhNTFV0aWxzOiBYTUxVdGlscyxcbiAgICBQeWRpbzogUHlkaW9cbn07XG5cbk9iamVjdC5hc3NpZ24od2luZG93LCBfZXh0ZW5kcyh7fSwgbmFtZXNwYWNlLCB7IFB5ZGlvQ29yZTogbmFtZXNwYWNlIH0pKTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbi8qKlxuICogQVBJIENsaWVudFxuICovXG5cbnZhciBQeWRpb0FwaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHlkaW9BcGkoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQeWRpb0FwaSk7XG4gICAgfVxuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnNldFB5ZGlvT2JqZWN0ID0gZnVuY3Rpb24gc2V0UHlkaW9PYmplY3QocHlkaW9PYmplY3QpIHtcbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QgPSBweWRpb09iamVjdDtcbiAgICAgICAgdGhpcy5fYmFzZVVybCA9IHB5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KCdzZXJ2ZXJBY2Nlc3NQYXRoJyk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5yZXF1ZXN0ID0gZnVuY3Rpb24gcmVxdWVzdChwYXJhbWV0ZXJzKSB7XG4gICAgICAgIHZhciBvbkNvbXBsZXRlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIG9uRXJyb3IgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICAvLyBDb25uZXhpb24gYWxyZWFkeSBoYW5kbGVzIHNlY3VyZV90b2tlblxuICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oKTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmRpc2NyZXRlKSB7XG4gICAgICAgICAgICBjLmRpc2NyZXRlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjLnNldFBhcmFtZXRlcnMocGFyYW1ldGVycyk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5tZXRob2QpIHtcbiAgICAgICAgICAgIGMuc2V0TWV0aG9kKHNldHRpbmdzLm1ldGhvZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFvbkNvbXBsZXRlKSB7XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MKSByZXR1cm4gdGhpcy5wYXJzZVhtbE1lc3NhZ2UodHJhbnNwb3J0LnJlc3BvbnNlWE1MKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgYy5vbkNvbXBsZXRlID0gb25Db21wbGV0ZTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmFzeW5jID09PSBmYWxzZSkge1xuICAgICAgICAgICAgYy5zZW5kU3luYygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYy5zZW5kQXN5bmMoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUubG9hZEZpbGUgPSBmdW5jdGlvbiBsb2FkRmlsZShmaWxlUGF0aCkge1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBvbkVycm9yID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oZmlsZVBhdGgpO1xuICAgICAgICBjLnNldE1ldGhvZCgnR0VUJyk7XG4gICAgICAgIGMub25Db21wbGV0ZSA9IG9uQ29tcGxldGU7XG4gICAgICAgIGMuc2VuZEFzeW5jKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBmaWxlXG4gICAgICogQHBhcmFtIGZpbGVQYXJhbWV0ZXJOYW1lXG4gICAgICogQHBhcmFtIHF1ZXJ5U3RyaW5nUGFyYW1zXG4gICAgICogQHBhcmFtIG9uQ29tcGxldGVcbiAgICAgKiBAcGFyYW0gb25FcnJvclxuICAgICAqIEBwYXJhbSBvblByb2dyZXNzXG4gICAgICogQHJldHVybnMgWEhSIEhhbmRsZSB0byBhYm9ydCB0cmFuc2ZlclxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnVwbG9hZEZpbGUgPSBmdW5jdGlvbiB1cGxvYWRGaWxlKGZpbGUsIGZpbGVQYXJhbWV0ZXJOYW1lKSB7XG4gICAgICAgIHZhciBxdWVyeVN0cmluZ1BhcmFtcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzNdO1xuICAgICAgICB2YXIgb25FcnJvciA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNCB8fCBhcmd1bWVudHNbNF0gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzRdO1xuICAgICAgICB2YXIgb25Qcm9ncmVzcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNSB8fCBhcmd1bWVudHNbNV0gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzVdO1xuICAgICAgICB2YXIgdXBsb2FkVXJsID0gYXJndW1lbnRzLmxlbmd0aCA8PSA2IHx8IGFyZ3VtZW50c1s2XSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbNl07XG4gICAgICAgIHZhciB4aHJTZXR0aW5ncyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNyB8fCBhcmd1bWVudHNbN10gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzddO1xuXG4gICAgICAgIGlmICghdXBsb2FkVXJsKSB7XG4gICAgICAgICAgICB1cGxvYWRVcmwgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnYWp4cFNlcnZlckFjY2VzcycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChxdWVyeVN0cmluZ1BhcmFtcykge1xuICAgICAgICAgICAgdXBsb2FkVXJsICs9ICh1cGxvYWRVcmwuaW5kZXhPZignPycpID09PSAtMSA/ICc/JyA6ICcmJykgKyBxdWVyeVN0cmluZ1BhcmFtcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh3aW5kb3cuQ29ubmV4aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3JldCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gV2FybmluZywgYXZvaWQgZG91YmxlIGVycm9yXG4gICAgICAgICAgICAgICAgdmFyIGVycm9yU2VudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBsb2NhbEVycm9yID0gZnVuY3Rpb24gbG9jYWxFcnJvcih4aHIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvclNlbnQpIG9uRXJyb3IoJ1JlcXVlc3QgZmFpbGVkIHdpdGggc3RhdHVzIDonICsgeGhyLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yU2VudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB2OiBjLnVwbG9hZEZpbGUoZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUsIHVwbG9hZFVybCwgb25Db21wbGV0ZSwgbG9jYWxFcnJvciwgb25Qcm9ncmVzcywgeGhyU2V0dGluZ3MpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pKCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3JldCA9PT0gJ29iamVjdCcpIHJldHVybiBfcmV0LnY7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdXNlclNlbGVjdGlvbiBVc2VyU2VsZWN0aW9uIEEgUHlkaW8gRGF0YU1vZGVsIHdpdGggc2VsZWN0ZWQgZmlsZXNcbiAgICAgKiBAcGFyYW0gcHJvdG90eXBlSGlkZGVuRm9ybSBFbGVtZW50IEEgaGlkZGVuIGZvcm0gZWxlbWVudDogY3VycmVudGx5IHJlbHlpbmcgb24gUHJvdG90eXBlSlMuXG4gICAgICogQHBhcmFtIGRsQWN0aW9uTmFtZSBTdHJpbmcgQWN0aW9uIG5hbWUgdG8gdHJpZ2dlciwgZG93bmxvYWQgYnkgZGVmYXVsdC5cbiAgICAgKiBAcGFyYW0gYWRkaXRpb25hbFBhcmFtZXRlcnMgT2JqZWN0IE9wdGlvbmFsIHNldCBvZiBrZXkvdmFsdWVzIHRvIHBhc3MgdG8gdGhlIGRvd25sb2FkLlxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmRvd25sb2FkU2VsZWN0aW9uID0gZnVuY3Rpb24gZG93bmxvYWRTZWxlY3Rpb24odXNlclNlbGVjdGlvbikge1xuICAgICAgICB2YXIgZGxBY3Rpb25OYW1lID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gJ2Rvd25sb2FkJyA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgdmFyIGFqeHBTZXJ2ZXJBY2Nlc3MgPSB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldChcImFqeHBTZXJ2ZXJBY2Nlc3NcIik7XG4gICAgICAgIHZhciBhZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQgfHwgJyc7XG4gICAgICAgIHZhciBhZ2VudElzTW9iaWxlID0gYWdlbnQuaW5kZXhPZignaVBob25lJykgIT0gLTEgfHwgYWdlbnQuaW5kZXhPZignaVBvZCcpICE9IC0xIHx8IGFnZW50LmluZGV4T2YoJ2lQYWQnKSAhPSAtMSB8fCBhZ2VudC5pbmRleE9mKCdpT3MnKSAhPSAtMTtcbiAgICAgICAgdmFyIGhpZGRlbkZvcm0gPSBweWRpbyAmJiBweWRpby5VSSAmJiBweWRpby5VSS5oYXNIaWRkZW5Eb3dubG9hZEZvcm0oKTtcbiAgICAgICAgaWYgKGFnZW50SXNNb2JpbGUgfHwgIWhpZGRlbkZvcm0pIHtcbiAgICAgICAgICAgIHZhciBkb3dubG9hZFVybCA9IGFqeHBTZXJ2ZXJBY2Nlc3MgKyAnJmdldF9hY3Rpb249JyArIGRsQWN0aW9uTmFtZTtcbiAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1ldGVycykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHBhcmFtIGluIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1ldGVycy5oYXNPd25Qcm9wZXJ0eShwYXJhbSkpIGRvd25sb2FkVXJsICs9IFwiJlwiICsgcGFyYW0gKyBcIj1cIiArIGFkZGl0aW9uYWxQYXJhbWV0ZXJzW3BhcmFtXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodXNlclNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGRvd25sb2FkVXJsID0gdXNlclNlbGVjdGlvbi51cGRhdGVGb3JtT3JVcmwobnVsbCwgZG93bmxvYWRVcmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZG9jdW1lbnQubG9jYXRpb24uaHJlZiA9IGRvd25sb2FkVXJsO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICB2YXIgcGFyYW1ldGVycyA9IF9leHRlbmRzKHt9LCBhZGRpdGlvbmFsUGFyYW1ldGVycywgeyBzZWN1cmVfdG9rZW46IHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KFwiU0VDVVJFX1RPS0VOXCIpLCBnZXRfYWN0aW9uOiBkbEFjdGlvbk5hbWUgfSk7XG4gICAgICAgICAgICB2YXIgbWluaXNpdGVfc2Vzc2lvbiA9IFB5ZGlvQXBpLmRldGVjdE1pbmlzaXRlU2Vzc2lvbihhanhwU2VydmVyQWNjZXNzKTtcbiAgICAgICAgICAgIGlmIChtaW5pc2l0ZV9zZXNzaW9uKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyc1snbWluaXNpdGVfc2Vzc2lvbiddID0gbWluaXNpdGVfc2Vzc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcHlkaW8uVUkuc2VuZERvd25sb2FkVG9IaWRkZW5Gb3JtKHVzZXJTZWxlY3Rpb24sIHBhcmFtZXRlcnMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmICh3aW5kb3cuY29uc29sZSkgd2luZG93LmNvbnNvbGUuZXJyb3IoXCJFcnJvciB3aGlsZSBzdWJtaXR0aW5nIGhpZGRlbiBmb3JtIGZvciBkb3dubG9hZFwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUucG9zdFBsYWluVGV4dENvbnRlbnQgPSBmdW5jdGlvbiBwb3N0UGxhaW5UZXh0Q29udGVudChmaWxlUGF0aCwgY29udGVudCwgZmluaXNoZWRDYWxsYmFjaykge1xuXG4gICAgICAgIHRoaXMucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAncHV0X2NvbnRlbnQnLFxuICAgICAgICAgICAgZmlsZTogZmlsZVBhdGgsXG4gICAgICAgICAgICBjb250ZW50OiBjb250ZW50XG4gICAgICAgIH0sIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB2YXIgc3VjY2VzcyA9IHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICBmaW5pc2hlZENhbGxiYWNrKHN1Y2Nlc3MpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBmaW5pc2hlZENhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBhIG1pbmlzaXRlX3Nlc3Npb24gcGFyYW1ldGVyIGluIHRoZSBVUkxcbiAgICAgKiBAcGFyYW0gc2VydmVyQWNjZXNzXG4gICAgICogQHJldHVybnMgc3RyaW5nfGJvb2xcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLmRldGVjdE1pbmlzaXRlU2Vzc2lvbiA9IGZ1bmN0aW9uIGRldGVjdE1pbmlzaXRlU2Vzc2lvbihzZXJ2ZXJBY2Nlc3MpIHtcbiAgICAgICAgdmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cCgnLio/WyZcXFxcP10nICsgJ21pbmlzaXRlX3Nlc3Npb24nICsgJz0oLio/KSY/Lio/Jyk7XG4gICAgICAgIHZhciB2YWwgPSBzZXJ2ZXJBY2Nlc3MucmVwbGFjZShyZWdleCwgXCIkMVwiKTtcbiAgICAgICAgcmV0dXJuIHZhbCA9PT0gc2VydmVyQWNjZXNzID8gZmFsc2UgOiB2YWw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdHMgaWYgY3VycmVudCBicm93c2VyIHN1cHBvcnRzIEhUTUw1IFVwbG9hZC5cbiAgICAgKiBAcmV0dXJucyBib29sZWFuXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5zdXBwb3J0c1VwbG9hZCA9IGZ1bmN0aW9uIHN1cHBvcnRzVXBsb2FkKCkge1xuICAgICAgICBpZiAod2luZG93LkNvbm5leGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5Gb3JtRGF0YSB8fCB3aW5kb3cuRmlsZVJlYWRlcjtcbiAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cualF1ZXJ5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LkZvcm1EYXRhO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSW5zdGFuY2lhdGUgYSBQeWRpb0FwaSBjbGllbnQgaWYgaXQncyBub3QgYWxyZWFkeSBpbnN0YW5jaWF0ZWQgYW5kIHJldHVybiBpdC5cbiAgICAgKiBAcmV0dXJucyBQeWRpb0FwaVxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkuZ2V0Q2xpZW50ID0gZnVuY3Rpb24gZ2V0Q2xpZW50KCkge1xuICAgICAgICBpZiAoUHlkaW9BcGkuX1B5ZGlvQ2xpZW50KSByZXR1cm4gUHlkaW9BcGkuX1B5ZGlvQ2xpZW50O1xuICAgICAgICB2YXIgY2xpZW50ID0gbmV3IFB5ZGlvQXBpKCk7XG4gICAgICAgIFB5ZGlvQXBpLl9QeWRpb0NsaWVudCA9IGNsaWVudDtcbiAgICAgICAgcmV0dXJuIGNsaWVudDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIGphdmFzY3JpcHQgbGlicmFyeVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gb25Mb2FkZWRDb2RlIEZ1bmN0aW9uIENhbGxiYWNrXG4gICAgICogQHBhcmFtIGFTeW5jIEJvb2xlYW4gbG9hZCBsaWJyYXJ5IGFzeW5jaHJvbmVvdXNseVxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkubG9hZExpYnJhcnkgPSBmdW5jdGlvbiBsb2FkTGlicmFyeShmaWxlTmFtZSwgb25Mb2FkZWRDb2RlLCBhU3luYykge1xuICAgICAgICBpZiAod2luZG93LnB5ZGlvICYmIHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KFwiYWp4cFZlcnNpb25cIikgJiYgZmlsZU5hbWUuaW5kZXhPZihcIj9cIikgPT0gLTEpIHtcbiAgICAgICAgICAgIGZpbGVOYW1lICs9IFwiP3Y9XCIgKyBweWRpby5QYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIFB5ZGlvQXBpLl9saWJVcmwgPSBmYWxzZTtcbiAgICAgICAgaWYgKHdpbmRvdy5weWRpbyAmJiBweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSkge1xuICAgICAgICAgICAgUHlkaW9BcGkuX2xpYlVybCA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbm4gPSBuZXcgQ29ubmV4aW9uKCk7XG4gICAgICAgIGNvbm4uX2xpYlVybCA9IGZhbHNlO1xuICAgICAgICBpZiAocHlkaW8uUGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QUkVGSVhfVVJJJykpIHtcbiAgICAgICAgICAgIGNvbm4uX2xpYlVybCA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbm4ubG9hZExpYnJhcnkoZmlsZU5hbWUsIG9uTG9hZGVkQ29kZSwgYVN5bmMpO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3dpdGNoUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIHN3aXRjaFJlcG9zaXRvcnkocmVwb3NpdG9yeUlkLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnc3dpdGNoX3JlcG9zaXRvcnknLFxuICAgICAgICAgICAgcmVwb3NpdG9yeV9pZDogcmVwb3NpdG9yeUlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3dpdGNoTGFuZ3VhZ2UgPSBmdW5jdGlvbiBzd2l0Y2hMYW5ndWFnZShsYW5nLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnZ2V0X2kxOG5fbWVzc2FnZXMnLFxuICAgICAgICAgICAgbGFuZzogbGFuZyxcbiAgICAgICAgICAgIGZvcm1hdDogJ2pzb24nXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUubG9hZFhtbFJlZ2lzdHJ5ID0gZnVuY3Rpb24gbG9hZFhtbFJlZ2lzdHJ5KGNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHhQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICB2YXIgcGFyYW1zID0geyBnZXRfYWN0aW9uOiAnZ2V0X3htbF9yZWdpc3RyeScgfTtcbiAgICAgICAgaWYgKHhQYXRoKSBwYXJhbXNbeFBhdGhdID0geFBhdGg7XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuZ2V0Qm9vdENvbmYgPSBmdW5jdGlvbiBnZXRCb290Q29uZihjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7IGdldF9hY3Rpb246ICdnZXRfYm9vdF9jb25mJyB9O1xuICAgICAgICB2YXIgY0IgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZUpTT04gJiYgdHJhbnNwb3J0LnJlc3BvbnNlSlNPTi5TRUNVUkVfVE9LRU4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLnNldCgnU0VDVVJFX1RPS0VOJywgdHJhbnNwb3J0LnJlc3BvbnNlSlNPTi5TRUNVUkVfVE9LRU4pO1xuICAgICAgICAgICAgICAgIENvbm5leGlvbi51cGRhdGVTZXJ2ZXJBY2Nlc3ModGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNvbXBsZXRlQ2FsbGJhY2sodHJhbnNwb3J0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHBhcmFtcywgY0IpO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUudXNlclNhdmVQcmVmZXJlbmNlID0gZnVuY3Rpb24gdXNlclNhdmVQcmVmZXJlbmNlKHByZWZOYW1lLCBwcmVmVmFsdWUpIHtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHsgZ2V0X2FjdGlvbjogXCJzYXZlX3VzZXJfcHJlZlwiLCBcInByZWZfbmFtZV8wXCI6IHByZWZOYW1lLCBcInByZWZfdmFsdWVfMFwiOiBwcmVmVmFsdWUgfSwgbnVsbCwgbnVsbCwgeyBkaXNjcmV0ZTogdHJ1ZSwgbWV0aG9kOiAncG9zdCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS51c2VyU2F2ZVByZWZlcmVuY2VzID0gZnVuY3Rpb24gdXNlclNhdmVQcmVmZXJlbmNlcyhwcmVmZXJlbmNlcywgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgcGFyYW1zID0geyAnZ2V0X2FjdGlvbic6ICdzYXZlX3VzZXJfcHJlZicgfTtcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBwcmVmZXJlbmNlcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICBwYXJhbXNbXCJwcmVmX25hbWVfXCIgKyBpXSA9IGtleTtcbiAgICAgICAgICAgIHBhcmFtc1tcInByZWZfdmFsdWVfXCIgKyBpXSA9IHZhbHVlO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHBhcmFtcywgY29tcGxldGVDYWxsYmFjaywgbnVsbCwgeyBkaXNjcmV0ZTogdHJ1ZSwgbWV0aG9kOiAncG9zdCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS51c2VyU2F2ZVBhc3N3b3JkID0gZnVuY3Rpb24gdXNlclNhdmVQYXNzd29yZChvbGRQYXNzLCBuZXdQYXNzLCBzZWVkLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnc2F2ZV91c2VyX3ByZWYnLFxuICAgICAgICAgICAgcHJlZl9uYW1lXzA6IFwicGFzc3dvcmRcIixcbiAgICAgICAgICAgIHByZWZfdmFsdWVfMDogbmV3UGFzcyxcbiAgICAgICAgICAgIGNydDogb2xkUGFzcyxcbiAgICAgICAgICAgIHBhc3Nfc2VlZDogc2VlZFxuICAgICAgICB9LCBjb21wbGV0ZUNhbGxiYWNrLCBudWxsLCB7IGRpc2NyZXRlOiB0cnVlLCBtZXRob2Q6ICdwb3N0JyB9KTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmJ1aWxkVXNlckF2YXRhclVybCA9IGZ1bmN0aW9uIGJ1aWxkVXNlckF2YXRhclVybCh1c2VySWQpIHtcbiAgICAgICAgdmFyIGF2YXRhcklkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAoYXZhdGFySWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldCgnYWp4cFNlcnZlckFjY2VzcycpICsgXCImZ2V0X2FjdGlvbj1nZXRfYmluYXJ5X3BhcmFtJmJpbmFyeV9pZD1cIiArIGF2YXRhcklkICsgXCImdXNlcl9pZD1cIiArIHVzZXJJZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5hcHBseUNoZWNrSG9vayA9IGZ1bmN0aW9uIGFwcGx5Q2hlY2tIb29rKG5vZGUsIGhvb2tOYW1lLCBob29rQXJnLCBjb21wbGV0ZUNhbGxiYWNrLCBhZGRpdGlvbmFsUGFyYW1zKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiBcImFwcGx5X2NoZWNrX2hvb2tcIixcbiAgICAgICAgICAgIGZpbGU6IG5vZGUuZ2V0UGF0aCgpLFxuICAgICAgICAgICAgaG9va19uYW1lOiBob29rTmFtZSxcbiAgICAgICAgICAgIGhvb2tfYXJnOiBob29rQXJnXG4gICAgICAgIH07XG4gICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1zKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBMYW5nVXRpbHMub2JqZWN0TWVyZ2UocGFyYW1zLCBhZGRpdGlvbmFsUGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZUNhbGxiYWNrLCBudWxsLCB7IGFzeW5jOiBmYWxzZSB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3RhbmRhcmQgcGFyc2VyIGZvciBzZXJ2ZXIgWE1MIGFuc3dlcnNcbiAgICAgKiBAcGFyYW0geG1sUmVzcG9uc2UgRE9NRG9jdW1lbnRcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5wYXJzZVhtbE1lc3NhZ2UgPSBmdW5jdGlvbiBwYXJzZVhtbE1lc3NhZ2UoeG1sUmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHhtbFJlc3BvbnNlID09IG51bGwgfHwgeG1sUmVzcG9uc2UuZG9jdW1lbnRFbGVtZW50ID09IG51bGwpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgY2hpbGRzID0geG1sUmVzcG9uc2UuZG9jdW1lbnRFbGVtZW50LmNoaWxkTm9kZXM7XG4gICAgICAgIHZhciByZWxvYWROb2RlcyA9IFtdLFxuICAgICAgICAgICAgZXJyb3IgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5MQVNUX0VSUk9SX0lEID0gbnVsbDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRzW2ldO1xuICAgICAgICAgICAgaWYgKGNoaWxkLnRhZ05hbWUgPT09IFwibWVzc2FnZVwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VUeHQgPSBcIk5vIG1lc3NhZ2VcIjtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZmlyc3RDaGlsZCkgbWVzc2FnZVR4dCA9IGNoaWxkLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRBdHRyaWJ1dGUoJ3R5cGUnKSA9PSAnRVJST1InKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihtZXNzYWdlVHh0KTtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5sb2cobWVzc2FnZVR4dCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC50YWdOYW1lID09PSBcInByb21wdFwiKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAocHlkaW8gJiYgcHlkaW8uVUkgJiYgcHlkaW8uVUkub3BlblByb21wdERpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICB2YXIganNvbkRhdGEgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShjaGlsZHNbaV0sIFwiZGF0YVwiKS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHlkaW8uVUkub3BlblByb21wdERpYWxvZyhKU09OLnBhcnNlKGpzb25EYXRhKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQudGFnTmFtZSA9PSBcInJlbG9hZF9pbnN0cnVjdGlvblwiKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgb2JOYW1lID0gY2hpbGQuZ2V0QXR0cmlidXRlKCdvYmplY3QnKTtcbiAgICAgICAgICAgICAgICBpZiAob2JOYW1lID09PSAnZGF0YScpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGUgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoJ25vZGUnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbG9hZE5vZGVzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmlsZSA9IGNoaWxkLmdldEF0dHJpYnV0ZSgnZmlsZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCkuc2V0UGVuZGluZ1NlbGVjdGlvbihmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbG9hZE5vZGVzLnB1c2godGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dE5vZGUoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9iTmFtZSA9PSAncmVwb3NpdG9yeV9saXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5yZWxvYWRSZXBvc2l0b3JpZXNMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC5ub2RlTmFtZSA9PSAnbm9kZXNfZGlmZicpIHtcblxuICAgICAgICAgICAgICAgIHZhciBkbSA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHRIb2xkZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAoZG0uZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGVzRGlmZnMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG0uZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGVzRGlmZnMoY2hpbGRzW2ldLCBkbSwgdGhpcy5fcHlkaW9PYmplY3QudXNlci5hY3RpdmVSZXBvc2l0b3J5LCAhd2luZG93LmN1cnJlbnRMaWdodEJveCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC50YWdOYW1lID09IFwibG9nZ2luZ19yZXN1bHRcIikge1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldEF0dHJpYnV0ZShcInNlY3VyZV90b2tlblwiKSkge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuc2V0KCdTRUNVUkVfVE9LRU4nLCBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJzZWN1cmVfdG9rZW5cIikpO1xuICAgICAgICAgICAgICAgICAgICBDb25uZXhpb24udXBkYXRlU2VydmVyQWNjZXNzKHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gY2hpbGQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpO1xuICAgICAgICAgICAgICAgIHZhciBlcnJvcklkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnMSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5sb2FkWG1sUmVnaXN0cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICcwJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnLTEnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JJZCA9IDI4NTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICcyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmxvYWRYbWxSZWdpc3RyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJy0yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySWQgPSAyODU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnLTMnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JJZCA9IDM2NjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICctNCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcklkID0gMzg2O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlcnJvcklkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5MQVNUX0VSUk9SX0lEID0gZXJyb3JJZDtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKHRoaXMuX3B5ZGlvT2JqZWN0Lk1lc3NhZ2VIYXNoW2Vycm9ySWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoaWxkLnRhZ05hbWUgPT0gXCJ0cmlnZ2VyX2JnX2FjdGlvblwiKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgX25hbWUgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpO1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlSWQgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJtZXNzYWdlSWRcIik7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtZXRlcnMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjaGlsZC5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJhbUNoaWxkID0gY2hpbGQuY2hpbGROb2Rlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtQ2hpbGQudGFnTmFtZSA9PSAncGFyYW0nKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnNbcGFyYW1DaGlsZC5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpXSA9IHBhcmFtQ2hpbGQuZ2V0QXR0cmlidXRlKFwidmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyYW1DaGlsZC50YWdOYW1lID09ICdjbGllbnRDYWxsYmFjaycgJiYgcGFyYW1DaGlsZC5maXJzdENoaWxkICYmIHBhcmFtQ2hpbGQuZmlyc3RDaGlsZC5ub2RlVmFsdWUpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrQ29kZSA9IHBhcmFtQ2hpbGQuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayA9IG5ldyBGdW5jdGlvbihjYWxsYmFja0NvZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfbmFtZSA9PSBcImphdmFzY3JpcHRfaW5zdHJ1Y3Rpb25cIiAmJiBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9weWRpb09iamVjdC5ub3RpZnkoXCJyZXNwb25zZS54bWxcIiwgeG1sUmVzcG9uc2UpO1xuICAgICAgICBpZiAocmVsb2FkTm9kZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCkubXVsdGlwbGVOb2Rlc1JlbG9hZChyZWxvYWROb2Rlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICFlcnJvcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3VibWl0cyBhIGZvcm0gdXNpbmcgQ29ubmV4aW9uIGNsYXNzLlxuICAgICAqIEBwYXJhbSBmb3JtTmFtZSBTdHJpbmcgVGhlIGlkIG9mIHRoZSBmb3JtXG4gICAgICogQHBhcmFtIHBvc3QgQm9vbGVhbiBXaGV0aGVyIHRvIFBPU1Qgb3IgR0VUXG4gICAgICogQHBhcmFtIGNvbXBsZXRlQ2FsbGJhY2sgRnVuY3Rpb24gQ2FsbGJhY2sgdG8gYmUgY2FsbGVkIG9uIGNvbXBsZXRlXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3VibWl0Rm9ybSA9IGZ1bmN0aW9uIHN1Ym1pdEZvcm0oZm9ybU5hbWUpIHtcbiAgICAgICAgdmFyIHBvc3QgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY29tcGxldGVDYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHt9O1xuICAgICAgICAvLyBUT0RPOiBVSSBJTVBMRU1FTlRBVElPTlxuICAgICAgICAkKGZvcm1OYW1lKS5nZXRFbGVtZW50cygpLmVhY2goZnVuY3Rpb24gKGZFbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgZlZhbHVlID0gZkVsZW1lbnQuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGlmIChmRWxlbWVudC5uYW1lID09ICdnZXRfYWN0aW9uJyAmJiBmVmFsdWUuc3Vic3RyKDAsIDQpID09ICdodHRwJykge1xuICAgICAgICAgICAgICAgIGZWYWx1ZSA9IFBhdGhVdGlscy5nZXRCYXNlbmFtZShmVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZFbGVtZW50LnR5cGUgPT0gJ3JhZGlvJyAmJiAhZkVsZW1lbnQuY2hlY2tlZCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKHBhcmFtc1tmRWxlbWVudC5uYW1lXSAmJiBmRWxlbWVudC5uYW1lLmVuZHNXaXRoKCdbXScpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4aXN0aW5nID0gcGFyYW1zW2ZFbGVtZW50Lm5hbWVdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT0gJ3N0cmluZycpIGV4aXN0aW5nID0gW2V4aXN0aW5nXTtcbiAgICAgICAgICAgICAgICBleGlzdGluZy5wdXNoKGZWYWx1ZSk7XG4gICAgICAgICAgICAgICAgcGFyYW1zW2ZFbGVtZW50Lm5hbWVdID0gZXhpc3Rpbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtc1tmRWxlbWVudC5uYW1lXSA9IGZWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0Tm9kZSgpKSB7XG4gICAgICAgICAgICBwYXJhbXNbJ2RpciddID0gdGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gY29tcGxldGVDYWxsYmFjaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9uQ29tcGxldGUgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIG9uQ29tcGxldGUsIG51bGwsIHsgbWV0aG9kOiBwb3N0ID8gJ3Bvc3QnIDogJ2dldCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5wb3N0U2VsZWN0aW9uV2l0aEFjdGlvbiA9IGZ1bmN0aW9uIHBvc3RTZWxlY3Rpb25XaXRoQWN0aW9uKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIHNlbGVjdGlvbk1vZGVsID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICBpZiAoIXNlbGVjdGlvbk1vZGVsKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb25Nb2RlbCA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHRIb2xkZXIoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogYWN0aW9uTmFtZSxcbiAgICAgICAgICAgIGRpcjogc2VsZWN0aW9uTW9kZWwuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKClcbiAgICAgICAgfTtcbiAgICAgICAgcGFyYW1zWydub2Rlc1tdJ10gPSBzZWxlY3Rpb25Nb2RlbC5nZXRGaWxlTmFtZXMoKTtcbiAgICAgICAgaWYgKGFkZGl0aW9uYWxQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHBhcmFtcywgYWRkaXRpb25hbFBhcmFtZXRlcnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciBhIHNpbXBsZSBkb3dubG9hZFxuICAgICAqIEBwYXJhbSB1cmwgU3RyaW5nXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS50cmlnZ2VyRG93bmxvYWQgPSBmdW5jdGlvbiB0cmlnZ2VyRG93bmxvYWQodXJsKSB7XG4gICAgICAgIGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSB1cmw7XG4gICAgfTtcblxuICAgIHJldHVybiBQeWRpb0FwaTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFB5ZGlvQXBpO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbi8qKlxuICogUHlkaW8gZW5jYXBzdWxhdGlvbiBvZiBYSFIgLyBGZXRjaFxuICovXG5yZXF1aXJlKCd3aGF0d2ctZmV0Y2gnKTtcblxudmFyIENvbm5leGlvbiA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSBiYXNlVXJsIFN0cmluZyBUaGUgYmFzZSB1cmwgZm9yIHNlcnZpY2VzXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBDb25uZXhpb24oYmFzZVVybCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29ubmV4aW9uKTtcblxuICAgICAgICB0aGlzLl9weWRpbyA9IHdpbmRvdy5weWRpbztcbiAgICAgICAgdGhpcy5fYmFzZVVybCA9IGJhc2VVcmwgfHwgd2luZG93LmFqeHBTZXJ2ZXJBY2Nlc3NQYXRoO1xuICAgICAgICB0aGlzLl9saWJVcmwgPSB3aW5kb3cuYWp4cFJlc291cmNlc0ZvbGRlciArICcvYnVpbGQnO1xuICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLl9tZXRob2QgPSAncG9zdCc7XG4gICAgICAgIHRoaXMuZGlzY3JldGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBDb25uZXhpb24udXBkYXRlU2VydmVyQWNjZXNzID0gZnVuY3Rpb24gdXBkYXRlU2VydmVyQWNjZXNzKHBhcmFtZXRlcnMpIHtcblxuICAgICAgICBpZiAocGFyYW1ldGVycy5nZXQoJ1NFQ1VSRV9UT0tFTicpKSB7XG4gICAgICAgICAgICBDb25uZXhpb24uU0VDVVJFX1RPS0VOID0gcGFyYW1ldGVycy5nZXQoJ1NFQ1VSRV9UT0tFTicpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzZXJ2ZXJBY2Nlc3NQYXRoID0gcGFyYW1ldGVycy5nZXQoJ2FqeHBTZXJ2ZXJBY2Nlc3MnKS5zcGxpdCgnPycpLnNoaWZ0KCk7XG4gICAgICAgIGlmIChwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSkge1xuICAgICAgICAgICAgcGFyYW1ldGVycy5zZXQoJ2FqeHBSZXNvdXJjZXNGb2xkZXInLCBwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSArIHBhcmFtZXRlcnMuZ2V0KCdhanhwUmVzb3VyY2VzRm9sZGVyJykpO1xuICAgICAgICAgICAgc2VydmVyQWNjZXNzUGF0aCA9IHBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpICsgc2VydmVyQWNjZXNzUGF0aCArICc/JyArIChDb25uZXhpb24uU0VDVVJFX1RPS0VOID8gJ3NlY3VyZV90b2tlbj0nICsgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiA6ICcnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlcnZlckFjY2Vzc1BhdGggPSBzZXJ2ZXJBY2Nlc3NQYXRoICsgJz8nICsgKENvbm5leGlvbi5TRUNVUkVfVE9LRU4gPyAnc2VjdXJlX3Rva2VuPScgKyBDb25uZXhpb24uU0VDVVJFX1RPS0VOIDogJycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BFUk1BTkVOVF9QQVJBTVMnKSkge1xuICAgICAgICAgICAgdmFyIHBlcm1QYXJhbXMgPSBwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BFUk1BTkVOVF9QQVJBTVMnKTtcbiAgICAgICAgICAgIHZhciBwZXJtU3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgcGVybWFuZW50IGluIHBlcm1QYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGVybVBhcmFtcy5oYXNPd25Qcm9wZXJ0eShwZXJtYW5lbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBlcm1TdHJpbmdzLnB1c2gocGVybWFuZW50ICsgJz0nICsgcGVybVBhcmFtc1twZXJtYW5lbnRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZXJtU3RyaW5ncyA9IHBlcm1TdHJpbmdzLmpvaW4oJyYnKTtcbiAgICAgICAgICAgIGlmIChwZXJtU3RyaW5ncykge1xuICAgICAgICAgICAgICAgIHNlcnZlckFjY2Vzc1BhdGggKz0gJyYnICsgcGVybVN0cmluZ3M7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwYXJhbWV0ZXJzLnNldCgnYWp4cFNlcnZlckFjY2VzcycsIHNlcnZlckFjY2Vzc1BhdGgpO1xuICAgICAgICAvLyBCQUNLV0FSRCBDT01QQVRcbiAgICAgICAgd2luZG93LmFqeHBTZXJ2ZXJBY2Nlc3NQYXRoID0gc2VydmVyQWNjZXNzUGF0aDtcbiAgICAgICAgaWYgKHdpbmRvdy5weWRpb0Jvb3RzdHJhcCAmJiB3aW5kb3cucHlkaW9Cb290c3RyYXAucGFyYW1ldGVycykge1xuICAgICAgICAgICAgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5zZXQoXCJhanhwU2VydmVyQWNjZXNzXCIsIHNlcnZlckFjY2Vzc1BhdGgpO1xuICAgICAgICAgICAgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5zZXQoXCJTRUNVUkVfVE9LRU5cIiwgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLmxvZyA9IGZ1bmN0aW9uIGxvZyhhY3Rpb24sIHN5bmNTdGF0dXMpIHtcbiAgICAgICAgaWYgKCFDb25uZXhpb24uUHlkaW9Mb2dzKSB7XG4gICAgICAgICAgICBDb25uZXhpb24uUHlkaW9Mb2dzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgQ29ubmV4aW9uLlB5ZGlvTG9ncy5wdXNoKHsgYWN0aW9uOiBhY3Rpb24sIHN5bmM6IHN5bmNTdGF0dXMgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHBhcmFtZXRlciB0byB0aGUgcXVlcnlcbiAgICAgKiBAcGFyYW0gcGFyYW1OYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBwYXJhbVZhbHVlIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hZGRQYXJhbWV0ZXIgPSBmdW5jdGlvbiBhZGRQYXJhbWV0ZXIocGFyYW1OYW1lLCBwYXJhbVZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLl9wYXJhbWV0ZXJzLmdldChwYXJhbU5hbWUpICYmIHBhcmFtTmFtZS5lbmRzV2l0aCgnW10nKSkge1xuICAgICAgICAgICAgdmFyIGV4aXN0aW5nID0gdGhpcy5fcGFyYW1ldGVycy5nZXQocGFyYW1OYW1lKTtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmcgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICAgIGV4aXN0aW5nID0gW2V4aXN0aW5nXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV4aXN0aW5nLnB1c2gocGFyYW1WYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLnNldChwYXJhbU5hbWUsIGV4aXN0aW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3BhcmFtZXRlcnMuc2V0KHBhcmFtTmFtZSwgcGFyYW1WYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgd2hvbGUgcGFyYW1ldGVyIGFzIGEgYnVuY2hcbiAgICAgKiBAcGFyYW0gaFBhcmFtZXRlcnMgTWFwXG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnNldFBhcmFtZXRlcnMgPSBmdW5jdGlvbiBzZXRQYXJhbWV0ZXJzKGhQYXJhbWV0ZXJzKSB7XG4gICAgICAgIGlmIChoUGFyYW1ldGVycyBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycyA9IGhQYXJhbWV0ZXJzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGhQYXJhbWV0ZXJzLl9vYmplY3QpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdQYXNzZWQgYSBsZWdhY3kgSGFzaCBvYmplY3QgdG8gQ29ubmV4aW9uLnNldFBhcmFtZXRlcnMnKTtcbiAgICAgICAgICAgICAgICBoUGFyYW1ldGVycyA9IGhQYXJhbWV0ZXJzLl9vYmplY3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gaFBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaFBhcmFtZXRlcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLnNldChrZXksIGhQYXJhbWV0ZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHF1ZXJ5IG1ldGhvZCAoZ2V0IHBvc3QpXG4gICAgICogQHBhcmFtIG1ldGhvZCBTdHJpbmdcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuc2V0TWV0aG9kID0gZnVuY3Rpb24gc2V0TWV0aG9kKG1ldGhvZCkge1xuICAgICAgICB0aGlzLl9tZXRob2QgPSBtZXRob2Q7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgc2VjdXJlIHRva2VuIHBhcmFtZXRlclxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hZGRTZWN1cmVUb2tlbiA9IGZ1bmN0aW9uIGFkZFNlY3VyZVRva2VuKCkge1xuXG4gICAgICAgIGlmIChDb25uZXhpb24uU0VDVVJFX1RPS0VOICYmIHRoaXMuX2Jhc2VVcmwuaW5kZXhPZignc2VjdXJlX3Rva2VuJykgPT0gLTEgJiYgIXRoaXMuX3BhcmFtZXRlcnMuZ2V0KCdzZWN1cmVfdG9rZW4nKSkge1xuXG4gICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcignc2VjdXJlX3Rva2VuJywgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYmFzZVVybC5pbmRleE9mKCdzZWN1cmVfdG9rZW49JykgIT09IC0xKSB7XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSBmcm9tIGJhc2VVcmwgYW5kIHNldCBpbnNpZGUgcGFyYW1zXG4gICAgICAgICAgICB2YXIgcGFydHMgPSB0aGlzLl9iYXNlVXJsLnNwbGl0KCdzZWN1cmVfdG9rZW49Jyk7XG4gICAgICAgICAgICB2YXIgdG9rcyA9IHBhcnRzWzFdLnNwbGl0KCcmJyk7XG4gICAgICAgICAgICB2YXIgdG9rZW4gPSB0b2tzLnNoaWZ0KCk7XG4gICAgICAgICAgICB2YXIgcmVzdCA9IHRva3Muam9pbignJicpO1xuICAgICAgICAgICAgdGhpcy5fYmFzZVVybCA9IHBhcnRzWzBdICsgKHJlc3QgPyAnJicgKyByZXN0IDogJycpO1xuICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycy5zZXQoJ3NlY3VyZV90b2tlbicsIHRva2VuKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmFkZFNlcnZlclBlcm1hbmVudFBhcmFtcyA9IGZ1bmN0aW9uIGFkZFNlcnZlclBlcm1hbmVudFBhcmFtcygpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9weWRpbyB8fCAhdGhpcy5fcHlkaW8uUGFyYW1ldGVycy5oYXMoJ1NFUlZFUl9QRVJNQU5FTlRfUEFSQU1TJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGVybVBhcmFtcyA9IHRoaXMuX3B5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUEVSTUFORU5UX1BBUkFNUycpO1xuICAgICAgICBmb3IgKHZhciBwZXJtYW5lbnQgaW4gcGVybVBhcmFtcykge1xuICAgICAgICAgICAgaWYgKHBlcm1QYXJhbXMuaGFzT3duUHJvcGVydHkocGVybWFuZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkUGFyYW1ldGVyKHBlcm1hbmVudCwgcGVybVBhcmFtc1twZXJtYW5lbnRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGEgc21hbGwgbG9hZGVyXG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnNob3dMb2FkZXIgPSBmdW5jdGlvbiBzaG93TG9hZGVyKCkge1xuICAgICAgICBpZiAodGhpcy5kaXNjcmV0ZSB8fCAhdGhpcy5fcHlkaW8pIHJldHVybjtcbiAgICAgICAgdGhpcy5fcHlkaW8ubm90aWZ5KFwiY29ubmVjdGlvbi1zdGFydFwiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSGlkZSBhIHNtYWxsIGxvYWRlclxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5oaWRlTG9hZGVyID0gZnVuY3Rpb24gaGlkZUxvYWRlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzY3JldGUgfHwgIXRoaXMuX3B5ZGlvKSByZXR1cm47XG4gICAgICAgIHRoaXMuX3B5ZGlvLm5vdGlmeShcImNvbm5lY3Rpb24tZW5kXCIpO1xuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLl9zZW5kID0gZnVuY3Rpb24gX3NlbmQoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGFTeW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICBDb25uZXhpb24ubG9nKHRoaXMuX3BhcmFtZXRlcnMuZ2V0KFwiZ2V0X2FjdGlvblwiKSwgYVN5bmMgPyAnYXN5bmMnIDogJ3N5bmMnKTtcbiAgICAgICAgdGhpcy5hZGRTZWN1cmVUb2tlbigpO1xuICAgICAgICB0aGlzLmFkZFNlcnZlclBlcm1hbmVudFBhcmFtcygpO1xuICAgICAgICB0aGlzLnNob3dMb2FkZXIoKTtcbiAgICAgICAgdmFyIG9UaGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBtZXRob2Q6IHRoaXMuX21ldGhvZCxcbiAgICAgICAgICAgIGNyZWRlbnRpYWxzOiAnc2FtZS1vcmlnaW4nXG4gICAgICAgIH07XG4gICAgICAgIHZhciB1cmwgPSB0aGlzLl9iYXNlVXJsO1xuICAgICAgICBpZiAoIWFTeW5jKSB7XG4gICAgICAgICAgICBvcHRpb25zLnN5bmNocm9ub3VzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYm9keVBhcnRzID0gW107XG4gICAgICAgIHRoaXMuX3BhcmFtZXRlcnMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZS5tYXAoZnVuY3Rpb24gKG9uZVYpIHtcbiAgICAgICAgICAgICAgICAgICAgYm9keVBhcnRzLnB1c2goa2V5ICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KG9uZVYpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYm9keVBhcnRzLnB1c2goa2V5ICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgcXVlcnlTdHJpbmcgPSBib2R5UGFydHMuam9pbignJicpO1xuICAgICAgICBpZiAodGhpcy5fbWV0aG9kID09PSAncG9zdCcpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuaGVhZGVycyA9IHsgXCJDb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIiB9O1xuICAgICAgICAgICAgb3B0aW9ucy5ib2R5ID0gcXVlcnlTdHJpbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cmwgKz0gKHVybC5pbmRleE9mKCc/JykgPiAtMSA/ICcmJyA6ICc/JykgKyBxdWVyeVN0cmluZztcbiAgICAgICAgfVxuICAgICAgICB3aW5kb3cuZmV0Y2godXJsLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXG4gICAgICAgICAgICB2YXIgaCA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdDb250ZW50LXR5cGUnKTtcbiAgICAgICAgICAgIGlmIChoLmluZGV4T2YoJy9qc29uJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuanNvbigpLnRoZW4oZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgb1RoaXMuYXBwbHlDb21wbGV0ZSh7IHJlc3BvbnNlSlNPTjoganNvbiB9LCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGguaW5kZXhPZignL3htbCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnRleHQoKS50aGVuKGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9UaGlzLmFwcGx5Q29tcGxldGUoeyByZXNwb25zZVhNTDogX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5wYXJzZVhtbCh0ZXh0KSB9LCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnRleHQoKS50aGVuKGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9UaGlzLmFwcGx5Q29tcGxldGUoeyByZXNwb25zZVRleHQ6IHRleHQgfSwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9KVsnY2F0Y2gnXShmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5fcHlkaW8pIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5fcHlkaW8uZGlzcGxheU1lc3NhZ2UoJ0VSUk9SJywgJ05ldHdvcmsgZXJyb3IgJyArIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VuZCBBc3luY2hyb25vdXNseVxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kQXN5bmMgPSBmdW5jdGlvbiBzZW5kQXN5bmMoKSB7XG4gICAgICAgIHRoaXMuX3NlbmQodHJ1ZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlbmQgc3luY2hyb25vdXNseVxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kU3luYyA9IGZ1bmN0aW9uIHNlbmRTeW5jKCkge1xuICAgICAgICB0aGlzLl9zZW5kKGZhbHNlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQXBwbHkgdGhlIGNvbXBsZXRlIGNhbGxiYWNrLCB0cnkgdG8gZ3JhYiBtYXhpbXVtIG9mIGVycm9yc1xuICAgICAqIEBwYXJhbSBwYXJzZWRCb2R5IFRyYW5zcG90XG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmFwcGx5Q29tcGxldGUgPSBmdW5jdGlvbiBhcHBseUNvbXBsZXRlKHBhcnNlZEJvZHksIHJlc3BvbnNlKSB7XG4gICAgICAgIHRoaXMuaGlkZUxvYWRlcigpO1xuICAgICAgICB2YXIgcHlkaW8gPSB0aGlzLl9weWRpbztcbiAgICAgICAgdmFyIG1lc3NhZ2UgPSB1bmRlZmluZWQsXG4gICAgICAgICAgICB0b2tlbk1lc3NhZ2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciB0b2sxID0gXCJPb29wcywgaXQgc2VlbXMgdGhhdCB5b3VyIHNlY3VyaXR5IHRva2VuIGhhcyBleHBpcmVkISBQbGVhc2UgJXMgYnkgaGl0dGluZyByZWZyZXNoIG9yIEY1IGluIHlvdXIgYnJvd3NlciFcIjtcbiAgICAgICAgdmFyIHRvazIgPSBcInJlbG9hZCB0aGUgcGFnZVwiO1xuICAgICAgICBpZiAod2luZG93Lk1lc3NhZ2VIYXNoICYmIHdpbmRvdy5NZXNzYWdlSGFzaFs0MzddKSB7XG4gICAgICAgICAgICB0b2sxID0gd2luZG93Lk1lc3NhZ2VIYXNoWzQzN107XG4gICAgICAgICAgICB0b2syID0gd2luZG93Lk1lc3NhZ2VIYXNoWzQzOF07XG4gICAgICAgIH1cbiAgICAgICAgdG9rZW5NZXNzYWdlID0gdG9rMS5yZXBsYWNlKFwiJXNcIiwgXCI8YSBocmVmPSdqYXZhc2NyaXB0OmRvY3VtZW50LmxvY2F0aW9uLnJlbG9hZCgpJyBzdHlsZT0ndGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7Jz5cIiArIHRvazIgKyBcIjwvYT5cIik7XG5cbiAgICAgICAgdmFyIGN0eXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuICAgICAgICBpZiAocGFyc2VkQm9keS5yZXNwb25zZVhNTCAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PSBcInBhcnNlcmVycm9yXCIpIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiUGFyc2luZyBlcnJvciA6IFxcblwiICsgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZC50ZXh0Q29udGVudDtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJzZWRCb2R5LnJlc3BvbnNlWE1MICYmIHBhcnNlZEJvZHkucmVzcG9uc2VYTUwucGFyc2VFcnJvciAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLnBhcnNlRXJyb3IuZXJyb3JDb2RlICE9IDApIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiUGFyc2luZyBFcnJvciA6IFxcblwiICsgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5wYXJzZUVycm9yLnJlYXNvbjtcbiAgICAgICAgfSBlbHNlIGlmIChjdHlwZS5pbmRleE9mKFwidGV4dC94bWxcIikgPiAtMSAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MID09IG51bGwpIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiRXhwZWN0ZWQgWE1MIGJ1dCBnb3QgZW1wdHkgcmVzcG9uc2UhXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoY3R5cGUuaW5kZXhPZihcInRleHQveG1sXCIpID09IC0xICYmIGN0eXBlLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpID09IC0xICYmIHBhcnNlZEJvZHkucmVzcG9uc2VUZXh0LmluZGV4T2YoXCI8Yj5GYXRhbCBlcnJvcjwvYj5cIikgPiAtMSkge1xuXG4gICAgICAgICAgICBtZXNzYWdlID0gcGFyc2VkQm9keS5yZXNwb25zZVRleHQucmVwbGFjZShcIjxiciAvPlwiLCBcIlwiKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT0gNTAwKSB7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIkludGVybmFsIFNlcnZlciBFcnJvcjogeW91IHNob3VsZCBjaGVjayB5b3VyIHdlYiBzZXJ2ZXIgbG9ncyB0byBmaW5kIHdoYXQncyBnb2luZyB3cm9uZyFcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVzc2FnZSkge1xuXG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zdGFydHNXaXRoKFwiWW91IGFyZSBub3QgYWxsb3dlZCB0byBhY2Nlc3MgdGhpcyByZXNvdXJjZS5cIikpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gdG9rZW5NZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHB5ZGlvKSB7XG4gICAgICAgICAgICAgICAgcHlkaW8uZGlzcGxheU1lc3NhZ2UoXCJFUlJPUlwiLCBtZXNzYWdlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxlcnQobWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnNlZEJvZHkucmVzcG9uc2VYTUwgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQpIHtcblxuICAgICAgICAgICAgdmFyIGF1dGhOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQsIFwicmVxdWlyZV9hdXRoXCIpO1xuICAgICAgICAgICAgaWYgKGF1dGhOb2RlICYmIHB5ZGlvKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSBweWRpby5nZXRDb250ZXh0SG9sZGVyKCkuZ2V0Um9vdE5vZGUoKTtcbiAgICAgICAgICAgICAgICBpZiAocm9vdCkge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5nZXRDb250ZXh0SG9sZGVyKCkuc2V0Q29udGV4dE5vZGUocm9vdCk7XG4gICAgICAgICAgICAgICAgICAgIHJvb3QuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHlkaW8uZ2V0Q29udHJvbGxlcigpLmZpcmVBY3Rpb24oJ2xvZ291dCcpO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5nZXRDb250cm9sbGVyKCkuZmlyZUFjdGlvbignbG9naW4nKTtcbiAgICAgICAgICAgICAgICB9LCAzNTApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbWVzc2FnZU5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCwgXCJtZXNzYWdlXCIpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2VOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VUeXBlID0gbWVzc2FnZU5vZGUuZ2V0QXR0cmlidXRlKFwidHlwZVwiKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlQ29udGVudCA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uZ2V0RG9tTm9kZVRleHQobWVzc2FnZU5vZGUpO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlQ29udGVudC5zdGFydHNXaXRoKFwiWW91IGFyZSBub3QgYWxsb3dlZCB0byBhY2Nlc3MgdGhpcyByZXNvdXJjZS5cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUNvbnRlbnQgPSB0b2tlbk1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChweWRpbykge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5kaXNwbGF5TWVzc2FnZShtZXNzYWdlVHlwZSwgbWVzc2FnZUNvbnRlbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlVHlwZSA9PSBcIkVSUk9SXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KG1lc3NhZ2VUeXBlICsgXCI6XCIgKyBtZXNzYWdlQ29udGVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VUeXBlID09IFwiU1VDQ0VTU1wiKSBtZXNzYWdlTm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG1lc3NhZ2VOb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vbkNvbXBsZXRlKSB7XG5cbiAgICAgICAgICAgIHBhcnNlZEJvZHkuc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzO1xuICAgICAgICAgICAgcGFyc2VkQm9keS5yZXNwb25zZU9iamVjdCA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgdGhpcy5vbkNvbXBsZXRlKHBhcnNlZEJvZHkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChweWRpbykge1xuICAgICAgICAgICAgcHlkaW8uZmlyZShcInNlcnZlcl9hbnN3ZXJcIiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS51cGxvYWRGaWxlID0gZnVuY3Rpb24gdXBsb2FkRmlsZShmaWxlLCBmaWxlUGFyYW1ldGVyTmFtZSwgdXBsb2FkVXJsLCBvbkNvbXBsZXRlLCBvbkVycm9yLCBvblByb2dyZXNzLCB4aHJTZXR0aW5ncykge1xuXG4gICAgICAgIGlmICh4aHJTZXR0aW5ncyA9PT0gdW5kZWZpbmVkKSB4aHJTZXR0aW5ncyA9IHt9O1xuXG4gICAgICAgIGlmICghb25Db21wbGV0ZSkgb25Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICBpZiAoIW9uRXJyb3IpIG9uRXJyb3IgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgaWYgKCFvblByb2dyZXNzKSBvblByb2dyZXNzID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgIHZhciB4aHIgPSB0aGlzLmluaXRpYWxpemVYSFJGb3JVcGxvYWQodXBsb2FkVXJsLCBvbkNvbXBsZXRlLCBvbkVycm9yLCBvblByb2dyZXNzLCB4aHJTZXR0aW5ncyk7XG4gICAgICAgIGlmICh3aW5kb3cuRm9ybURhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZEZpbGVVc2luZ0Zvcm1EYXRhKHhociwgZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHdpbmRvdy5GaWxlUmVhZGVyKSB7XG4gICAgICAgICAgICB2YXIgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMueGhyU2VuZEFzQmluYXJ5KHhociwgZmlsZS5uYW1lLCBlLnRhcmdldC5yZXN1bHQsIGZpbGVQYXJhbWV0ZXJOYW1lKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgICAgICBmaWxlUmVhZGVyLnJlYWRBc0JpbmFyeVN0cmluZyhmaWxlKTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWxlLmdldEFzQmluYXJ5KSB7XG4gICAgICAgICAgICB0aGlzLnhoclNlbmRBc0JpbmFyeSh4aHIsIGZpbGUubmFtZSwgZmlsZS5nZXRBc0JpbmFyeSgpLCBmaWxlUGFyYW1ldGVyTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5pbml0aWFsaXplWEhSRm9yVXBsb2FkID0gZnVuY3Rpb24gaW5pdGlhbGl6ZVhIUkZvclVwbG9hZCh1cmwsIG9uQ29tcGxldGUsIG9uRXJyb3IsIG9uUHJvZ3Jlc3MsIHhoclNldHRpbmdzKSB7XG5cbiAgICAgICAgaWYgKHhoclNldHRpbmdzID09PSB1bmRlZmluZWQpIHhoclNldHRpbmdzID0ge307XG5cbiAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICB2YXIgdXBsb2FkID0geGhyLnVwbG9hZDtcbiAgICAgICAgaWYgKHhoclNldHRpbmdzLndpdGhDcmVkZW50aWFscykge1xuICAgICAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdXBsb2FkLmFkZEV2ZW50TGlzdGVuZXIoXCJwcm9ncmVzc1wiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgaWYgKCFlLmxlbmd0aENvbXB1dGFibGUpIHJldHVybjtcbiAgICAgICAgICAgIG9uUHJvZ3Jlc3MoZSk7XG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPT0gNCkge1xuICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgb25Db21wbGV0ZSh4aHIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9uRXJyb3IoeGhyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHVwbG9hZC5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb25FcnJvcih4aHIpO1xuICAgICAgICB9O1xuICAgICAgICB4aHIub3BlbihcIlBPU1RcIiwgdXJsLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kRmlsZVVzaW5nRm9ybURhdGEgPSBmdW5jdGlvbiBzZW5kRmlsZVVzaW5nRm9ybURhdGEoeGhyLCBmaWxlLCBmaWxlUGFyYW1ldGVyTmFtZSkge1xuICAgICAgICB2YXIgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgZm9ybURhdGEuYXBwZW5kKGZpbGVQYXJhbWV0ZXJOYW1lLCBmaWxlKTtcbiAgICAgICAgeGhyLnNlbmQoZm9ybURhdGEpO1xuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnhoclNlbmRBc0JpbmFyeSA9IGZ1bmN0aW9uIHhoclNlbmRBc0JpbmFyeSh4aHIsIGZpbGVOYW1lLCBmaWxlRGF0YSwgZmlsZVBhcmFtZXRlck5hbWUpIHtcbiAgICAgICAgdmFyIGJvdW5kYXJ5ID0gJy0tLS1NdWx0aVBhcnRGb3JtQm91bmRhcnknICsgbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKFwiQ29udGVudC1UeXBlXCIsIFwibXVsdGlwYXJ0L2Zvcm0tZGF0YSwgYm91bmRhcnk9XCIgKyBib3VuZGFyeSk7XG5cbiAgICAgICAgdmFyIGJvZHkgPSBcIi0tXCIgKyBib3VuZGFyeSArIFwiXFxyXFxuXCI7XG4gICAgICAgIGJvZHkgKz0gXCJDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9J1wiICsgZmlsZVBhcmFtZXRlck5hbWUgKyBcIic7IGZpbGVuYW1lPSdcIiArIHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChmaWxlTmFtZSkpICsgXCInXFxyXFxuXCI7XG4gICAgICAgIGJvZHkgKz0gXCJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVxcclxcblxcclxcblwiO1xuICAgICAgICBib2R5ICs9IGZpbGVEYXRhICsgXCJcXHJcXG5cIjtcbiAgICAgICAgYm9keSArPSBcIi0tXCIgKyBib3VuZGFyeSArIFwiLS1cXHJcXG5cIjtcblxuICAgICAgICB4aHIuc2VuZEFzQmluYXJ5KGJvZHkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgamF2YXNjcmlwdCBsaWJyYXJ5XG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBvbkxvYWRlZENvZGUgRnVuY3Rpb24gQ2FsbGJhY2tcbiAgICAgICAgKiBAcGFyYW0gYVN5bmMgQm9vbGVhbiBsb2FkIGxpYnJhcnkgYXN5bmNocm9uZW91c2x5XG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmxvYWRMaWJyYXJ5ID0gZnVuY3Rpb24gbG9hZExpYnJhcnkoZmlsZU5hbWUsIG9uTG9hZGVkQ29kZSwgYVN5bmMpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHdpbmRvdy5weWRpb0Jvb3RzdHJhcCAmJiB3aW5kb3cucHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJhanhwVmVyc2lvblwiKSAmJiBmaWxlTmFtZS5pbmRleE9mKFwiP1wiKSA9PSAtMSkge1xuICAgICAgICAgICAgZmlsZU5hbWUgKz0gXCI/dj1cIiArIHdpbmRvdy5weWRpb0Jvb3RzdHJhcC5wYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1cmwgPSB0aGlzLl9saWJVcmwgPyB0aGlzLl9saWJVcmwgKyAnLycgKyBmaWxlTmFtZSA6IGZpbGVOYW1lO1xuICAgICAgICB2YXIgcHlkaW8gPSB0aGlzLl9weWRpbztcblxuICAgICAgICB2YXIgc2NyaXB0TG9hZGVkID0gZnVuY3Rpb24gc2NyaXB0TG9hZGVkKHNjcmlwdCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAod2luZG93LmV4ZWNTY3JpcHQpIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmV4ZWNTY3JpcHQoc2NyaXB0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubXlfY29kZSA9IHNjcmlwdDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2NyaXB0X3RhZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHRfdGFnLnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0JztcbiAgICAgICAgICAgICAgICAgICAgc2NyaXB0X3RhZy5pbm5lckhUTUwgPSAnZXZhbCh3aW5kb3cubXlfY29kZSknO1xuICAgICAgICAgICAgICAgICAgICBoZWFkLmFwcGVuZENoaWxkKHNjcmlwdF90YWcpO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgd2luZG93Lm15X2NvZGU7XG4gICAgICAgICAgICAgICAgICAgIGhlYWQucmVtb3ZlQ2hpbGQoc2NyaXB0X3RhZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvbkxvYWRlZENvZGUgIT0gbnVsbCkgb25Mb2FkZWRDb2RlKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgYWxlcnQoJ2Vycm9yIGxvYWRpbmcgJyArIGZpbGVOYW1lICsgJzonICsgZS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAoY29uc29sZSkgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChweWRpbykgcHlkaW8uZmlyZShcInNlcnZlcl9hbnN3ZXJcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGFTeW5jKSB7XG4gICAgICAgICAgICB3aW5kb3cuZmV0Y2godXJsLCB7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICAgICAgICBjcmVkZW50aWFsczogJ3NhbWUtb3JpZ2luJ1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoc2NyaXB0KSB7XG4gICAgICAgICAgICAgICAgc2NyaXB0TG9hZGVkKHNjcmlwdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gU0hPVUxEIEJFIFJFTU9WRUQhIVxuICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHRMb2FkZWQoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KCdlcnJvciBsb2FkaW5nICcgKyBmaWxlTmFtZSArICc6IFN0YXR1cyBjb2RlIHdhcyAnICsgeGhyLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzMik7XG4gICAgICAgICAgICAgICAgeGhyLm9wZW4oXCJHRVRcIiwgdXJsLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgeGhyLnNlbmQoKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIENvbm5leGlvbjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvbm5leGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG4vKipcbiAqIEFQSSBDbGllbnRcbiAqL1xuXG52YXIgTWV0YUNhY2hlU2VydmljZSA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoTWV0YUNhY2hlU2VydmljZSwgX09ic2VydmFibGUpO1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5nZXRJbnN0YW5jZSA9IGZ1bmN0aW9uIGdldEluc3RhbmNlKCkge1xuICAgICAgICBpZiAoIU1ldGFDYWNoZVNlcnZpY2UuSU5TVEFOQ0UpIHtcbiAgICAgICAgICAgIE1ldGFDYWNoZVNlcnZpY2UuSU5TVEFOQ0UgPSBuZXcgTWV0YUNhY2hlU2VydmljZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNZXRhQ2FjaGVTZXJ2aWNlLklOU1RBTkNFO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBNZXRhQ2FjaGVTZXJ2aWNlKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTWV0YUNhY2hlU2VydmljZSk7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5fc3RyZWFtcyA9IG5ldyBNYXAoKTtcbiAgICB9XG5cbiAgICBNZXRhQ2FjaGVTZXJ2aWNlLnByb3RvdHlwZS5oYXNLZXkgPSBmdW5jdGlvbiBoYXNLZXkoc3RyZWFtTmFtZSwga2V5TmFtZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLmdldCgnZGF0YScpLmhhcyhrZXlOYW1lKTtcbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuZ2V0QnlLZXkgPSBmdW5jdGlvbiBnZXRCeUtleShzdHJlYW1OYW1lLCBrZXlOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKS5nZXQoa2V5TmFtZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLmRlbGV0ZUtleSA9IGZ1bmN0aW9uIGRlbGV0ZUtleShzdHJlYW1OYW1lLCBrZXlOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKVsnZGVsZXRlJ10oa2V5TmFtZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLnNldEtleSA9IGZ1bmN0aW9uIHNldEtleShzdHJlYW1OYW1lLCBrZXlOYW1lLCB2YWx1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignU3RyZWFtICcgKyBzdHJlYW1OYW1lICsgJyBub3QgcmVnaXN0ZXJlZCwgcGxlYXNlIHJlZ2lzdGVyIGZpcnN0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkuZ2V0KCdkYXRhJykuc2V0KGtleU5hbWUsIHZhbHVlKTtcbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuY2xlYXJNZXRhU3RyZWFtS2V5cyA9IGZ1bmN0aW9uIGNsZWFyTWV0YVN0cmVhbUtleXMoc3RyZWFtTmFtZSkge1xuICAgICAgICBpZiAodGhpcy5fc3RyZWFtcy5oYXMoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLnNldCgnZGF0YScsIG5ldyBNYXAoKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJNZXRhU3RyZWFtID0gZnVuY3Rpb24gcmVnaXN0ZXJNZXRhU3RyZWFtKHN0cmVhbU5hbWUsIGV4cGlyYXRpb25Qb2xpY3kpIHtcbiAgICAgICAgaWYgKHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgIGRhdGEuc2V0KCdleHBpcmF0aW9uUG9saWN5JywgZXhwaXJhdGlvblBvbGljeSk7XG4gICAgICAgIGRhdGEuc2V0KCdkYXRhJywgbmV3IE1hcCgpKTtcbiAgICAgICAgdGhpcy5fc3RyZWFtcy5zZXQoc3RyZWFtTmFtZSwgZGF0YSk7XG4gICAgICAgIHB5ZGlvLm9ic2VydmUoXCJyZXBvc2l0b3J5X2xpc3RfcmVmcmVzaGVkXCIsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBBbHdheXMga2VlcCB0aGUgY2FjaGUgYXQgd29ya3NwYWNlIHNjb3BlXG4gICAgICAgICAgICB0aGlzLl9zdHJlYW1zWydkZWxldGUnXShzdHJlYW1OYW1lKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLm1ldGFGb3JOb2RlID0gZnVuY3Rpb24gbWV0YUZvck5vZGUoc3RyZWFtTmFtZSwgYWp4cE5vZGUsIGxvYWRlckNhbGxiYWNrLCByZW1vdGVQYXJzZXIsIGNhY2hlTG9hZGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmhhcyhzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBtZXRhIHN0cmVhbSAnICsgc3RyZWFtTmFtZSArICcsIHBsZWFzZSByZWdpc3RlciBpdCBiZWZvcmUgdXNpbmcgaXQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGVmID0gdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSk7XG4gICAgICAgIHZhciBrZXkgPSBhanhwTm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIHZhciBleHBpcmF0aW9uUG9saWN5ID0gZGVmLmdldCgnZXhwaXJhdGlvblBvbGljeScpO1xuICAgICAgICBpZiAoZGVmLmdldCgnZGF0YScpLmhhcyhrZXkpKSB7XG4gICAgICAgICAgICBjYWNoZUxvYWRlcihkZWYuZ2V0KCdkYXRhJykuZ2V0KGtleSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2xlYXJWYWx1ZU9ic2VydmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVmLmdldCgnZGF0YScpWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2FjaGUgcmVzcG9uc2UgaWYgc3VjY2Vzc1xuICAgICAgICAgICAgICAgIHZhciBjYWNoZUNhbGxiYWNrID0gZnVuY3Rpb24gY2FjaGVDYWxsYmFjayh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0RhdGEgPSByZW1vdGVQYXJzZXIodHJhbnNwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0RhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYWNoZWREYXRhID0gbmV3RGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXdEYXRhIGluc3RhbmNlb2YgQWp4cE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWREYXRhID0gbmV3IEFqeHBOb2RlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGVkRGF0YS5yZXBsYWNlQnkobmV3RGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWYuZ2V0KCdkYXRhJykuc2V0KGtleSwgY2FjaGVkRGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwaXJhdGlvblBvbGljeSA9PSBNZXRhQ2FjaGVTZXJ2aWNlLkVYUElSQVRJT05fTE9DQUxfTk9ERSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFqeHBOb2RlLm9ic2VydmVPbmNlKFwibm9kZV9yZW1vdmVkXCIsIGNsZWFyVmFsdWVPYnNlcnZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWp4cE5vZGUub2JzZXJ2ZU9uY2UoXCJub2RlX3JlcGxhY2VkXCIsIGNsZWFyVmFsdWVPYnNlcnZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGxvYWRlckNhbGxiYWNrKGFqeHBOb2RlLCBjYWNoZUNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuaW52YWxpZGF0ZU1ldGFGb3JLZXlzID0gZnVuY3Rpb24gaW52YWxpZGF0ZU1ldGFGb3JLZXlzKHN0cmVhbU5hbWUsIGtleVBhdHRlcm4pIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmhhcyhzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBtZXRhIHN0cmVhbSAnICsgc3RyZWFtTmFtZSArICcsIHBsZWFzZSByZWdpc3RlciBpdCBiZWZvcmUgdXNpbmcgaXQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLmdldCgnZGF0YScpO1xuICAgICAgICBkYXRhLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIGlmIChrZXkubWF0Y2goa2V5UGF0dGVybikpIHtcbiAgICAgICAgICAgICAgICBkYXRhWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIE1ldGFDYWNoZVNlcnZpY2U7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5NZXRhQ2FjaGVTZXJ2aWNlLkVYUElSQVRJT05fTE9DQUxfTk9ERSA9ICdMT0NBTF9OT0RFJztcbk1ldGFDYWNoZVNlcnZpY2UuRVhQSVJBVElPTl9NQU5VQUxfVFJJR0dFUiA9ICdNQU5VQUxfVFJJR0dFUic7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IE1ldGFDYWNoZVNlcnZpY2U7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIFN5c3RlbUpTID0gcmVxdWlyZSgnc3lzdGVtanMnKTtcblxuLyoqXG4gKiBBIG1hbmFnZXIgdGhhdCBjYW4gaGFuZGxlIHRoZSBsb2FkaW5nIG9mIEpTLCBDU1MgYW5kIGNoZWNrcyBkZXBlbmRlbmNpZXNcbiAqL1xuXG52YXIgUmVzb3VyY2VzTWFuYWdlciA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gUmVzb3VyY2VzTWFuYWdlcigpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlc291cmNlc01hbmFnZXIpO1xuXG4gICAgICAgIHRoaXMubWFpbkZvcm1Db250YWluZXJJZCA9ICdhbGxfZm9ybXMnO1xuICAgICAgICB0aGlzLnJlc291cmNlcyA9IHt9O1xuICAgICAgICB0aGlzLmxvYWRlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBKYXZhc2NyaXB0IHJlc291cmNlXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBjbGFzc05hbWUgU3RyaW5nXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGRKU1Jlc291cmNlID0gZnVuY3Rpb24gYWRkSlNSZXNvdXJjZShmaWxlTmFtZSwgY2xhc3NOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuanMpIHtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmpzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNvdXJjZXMuanMucHVzaCh7XG4gICAgICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICAgIGF1dG9sb2FkOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIENTUyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmFkZENTU1Jlc291cmNlID0gZnVuY3Rpb24gYWRkQ1NTUmVzb3VyY2UoZmlsZU5hbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlc291cmNlcy5jc3MpIHtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmNzcyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzb3VyY2VzLmNzcy5wdXNoKGZpbGVOYW1lKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIEZPUk0gZnJvbSBodG1sIHNuaXBwZXJcbiAgICAgKiBAcGFyYW0gZm9ybUlkIFN0cmluZ1xuICAgICAqIEBwYXJhbSBodG1sU25pcHBldCBTdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmFkZEd1aUZvcm0gPSBmdW5jdGlvbiBhZGRHdWlGb3JtKGZvcm1JZCwgaHRtbFNuaXBwZXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlc291cmNlcy5mb3Jtcykge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9ybXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9ybXMuc2V0KGZvcm1JZCwgaHRtbFNuaXBwZXQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBkZXBlbmRlbmN5IHRvIGFub3RoZXIgcGx1Z2luXG4gICAgICogQHBhcmFtIGRhdGEgT2JqZWN0XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGREZXBlbmRlbmN5ID0gZnVuY3Rpb24gYWRkRGVwZW5kZW5jeShkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMucHVzaChkYXRhKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgc29tZSBkZXBlbmRlbmNpZXMgbXVzdCBiZSBsb2FkZWQgYmVmb3JlXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUuaGFzRGVwZW5kZW5jaWVzID0gZnVuY3Rpb24gaGFzRGVwZW5kZW5jaWVzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzIHx8IGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIHJlc291cmNlc1xuICAgICAqIEBwYXJhbSByZXNvdXJjZXNSZWdpc3RyeSBQeWRpbyByZXNvdXJjZXMgcmVnaXN0cnlcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiBsb2FkKHJlc291cmNlc1JlZ2lzdHJ5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGpzQXV0b2xvYWRPbmx5ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IEZ1bmNVdGlscy5FbXB0eSA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICBpZiAodGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaGFzRGVwZW5kZW5jaWVzKCkgJiYgIXRoaXMuZGVwZW5kZW5jaWVzTG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMuZm9yRWFjaCgoZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc291cmNlc1JlZ2lzdHJ5W2VsXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBMb2FkIGRlcGVuZGVuY2llcyBhbmQgdHJ5IGFnYWluXG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlc1JlZ2lzdHJ5W2VsXS5sb2FkKHJlc291cmNlc1JlZ2lzdHJ5LCBmYWxzZSwgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZChyZXNvdXJjZXNSZWdpc3RyeSwgZmFsc2UsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VzLmZvcm1zKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5mb3Jtcy5mb3JFYWNoKChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgICAgIC8vIFJFTU9WRURcbiAgICAgICAgICAgICAgICAvL3RoaXMubG9hZEd1aUZvcm0oa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNvdXJjZXMuanMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGl0ID0gX3RoaXMucmVzb3VyY2VzLmpzLnZhbHVlcygpO1xuICAgICAgICAgICAgICAgIHZhciBjYiA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSBpdC5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3QudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChqc0F1dG9sb2FkT25seSAmJiAhb2JqZWN0LnZhbHVlLmF1dG9sb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRKU1Jlc291cmNlKG9iamVjdC52YWx1ZS5maWxlTmFtZSwgb2JqZWN0LnZhbHVlLmNsYXNzTmFtZSwgY2IsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpO1xuICAgICAgICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNvdXJjZXMuY3NzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5jc3MuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkQ1NTUmVzb3VyY2UodmFsdWUpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIGphdmFzY3JpcHQgZmlsZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIFN0cmluZ1xuICAgICAgICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvblxuICAgICAgICAqIEBwYXJhbSBhU3luYyBCb29sZWFuXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5sb2FkSlNSZXNvdXJjZSA9IGZ1bmN0aW9uIGxvYWRKU1Jlc291cmNlKGZpbGVOYW1lLCBjbGFzc05hbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBhU3luYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgaWYgKCFSZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCkge1xuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBTeXN0ZW1KU1snaW1wb3J0J10oY2xhc3NOYW1lKS50aGVuKGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIENTUyBmaWxlXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUubG9hZENTU1Jlc291cmNlID0gZnVuY3Rpb24gbG9hZENTU1Jlc291cmNlKGZpbGVOYW1lKSB7XG5cbiAgICAgICAgaWYgKHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpKSB7XG4gICAgICAgICAgICBmaWxlTmFtZSA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpICsgZmlsZU5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgZmlsZU5hbWUgPSBmaWxlTmFtZSArIFwiP3Y9XCIgKyBweWRpby5QYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuXG4gICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICB2YXIgbGlua3MgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbGluaycpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGluayA9IGxpbmtzW2ldO1xuICAgICAgICAgICAgaWYgKGxpbmsucmVsID09PSAnc3R5bGVzaGVldCcgJiYgbGluay5ocmVmLmVuZHNXaXRoKGZpbGVOYW1lKSkge1xuICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTticmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICB2YXIgaGVhZCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF07XG4gICAgICAgICAgICB2YXIgY3NzTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTtcbiAgICAgICAgICAgIGNzc05vZGUudHlwZSA9ICd0ZXh0L2Nzcyc7XG4gICAgICAgICAgICBjc3NOb2RlLnJlbCA9ICdzdHlsZXNoZWV0JztcbiAgICAgICAgICAgIGNzc05vZGUuaHJlZiA9IGZpbGVOYW1lO1xuICAgICAgICAgICAgY3NzTm9kZS5tZWRpYSA9ICdzY3JlZW4nO1xuICAgICAgICAgICAgaGVhZC5hcHBlbmRDaGlsZChjc3NOb2RlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIHRoZSByZXNvdXJjZXMgZnJvbSBYTUxcbiAgICAgKiBAcGFyYW0gbm9kZSBYTUxOb2RlXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5sb2FkRnJvbVhtbE5vZGUgPSBmdW5jdGlvbiBsb2FkRnJvbVhtbE5vZGUobm9kZSkge1xuICAgICAgICB2YXIgY2xGb3JtID0ge30sXG4gICAgICAgICAgICBrID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAobm9kZS5ub2RlTmFtZSA9PSBcInJlc291cmNlc1wiKSB7XG4gICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuY2hpbGROb2Rlc1trXS5ub2RlTmFtZSA9PSAnanMnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkSlNSZXNvdXJjZShSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrKG5vZGUuY2hpbGROb2Rlc1trXSksIG5vZGUuY2hpbGROb2Rlc1trXS5nZXRBdHRyaWJ1dGUoJ2NsYXNzTmFtZScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1trXS5ub2RlTmFtZSA9PSAnY3NzJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENTU1Jlc291cmNlKFJlc291cmNlc01hbmFnZXIuZ2V0RmlsZU9yRmFsbGJhY2sobm9kZS5jaGlsZE5vZGVzW2tdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJkZXBlbmRlbmNpZXNcIikge1xuICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmNoaWxkTm9kZXNba10ubm9kZU5hbWUgPT0gXCJwbHVnaW5SZXNvdXJjZXNcIikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZERlcGVuZGVuY3kobm9kZS5jaGlsZE5vZGVzW2tdLmdldEF0dHJpYnV0ZShcInBsdWdpbk5hbWVcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwiY2xpZW50Rm9ybVwiKSB7XG4gICAgICAgICAgICBpZiAoIW5vZGUuZ2V0QXR0cmlidXRlKFwidGhlbWVcIikgfHwgbm9kZS5nZXRBdHRyaWJ1dGUoXCJ0aGVtZVwiKSA9PSBweWRpby5QYXJhbWV0ZXJzLmdldChcInRoZW1lXCIpKSB7XG4gICAgICAgICAgICAgICAgY2xGb3JtID0geyBmb3JtSWQ6IG5vZGUuZ2V0QXR0cmlidXRlKFwiaWRcIiksIGZvcm1Db2RlOiBub2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNsRm9ybS5mb3JtSWQpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkR3VpRm9ybShjbEZvcm0uZm9ybUlkLCBjbEZvcm0uZm9ybUNvZGUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGFsaWFzTmFtZVxuICAgICAqIEBwYXJhbSBhbGlhc1BhdGhcbiAgICAgKiBAdG9kbyBNT1ZFIE9VVFNJREU/XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmFkZEltYWdlTGlicmFyeSA9IGZ1bmN0aW9uIGFkZEltYWdlTGlicmFyeShhbGlhc05hbWUsIGFsaWFzUGF0aCkge1xuICAgICAgICBpZiAoIXdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMpIHdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMgPSB7fTtcbiAgICAgICAgd2luZG93LkFqeHBJbWFnZUxpYnJhcmllc1thbGlhc05hbWVdID0gYWxpYXNQYXRoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBkZWZhdWx0IGltYWdlcyBwYXRoXG4gICAgICogQHBhcmFtIHNyYyBJY29uIHNvdXJjZVxuICAgICAqIEBwYXJhbSBkZWZhdWx0UGF0aCBEZWZhdWx0IHBhdGgsIGNhbiBjb250YWluIElDT05fU0laRVxuICAgICAqIEBwYXJhbSBzaXplIEludGVnZXIgc2l6ZSBvcHRpb25hbFxuICAgICAqIEByZXR1cm5zIHN0cmluZ1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5yZXNvbHZlSW1hZ2VTb3VyY2UgPSBmdW5jdGlvbiByZXNvbHZlSW1hZ2VTb3VyY2Uoc3JjLCBkZWZhdWx0UGF0aCwgc2l6ZSkge1xuICAgICAgICBpZiAoIXNyYykgcmV0dXJuIFwiXCI7XG4gICAgICAgIHZhciBpbWFnZXNGb2xkZXIgPSBhanhwUmVzb3VyY2VzRm9sZGVyICsgJy9pbWFnZXMnO1xuICAgICAgICBpZiAocHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoJ2FqeHBJbWFnZXNDb21tb24nKSkge1xuICAgICAgICAgICAgaW1hZ2VzRm9sZGVyID0gaW1hZ2VzRm9sZGVyLnJlcGxhY2UoJy8nICsgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoJ3RoZW1lJykgKyAnLycsICcvY29tbW9uLycpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlZmF1bHRQYXRoICYmIGRlZmF1bHRQYXRoWzBdICE9PSAnLycpIHtcbiAgICAgICAgICAgIGRlZmF1bHRQYXRoID0gJy8nICsgZGVmYXVsdFBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMgfHwgc3JjLmluZGV4T2YoXCIvXCIpID09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gaW1hZ2VzRm9sZGVyICsgKGRlZmF1bHRQYXRoID8gc2l6ZSA/IGRlZmF1bHRQYXRoLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBkZWZhdWx0UGF0aCA6ICcnKSArICcvJyArIHNyYztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmFkaWMgPSBzcmMuc3Vic3RyaW5nKDAsIHNyYy5pbmRleE9mKFwiL1wiKSk7XG4gICAgICAgIGlmICh3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzW3JhZGljXSkge1xuICAgICAgICAgICAgc3JjID0gc3JjLnJlcGxhY2UocmFkaWMsIHdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXNbcmFkaWNdKTtcbiAgICAgICAgICAgIGlmIChweWRpb0Jvb3RzdHJhcC5wYXJhbWV0ZXJzLmdldChcIlNFUlZFUl9QUkVGSVhfVVJJXCIpKSB7XG4gICAgICAgICAgICAgICAgc3JjID0gcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJTRVJWRVJfUFJFRklYX1VSSVwiKSArIHNyYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaXplID8gc3JjLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBzcmM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaW1hZ2VzRm9sZGVyICsgKGRlZmF1bHRQYXRoID8gc2l6ZSA/IGRlZmF1bHRQYXRoLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBkZWZhdWx0UGF0aCA6ICcnKSArICcvJyArIHNyYztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAqIENoZWNrIGlmIHJlc291cmNlcyBhcmUgdGFnZ2VkIGF1dG9sb2FkIGFuZCBsb2FkIHRoZW1cbiAgICAqIEBwYXJhbSByZWdpc3RyeSBET01Eb2N1bWVudCBYTUwgUmVnaXN0cnlcbiAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMgPSBmdW5jdGlvbiBsb2FkQXV0b0xvYWRSZXNvdXJjZXMoKSB7XG4gICAgICAgIHZhciByZWdpc3RyeSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgaWYgKCFyZWdpc3RyeSkge1xuICAgICAgICAgICAgcmVnaXN0cnkgPSB3aW5kb3cucHlkaW8uUmVnaXN0cnkuZ2V0WE1MKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hbmFnZXIgPSBuZXcgUmVzb3VyY2VzTWFuYWdlcigpO1xuICAgICAgICB2YXIganNOb2RlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhyZWdpc3RyeSwgJ3BsdWdpbnMvKi9jbGllbnRfc2V0dGluZ3MvcmVzb3VyY2VzL2pzJyk7XG4gICAgICAgIHZhciBub2RlID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIHZhciBzeXNqc01hcCA9IHt9O1xuICAgICAgICB2YXIgc3lzanNNZXRhID0ge1xuICAgICAgICAgICAgJyonOiB7IGF1dGhvcml6YXRpb246IHRydWUgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVxdWlyZXMgPSB7fTtcblxuICAgICAgICBmb3IgKHZhciBfaXRlcmF0b3IgPSBqc05vZGVzLCBfaXNBcnJheSA9IEFycmF5LmlzQXJyYXkoX2l0ZXJhdG9yKSwgX2kgPSAwLCBfaXRlcmF0b3IgPSBfaXNBcnJheSA/IF9pdGVyYXRvciA6IF9pdGVyYXRvcltTeW1ib2wuaXRlcmF0b3JdKCk7Oykge1xuICAgICAgICAgICAgaWYgKF9pc0FycmF5KSB7XG4gICAgICAgICAgICAgICAgaWYgKF9pID49IF9pdGVyYXRvci5sZW5ndGgpIGJyZWFrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBfaXRlcmF0b3JbX2krK107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIF9pID0gX2l0ZXJhdG9yLm5leHQoKTtcbiAgICAgICAgICAgICAgICBpZiAoX2kuZG9uZSkgYnJlYWs7XG4gICAgICAgICAgICAgICAgbm9kZSA9IF9pLnZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbmFtZXNwYWNlID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2NsYXNzTmFtZScpO1xuICAgICAgICAgICAgdmFyIGZpbGVwYXRoID0gUmVzb3VyY2VzTWFuYWdlci5nZXRGaWxlT3JGYWxsYmFjayhub2RlKTtcbiAgICAgICAgICAgIHZhciBkZXBzID0gW107XG4gICAgICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2RlcGVuZHMnKSkge1xuICAgICAgICAgICAgICAgIGRlcHMgPSBub2RlLmdldEF0dHJpYnV0ZSgnZGVwZW5kcycpLnNwbGl0KCcsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2V4cG9zZScpKSB7XG4gICAgICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5fX3JlcXVpcmVzW25vZGUuZ2V0QXR0cmlidXRlKCdleHBvc2UnKV0gPSBuYW1lc3BhY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzeXNqc01hcFtuYW1lc3BhY2VdID0gZmlsZXBhdGg7XG4gICAgICAgICAgICBzeXNqc01ldGFbbmFtZXNwYWNlXSA9IHsgZm9ybWF0OiAnZ2xvYmFsJywgZGVwczogZGVwcyB9O1xuICAgICAgICB9XG4gICAgICAgIFN5c3RlbUpTLmNvbmZpZyh7IG1hcDogc3lzanNNYXAsIG1ldGE6IHN5c2pzTWV0YSB9KTtcbiAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5fX2NvbmZpZ3NQYXJzZWQgPSB0cnVlO1xuXG4gICAgICAgIHZhciBjc3NOb2RlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhyZWdpc3RyeSwgJ3BsdWdpbnMvKi9jbGllbnRfc2V0dGluZ3MvcmVzb3VyY2VzL2Nzc1tAYXV0b2xvYWQ9XCJ0cnVlXCJdJyk7XG4gICAgICAgIGZvciAodmFyIF9pdGVyYXRvcjIgPSBjc3NOb2RlcywgX2lzQXJyYXkyID0gQXJyYXkuaXNBcnJheShfaXRlcmF0b3IyKSwgX2kyID0gMCwgX2l0ZXJhdG9yMiA9IF9pc0FycmF5MiA/IF9pdGVyYXRvcjIgOiBfaXRlcmF0b3IyW1N5bWJvbC5pdGVyYXRvcl0oKTs7KSB7XG4gICAgICAgICAgICBpZiAoX2lzQXJyYXkyKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9pMiA+PSBfaXRlcmF0b3IyLmxlbmd0aCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgbm9kZSA9IF9pdGVyYXRvcjJbX2kyKytdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfaTIgPSBfaXRlcmF0b3IyLm5leHQoKTtcbiAgICAgICAgICAgICAgICBpZiAoX2kyLmRvbmUpIGJyZWFrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBfaTIudmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1hbmFnZXIubG9hZENTU1Jlc291cmNlKFJlc291cmNlc01hbmFnZXIuZ2V0RmlsZU9yRmFsbGJhY2sobm9kZSkpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFJlc291cmNlc01hbmFnZXIuZ2V0RmlsZU9yRmFsbGJhY2sgPSBmdW5jdGlvbiBnZXRGaWxlT3JGYWxsYmFjayhub2RlKSB7XG4gICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnZmFsbGJhY2tDb25kaXRpb24nKSAmJiBldmFsKG5vZGUuZ2V0QXR0cmlidXRlKCdmYWxsYmFja0NvbmRpdGlvbicpKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGUuZ2V0QXR0cmlidXRlKCdmYWxsYmFja0ZpbGUnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBub2RlLmdldEF0dHJpYnV0ZSgnZmlsZScpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFJlc291cmNlc01hbmFnZXIucmVxdWlyZUxpYiA9IGZ1bmN0aW9uIHJlcXVpcmVMaWIobW9kdWxlKSB7XG4gICAgICAgIHZhciBwcm9taXNlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgaWYgKHdpbmRvd1ttb2R1bGVdKSByZXR1cm4gd2luZG93W21vZHVsZV07XG4gICAgICAgIGlmIChSZXNvdXJjZXNNYW5hZ2VyLl9fcmVxdWlyZXMgJiYgUmVzb3VyY2VzTWFuYWdlci5fX3JlcXVpcmVzW21vZHVsZV0pIHtcbiAgICAgICAgICAgIHZhciBnbG9iYWxOUyA9IFJlc291cmNlc01hbmFnZXIuX19yZXF1aXJlc1ttb2R1bGVdO1xuICAgICAgICAgICAgaWYgKHByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gU3lzdGVtSlNbJ2ltcG9ydCddKGdsb2JhbE5TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh3aW5kb3dbZ2xvYmFsTlNdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdpbmRvd1tnbG9iYWxOU107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUmVxdWlyaW5nIGEgcmVtb3RlIGxpYiB0aGF0IHdhcyBub3QgcHJldmlvdXNseSBsb2FkZWQgKCcgKyBnbG9iYWxOUyArICcpLiBZb3UgbWF5IGJlIG1pc3NpbmcgYSBkZXBlbmRlbmN5IGRlY2xhcmF0aW9uIGluIG1hbmlmZXN0LCBvciB5b3UgY2FuIHVzZSByZXF1aXJlTGliKG1vZHVsZU5hbWUsIHRydWUpIHRvIHJlY2VpdmUgYSBQcm9taXNlLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBhbnkgcmVmZXJlbmNlIHRvIGxpYiAnICsgbW9kdWxlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIG1vZHVsZSBpcyByZWdpc3RlcmVkIChub3QgbmVjZXNzYXJpbHkgbG9hZGVkIHlldClcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lXG4gICAgICogQHJldHVybnMge01hcHxib29sZWFufVxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5tb2R1bGVJc0F2YWlsYWJsZSA9IGZ1bmN0aW9uIG1vZHVsZUlzQXZhaWxhYmxlKGNsYXNzTmFtZSkge1xuICAgICAgICB2YXIgY29uZmlnID0gU3lzdGVtSlMuZ2V0Q29uZmlnKCk7XG4gICAgICAgIHJldHVybiBjb25maWcubWFwICYmIGNvbmZpZy5tYXBbY2xhc3NOYW1lXTtcbiAgICB9O1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQ2xhc3Nlc0FuZEFwcGx5ID0gZnVuY3Rpb24gbG9hZENsYXNzZXNBbmRBcHBseShjbGFzc05hbWVzLCBjYWxsYmFja0Z1bmMpIHtcbiAgICAgICAgaWYgKCFSZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCkge1xuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBQcm9taXNlLmFsbChjbGFzc05hbWVzLm1hcChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgcmV0dXJuIFN5c3RlbUpTWydpbXBvcnQnXShjKTtcbiAgICAgICAgfSkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY2FsbGJhY2tGdW5jKCk7XG4gICAgICAgIH0pWydjYXRjaCddKGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCBMb2FkaW5nICcgKyBjbGFzc05hbWVzLmpvaW4oJywgJykgKyAnIDogJywgcmVhc29uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9O1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5kZXRlY3RNb2R1bGVUb0xvYWRBbmRBcHBseSA9IGZ1bmN0aW9uIGRldGVjdE1vZHVsZVRvTG9hZEFuZEFwcGx5KGNhbGxiYWNrU3RyaW5nLCBjYWxsYmFja0Z1bmMpIHtcbiAgICAgICAgdmFyIGFzeW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICBpZiAoIVJlc291cmNlc01hbmFnZXIuX19jb25maWdzUGFyc2VkKSB7XG4gICAgICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRBdXRvTG9hZFJlc291cmNlcygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBjYWxsYmFja1N0cmluZy5zcGxpdCgnLicsIDEpLnNoaWZ0KCk7XG4gICAgICAgIGlmIChhc3luYykge1xuICAgICAgICAgICAgU3lzdGVtSlNbJ2ltcG9ydCddKGNsYXNzTmFtZSkudGhlbihjYWxsYmFja0Z1bmMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkU2NyaXB0U3luYyhjbGFzc05hbWUsIGNhbGxiYWNrRnVuYyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRTY3JpcHRTeW5jID0gZnVuY3Rpb24gbG9hZFNjcmlwdFN5bmMobmFtZSwgY2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIHJlZ2VuZXJhdG9yUnVudGltZS5hc3luYyhmdW5jdGlvbiBsb2FkU2NyaXB0U3luYyQoY29udGV4dCQyJDApIHtcbiAgICAgICAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKGNvbnRleHQkMiQwLnByZXYgPSBjb250ZXh0JDIkMC5uZXh0KSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0JDIkMC5uZXh0ID0gMjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlZ2VuZXJhdG9yUnVudGltZS5hd3JhcChTeXN0ZW1KU1snaW1wb3J0J10obmFtZSkpO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2VuZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb250ZXh0JDIkMC5zdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIG51bGwsIHRoaXMpO1xuICAgIH07XG5cbiAgICByZXR1cm4gUmVzb3VyY2VzTWFuYWdlcjtcbn0pKCk7XG5cblJlc291cmNlc01hbmFnZXIuX19jb25maWdzUGFyc2VkID0gZmFsc2U7XG5SZXNvdXJjZXNNYW5hZ2VyLl9fcmVxdWlyZXMgPSB7fTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUmVzb3VyY2VzTWFuYWdlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX1B5ZGlvQXBpID0gcmVxdWlyZSgnLi9QeWRpb0FwaScpO1xuXG52YXIgX1B5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX1B5ZGlvQXBpKTtcblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBVc2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBVc2VyKGlkLCBsYWJlbCwgdHlwZSwgZ3JvdXAsIGF2YXRhciwgdGVtcG9yYXJ5LCBleHRlcm5hbCwgZXh0ZW5kZWRMYWJlbCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVXNlcik7XG5cbiAgICAgICAgdGhpcy5faWQgPSBpZDtcbiAgICAgICAgdGhpcy5fbGFiZWwgPSBsYWJlbDtcbiAgICAgICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gICAgICAgIGlmICh0aGlzLl90eXBlID09PSAnZ3JvdXAnKSB7XG4gICAgICAgICAgICB0aGlzLl9ncm91cCA9IGlkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2F2YXRhciA9IGF2YXRhcjtcbiAgICAgICAgdGhpcy5fdGVtcG9yYXJ5ID0gdGVtcG9yYXJ5O1xuICAgICAgICB0aGlzLl9leHRlcm5hbCA9IGV4dGVybmFsO1xuICAgICAgICB0aGlzLl9leHRlbmRlZExhYmVsID0gZXh0ZW5kZWRMYWJlbDtcbiAgICB9XG5cbiAgICBVc2VyLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KHVzZXIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBVc2VyKHVzZXIuaWQsIHVzZXIubGFiZWwsIHVzZXIudHlwZSwgdXNlci5ncm91cCwgdXNlci5hdmF0YXIsIHVzZXIudGVtcG9yYXJ5LCB1c2VyLmV4dGVybmFsKTtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuYXNPYmplY3QgPSBmdW5jdGlvbiBhc09iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlkOiB0aGlzLl9pZCxcbiAgICAgICAgICAgIGxhYmVsOiB0aGlzLl9sYWJlbCxcbiAgICAgICAgICAgIHR5cGU6IHRoaXMuX3R5cGUsXG4gICAgICAgICAgICBncm91cDogdGhpcy5fZ3JvdXAsXG4gICAgICAgICAgICBhdmF0YXI6IHRoaXMuX2F2YXRhcixcbiAgICAgICAgICAgIHRlbXBvcmFyeTogdGhpcy5fdGVtcG9yYXJ5LFxuICAgICAgICAgICAgZXh0ZXJuYWw6IHRoaXMuX2V4dGVybmFsLFxuICAgICAgICAgICAgZXh0ZW5kZWRMYWJlbDogdGhpcy5fZXh0ZW5kZWRMYWJlbFxuICAgICAgICB9O1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRJZCA9IGZ1bmN0aW9uIGdldElkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faWQ7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldExhYmVsID0gZnVuY3Rpb24gZ2V0TGFiZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYWJlbDtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uIGdldFR5cGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90eXBlO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRHcm91cCA9IGZ1bmN0aW9uIGdldEdyb3VwKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ3JvdXA7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldEF2YXRhciA9IGZ1bmN0aW9uIGdldEF2YXRhcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2F2YXRhcjtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0VGVtcG9yYXJ5ID0gZnVuY3Rpb24gZ2V0VGVtcG9yYXJ5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdGVtcG9yYXJ5O1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRFeHRlcm5hbCA9IGZ1bmN0aW9uIGdldEV4dGVybmFsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXh0ZXJuYWw7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldEV4dGVuZGVkTGFiZWwgPSBmdW5jdGlvbiBnZXRFeHRlbmRlZExhYmVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXh0ZW5kZWRMYWJlbDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFVzZXI7XG59KSgpO1xuXG52YXIgVXNlcnNBcGkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFVzZXJzQXBpKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVXNlcnNBcGkpO1xuICAgIH1cblxuICAgIFVzZXJzQXBpLmF1dGhvcml6ZWRVc2Vyc1N0YXJ0aW5nV2l0aCA9IGZ1bmN0aW9uIGF1dGhvcml6ZWRVc2Vyc1N0YXJ0aW5nV2l0aCh0b2tlbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHVzZXJzT25seSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgZXhpc3RpbmdPbmx5ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX2xpc3RfYXV0aG9yaXplZF91c2VycycsXG4gICAgICAgICAgICB2YWx1ZTogdG9rZW4sXG4gICAgICAgICAgICBmb3JtYXQ6ICdqc29uJ1xuICAgICAgICB9O1xuICAgICAgICBpZiAodXNlcnNPbmx5KSB7XG4gICAgICAgICAgICBwYXJhbXNbJ3VzZXJzX29ubHknXSA9ICd0cnVlJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhpc3RpbmdPbmx5KSB7XG4gICAgICAgICAgICBwYXJhbXNbJ2V4aXN0aW5nX29ubHknXSA9ICd0cnVlJztcbiAgICAgICAgfVxuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIHZhciBzdWdnZXN0aW9ucyA9IFtdO1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTCkge1xuICAgICAgICAgICAgICAgIHZhciBsaXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXModHJhbnNwb3J0LnJlc3BvbnNlWE1MLCAnLy9saScpO1xuICAgICAgICAgICAgICAgIGxpcy5tYXAoZnVuY3Rpb24gKGxpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzcGFuTGFiZWwgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoR2V0U2luZ2xlTm9kZVRleHQobGksICdzcGFuW0BjbGFzcz1cInVzZXJfZW50cnlfbGFiZWxcIl0nKTtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChuZXcgVXNlcihsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtZW50cnlfaWQnKSwgbGkuZ2V0QXR0cmlidXRlKCdkYXRhLWxhYmVsJyksIGxpLmdldEF0dHJpYnV0ZSgnY2xhc3MnKSwgbGkuZ2V0QXR0cmlidXRlKCdkYXRhLWdyb3VwJyksIGxpLmdldEF0dHJpYnV0ZSgnZGF0YS1hdmF0YXInKSwgbGkuZ2V0QXR0cmlidXRlKCdkYXRhLXRlbXBvcmFyeScpID8gdHJ1ZSA6IGZhbHNlLCBsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtZXh0ZXJuYWwnKSA9PSAndHJ1ZScsIHNwYW5MYWJlbCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0cmFuc3BvcnQucmVzcG9uc2VKU09OKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRhdGEgPSB0cmFuc3BvcnQucmVzcG9uc2VKU09OO1xuICAgICAgICAgICAgICAgIGRhdGEubWFwKGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaWQgPSBlbnRyeS5pZDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxhYmVsID0gZW50cnkubGFiZWw7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gZW50cnkudHlwZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdyb3VwID0gZW50cnkuZ3JvdXA7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhdmF0YXIgPSBlbnRyeS5hdmF0YXI7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZW1wb3JhcnkgPSBlbnRyeS50ZW1wb3Jhcnk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBleHRlcm5hbCA9IGVudHJ5LmV4dGVybmFsO1xuXG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2gobmV3IFVzZXIoaWQsIGxhYmVsLCB0eXBlLCBncm91cCwgYXZhdGFyLCB0ZW1wb3JhcnksIGV4dGVybmFsLCBsYWJlbCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbGJhY2soc3VnZ2VzdGlvbnMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuY3JlYXRlVXNlckZyb21Qb3N0ID0gZnVuY3Rpb24gY3JlYXRlVXNlckZyb21Qb3N0KHBvc3RWYWx1ZXMsIGNhbGxiYWNrKSB7XG4gICAgICAgIHBvc3RWYWx1ZXNbJ2dldF9hY3Rpb24nXSA9ICd1c2VyX2NyZWF0ZV91c2VyJztcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocG9zdFZhbHVlcywgKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHBvc3RWYWx1ZXMsIHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuZGVsZXRlVXNlciA9IGZ1bmN0aW9uIGRlbGV0ZVVzZXIodXNlcklkLCBjYWxsYmFjaykge1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl9kZWxldGVfdXNlcicsXG4gICAgICAgICAgICB1c2VyX2lkOiB1c2VySWRcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLnNhdmVTZWxlY3Rpb25TdXBwb3J0ZWQgPSBmdW5jdGlvbiBzYXZlU2VsZWN0aW9uU3VwcG9ydGVkKCkge1xuICAgICAgICByZXR1cm4gZ2xvYmFsLnB5ZGlvLmdldENvbnRyb2xsZXIoKS5hY3Rpb25zLmdldCgndXNlcl90ZWFtX2NyZWF0ZScpICE9PSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLmRlbGV0ZVRlYW0gPSBmdW5jdGlvbiBkZWxldGVUZWFtKHRlYW1JZCwgY2FsbGJhY2spIHtcbiAgICAgICAgdGVhbUlkID0gdGVhbUlkLnJlcGxhY2UoJy9BSlhQX1RFQU0vJywgJycpO1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl90ZWFtX2RlbGV0ZScsXG4gICAgICAgICAgICB0ZWFtX2lkOiB0ZWFtSWRcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5zYXZlU2VsZWN0aW9uQXNUZWFtID0gZnVuY3Rpb24gc2F2ZVNlbGVjdGlvbkFzVGVhbSh0ZWFtTmFtZSwgdXNlcklkcywgY2FsbGJhY2spIHtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfdGVhbV9jcmVhdGUnLFxuICAgICAgICAgICAgdGVhbV9sYWJlbDogdGVhbU5hbWUsXG4gICAgICAgICAgICAndXNlcl9pZHNbXSc6IHVzZXJJZHNcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5hZGRVc2VyVG9UZWFtID0gZnVuY3Rpb24gYWRkVXNlclRvVGVhbSh0ZWFtSWQsIHVzZXJJZCwgY2FsbGJhY2spIHtcbiAgICAgICAgdGVhbUlkID0gdGVhbUlkLnJlcGxhY2UoJy9BSlhQX1RFQU0vJywgJycpO1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl90ZWFtX2FkZF91c2VyJyxcbiAgICAgICAgICAgIHRlYW1faWQ6IHRlYW1JZCxcbiAgICAgICAgICAgIHVzZXJfaWQ6IHVzZXJJZFxuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLnJlbW92ZVVzZXJGcm9tVGVhbSA9IGZ1bmN0aW9uIHJlbW92ZVVzZXJGcm9tVGVhbSh0ZWFtSWQsIHVzZXJJZCwgY2FsbGJhY2spIHtcbiAgICAgICAgdGVhbUlkID0gdGVhbUlkLnJlcGxhY2UoJy9BSlhQX1RFQU0vJywgJycpO1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl90ZWFtX2RlbGV0ZV91c2VyJyxcbiAgICAgICAgICAgIHRlYW1faWQ6IHRlYW1JZCxcbiAgICAgICAgICAgIHVzZXJfaWQ6IHVzZXJJZFxuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLnVwZGF0ZVRlYW1MYWJlbCA9IGZ1bmN0aW9uIHVwZGF0ZVRlYW1MYWJlbCh0ZWFtSWQsIG5ld0xhYmVsLCBjYWxsYmFjaykge1xuICAgICAgICB0ZWFtSWQgPSB0ZWFtSWQucmVwbGFjZSgnL0FKWFBfVEVBTS8nLCAnJyk7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX3RlYW1fdXBkYXRlX2xhYmVsJyxcbiAgICAgICAgICAgIHRlYW1faWQ6IHRlYW1JZCxcbiAgICAgICAgICAgIHRlYW1fbGFiZWw6IG5ld0xhYmVsXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFVzZXJzQXBpO1xufSkoKTtcblxuZXhwb3J0cy5Vc2VyID0gVXNlcjtcbmV4cG9ydHMuVXNlcnNBcGkgPSBVc2Vyc0FwaTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBMb2dnZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExvZ2dlcigpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIExvZ2dlcik7XG4gICAgfVxuXG4gICAgTG9nZ2VyLmxvZyA9IGZ1bmN0aW9uIGxvZyhtZXNzYWdlKSB7XG4gICAgICAgIGlmICh3aW5kb3cuY29uc29sZSkgY29uc29sZS5sb2cobWVzc2FnZSk7XG4gICAgfTtcblxuICAgIExvZ2dlci5lcnJvciA9IGZ1bmN0aW9uIGVycm9yKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5jb25zb2xlKSBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICBMb2dnZXIuZGVidWcgPSBmdW5jdGlvbiBkZWJ1ZyhtZXNzYWdlKSB7XG4gICAgICAgIGlmICh3aW5kb3cuY29uc29sZSkgY29uc29sZS5kZWJ1ZyhtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIExvZ2dlcjtcbn0pKCk7XG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gTG9nZ2VyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzW1wiZGVmYXVsdFwiXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIE9ic2VydmFibGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE9ic2VydmFibGUoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBPYnNlcnZhYmxlKTtcbiAgICB9XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5fb2JqZWN0RXZlbnRTZXR1cCA9IGZ1bmN0aW9uIF9vYmplY3RFdmVudFNldHVwKGV2ZW50X25hbWUpIHtcbiAgICAgICAgdGhpcy5fb2JzZXJ2ZXJzID0gdGhpcy5fb2JzZXJ2ZXJzIHx8IHt9O1xuICAgICAgICB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0gPSB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0gfHwgW107XG4gICAgfTtcblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbiBvYnNlcnZlKGV2ZW50X25hbWUsIG9ic2VydmVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXZlbnRfbmFtZSA9PSAnc3RyaW5nJyAmJiB0eXBlb2Ygb2JzZXJ2ZXIgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRoaXMuX29iamVjdEV2ZW50U2V0dXAoZXZlbnRfbmFtZSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdLmluZGV4T2Yob2JzZXJ2ZXIpID09IC0xKSB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0ucHVzaChvYnNlcnZlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBlIGluIGV2ZW50X25hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRfbmFtZS5oYXNPd25Qcm9wZXJ0eShlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9ic2VydmUoZSwgZXZlbnRfbmFtZVtlXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLnN0b3BPYnNlcnZpbmcgPSBmdW5jdGlvbiBzdG9wT2JzZXJ2aW5nKGV2ZW50X25hbWUsIG9ic2VydmVyKSB7XG4gICAgICAgIHRoaXMuX29iamVjdEV2ZW50U2V0dXAoZXZlbnRfbmFtZSk7XG4gICAgICAgIGlmIChldmVudF9uYW1lICYmIG9ic2VydmVyKSB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0gPSB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0uZmlsdGVyKGZ1bmN0aW9uIChvKSB7XG4gICAgICAgICAgICByZXR1cm4gbyAhPSBvYnNlcnZlcjtcbiAgICAgICAgfSk7ZWxzZSBpZiAoZXZlbnRfbmFtZSkge1xuICAgICAgICAgICAgdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9vYnNlcnZlcnMgPSB7fTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5vYnNlcnZlT25jZSA9IGZ1bmN0aW9uIG9ic2VydmVPbmNlKGV2ZW50X25hbWUsIG91dGVyX29ic2VydmVyKSB7XG4gICAgICAgIHZhciBpbm5lcl9vYnNlcnZlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBvdXRlcl9vYnNlcnZlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgdGhpcy5zdG9wT2JzZXJ2aW5nKGV2ZW50X25hbWUsIGlubmVyX29ic2VydmVyKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5fb2JqZWN0RXZlbnRTZXR1cChldmVudF9uYW1lKTtcbiAgICAgICAgdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdLnB1c2goaW5uZXJfb2JzZXJ2ZXIpO1xuICAgIH07XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5ub3RpZnkgPSBmdW5jdGlvbiBub3RpZnkoZXZlbnRfbmFtZSkge1xuICAgICAgICB0aGlzLl9vYmplY3RFdmVudFNldHVwKGV2ZW50X25hbWUpO1xuICAgICAgICB2YXIgY29sbGVjdGVkX3JldHVybl92YWx1ZXMgPSBbXTtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5mcm9tKGFyZ3VtZW50cykuc2xpY2UoMSk7XG4gICAgICAgIHZhciBvYnNlcnZlcnNDb3B5ID0gdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdLnNsaWNlKDApO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9ic2VydmVyc0NvcHkubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGNvbGxlY3RlZF9yZXR1cm5fdmFsdWVzLnB1c2gob2JzZXJ2ZXJzQ29weVtpXS5hcHBseShvYnNlcnZlcnNDb3B5W2ldLCBhcmdzKSB8fCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sbGVjdGVkX3JldHVybl92YWx1ZXM7XG4gICAgfTtcblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLmhhc09ic2VydmVycyA9IGZ1bmN0aW9uIGhhc09ic2VydmVycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29ic2VydmVycy5sZW5ndGg7XG4gICAgfTtcblxuICAgIHJldHVybiBPYnNlcnZhYmxlO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gT2JzZXJ2YWJsZTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBfdXRpbExhbmdVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvTGFuZ1V0aWxzJyk7XG5cbnZhciBfdXRpbExhbmdVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsTGFuZ1V0aWxzKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlciA9IHJlcXVpcmUoJy4uL2h0dHAvUmVzb3VyY2VzTWFuYWdlcicpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBSZXNvdXJjZXNNYW5hZ2VyKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIF91dGlsRnVuY1V0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9GdW5jVXRpbHMnKTtcblxudmFyIF91dGlsRnVuY1V0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxGdW5jVXRpbHMpO1xuXG4vKipcbiAqIEEgXCJDb21tYW5kXCIgb2JqZWN0LCBlbmNhcHN1bGF0aW5nIGl0cyBjYWxsYmFja3MsIGRpc3BsYXkgYXR0cmlidXRlcywgZXRjLlxuICovXG5cbnZhciBBY3Rpb24gPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG5cdF9pbmhlcml0cyhBY3Rpb24sIF9PYnNlcnZhYmxlKTtcblxuXHQvKipcbiAgKiBTdGFuZGFyZCBjb25zdHJ1Y3RvclxuICAqL1xuXG5cdGZ1bmN0aW9uIEFjdGlvbigpIHtcblx0XHRfY2xhc3NDYWxsQ2hlY2sodGhpcywgQWN0aW9uKTtcblxuXHRcdF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG5cdFx0dGhpcy5fX0RFRkFVTFRfSUNPTl9QQVRIID0gXCJhY3Rpb25zL0lDT05fU0laRVwiO1xuXHRcdHRoaXMub3B0aW9ucyA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLm9iamVjdE1lcmdlKHtcblx0XHRcdG5hbWU6ICcnLFxuXHRcdFx0aWNvbl9jbGFzczogJycsXG5cdFx0XHR0ZXh0OiAnJyxcblx0XHRcdHRpdGxlOiAnJyxcblx0XHRcdHRleHRfaWQ6ICcnLFxuXHRcdFx0dGl0bGVfaWQ6ICcnLFxuXHRcdFx0d2VpZ2h0OiAwLFxuXHRcdFx0aGFzQWNjZXNzS2V5OiBmYWxzZSxcblx0XHRcdGFjY2Vzc0tleTogJycsXG5cdFx0XHRzdWJNZW51OiBmYWxzZSxcblx0XHRcdHN1Yk1lbnVVcGRhdGVJbWFnZTogZmFsc2UsXG5cdFx0XHRzdWJNZW51VXBkYXRlVGl0bGU6IGZhbHNlLFxuXHRcdFx0Y2FsbGJhY2tDb2RlOiAnJyxcblx0XHRcdGNhbGxiYWNrOiBmdW5jdGlvbiBjYWxsYmFjaygpIHt9LFxuXHRcdFx0bGlzdGVuZXJzOiBbXSxcblx0XHRcdGFjdGl2ZUNvbmRpdGlvbjogbnVsbFxuXHRcdH0sIGFyZ3VtZW50c1swXSB8fCB7fSk7XG5cblx0XHR0aGlzLmNvbnRleHQgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5vYmplY3RNZXJnZSh7XG5cdFx0XHRzZWxlY3Rpb246IHRydWUsXG5cdFx0XHRkaXI6IGZhbHNlLFxuXHRcdFx0YWxsb3dlZE1pbWVzOiBbXSxcblx0XHRcdGV2YWxNZXRhZGF0YTogJycsXG5cdFx0XHRyb290OiB0cnVlLFxuXHRcdFx0aW5aaXA6IHRydWUsXG5cdFx0XHRyZWN5Y2xlOiBmYWxzZSxcblx0XHRcdGJlaGF2aW91cjogJ2hpZGRlbicsXG5cdFx0XHRhY3Rpb25CYXI6IGZhbHNlLFxuXHRcdFx0YWN0aW9uQmFyR3JvdXA6ICdkZWZhdWx0Jyxcblx0XHRcdGNvbnRleHRNZW51OiBmYWxzZSxcblx0XHRcdGFqeHBXaWRnZXRzOiBudWxsLFxuXHRcdFx0aW5mb1BhbmVsOiBmYWxzZVxuXHRcdH0sIGFyZ3VtZW50c1sxXSB8fCB7fSk7XG5cblx0XHR0aGlzLnNlbGVjdGlvbkNvbnRleHQgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5vYmplY3RNZXJnZSh7XG5cdFx0XHRkaXI6IGZhbHNlLFxuXHRcdFx0ZmlsZTogdHJ1ZSxcblx0XHRcdHJlY3ljbGU6IGZhbHNlLFxuXHRcdFx0YmVoYXZpb3VyOiAnZGlzYWJsZWQnLFxuXHRcdFx0YWxsb3dlZE1pbWVzOiBbXSxcblx0XHRcdGV2YWxNZXRhZGF0YTogJycsXG5cdFx0XHR1bmlxdWU6IHRydWUsXG5cdFx0XHRtdWx0aXBsZU9ubHk6IGZhbHNlLFxuXHRcdFx0ZW5hYmxlUm9vdDogZmFsc2Vcblx0XHR9LCBhcmd1bWVudHNbMl0gfHwge30pO1xuXG5cdFx0dGhpcy5yaWdodHNDb250ZXh0ID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ub2JqZWN0TWVyZ2Uoe1xuXHRcdFx0bm9Vc2VyOiB0cnVlLFxuXHRcdFx0dXNlckxvZ2dlZDogdHJ1ZSxcblx0XHRcdGd1ZXN0TG9nZ2VkOiBmYWxzZSxcblx0XHRcdHJlYWQ6IGZhbHNlLFxuXHRcdFx0d3JpdGU6IGZhbHNlLFxuXHRcdFx0YWRtaW5Pbmx5OiBmYWxzZVxuXHRcdH0sIGFyZ3VtZW50c1szXSB8fCB7fSk7XG5cblx0XHR0aGlzLnN1Yk1lbnVJdGVtcyA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLm9iamVjdE1lcmdlKHtcblx0XHRcdHN0YXRpY0l0ZW1zOiBudWxsLFxuXHRcdFx0ZHluYW1pY0l0ZW1zOiBudWxsLFxuXHRcdFx0ZHluYW1pY0J1aWxkZXJDb2RlOiBudWxsLFxuXHRcdFx0cG9wb3ZlckNvbnRlbnQ6IG51bGxcblx0XHR9LCBhcmd1bWVudHNbNF0gfHwge30pO1xuXG5cdFx0dGhpcy5lbGVtZW50cyA9IFtdO1xuXHRcdHRoaXMuY29udGV4dEhpZGRlbiA9IGZhbHNlO1xuXHRcdHRoaXMuZGVueSA9IGZhbHNlO1xuXHRcdGlmICh0aGlzLmNvbnRleHQuc3ViTWVudSkge1xuXHRcdFx0aWYgKCF0aGlzLm9wdGlvbnMuYWN0aW9uQmFyKSB7XG5cdFx0XHRcdGFsZXJ0KCdXYXJuaW5nLCB3cm9uZyBhY3Rpb24gZGVmaW5pdGlvbi4gQ2Fubm90IHVzZSBhIHN1Yk1lbnUgaWYgbm90IGRpc3BsYXllZCBpbiB0aGUgYWN0aW9uQmFyIScpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdEFjdGlvbi5wcm90b3R5cGUuX2V2YWxTY3JpcHRzID0gZnVuY3Rpb24gX2V2YWxTY3JpcHRzKGRhdGEsIGxvY2FsU2NvcGVNZXRhZGF0YSkge1xuXHRcdHZhciBtZXRhZGF0YSA9IGxvY2FsU2NvcGVNZXRhZGF0YTtcblx0XHRyZXR1cm4gZXZhbChkYXRhKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZXRzIHRoZSBtYW5hZ2VyIGZvciB0aGlzIGFjdGlvblxuICAqIEBwYXJhbSBtYW5hZ2VyIEFjdGlvbnNNYW5hZ2VyXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5zZXRNYW5hZ2VyID0gZnVuY3Rpb24gc2V0TWFuYWdlcihtYW5hZ2VyKSB7XG5cdFx0dGhpcy5tYW5hZ2VyID0gbWFuYWdlcjtcblx0XHRpZiAodGhpcy5vcHRpb25zLnN1Yk1lbnUpIHtcblx0XHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNJdGVtcykge1xuXHRcdFx0XHR0aGlzLmJ1aWxkU3VibWVudVN0YXRpY0l0ZW1zKCk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0l0ZW1zIHx8IHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyQ29kZSkge1xuXHRcdFx0XHR0aGlzLnByZXBhcmVTdWJtZW51RHluYW1pY0J1aWxkZXIoKTtcblx0XHRcdH0gZWxzZSBpZiAodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJNb2R1bGUpIHtcblx0XHRcdFx0X2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLmRldGVjdE1vZHVsZVRvTG9hZEFuZEFwcGx5KHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyTW9kdWxlLCB0aGlzLnByZXBhcmVTdWJtZW51RHluYW1pY0J1aWxkZXIuYmluZCh0aGlzKSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMubGlzdGVuZXJzWydpbml0J10pIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHdpbmRvdy5saXN0ZW5lckNvbnRleHQgPSB0aGlzO1xuXHRcdFx0XHRpZiAodHlwZW9mIHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbJ2luaXQnXSA9PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdFx0dGhpcy5fZXZhbFNjcmlwdHModGhpcy5vcHRpb25zLmxpc3RlbmVyc1snaW5pdCddKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMubGlzdGVuZXJzWydpbml0J10oKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcignRXJyb3Igd2hpbGUgZXZhbHVhdGluZyBpbml0IHNjcmlwdCBmb3IgYWN0aW9uICcgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEV4ZWN1dGUgdGhlIGFjdGlvbiBjb2RlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uIGFwcGx5KCkge1xuXHRcdGlmICh0aGlzLmRlbnkpIHJldHVybjtcblx0XHR0aGlzLm1hbmFnZXIucHVibGlzaEFjdGlvbkV2ZW50KFwiYmVmb3JlQXBwbHktXCIgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdFx0d2luZG93LmFjdGlvbkFyZ3VtZW50cyA9IFtdO1xuXHRcdHdpbmRvdy5hY3Rpb25NYW5hZ2VyID0gdGhpcy5tYW5hZ2VyO1xuXHRcdGlmIChhcmd1bWVudHNbMF0pIHdpbmRvdy5hY3Rpb25Bcmd1bWVudHMgPSBhcmd1bWVudHNbMF07XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5jYWxsYmFja0NvZGUpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHRoaXMuX2V2YWxTY3JpcHRzKHRoaXMub3B0aW9ucy5jYWxsYmFja0NvZGUpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihlKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy5jYWxsYmFjaykge1xuXHRcdFx0dGhpcy5vcHRpb25zLmNhbGxiYWNrKHRoaXMubWFuYWdlciwgYXJndW1lbnRzWzBdKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5zdWJNZW51ICYmIGFyZ3VtZW50c1swXSAmJiBhcmd1bWVudHNbMF1bMF0pIHtcblx0XHRcdHRoaXMubm90aWZ5KFwic3VibWVudV9hY3RpdmVcIiwgYXJndW1lbnRzWzBdWzBdKTtcblx0XHR9XG5cdFx0d2luZG93LmFjdGlvbkFyZ3VtZW50cyA9IG51bGw7XG5cdFx0d2luZG93LmFjdGlvbk1hbmFnZXIgPSBudWxsO1xuXHRcdHRoaXMubWFuYWdlci5wdWJsaXNoQWN0aW9uRXZlbnQoXCJhZnRlckFwcGx5LVwiICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFVwZGF0ZXMgdGhlIGFjdGlvbiBzdGF0dXMgb24gY29udGV4dCBjaGFuZ2VcbiAgICAgKiBAcGFyYW0gUHlkaW9EYXRhTW9kZWwgZGF0YU1vZGVsXG4gICAgICogQHBhcmFtIGJvb2xlYW4gdXNlcnNFbmFibGVkXG4gICAgICogQHBhcmFtIHN0cmluZyBjcnRVc2VyXG4gICogQHJldHVybnMgdm9pZFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZmlyZUNvbnRleHRDaGFuZ2UgPSBmdW5jdGlvbiBmaXJlQ29udGV4dENoYW5nZShkYXRhTW9kZWwsIHVzZXJzRW5hYmxlZCwgY3J0VXNlcikge1xuXG5cdFx0dmFyIGNydElzUmVjeWNsZSA9IGZhbHNlO1xuXHRcdHZhciBjcnRJblppcCA9IGZhbHNlO1xuXHRcdHZhciBjcnRJc1Jvb3QgPSBmYWxzZTtcblx0XHR2YXIgY3J0QWp4cE1pbWUgPSAnJztcblx0XHR2YXIgY3J0SXNSZWFkT25seSA9IGZhbHNlO1xuXG5cdFx0dmFyIGNydE5vZGUgPSBkYXRhTW9kZWwuZ2V0Q29udGV4dE5vZGUoKTtcblx0XHRpZiAoY3J0Tm9kZSkge1xuXHRcdFx0Y3J0SXNSZWN5Y2xlID0gY3J0Tm9kZS5nZXRBanhwTWltZSgpID09IFwiYWp4cF9yZWN5Y2xlXCI7XG5cdFx0XHRjcnRJblppcCA9IGNydE5vZGUuaGFzQWp4cE1pbWVJbkJyYW5jaChcImFqeHBfYnJvd3NhYmxlX2FyY2hpdmVcIik7XG5cdFx0XHRjcnRJc1Jvb3QgPSBjcnROb2RlLmlzUm9vdCgpO1xuXHRcdFx0Y3J0QWp4cE1pbWUgPSBjcnROb2RlLmdldEFqeHBNaW1lKCk7XG5cdFx0XHRjcnRJc1JlYWRPbmx5ID0gY3J0Tm9kZS5oYXNNZXRhZGF0YUluQnJhbmNoKFwiYWp4cF9yZWFkb25seVwiLCBcInRydWVcIik7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJjb250ZXh0Q2hhbmdlXCJdKSB7XG5cdFx0XHRpZiAodGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcImNvbnRleHRDaGFuZ2VcIl0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wiY29udGV4dENoYW5nZVwiXSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0d2luZG93Lmxpc3RlbmVyQ29udGV4dCA9IHRoaXM7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0dGhpcy5fZXZhbFNjcmlwdHModGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcImNvbnRleHRDaGFuZ2VcIl0pO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoXCJFcnJvciB3aGlsZSBldmFsdWF0aW5nIHNjcmlwdCBmb3IgY29udGV4dENoYW5nZSBldmVudCAtIGFjdGlvbiBcIiArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHR2YXIgcmlnaHRzQ29udGV4dCA9IHRoaXMucmlnaHRzQ29udGV4dDtcblx0XHRpZiAoIXJpZ2h0c0NvbnRleHQubm9Vc2VyICYmICF1c2Vyc0VuYWJsZWQpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LnVzZXJMb2dnZWQgPT0gJ29ubHknICYmIGNydFVzZXIgPT0gbnVsbCB8fCByaWdodHNDb250ZXh0Lmd1ZXN0TG9nZ2VkICYmIHJpZ2h0c0NvbnRleHQuZ3Vlc3RMb2dnZWQgPT0gJ2hpZGRlbicgJiYgY3J0VXNlciAhPSBudWxsICYmIGNydFVzZXIuaWQgPT0gJ2d1ZXN0Jykge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQudXNlckxvZ2dlZCA9PSAnaGlkZGVuJyAmJiBjcnRVc2VyICE9IG51bGwgJiYgIShjcnRVc2VyLmlkID09ICdndWVzdCcgJiYgcmlnaHRzQ29udGV4dC5ndWVzdExvZ2dlZCAmJiByaWdodHNDb250ZXh0Lmd1ZXN0TG9nZ2VkID09ICdzaG93JykpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LmFkbWluT25seSAmJiAoY3J0VXNlciA9PSBudWxsIHx8ICFjcnRVc2VyLmlzQWRtaW4pKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC5yZWFkICYmIGNydFVzZXIgIT0gbnVsbCAmJiAhY3J0VXNlci5jYW5SZWFkKCkpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LndyaXRlICYmIGNydFVzZXIgIT0gbnVsbCAmJiAhY3J0VXNlci5jYW5Xcml0ZSgpKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC53cml0ZSAmJiBjcnRJc1JlYWRPbmx5KSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5jb250ZXh0LmFsbG93ZWRNaW1lcy5sZW5ndGgpIHtcblx0XHRcdGlmICh0aGlzLmNvbnRleHQuYWxsb3dlZE1pbWVzLmluZGV4T2YoXCIqXCIpID09IC0xICYmIHRoaXMuY29udGV4dC5hbGxvd2VkTWltZXMuaW5kZXhPZihjcnRBanhwTWltZSkgPT0gLTEpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHRcdH1cblx0XHRcdGlmICh0aGlzLmNvbnRleHQuYWxsb3dlZE1pbWVzLmluZGV4T2YoXCJeXCIgKyBjcnRBanhwTWltZSkgIT0gLTEpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHRoaXMuY29udGV4dC5yZWN5Y2xlKSB7XG5cdFx0XHRpZiAodGhpcy5jb250ZXh0LnJlY3ljbGUgPT0gJ29ubHknICYmICFjcnRJc1JlY3ljbGUpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHRcdH1cblx0XHRcdGlmICh0aGlzLmNvbnRleHQucmVjeWNsZSA9PSAnaGlkZGVuJyAmJiBjcnRJc1JlY3ljbGUpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCF0aGlzLmNvbnRleHQuaW5aaXAgJiYgY3J0SW5aaXApIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmICghdGhpcy5jb250ZXh0LnJvb3QgJiYgY3J0SXNSb290KSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblxuXHRcdHRoaXMuc2hvd0ZvckNvbnRleHQoZGF0YU1vZGVsKTtcblx0fTtcblxuXHQvKipcbiAgKiBVcGF0ZXMgdGhlIGFjdGlvbiBzdGF0dXMgb24gc2VsZWN0aW9uIGNoYW5nZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZmlyZVNlbGVjdGlvbkNoYW5nZSA9IGZ1bmN0aW9uIGZpcmVTZWxlY3Rpb25DaGFuZ2UoKSB7XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJzZWxlY3Rpb25DaGFuZ2VcIl0pIHtcblx0XHRcdGlmICh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wic2VsZWN0aW9uQ2hhbmdlXCJdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcblx0XHRcdFx0dGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcInNlbGVjdGlvbkNoYW5nZVwiXSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0d2luZG93Lmxpc3RlbmVyQ29udGV4dCA9IHRoaXM7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0dGhpcy5fZXZhbFNjcmlwdHModGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcInNlbGVjdGlvbkNoYW5nZVwiXSk7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihcIkVycm9yIHdoaWxlIGV2YWx1YXRpbmcgc2NyaXB0IGZvciBzZWxlY3Rpb25DaGFuZ2UgZXZlbnQgLSBhY3Rpb24gXCIgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5hY3RpdmVDb25kaXRpb24pIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHZhciByZXN1bHQgPSB0aGlzLm9wdGlvbnMuYWN0aXZlQ29uZGl0aW9uKCk7XG5cdFx0XHRcdGlmIChyZXN1bHQgPT09IGZhbHNlKSB0aGlzLmRpc2FibGUoKTtlbHNlIGlmIChyZXN1bHQgPT09IHRydWUpIHRoaXMuZW5hYmxlKCk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKFwiRXJyb3Igd2hpbGUgZXZhbHVhdGluZyBhY3RpdmVDb25kaXRpb24oKSBzY3JpcHQgZm9yIGFjdGlvbiBcIiArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHRoaXMuY29udGV4dEhpZGRlbiB8fCAhdGhpcy5jb250ZXh0LnNlbGVjdGlvbikge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR2YXIgdXNlclNlbGVjdGlvbiA9IGFyZ3VtZW50c1swXTtcblx0XHR2YXIgaGFzUm9vdCA9IGZhbHNlO1xuXHRcdGlmICh1c2VyU2VsZWN0aW9uICE9IG51bGwpIHtcblx0XHRcdGhhc1Jvb3QgPSB1c2VyU2VsZWN0aW9uLnNlbGVjdGlvbkhhc1Jvb3ROb2RlKCk7XG5cdFx0XHR2YXIgYlVuaXF1ZSA9IHVzZXJTZWxlY3Rpb24uaXNVbmlxdWUoKTtcblx0XHRcdHZhciBiRmlsZSA9IHVzZXJTZWxlY3Rpb24uaGFzRmlsZSgpO1xuXHRcdFx0dmFyIGJEaXIgPSB1c2VyU2VsZWN0aW9uLmhhc0RpcigpO1xuXHRcdFx0dmFyIGJSZWN5Y2xlID0gdXNlclNlbGVjdGlvbi5pc1JlY3ljbGUoKTtcblx0XHR9XG5cdFx0dmFyIHNlbGVjdGlvbkNvbnRleHQgPSB0aGlzLnNlbGVjdGlvbkNvbnRleHQ7XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmxlbmd0aCkge1xuXHRcdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYmVoYXZpb3VyID09ICdoaWRkZW4nKSB0aGlzLmhpZGUoKTtlbHNlIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5ldmFsTWV0YWRhdGEgJiYgdXNlclNlbGVjdGlvbiAmJiB1c2VyU2VsZWN0aW9uLmlzVW5pcXVlKCkpIHtcblx0XHRcdHZhciByZXN1bHQgPSB0aGlzLl9ldmFsU2NyaXB0cyhzZWxlY3Rpb25Db250ZXh0LmV2YWxNZXRhZGF0YSwgdXNlclNlbGVjdGlvbi5nZXRVbmlxdWVOb2RlKCkuZ2V0TWV0YWRhdGEoKSk7XG5cdFx0XHRpZiAoIXJlc3VsdCkge1xuXHRcdFx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5iZWhhdmlvdXIgPT0gJ2hpZGRlbicpIHRoaXMuaGlkZSgpO2Vsc2UgdGhpcy5kaXNhYmxlKCk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCFzZWxlY3Rpb25Db250ZXh0LmVuYWJsZVJvb3QgJiYgaGFzUm9vdCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC51bmlxdWUgJiYgIWJVbmlxdWUpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQubXVsdGlwbGVPbmx5ICYmIGJVbmlxdWUpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKChzZWxlY3Rpb25Db250ZXh0LmZpbGUgfHwgc2VsZWN0aW9uQ29udGV4dC5kaXIpICYmICFiRmlsZSAmJiAhYkRpcikge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5kaXIgJiYgIXNlbGVjdGlvbkNvbnRleHQuZmlsZSAmJiBiRmlsZSB8fCAhc2VsZWN0aW9uQ29udGV4dC5kaXIgJiYgc2VsZWN0aW9uQ29udGV4dC5maWxlICYmIGJEaXIpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKCFzZWxlY3Rpb25Db250ZXh0LnJlY3ljbGUgJiYgYlJlY3ljbGUpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMucmlnaHRzQ29udGV4dC53cml0ZSAmJiB1c2VyU2VsZWN0aW9uLmhhc1JlYWRPbmx5KCkpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmxlbmd0aCAmJiB1c2VyU2VsZWN0aW9uICYmIHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmluZGV4T2YoJyonKSA9PSAtMSAmJiAhdXNlclNlbGVjdGlvbi5oYXNNaW1lKHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzKSkge1xuXHRcdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYmVoYXZpb3VyID09ICdoaWRkZW4nKSByZXR1cm4gdGhpcy5oaWRlKCk7ZWxzZSByZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5sZW5ndGggJiYgdXNlclNlbGVjdGlvbiAmJiBzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5pbmRleE9mKFwiXlwiKSAhPT0gLTEpIHtcblx0XHRcdHZhciBmb3JiaWRkZW5WYWx1ZUZvdW5kID0gZmFsc2U7XG5cdFx0XHRzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChtKSB7XG5cdFx0XHRcdGlmIChtLmluZGV4T2YoXCJeXCIpID09IC0xKSByZXR1cm47XG5cdFx0XHRcdGlmICh1c2VyU2VsZWN0aW9uLmhhc01pbWUoW20ucmVwbGFjZShcIl5cIiwgXCJcIildKSkge1xuXHRcdFx0XHRcdGZvcmJpZGRlblZhbHVlRm91bmQgPSB0cnVlO1xuXHRcdFx0XHRcdC8vdGhyb3cgJGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdGlmIChmb3JiaWRkZW5WYWx1ZUZvdW5kKSB7XG5cdFx0XHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmJlaGF2aW91ciA9PSAnaGlkZGVuJykgcmV0dXJuIHRoaXMuaGlkZSgpO2Vsc2UgcmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLnNob3coKTtcblx0XHR0aGlzLmVuYWJsZSgpO1xuXHR9O1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZ2V0TWVudURhdGEgPSBmdW5jdGlvbiBnZXRNZW51RGF0YSgpIHtcblx0XHR2YXIgbWVudUl0ZW0gPSB7XG5cdFx0XHRuYW1lOiB0aGlzLmdldEtleWVkVGV4dCgpLFxuXHRcdFx0cmF3X25hbWU6IHRoaXMub3B0aW9ucy50ZXh0LFxuXHRcdFx0YWx0OiB0aGlzLm9wdGlvbnMudGl0bGUsXG5cdFx0XHRhY3Rpb25faWQ6IHRoaXMub3B0aW9ucy5uYW1lLFxuXHRcdFx0d2VpZ2h0OiB0aGlzLm9wdGlvbnMud2VpZ2h0IHx8IDAsXG5cdFx0XHRjYWxsYmFjazogKGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdHRoaXMuYXBwbHkoKTtcblx0XHRcdH0pLmJpbmQodGhpcylcblx0XHR9O1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuaWNvbl9jbGFzcykge1xuXHRcdFx0bWVudUl0ZW0uaWNvbl9jbGFzcyA9IHRoaXMub3B0aW9ucy5pY29uX2NsYXNzO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLnN1Yk1lbnUpIHtcblx0XHRcdG1lbnVJdGVtLnN1Yk1lbnUgPSBbXTtcblx0XHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNPcHRpb25zKSB7XG5cdFx0XHRcdG1lbnVJdGVtLnN1Yk1lbnUgPSB0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNPcHRpb25zO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyKSB7XG5cdFx0XHRcdG1lbnVJdGVtLnN1Yk1lbnVCZWZvcmVTaG93ID0gdGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXI7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBtZW51SXRlbTtcblx0fTtcblxuXHQvKipcbiAgKiBQYXJzZXMgYW4gWE1MIGZyYWdtZW50IHRvIGNvbmZpZ3VyZSB0aGlzIGFjdGlvblxuICAqIEBwYXJhbSB4bWxOb2RlIE5vZGUgWE1MIEZyYWdtZW50IGRlc2NyaWJpbmcgdGhlIGFjdGlvblxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuY3JlYXRlRnJvbVhNTCA9IGZ1bmN0aW9uIGNyZWF0ZUZyb21YTUwoeG1sTm9kZSkge1xuXHRcdHZhciBfdGhpcyA9IHRoaXM7XG5cblx0XHR0aGlzLm9wdGlvbnMubmFtZSA9IHhtbE5vZGUuZ2V0QXR0cmlidXRlKCduYW1lJyk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB4bWxOb2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBub2RlID0geG1sTm9kZS5jaGlsZE5vZGVzW2ldO1xuXHRcdFx0dmFyIGRlZmF1bHRBdHRyaWJ1dGVzID0ge1xuXHRcdFx0XHRkaXI6IFwiZGlyRGVmYXVsdFwiLFxuXHRcdFx0XHRmaWxlOiBcImZpbGVEZWZhdWx0XCIsXG5cdFx0XHRcdGRyYWduZHJvcDogXCJkcmFnbmRyb3BEZWZhdWx0XCIsXG5cdFx0XHRcdGN0cmxkcmFnbmRyb3A6IFwiY3RybERyYWduZHJvcERlZmF1bHRcIixcblx0XHRcdFx0ZXhwaXJlOiBcImV4cGlyZURlZmF1bHRcIlxuXHRcdFx0fTtcblx0XHRcdGZvciAodmFyIGtleSBpbiBkZWZhdWx0QXR0cmlidXRlcykge1xuXHRcdFx0XHRpZiAoIWRlZmF1bHRBdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KGtleSkpIGNvbnRpbnVlO1xuXHRcdFx0XHR2YXIgdmFsdWUgPSBkZWZhdWx0QXR0cmlidXRlc1trZXldO1xuXHRcdFx0XHRpZiAoeG1sTm9kZS5nZXRBdHRyaWJ1dGUodmFsdWUpICYmIHhtbE5vZGUuZ2V0QXR0cmlidXRlKHZhbHVlKSA9PSBcInRydWVcIikge1xuXHRcdFx0XHRcdGlmICghdGhpcy5kZWZhdWx0cykgdGhpcy5kZWZhdWx0cyA9IHt9O1xuXHRcdFx0XHRcdHRoaXMuZGVmYXVsdHNba2V5XSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHZhciBqO1xuXHRcdFx0aWYgKG5vZGUubm9kZU5hbWUgPT0gXCJwcm9jZXNzaW5nXCIpIHtcblx0XHRcdFx0dmFyIGNsaWVudEZvcm1EYXRhID0ge307XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHR2YXIgcHJvY2Vzc05vZGUgPSBub2RlLmNoaWxkTm9kZXNbal07XG5cdFx0XHRcdFx0aWYgKHByb2Nlc3NOb2RlLm5vZGVOYW1lID09IFwiY2xpZW50Q2FsbGJhY2tcIikge1xuXHRcdFx0XHRcdFx0aWYgKHByb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbW9kdWxlJykpIHtcblx0XHRcdFx0XHRcdFx0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgZk5hbWUgPSBwcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpO1xuXHRcdFx0XHRcdFx0XHRcdF90aGlzLm9wdGlvbnMuY2FsbGJhY2sgPSBmdW5jdGlvbiAobWFuYWdlciwgb3RoZXJBcmd1bWVudHMpIHtcblx0XHRcdFx0XHRcdFx0XHRcdF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5kZXRlY3RNb2R1bGVUb0xvYWRBbmRBcHBseShmTmFtZSwgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRfdXRpbEZ1bmNVdGlsczJbJ2RlZmF1bHQnXS5leGVjdXRlRnVuY3Rpb25CeU5hbWUoZk5hbWUsIHdpbmRvdywgbWFuYWdlciwgb3RoZXJBcmd1bWVudHMpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdFx0XHRpZiAoX3RoaXMuZGVmYXVsdHMgJiYgKF90aGlzLmRlZmF1bHRzWydkcmFnbmRyb3AnXSB8fCBfdGhpcy5kZWZhdWx0c1snY3RybGRyYWduZHJvcCddKSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0X3RoaXMub3B0aW9ucy5kcmFnbmRyb3BDaGVja01vZHVsZSA9IGZOYW1lO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSkoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAocHJvY2Vzc05vZGUuZmlyc3RDaGlsZCkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuY2FsbGJhY2tDb2RlID0gcHJvY2Vzc05vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUudHJpbSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAocHJvY2Vzc05vZGUubm9kZU5hbWUgPT0gXCJjbGllbnRMaXN0ZW5lclwiKSB7XG5cdFx0XHRcdFx0XHRpZiAocHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCdtb2R1bGUnKSkge1xuXHRcdFx0XHRcdFx0XHQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBtb2R1bGVOYW1lID0gcHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCdtb2R1bGUnKTtcblx0XHRcdFx0XHRcdFx0XHRfdGhpcy5vcHRpb25zLmxpc3RlbmVyc1twcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ25hbWUnKV0gPSAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0X2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLmRldGVjdE1vZHVsZVRvTG9hZEFuZEFwcGx5KG1vZHVsZU5hbWUsIChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciBmdW5jID0gX3V0aWxGdW5jVXRpbHMyWydkZWZhdWx0J10uZ2V0RnVuY3Rpb25CeU5hbWUobW9kdWxlTmFtZSwgd2luZG93KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKGZ1bmMpIGZ1bmMuYXBwbHkodGhpcyk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9KS5iaW5kKHRoaXMpKTtcblx0XHRcdFx0XHRcdFx0XHR9KS5iaW5kKF90aGlzKTtcblx0XHRcdFx0XHRcdFx0fSkoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAocHJvY2Vzc05vZGUuZmlyc3RDaGlsZCkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLm9wdGlvbnMubGlzdGVuZXJzW3Byb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbmFtZScpXSA9IHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlLnRyaW0oKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYgKHByb2Nlc3NOb2RlLm5vZGVOYW1lID09IFwiYWN0aXZlQ29uZGl0aW9uXCIgJiYgcHJvY2Vzc05vZGUuZmlyc3RDaGlsZCkge1xuXHRcdFx0XHRcdFx0dGhpcy5vcHRpb25zLmFjdGl2ZUNvbmRpdGlvbiA9IG5ldyBGdW5jdGlvbihwcm9jZXNzTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZS50cmltKCkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwiZ3VpXCIpIHtcblx0XHRcdFx0dGhpcy5vcHRpb25zLnRleHRfaWQgPSBub2RlLmdldEF0dHJpYnV0ZSgndGV4dCcpO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMudGl0bGVfaWQgPSBub2RlLmdldEF0dHJpYnV0ZSgndGl0bGUnKTtcblx0XHRcdFx0dGhpcy5vcHRpb25zLnRleHQgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShub2RlLmdldEF0dHJpYnV0ZSgndGV4dCcpKSB8fCAnbm90X2ZvdW5kJztcblx0XHRcdFx0dGhpcy5vcHRpb25zLnRpdGxlID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2Uobm9kZS5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykpIHx8ICdub3RfZm91bmQnO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMuc3JjID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3NyYycpO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMuaWNvbl9jbGFzcyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdpY29uQ2xhc3MnKTtcblx0XHRcdFx0dGhpcy5vcHRpb25zLndlaWdodCA9IG5vZGUuZ2V0QXR0cmlidXRlKCd3ZWlnaHQnKSB8fCAwO1xuXHRcdFx0XHRpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2hhc0FjY2Vzc0tleScpICYmIG5vZGUuZ2V0QXR0cmlidXRlKCdoYXNBY2Nlc3NLZXknKSA9PSBcInRydWVcIikge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkgPSBub2RlLmdldEF0dHJpYnV0ZSgnYWNjZXNzS2V5Jyk7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLmhhc0FjY2Vzc0tleSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdzcGVjaWFsQWNjZXNzS2V5JykpIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuc3BlY2lhbEFjY2Vzc0tleSA9IG5vZGUuZ2V0QXR0cmlidXRlKCdzcGVjaWFsQWNjZXNzS2V5Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdGlmIChub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWUgPT0gXCJjb250ZXh0XCIpIHtcblx0XHRcdFx0XHRcdHRoaXMuYXR0cmlidXRlc1RvT2JqZWN0KHRoaXMuY29udGV4dCwgbm9kZS5jaGlsZE5vZGVzW2pdKTtcblx0XHRcdFx0XHRcdGlmICh0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzID0gdGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzLnNwbGl0KCcsJyk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMgPSBbXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vIEJhY2t3YXJkIGNvbXBhdGliaWxpdHlcblx0XHRcdFx0XHRcdGlmICh0aGlzLmNvbnRleHQuaW5mb1BhbmVsKSB0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMucHVzaCgnSW5mb1BhbmVsJyk7XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5jb250ZXh0LmFjdGlvbkJhcikgdGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzLnB1c2goJ0FjdGlvbnNUb29sYmFyJyk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWUgPT0gXCJzZWxlY3Rpb25Db250ZXh0XCIpIHtcblx0XHRcdFx0XHRcdHRoaXMuYXR0cmlidXRlc1RvT2JqZWN0KHRoaXMuc2VsZWN0aW9uQ29udGV4dCwgbm9kZS5jaGlsZE5vZGVzW2pdKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAobm9kZS5ub2RlTmFtZSA9PSBcInJpZ2h0c0NvbnRleHRcIikge1xuXHRcdFx0XHR0aGlzLmF0dHJpYnV0ZXNUb09iamVjdCh0aGlzLnJpZ2h0c0NvbnRleHQsIG5vZGUpO1xuXHRcdFx0fSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwic3ViTWVudVwiKSB7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy5zdWJNZW51ID0gdHJ1ZTtcblx0XHRcdFx0aWYgKG5vZGUuZ2V0QXR0cmlidXRlKFwidXBkYXRlSW1hZ2VPblNlbGVjdFwiKSAmJiBub2RlLmdldEF0dHJpYnV0ZShcInVwZGF0ZUltYWdlT25TZWxlY3RcIikgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuc3ViTWVudVVwZGF0ZUltYWdlID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm9kZS5nZXRBdHRyaWJ1dGUoXCJ1cGRhdGVUaXRsZU9uU2VsZWN0XCIpICYmIG5vZGUuZ2V0QXR0cmlidXRlKFwidXBkYXRlVGl0bGVPblNlbGVjdFwiKSA9PSBcInRydWVcIikge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5zdWJNZW51VXBkYXRlVGl0bGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHRpZiAobm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lID09IFwic3RhdGljSXRlbXNcIiB8fCBub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWUgPT0gXCJkeW5hbWljSXRlbXNcIikge1xuXHRcdFx0XHRcdFx0dGhpcy5zdWJNZW51SXRlbXNbbm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lXSA9IFtdO1xuXHRcdFx0XHRcdFx0Zm9yICh2YXIgayA9IDA7IGsgPCBub2RlLmNoaWxkTm9kZXNbal0uY2hpbGROb2Rlcy5sZW5ndGg7IGsrKykge1xuXHRcdFx0XHRcdFx0XHRpZiAobm9kZS5jaGlsZE5vZGVzW2pdLmNoaWxkTm9kZXNba10ubm9kZU5hbWUuc3RhcnRzV2l0aChcIml0ZW1cIikpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgaXRlbSA9IHt9O1xuXHRcdFx0XHRcdFx0XHRcdGZvciAodmFyIHogPSAwOyB6IDwgbm9kZS5jaGlsZE5vZGVzW2pdLmNoaWxkTm9kZXNba10uYXR0cmlidXRlcy5sZW5ndGg7IHorKykge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIGF0dHJpYnV0ZSA9IG5vZGUuY2hpbGROb2Rlc1tqXS5jaGlsZE5vZGVzW2tdLmF0dHJpYnV0ZXNbel07XG5cdFx0XHRcdFx0XHRcdFx0XHRpdGVtW2F0dHJpYnV0ZS5ub2RlTmFtZV0gPSBhdHRyaWJ1dGUudmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zW25vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZV0ucHVzaChpdGVtKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAobm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lID09IFwiZHluYW1pY0J1aWxkZXJcIikge1xuXHRcdFx0XHRcdFx0aWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5nZXRBdHRyaWJ1dGUoXCJtb2R1bGVcIikpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJNb2R1bGUgPSBub2RlLmNoaWxkTm9kZXNbal0uZ2V0QXR0cmlidXRlKFwibW9kdWxlXCIpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJDb2RlID0gbm9kZS5jaGlsZE5vZGVzW2pdLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIXRoaXMub3B0aW9ucy5oYXNBY2Nlc3NLZXkpIHJldHVybjtcblx0XHRpZiAodGhpcy5vcHRpb25zLmFjY2Vzc0tleSA9PSAnJyB8fCAhdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UodGhpcy5vcHRpb25zLmFjY2Vzc0tleSkgfHwgdGhpcy5vcHRpb25zLnRleHQuaW5kZXhPZih0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZSh0aGlzLm9wdGlvbnMuYWNjZXNzS2V5KSkgPT0gLTEpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkgPSB0aGlzLm9wdGlvbnMudGV4dC5jaGFyQXQoMCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZSh0aGlzLm9wdGlvbnMuYWNjZXNzS2V5KTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogQ3JlYXRlcyB0aGUgc3VibWVudSBpdGVtc1xuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuYnVpbGRTdWJtZW51U3RhdGljSXRlbXMgPSBmdW5jdGlvbiBidWlsZFN1Ym1lbnVTdGF0aWNJdGVtcygpIHtcblx0XHR2YXIgbWVudUl0ZW1zID0gW107XG5cdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY0l0ZW1zKSB7XG5cdFx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNJdGVtcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG5cdFx0XHRcdHZhciBpdGVtVGV4dCA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0udGV4dCk7XG5cdFx0XHRcdGlmIChpdGVtLmhhc0FjY2Vzc0tleSAmJiAoaXRlbS5oYXNBY2Nlc3NLZXkgPT0gJ3RydWUnIHx8IGl0ZW0uaGFzQWNjZXNzS2V5ID09PSB0cnVlKSAmJiB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLmFjY2Vzc0tleSkpIHtcblx0XHRcdFx0XHRpdGVtVGV4dCA9IHRoaXMuZ2V0S2V5ZWRUZXh0KHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0udGV4dCksIHRydWUsIHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0uYWNjZXNzS2V5KSk7XG5cdFx0XHRcdFx0aWYgKCF0aGlzLnN1Yk1lbnVJdGVtcy5hY2Nlc3NLZXlzKSB0aGlzLnN1Yk1lbnVJdGVtcy5hY2Nlc3NLZXlzID0gW107XG5cdFx0XHRcdFx0dGhpcy5tYW5hZ2VyLnJlZ2lzdGVyS2V5KHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0uYWNjZXNzS2V5KSwgdGhpcy5vcHRpb25zLm5hbWUsIGl0ZW0uY29tbWFuZCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0bWVudUl0ZW1zLnB1c2goe1xuXHRcdFx0XHRcdG5hbWU6IGl0ZW1UZXh0LFxuXHRcdFx0XHRcdGFsdDogdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS50aXRsZSksXG5cdFx0XHRcdFx0aW1hZ2VfdW5yZXNvbHZlZDogaXRlbS5zcmMsXG5cdFx0XHRcdFx0aWNvbl9jbGFzczogaXRlbS5pY29uX2NsYXNzLFxuXHRcdFx0XHRcdGlzRGVmYXVsdDogaXRlbS5pc0RlZmF1bHQgPyB0cnVlIDogZmFsc2UsXG5cdFx0XHRcdFx0Y2FsbGJhY2s6IChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmFwcGx5KFtpdGVtXSk7XG5cdFx0XHRcdFx0fSkuYmluZCh0aGlzKVxuXHRcdFx0XHR9KTtcblx0XHRcdH0sIHRoaXMpO1xuXHRcdH1cblx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNPcHRpb25zID0gbWVudUl0ZW1zO1xuXHR9O1xuXG5cdC8qKlxuICAqIENhY2hlcyBzb21lIGRhdGEgZm9yIGR5bmFtaWNhbGx5IGJ1aWx0IG1lbnVzXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5wcmVwYXJlU3VibWVudUR5bmFtaWNCdWlsZGVyID0gZnVuY3Rpb24gcHJlcGFyZVN1Ym1lbnVEeW5hbWljQnVpbGRlcigpIHtcblx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlciA9IChmdW5jdGlvbiAoY29udHJvbGxlcikge1xuXHRcdFx0dmFyIG1lbnVJdGVtcyA9IFtdO1xuXHRcdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyQ29kZSkge1xuXHRcdFx0XHR3aW5kb3cuYnVpbGRlckNvbnRleHQgPSB0aGlzO1xuXHRcdFx0XHR0aGlzLl9ldmFsU2NyaXB0cyh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlckNvZGUpO1xuXHRcdFx0XHRtZW51SXRlbXMgPSB0aGlzLmJ1aWxkZXJNZW51SXRlbXMgfHwgW107XG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyTW9kdWxlKSB7XG5cdFx0XHRcdHZhciBmdW5jID0gX3V0aWxGdW5jVXRpbHMyWydkZWZhdWx0J10uZ2V0RnVuY3Rpb25CeU5hbWUodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJNb2R1bGUsIHdpbmRvdyk7XG5cdFx0XHRcdGlmIChmdW5jKSB7XG5cdFx0XHRcdFx0bWVudUl0ZW1zID0gZnVuYy5hcHBseSh0aGlzKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bWVudUl0ZW1zID0gW107XG5cdFx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNJdGVtcy5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG5cdFx0XHRcdFx0aWYgKGl0ZW0uc2VwYXJhdG9yKSB7XG5cdFx0XHRcdFx0XHRtZW51SXRlbXMucHVzaChpdGVtKTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0dmFyIGFjdGlvbiA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRpZiAoaXRlbVsnYWN0aW9uSWQnXSBpbnN0YW5jZW9mIEFjdGlvbikge1xuXHRcdFx0XHRcdFx0YWN0aW9uID0gaXRlbVsnYWN0aW9uSWQnXTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0YWN0aW9uID0gdGhpcy5tYW5hZ2VyLmFjdGlvbnMuZ2V0KGl0ZW1bJ2FjdGlvbklkJ10pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoYWN0aW9uLmRlbnkpIHJldHVybjtcblx0XHRcdFx0XHR2YXIgaXRlbURhdGEgPSB7XG5cdFx0XHRcdFx0XHRuYW1lOiBhY3Rpb24uZ2V0S2V5ZWRUZXh0KCksXG5cdFx0XHRcdFx0XHRhbHQ6IGFjdGlvbi5vcHRpb25zLnRpdGxlLFxuXHRcdFx0XHRcdFx0aWNvbl9jbGFzczogYWN0aW9uLm9wdGlvbnMuaWNvbl9jbGFzcyxcblx0XHRcdFx0XHRcdGltYWdlX3VucmVzb2x2ZWQ6IGFjdGlvbi5vcHRpb25zLnNyYyxcblx0XHRcdFx0XHRcdGNhbGxiYWNrOiAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmFwcGx5KCk7XG5cdFx0XHRcdFx0XHR9KS5iaW5kKGFjdGlvbilcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdGlmIChhY3Rpb24ub3B0aW9ucy5zdWJNZW51KSB7XG5cdFx0XHRcdFx0XHRpdGVtRGF0YS5zdWJNZW51ID0gW107XG5cdFx0XHRcdFx0XHRpZiAoYWN0aW9uLnN1Yk1lbnVJdGVtcy5zdGF0aWNPcHRpb25zKSB7XG5cdFx0XHRcdFx0XHRcdGl0ZW1EYXRhLnN1Yk1lbnUgPSBhY3Rpb24uc3ViTWVudUl0ZW1zLnN0YXRpY09wdGlvbnM7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoYWN0aW9uLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlcikge1xuXHRcdFx0XHRcdFx0XHRpdGVtRGF0YS5zdWJNZW51QmVmb3JlU2hvdyA9IGFjdGlvbi5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXI7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdG1lbnVJdGVtcy5wdXNoKGl0ZW1EYXRhKTtcblx0XHRcdFx0fSwgdGhpcyk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWVudUl0ZW1zO1xuXHRcdH0pLmJpbmQodGhpcyk7XG5cdH07XG5cblx0LyoqXG4gICogUmVmcmVzaCBpY29uIGltYWdlIHNvdXJjZVxuICAqIEBwYXJhbSBuZXdTcmMgU3RyaW5nIFRoZSBpbWFnZSBzb3VyY2UuIENhbiByZWZlcmVuY2UgYW4gaW1hZ2UgbGlicmFyeVxuICAgICAqIEBwYXJhbSBpY29uQ2xhc3MgU3RyaW5nIE9wdGlvbmFsIGNsYXNzIHRvIHJlcGxhY2UgaW1hZ2VcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnNldEljb25DbGFzc05hbWUgPSBmdW5jdGlvbiBzZXRJY29uQ2xhc3NOYW1lKGljb25DbGFzcykge1xuXHRcdHZhciBpY29uX2NsYXNzID0gdGhpcy5vcHRpb25zLmljb25fY2xhc3M7XG5cblx0XHR0aGlzLm5vdGlmeShcInVwZGF0ZV9pY29uXCIsIHsgbmV3X2NsYXNzOiBpY29uQ2xhc3MsIHByZXZpb3VzX2NsYXNzOiBpY29uX2NsYXNzIH0pO1xuXHRcdHRoaXMub3B0aW9ucy5pY29uX2NsYXNzID0gaWNvbkNsYXNzO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJlZnJlc2ggdGhlIGFjdGlvbiBsYWJlbFxuICAqIEBwYXJhbSBuZXdMYWJlbCBTdHJpbmcgdGhlIG5ldyBsYWJlbFxuICAqIEBwYXJhbSBuZXdUaXRsZSBTdHJpbmcgdGhlIG5ldyB0b29sdGlwXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5zZXRMYWJlbCA9IGZ1bmN0aW9uIHNldExhYmVsKG5ld0xhYmVsLCBuZXdUaXRsZSkge1xuXHRcdHRoaXMub3B0aW9ucy50ZXh0ID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UobmV3TGFiZWwpO1xuXHRcdHRoaXMubm90aWZ5KFwidXBkYXRlX2xhYmVsXCIsIHRoaXMuZ2V0S2V5ZWRUZXh0KCkpO1xuXHRcdGlmIChuZXdUaXRsZSkge1xuXHRcdFx0dGhpcy5vcHRpb25zLnRpdGxlID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UobmV3VGl0bGUpO1xuXHRcdFx0dGhpcy5ub3RpZnkoXCJ1cGRhdGVfdGl0bGVcIiwgdGhpcy5vcHRpb25zLnRpdGxlKTtcblx0XHR9XG5cdH07XG5cblx0QWN0aW9uLnByb3RvdHlwZS5yZWZyZXNoSW5zdGFuY2VzID0gZnVuY3Rpb24gcmVmcmVzaEluc3RhbmNlcygpIHt9O1xuXG5cdC8qKlxuICAqIEdyYWIgaXRzIGxhYmVsIGZyb20gdGhlIGkxOG5cbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnJlZnJlc2hGcm9tSTE4Tkhhc2ggPSBmdW5jdGlvbiByZWZyZXNoRnJvbUkxOE5IYXNoKCkge1xuXHRcdHRoaXMuc2V0TGFiZWwodGhpcy5vcHRpb25zLnRleHRfaWQsIHRoaXMub3B0aW9ucy50aXRsZV9pZCk7XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJuIGRhdGEgbmVjZXNzYXJ5IHRvIGJ1aWxkIEluZm9QYW5lbFxuICAqIEByZXR1cm5zIE9iamVjdFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUudG9JbmZvUGFuZWwgPSBmdW5jdGlvbiB0b0luZm9QYW5lbCgpIHtcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybiBuZWNlc3NhcnkgZGF0YSB0byBidWlsZCBjb250ZXh0dWFsIG1lbnVcbiAgKiBAcmV0dXJucyBPYmplY3RcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnRvQ29udGV4dE1lbnUgPSBmdW5jdGlvbiB0b0NvbnRleHRNZW51KCkge1xuXHRcdHJldHVybiB0aGlzLm9wdGlvbnM7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBzaG93L2hpZGUgc3RhdGVcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmhpZGVGb3JDb250ZXh0ID0gZnVuY3Rpb24gaGlkZUZvckNvbnRleHQoKSB7XG5cdFx0dGhpcy5oaWRlKCk7XG5cdFx0dGhpcy5jb250ZXh0SGlkZGVuID0gdHJ1ZTtcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIHNob3cvaGlkZSBzdGF0ZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuc2hvd0ZvckNvbnRleHQgPSBmdW5jdGlvbiBzaG93Rm9yQ29udGV4dChkYXRhTW9kZWwpIHtcblx0XHR0aGlzLmNvbnRleHRIaWRkZW4gPSBmYWxzZTtcblx0XHR0aGlzLnNob3coKTtcblx0XHRpZiAodGhpcy5zZWxlY3Rpb25Db250ZXh0KSB7XG5cdFx0XHR0aGlzLmZpcmVTZWxlY3Rpb25DaGFuZ2UoZGF0YU1vZGVsKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBzaG93L2hpZGUgc3RhdGVcbiAgKiBOb3RpZmllcyBcImhpZGVcIiBFdmVudFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uIGhpZGUoKSB7XG5cdFx0dGhpcy5kZW55ID0gdHJ1ZTtcblx0XHR0aGlzLm5vdGlmeSgnaGlkZScpO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgc2hvdy9oaWRlIHN0YXRlXG4gICogTm90aWZpZXMgXCJzaG93XCIgRXZlbnQgXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcblx0XHR0aGlzLmRlbnkgPSBmYWxzZTtcblx0XHR0aGlzLm5vdGlmeSgnc2hvdycpO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgZW5hYmxlL2Rpc2FibGUgc3RhdGVcbiAgKiBOb3RpZmllcyBcImRpc2FibGVcIiBFdmVudCBcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiBkaXNhYmxlKCkge1xuXHRcdHRoaXMuZGVueSA9IHRydWU7XG5cdFx0dGhpcy5ub3RpZnkoJ2Rpc2FibGUnKTtcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIGVuYWJsZS9kaXNhYmxlIHN0YXRlXG4gICogTm90aWZpZXMgXCJlbmFibGVcIiBFdmVudCBcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZSgpIHtcblx0XHR0aGlzLmRlbnkgPSBmYWxzZTtcblx0XHR0aGlzLm5vdGlmeSgnZW5hYmxlJyk7XG5cdH07XG5cblx0LyoqXG4gICogVG8gYmUgY2FsbGVkIHdoZW4gcmVtb3ZpbmdcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uIHJlbW92ZSgpIHtcblx0XHR0aGlzLm5vdGlmeShcInJlbW92ZVwiKTtcblx0fTtcblxuXHQvKipcbiAgKiBDcmVhdGUgYSB0ZXh0IGxhYmVsIHdpdGggYWNjZXNzLWtleSB1bmRlcmxpbmVkLlxuICAqIEBwYXJhbSBkaXNwbGF5U3RyaW5nIFN0cmluZyB0aGUgbGFiZWxcbiAgKiBAcGFyYW0gaGFzQWNjZXNzS2V5IEJvb2xlYW4gd2hldGhlciB0aGVyZSBpcyBhbiBhY2Nlc3NLZXkgb3Igbm90XG4gICogQHBhcmFtIGFjY2Vzc0tleSBTdHJpbmcgVGhlIGtleSB0byB1bmRlcmxpbmVcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmdldEtleWVkVGV4dCA9IGZ1bmN0aW9uIGdldEtleWVkVGV4dChkaXNwbGF5U3RyaW5nLCBoYXNBY2Nlc3NLZXksIGFjY2Vzc0tleSkge1xuXHRcdGlmICghZGlzcGxheVN0cmluZykge1xuXHRcdFx0ZGlzcGxheVN0cmluZyA9IHRoaXMub3B0aW9ucy50ZXh0O1xuXHRcdH1cblx0XHRpZiAoIWhhc0FjY2Vzc0tleSkge1xuXHRcdFx0aGFzQWNjZXNzS2V5ID0gdGhpcy5vcHRpb25zLmhhc0FjY2Vzc0tleTtcblx0XHR9XG5cdFx0aWYgKCFhY2Nlc3NLZXkpIHtcblx0XHRcdGFjY2Vzc0tleSA9IHRoaXMub3B0aW9ucy5hY2Nlc3NLZXk7XG5cdFx0fVxuXHRcdGlmICghaGFzQWNjZXNzS2V5KSByZXR1cm4gZGlzcGxheVN0cmluZztcblx0XHR2YXIga2V5UG9zID0gZGlzcGxheVN0cmluZy50b0xvd2VyQ2FzZSgpLmluZGV4T2YoYWNjZXNzS2V5LnRvTG93ZXJDYXNlKCkpO1xuXHRcdGlmIChrZXlQb3MgPT0gLTEpIHtcblx0XHRcdHJldHVybiBkaXNwbGF5U3RyaW5nICsgJyAoPHU+JyArIGFjY2Vzc0tleSArICc8L3U+KSc7XG5cdFx0fVxuXHRcdGlmIChkaXNwbGF5U3RyaW5nLmNoYXJBdChrZXlQb3MpICE9IGFjY2Vzc0tleSkge1xuXHRcdFx0Ly8gY2FzZSBkaWZmZXJcblx0XHRcdGFjY2Vzc0tleSA9IGRpc3BsYXlTdHJpbmcuY2hhckF0KGtleVBvcyk7XG5cdFx0fVxuXHRcdHZhciByZXR1cm5TdHJpbmcgPSBkaXNwbGF5U3RyaW5nLnN1YnN0cmluZygwLCBkaXNwbGF5U3RyaW5nLmluZGV4T2YoYWNjZXNzS2V5KSk7XG5cdFx0cmV0dXJuU3RyaW5nICs9ICc8dT4nICsgYWNjZXNzS2V5ICsgJzwvdT4nO1xuXHRcdHJldHVyblN0cmluZyArPSBkaXNwbGF5U3RyaW5nLnN1YnN0cmluZyhkaXNwbGF5U3RyaW5nLmluZGV4T2YoYWNjZXNzS2V5KSArIDEsIGRpc3BsYXlTdHJpbmcubGVuZ3RoKTtcblx0XHRyZXR1cm4gcmV0dXJuU3RyaW5nO1xuXHR9O1xuXG5cdC8qKlxuICAqIFV0aWxpdGFyeSBmdW5jdGlvbiB0byB0cmFuc2Zvcm0gWE1MIE5vZGUgYXR0cmlidXRlcyBpbnRvIE9iamVjdCBtYXBwaW5nIGtleXMuXG4gICogQHBhcmFtIG9iamVjdCBPYmplY3QgVGhlIHRhcmdldCBvYmplY3RcbiAgKiBAcGFyYW0gbm9kZSBOb2RlIFRoZSBzb3VyY2Ugbm9kZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuYXR0cmlidXRlc1RvT2JqZWN0ID0gZnVuY3Rpb24gYXR0cmlidXRlc1RvT2JqZWN0KG9iamVjdCwgbm9kZSkge1xuXHRcdGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcblx0XHRcdGlmICghb2JqZWN0Lmhhc093blByb3BlcnR5KGtleSkgfHwgIW5vZGUuZ2V0QXR0cmlidXRlKGtleSkpIGNvbnRpbnVlO1xuXHRcdFx0dmFyIHZhbHVlID0gbm9kZS5nZXRBdHRyaWJ1dGUoa2V5KTtcblx0XHRcdGlmICh2YWx1ZSA9PSAndHJ1ZScpIHZhbHVlID0gdHJ1ZTtlbHNlIGlmICh2YWx1ZSA9PSAnZmFsc2UnKSB2YWx1ZSA9IGZhbHNlO1xuXHRcdFx0aWYgKGtleSA9PSAnYWxsb3dlZE1pbWVzJykge1xuXHRcdFx0XHRpZiAodmFsdWUgJiYgdmFsdWUuc3BsaXQoJywnKS5sZW5ndGgpIHtcblx0XHRcdFx0XHR2YWx1ZSA9IHZhbHVlLnNwbGl0KCcsJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dmFsdWUgPSBbXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0b2JqZWN0W2tleV0gPSB2YWx1ZTtcblx0XHR9XG5cdH07XG5cblx0cmV0dXJuIEFjdGlvbjtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEFjdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgXCJkZWZhdWx0XCI6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgQ29udGV4dE1lbnVNb2RlbCA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoQ29udGV4dE1lbnVNb2RlbCwgX09ic2VydmFibGUpO1xuXG4gICAgZnVuY3Rpb24gQ29udGV4dE1lbnVNb2RlbCgpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbnRleHRNZW51TW9kZWwpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGVbXCJzdXBlclwiXSA9IGZ1bmN0aW9uIF9zdXBlcigpIHtcbiAgICAgICAgdGhpcy5fY3VycmVudE5vZGUgPSBudWxsO1xuICAgICAgICB0aGlzLl9wb3NpdGlvbiA9IG51bGw7XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwuZ2V0SW5zdGFuY2UgPSBmdW5jdGlvbiBnZXRJbnN0YW5jZSgpIHtcbiAgICAgICAgaWYgKCFDb250ZXh0TWVudU1vZGVsLl9fSU5TVEFOQ0UpIHtcbiAgICAgICAgICAgIENvbnRleHRNZW51TW9kZWwuX19JTlNUQU5DRSA9IG5ldyBDb250ZXh0TWVudU1vZGVsKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIENvbnRleHRNZW51TW9kZWwuX19JTlNUQU5DRTtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGUub3BlbkF0UG9zaXRpb24gPSBmdW5jdGlvbiBvcGVuQXRQb3NpdGlvbihjbGllbnRYLCBjbGllbnRZKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgdGhpcy5fcG9zaXRpb24gPSB7IHg6IGNsaWVudFgsIHk6IGNsaWVudFkgfTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJvcGVuXCIpO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZS5vcGVuTm9kZUF0UG9zaXRpb24gPSBmdW5jdGlvbiBvcGVuTm9kZUF0UG9zaXRpb24obm9kZSwgY2xpZW50WCwgY2xpZW50WSkge1xuICAgICAgICB0aGlzLl9jdXJyZW50Tm9kZSA9IG5vZGU7XG4gICAgICAgIHRoaXMuX3Bvc2l0aW9uID0geyB4OiBjbGllbnRYLCB5OiBjbGllbnRZIH07XG4gICAgICAgIHRoaXMubm90aWZ5KFwib3BlblwiLCBub2RlKTtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGUuZ2V0Tm9kZSA9IGZ1bmN0aW9uIGdldE5vZGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jdXJyZW50Tm9kZTtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGUuZ2V0UG9zaXRpb24gPSBmdW5jdGlvbiBnZXRQb3NpdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Bvc2l0aW9uO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgICAgICB0aGlzLl9jdXJyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiY2xvc2VcIik7XG4gICAgfTtcblxuICAgIHJldHVybiBDb250ZXh0TWVudU1vZGVsO1xufSkoX2xhbmdPYnNlcnZhYmxlMltcImRlZmF1bHRcIl0pO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IENvbnRleHRNZW51TW9kZWw7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgX0FjdGlvbiA9IHJlcXVpcmUoJy4vQWN0aW9uJyk7XG5cbnZhciBfQWN0aW9uMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0FjdGlvbik7XG5cbi8qKlxuICogU2luZ2xldG9uIGNsYXNzIHRoYXQgbWFuYWdlcyBhbGwgYWN0aW9ucy4gQ2FuIGJlIGNhbGxlZCBkaXJlY3RseSB1c2luZyBweWRpby5nZXRDb250cm9sbGVyKCkuXG4gKi9cblxudmFyIENvbnRyb2xsZXIgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKENvbnRyb2xsZXIsIF9PYnNlcnZhYmxlKTtcblxuICAgIC8qKlxuICAgICAqIFN0YW5kYXJkIGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHB5ZGlvT2JqZWN0IFB5ZGlvXG4gICAgICogQHBhcmFtIGRhdGFNb2RlbEVsZW1lbnRJZFxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gQ29udHJvbGxlcihweWRpb09iamVjdCkge1xuICAgICAgICB2YXIgZGF0YU1vZGVsRWxlbWVudElkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29udHJvbGxlcik7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QgPSBweWRpb09iamVjdDtcbiAgICAgICAgdGhpcy5fcmVnaXN0ZXJlZEtleXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMudXNlcnNFbmFibGVkID0gcHlkaW9PYmplY3QuUGFyYW1ldGVycy5nZXQoXCJ1c2Vyc0VuYWJsZWRcIik7XG5cbiAgICAgICAgdGhpcy5zdWJNZW51cyA9IFtdO1xuICAgICAgICB0aGlzLmFjdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZGVmYXVsdEFjdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMudG9vbGJhcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuX2d1aUFjdGlvbnMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5jb250ZXh0Q2hhbmdlZE9icyA9IChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ29udGV4dENoYW5nZSgpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSwgMCk7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZE9icyA9IChmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlU2VsZWN0aW9uQ2hhbmdlKCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpLCAwKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcblxuICAgICAgICBpZiAoZGF0YU1vZGVsRWxlbWVudElkKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsRGF0YU1vZGVsID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGF0YU1vZGVsRWxlbWVudElkKS5hanhwUGFuZU9iamVjdC5nZXREYXRhTW9kZWwoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICBpZiAodGhpcy5fZGF0YU1vZGVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY29ubmVjdERhdGFNb2RlbCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5vYnNlcnZlT25jZShcImRhdGFtb2RlbC1sb2FkZWQtXCIgKyBkYXRhTW9kZWxFbGVtZW50SWQsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRhdGFNb2RlbEVsZW1lbnRJZCkuYWp4cFBhbmVPYmplY3QuZ2V0RGF0YU1vZGVsKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2Nvbm5lY3REYXRhTW9kZWwoKTtcbiAgICAgICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubG9jYWxEYXRhTW9kZWwgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2Nvbm5lY3REYXRhTW9kZWwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVzZXJzRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qub2JzZXJ2ZShcInVzZXJfbG9nZ2VkXCIsIChmdW5jdGlvbiAodXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXNlcih1c2VyKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX3B5ZGlvT2JqZWN0LnVzZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodGhpcy5fcHlkaW9PYmplY3QudXNlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5wdWJsaXNoQWN0aW9uRXZlbnQgPSBmdW5jdGlvbiBwdWJsaXNoQWN0aW9uRXZlbnQoZXZlbnROYW1lLCBkYXRhKSB7XG4gICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmZpcmUoZXZlbnROYW1lLCBkYXRhKTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuX2Nvbm5lY3REYXRhTW9kZWwgPSBmdW5jdGlvbiBfY29ubmVjdERhdGFNb2RlbCgpIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWxEYXRhTW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbC5vYnNlcnZlKFwiY29udGV4dF9jaGFuZ2VkXCIsIHRoaXMuY29udGV4dENoYW5nZWRPYnMpO1xuICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsLm9ic2VydmUoXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzLnNlbGVjdGlvbkNoYW5nZWRPYnMpO1xuICAgICAgICAgICAgdGhpcy5sb2FkQWN0aW9uc0Zyb21SZWdpc3RyeSgpO1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qub2JzZXJ2ZShcInJlZ2lzdHJ5X2xvYWRlZFwiLCAoZnVuY3Rpb24gKHJlZ2lzdHJ5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkQWN0aW9uc0Zyb21SZWdpc3RyeShyZWdpc3RyeSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0Lm9ic2VydmUoXCJjb250ZXh0X2NoYW5nZWRcIiwgdGhpcy5jb250ZXh0Q2hhbmdlZE9icyk7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5vYnNlcnZlKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkT2JzKTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbCA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHRIb2xkZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS51cGRhdGVHdWlBY3Rpb25zID0gZnVuY3Rpb24gdXBkYXRlR3VpQWN0aW9ucyhhY3Rpb25zKSB7XG4gICAgICAgIGFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKHYsIGspIHtcbiAgICAgICAgICAgIHRoaXMuX2d1aUFjdGlvbnMuc2V0KGssIHYpO1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlckFjdGlvbih2KTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIC8vdGhpcy5ub3RpZnkoXCJhY3Rpb25zX3JlZnJlc2hlZFwiKTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZGVsZXRlRnJvbUd1aUFjdGlvbnMgPSBmdW5jdGlvbiBkZWxldGVGcm9tR3VpQWN0aW9ucyhhY3Rpb25OYW1lKSB7XG4gICAgICAgIHRoaXMuX2d1aUFjdGlvbnNbJ2RlbGV0ZSddKGFjdGlvbk5hbWUpO1xuICAgICAgICAvL3RoaXMubm90aWZ5KFwiYWN0aW9uc19yZWZyZXNoZWRcIik7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnJlZnJlc2hHdWlBY3Rpb25zSTE4biA9IGZ1bmN0aW9uIHJlZnJlc2hHdWlBY3Rpb25zSTE4bigpIHtcbiAgICAgICAgdGhpcy5fZ3VpQWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICB2YWx1ZS5yZWZyZXNoRnJvbUkxOE5IYXNoKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXREYXRhTW9kZWwgPSBmdW5jdGlvbiBnZXREYXRhTW9kZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kYXRhTW9kZWw7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICBpZiAodGhpcy5sb2NhbERhdGFNb2RlbCAmJiB0aGlzLl9kYXRhTW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbC5zdG9wT2JzZXJ2aW5nKFwiY29udGV4dF9jaGFuZ2VkXCIsIHRoaXMuY29udGV4dENoYW5nZWRPYnMpO1xuICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsLnN0b3BPYnNlcnZpbmcoXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzLnNlbGVjdGlvbkNoYW5nZWRPYnMpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldE1lc3NhZ2UgPSBmdW5jdGlvbiBnZXRNZXNzYWdlKG1lc3NhZ2VJZCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3B5ZGlvT2JqZWN0Lk1lc3NhZ2VIYXNoW21lc3NhZ2VJZF07XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlSWQ7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ09NUEFUSUJJTElUWSBNRVRIRFxuICAgICAqIEBwYXJhbSB4bWxEb2NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnBhcnNlWG1sTWVzc2FnZSA9IGZ1bmN0aW9uIHBhcnNlWG1sTWVzc2FnZSh4bWxEb2MpIHtcbiAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZGVidWcoXCJDb250cm9sbGVyLnBhcnNlWG1sTWVzc2FnZSgpIGlzIGRlcHJlY2F0ZWQsIHVzZSBQeWRpb0FwaSBpbnN0ZWFkXCIpO1xuICAgICAgICByZXR1cm4gX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5wYXJzZVhtbE1lc3NhZ2UoeG1sRG9jKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3VibWl0cyBhIGZvcm0gdXNpbmcgQ29ubmV4aW9uIGNsYXNzLlxuICAgICAqIEBwYXJhbSBmb3JtTmFtZSBTdHJpbmcgVGhlIGlkIG9mIHRoZSBmb3JtXG4gICAgICogQHBhcmFtIHBvc3QgQm9vbGVhbiBXaGV0aGVyIHRvIFBPU1Qgb3IgR0VUXG4gICAgICogQHBhcmFtIGNvbXBsZXRlQ2FsbGJhY2sgRnVuY3Rpb24gQ2FsbGJhY2sgdG8gYmUgY2FsbGVkIG9uIGNvbXBsZXRlXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5zdWJtaXRGb3JtID0gZnVuY3Rpb24gc3VibWl0Rm9ybShmb3JtTmFtZSwgcG9zdCwgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5kZWJ1ZyhcIkNvbnRyb2xsZXIuc3VibWl0Rm9ybSgpIGlzIGRlcHJlY2F0ZWQsIHVzZSBQeWRpb0FwaSBpbnN0ZWFkXCIpO1xuICAgICAgICByZXR1cm4gX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5zdWJtaXRGb3JtKGZvcm1OYW1lLCBwb3N0LCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3RvcmVzIHRoZSBjdXJyZW50bHkgbG9nZ2VkIHVzZXIgb2JqZWN0XG4gICAgICogQHBhcmFtIG9Vc2VyIFVzZXIgVXNlciBpbnN0YW5jZVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuc2V0VXNlciA9IGZ1bmN0aW9uIHNldFVzZXIob1VzZXIpIHtcbiAgICAgICAgdGhpcy5vVXNlciA9IG9Vc2VyO1xuICAgICAgICBpZiAob1VzZXIgIT0gbnVsbCAmJiBvVXNlci5pZCAhPSAnZ3Vlc3QnICYmIG9Vc2VyLmdldFByZWZlcmVuY2UoJ2xhbmcnKSAhPSBudWxsICYmIG9Vc2VyLmdldFByZWZlcmVuY2UoJ2xhbmcnKSAhPSBcIlwiICYmIG9Vc2VyLmdldFByZWZlcmVuY2UoJ2xhbmcnKSAhPSB0aGlzLl9weWRpb09iamVjdC5jdXJyZW50TGFuZ3VhZ2UgJiYgIW9Vc2VyLmxvY2spIHtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmxvYWRJMThOTWVzc2FnZXMob1VzZXIuZ2V0UHJlZmVyZW5jZSgnbGFuZycpKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaWx0ZXIgdGhlIGFjdGlvbnMgZ2l2ZW4gdGhlIHNyY0VsZW1lbnQgcGFzc2VkIGFzIGFyZ3VtZW50cy5cbiAgICAgKiBAcGFyYW0gYWN0aW9uc1NlbGVjdG9yQXR0IFN0cmluZyBBbiBpZGVudGlmaWVyIGFtb25nIHNlbGVjdGlvbkNvbnRleHQsIGdlbmVyaWNDb250ZXh0LCBhIHdlYmZ4IG9iamVjdCBpZFxuICAgICAgICAqIEBwYXJhbSBpZ25vcmVHcm91cHMgQXJyYXkgYSBsaXN0IG9mIGdyb3VwcyB0byBpZ25vcmVcbiAgICAgKiBAcmV0dXJucyBBcnJheVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0Q29udGV4dEFjdGlvbnMgPSBmdW5jdGlvbiBnZXRDb250ZXh0QWN0aW9ucyhhY3Rpb25zU2VsZWN0b3JBdHQsIGlnbm9yZUdyb3Vwcywgb25seUdyb3Vwcykge1xuICAgICAgICB2YXIgY29udGV4dEFjdGlvbnMgPSBbXTtcbiAgICAgICAgdmFyIGRlZmF1bHRHcm91cCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIGNvbnRleHRBY3Rpb25zR3JvdXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIWFjdGlvbi5jb250ZXh0LmNvbnRleHRNZW51ICYmICEob25seUdyb3VwcyAmJiBvbmx5R3JvdXBzLmxlbmd0aCkpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zU2VsZWN0b3JBdHQgPT0gJ3NlbGVjdGlvbkNvbnRleHQnICYmICFhY3Rpb24uY29udGV4dC5zZWxlY3Rpb24pIHJldHVybjtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zU2VsZWN0b3JBdHQgPT0gJ2RpcmVjdG9yeUNvbnRleHQnICYmICFhY3Rpb24uY29udGV4dC5kaXIpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zU2VsZWN0b3JBdHQgPT0gJ2dlbmVyaWNDb250ZXh0JyAmJiBhY3Rpb24uY29udGV4dC5zZWxlY3Rpb24pIHJldHVybjtcbiAgICAgICAgICAgIGlmIChhY3Rpb24uY29udGV4dEhpZGRlbiB8fCBhY3Rpb24uZGVueSkgcmV0dXJuO1xuICAgICAgICAgICAgYWN0aW9uLmNvbnRleHQuYWN0aW9uQmFyR3JvdXAuc3BsaXQoJywnKS5mb3JFYWNoKGZ1bmN0aW9uIChiYXJHcm91cCkge1xuICAgICAgICAgICAgICAgIGlmICghY29udGV4dEFjdGlvbnNHcm91cC5oYXMoYmFyR3JvdXApKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRBY3Rpb25zR3JvdXAuc2V0KGJhckdyb3VwLCBbXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgaXNEZWZhdWx0ID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1NlbGVjdG9yQXR0ID09ICdzZWxlY3Rpb25Db250ZXh0Jykge1xuICAgICAgICAgICAgICAgIC8vIHNldCBkZWZhdWx0IGluIGJvbGRcbiAgICAgICAgICAgICAgICB2YXIgdXNlclNlbGVjdGlvbiA9IHRoaXMuX2RhdGFNb2RlbDtcbiAgICAgICAgICAgICAgICBpZiAoIXVzZXJTZWxlY3Rpb24uaXNFbXB0eSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWZhdWx0QWN0aW9uID0gJ2ZpbGUnO1xuICAgICAgICAgICAgICAgICAgICBpZiAodXNlclNlbGVjdGlvbi5pc1VuaXF1ZSgpICYmICh1c2VyU2VsZWN0aW9uLmhhc0RpcigpIHx8IHVzZXJTZWxlY3Rpb24uaGFzTWltZShbJ2FqeHBfYnJvd3NhYmxlX2FyY2hpdmUnXSkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0QWN0aW9uID0gJ2Rpcic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVmYXVsdEFjdGlvbnMuZ2V0KGRlZmF1bHRBY3Rpb24pICYmIGFjdGlvbi5vcHRpb25zLm5hbWUgPT0gdGhpcy5kZWZhdWx0QWN0aW9ucy5nZXQoZGVmYXVsdEFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzRGVmYXVsdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhY3Rpb24uY29udGV4dC5hY3Rpb25CYXJHcm91cC5zcGxpdCgnLCcpLmZvckVhY2goZnVuY3Rpb24gKGJhckdyb3VwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lbnVJdGVtID0gYWN0aW9uLmdldE1lbnVEYXRhKCk7XG4gICAgICAgICAgICAgICAgbWVudUl0ZW0uaXNEZWZhdWx0ID0gaXNEZWZhdWx0O1xuICAgICAgICAgICAgICAgIGNvbnRleHRBY3Rpb25zR3JvdXAuZ2V0KGJhckdyb3VwKS5wdXNoKG1lbnVJdGVtKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNEZWZhdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHRHcm91cCA9IGJhckdyb3VwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdmFyIGZpcnN0ID0gdHJ1ZSxcbiAgICAgICAgICAgIGtleXMgPSBbXTtcbiAgICAgICAgY29udGV4dEFjdGlvbnNHcm91cCA9IHRoaXMuX3NvcnRUb29sYmFyc0FjdGlvbnMoY29udGV4dEFjdGlvbnNHcm91cCk7XG4gICAgICAgIGNvbnRleHRBY3Rpb25zR3JvdXAuZm9yRWFjaChmdW5jdGlvbiAodiwgaykge1xuICAgICAgICAgICAgaWYgKGRlZmF1bHRHcm91cCAmJiBrID09IGRlZmF1bHRHcm91cCkgcmV0dXJuO1xuICAgICAgICAgICAga2V5cy5wdXNoKGspO1xuICAgICAgICB9KTtcbiAgICAgICAga2V5cy5zb3J0KCk7XG4gICAgICAgIGlmIChkZWZhdWx0R3JvdXAgJiYgY29udGV4dEFjdGlvbnNHcm91cC5oYXMoZGVmYXVsdEdyb3VwKSkge1xuICAgICAgICAgICAga2V5cy51bnNoaWZ0KGRlZmF1bHRHcm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFjdGlvbnNQdXNoZWQgPSB7fTtcbiAgICAgICAga2V5cy5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gY29udGV4dEFjdGlvbnNHcm91cC5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmICghZmlyc3QpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0QWN0aW9ucy5wdXNoKHsgc2VwYXJhdG9yOiB0cnVlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlnbm9yZUdyb3VwcyAmJiBpZ25vcmVHcm91cHMuaW5kZXhPZihrZXkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvbmx5R3JvdXBzICYmIG9ubHlHcm91cHMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpcnN0ID0gZmFsc2U7XG4gICAgICAgICAgICB2YWx1ZS5mb3JFYWNoKGZ1bmN0aW9uIChtSXRlbSkge1xuICAgICAgICAgICAgICAgIHZhciBhY3Rpb25JZCA9IG1JdGVtLmFjdGlvbl9pZDtcbiAgICAgICAgICAgICAgICBpZiAoIWFjdGlvbnNQdXNoZWRbYWN0aW9uSWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRBY3Rpb25zLnB1c2gobUl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb25zUHVzaGVkW2FjdGlvbklkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29udGV4dEFjdGlvbnM7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldFRvb2xiYXJzQWN0aW9ucyA9IGZ1bmN0aW9uIGdldFRvb2xiYXJzQWN0aW9ucygpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB2YXIgdG9vbGJhcnNMaXN0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gW10gOiBhcmd1bWVudHNbMF07XG4gICAgICAgIHZhciBncm91cE90aGVyTGlzdCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IFtdIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIHZhciB0b29sYmFycyA9IG5ldyBNYXAoKSxcbiAgICAgICAgICAgIGdyb3VwT3RoZXJCYXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB2YXIgbGFzdFRiYXJBZGRlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGlmIChhY3Rpb24uY29udGV4dC5hY3Rpb25CYXIpIHtcbiAgICAgICAgICAgICAgICBhY3Rpb24uY29udGV4dC5hY3Rpb25CYXJHcm91cC5zcGxpdChcIixcIikubWFwKChmdW5jdGlvbiAoYmFyR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRvb2xiYXJzTGlzdC5pbmRleE9mKGJhckdyb3VwKSA9PT0gLTEgJiYgZ3JvdXBPdGhlckxpc3QuaW5kZXhPZihiYXJHcm91cCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHRCYXJVcGRhdGUgPSB0b29sYmFyc0xpc3QuaW5kZXhPZihiYXJHcm91cCkgIT09IC0xID8gdG9vbGJhcnMgOiBncm91cE90aGVyQmFycztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRCYXJVcGRhdGUuZ2V0KGJhckdyb3VwKSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0QmFyVXBkYXRlLnNldChiYXJHcm91cCwgW10pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRCYXJVcGRhdGUuZ2V0KGJhckdyb3VwKS5wdXNoKGFjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0QmFyVXBkYXRlID09PSB0b29sYmFycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFRiYXJBZGRlZCA9IGJhckdyb3VwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuXG4gICAgICAgIC8vIFJlZ3JvdXAgYWN0aW9ucyBhcnRpZmljaWFsbHlcbiAgICAgICAgaWYgKGdyb3VwT3RoZXJMaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3VibWVudUl0ZW1zID0gW107XG4gICAgICAgICAgICAgICAgZ3JvdXBPdGhlckxpc3QubWFwKChmdW5jdGlvbiAob3RoZXJUb29sYmFyKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIG90aGVyQWN0aW9ucyA9IGdyb3VwT3RoZXJCYXJzLmdldChvdGhlclRvb2xiYXIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW90aGVyQWN0aW9ucykgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICBvdGhlckFjdGlvbnMubWFwKGZ1bmN0aW9uIChhY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1lbnVJdGVtcy5wdXNoKHsgYWN0aW9uSWQ6IGFjdCB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChncm91cE90aGVyTGlzdC5pbmRleE9mKG90aGVyVG9vbGJhcikgPCBncm91cE90aGVyTGlzdC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJtZW51SXRlbXMucHVzaCh7IHNlcGFyYXRvcjogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpKTtcbiAgICAgICAgICAgICAgICB2YXIgbW9yZUFjdGlvbiA9IG5ldyBfQWN0aW9uMlsnZGVmYXVsdCddKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ2dyb3VwX21vcmVfYWN0aW9uJyxcbiAgICAgICAgICAgICAgICAgICAgaWNvbl9jbGFzczogJ2ljb24tbm9uZScsXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IE1lc3NhZ2VIYXNoWzQ1Nl0sXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBNZXNzYWdlSGFzaFs0NTZdLFxuICAgICAgICAgICAgICAgICAgICBoYXNBY2Nlc3NLZXk6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBzdWJNZW51OiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gY2FsbGJhY2soKSB7fVxuICAgICAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgZGlyOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25CYXI6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbkJhckdyb3VwOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dE1lbnU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBpbmZvUGFuZWw6IGZhbHNlXG5cbiAgICAgICAgICAgICAgICB9LCB7fSwge30sIHsgZHluYW1pY0l0ZW1zOiBzdWJtZW51SXRlbXMgfSk7XG4gICAgICAgICAgICAgICAgX3RoaXMucmVnaXN0ZXJBY3Rpb24obW9yZUFjdGlvbik7XG4gICAgICAgICAgICAgICAgX3RoaXMuYWN0aW9ucy5zZXQoXCJncm91cF9tb3JlX2FjdGlvblwiLCBtb3JlQWN0aW9uKTtcbiAgICAgICAgICAgICAgICB0b29sYmFycy5zZXQoJ01PUkVfQUNUSU9OJywgW21vcmVBY3Rpb25dKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc29ydFRvb2xiYXJzQWN0aW9ucyh0b29sYmFycyk7XG4gICAgICAgIHJldHVybiB0b29sYmFycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2VuZXJpYyBtZXRob2QgdG8gZ2V0IGFjdGlvbnMgZm9yIGEgZ2l2ZW4gY29tcG9uZW50IHBhcnQuXG4gICAgICogQHBhcmFtIGFqeHBDbGFzc05hbWUgU3RyaW5nIFxuICAgICAqIEBwYXJhbSB3aWRnZXRJZCBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBbXVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0QWN0aW9uc0ZvckFqeHBXaWRnZXQgPSBmdW5jdGlvbiBnZXRBY3Rpb25zRm9yQWp4cFdpZGdldChhanhwQ2xhc3NOYW1lLCB3aWRnZXRJZCkge1xuICAgICAgICB2YXIgYWN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoYWN0aW9uLmNvbnRleHQuYWp4cFdpZGdldHMgJiYgKGFjdGlvbi5jb250ZXh0LmFqeHBXaWRnZXRzLmluZGV4T2YoYWp4cENsYXNzTmFtZSArICc6OicgKyB3aWRnZXRJZCkgIT0gLTEgfHwgYWN0aW9uLmNvbnRleHQuYWp4cFdpZGdldHMuaW5kZXhPZihhanhwQ2xhc3NOYW1lKSAhPSAtMSkgJiYgIWFjdGlvbi5kZW55KSBhY3Rpb25zLnB1c2goYWN0aW9uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBhY3Rpb25zO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyBhIGRlZmF1bHQgYWN0aW9uIGFuZCBmaXJlcyBpdC5cbiAgICAgKiBAcGFyYW0gZGVmYXVsdE5hbWUgU3RyaW5nIChcImZpbGVcIiwgXCJkaXJcIiwgXCJkcmFnbmRyb3BcIiwgXCJjdHJsZHJhZ25kcm9wXCIpXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5maXJlRGVmYXVsdEFjdGlvbiA9IGZ1bmN0aW9uIGZpcmVEZWZhdWx0QWN0aW9uKGRlZmF1bHROYW1lKSB7XG4gICAgICAgIHZhciBhY3Rpb25OYW1lID0gdGhpcy5kZWZhdWx0QWN0aW9ucy5nZXQoZGVmYXVsdE5hbWUpO1xuICAgICAgICBpZiAoYWN0aW9uTmFtZSkge1xuICAgICAgICAgICAgYXJndW1lbnRzWzBdID0gYWN0aW9uTmFtZTtcbiAgICAgICAgICAgIGlmIChhY3Rpb25OYW1lID09PSBcImxzXCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb25zLmdldChhY3Rpb25OYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uKSBhY3Rpb24uZW5hYmxlKCk7IC8vIEZvcmNlIGVuYWJsZSBvbiBkZWZhdWx0IGFjdGlvblxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5maXJlQWN0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmlyZSBhbiBhY3Rpb24gYmFzZWQgb24gaXRzIG5hbWVcbiAgICAgKiBAcGFyYW0gYWN0aW9uTmFtZSBTdHJpbmcgVGhlIG5hbWUgb2YgdGhlIGFjdGlvblxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZmlyZUFjdGlvbiA9IGZ1bmN0aW9uIGZpcmVBY3Rpb24oYWN0aW9uTmFtZSkge1xuICAgICAgICB2YXIgYWN0aW9uID0gdGhpcy5hY3Rpb25zLmdldChhY3Rpb25OYW1lKTtcbiAgICAgICAgaWYgKGFjdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LmZyb20oYXJndW1lbnRzKS5zbGljZSgxKTtcbiAgICAgICAgICAgIGFjdGlvbi5hcHBseShhcmdzKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYW4gYWNjZXNza2V5IGZvciBhIGdpdmVuIGFjdGlvbi4gXG4gICAgICogQHBhcmFtIGtleSBTdHJpbmcgVGhlIGFjY2VzcyBrZXlcbiAgICAgKiBAcGFyYW0gYWN0aW9uTmFtZSBTdHJpbmcgVGhlIG5hbWUgb2YgdGhlIGFjdGlvblxuICAgICAqIEBwYXJhbSBvcHRpb25uYWxDb21tYW5kIFN0cmluZyBBbiBvcHRpb25uYWwgYXJndW1lbnQgXG4gICAgICogdGhhdCB3aWxsIGJlIHBhc3NlZCB0byB0aGUgYWN0aW9uIHdoZW4gZmlyZWQuXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5yZWdpc3RlcktleSA9IGZ1bmN0aW9uIHJlZ2lzdGVyS2V5KGtleSwgYWN0aW9uTmFtZSwgb3B0aW9ubmFsQ29tbWFuZCkge1xuICAgICAgICBpZiAob3B0aW9ubmFsQ29tbWFuZCkge1xuICAgICAgICAgICAgYWN0aW9uTmFtZSA9IGFjdGlvbk5hbWUgKyBcIjo6XCIgKyBvcHRpb25uYWxDb21tYW5kO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRLZXlzLnNldChrZXkudG9Mb3dlckNhc2UoKSwgYWN0aW9uTmFtZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhbGwgcmVnaXN0ZXJlZCBrZXlzLlxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuY2xlYXJSZWdpc3RlcmVkS2V5cyA9IGZ1bmN0aW9uIGNsZWFyUmVnaXN0ZXJlZEtleXMoKSB7XG4gICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRLZXlzID0gbmV3IE1hcCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VycyBhbiBhY3Rpb24gYnkgaXRzIGFjY2VzcyBrZXkuXG4gICAgICogQHBhcmFtIGtleU5hbWUgU3RyaW5nIEEga2V5IG5hbWVcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmZpcmVBY3Rpb25CeUtleSA9IGZ1bmN0aW9uIGZpcmVBY3Rpb25CeUtleShrZXlOYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLl9yZWdpc3RlcmVkS2V5cy5nZXQoa2V5TmFtZSkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9yZWdpc3RlcmVkS2V5cy5nZXQoa2V5TmFtZSkuaW5kZXhPZihcIjo6XCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJ0cyA9IHRoaXMuX3JlZ2lzdGVyZWRLZXlzLmdldChrZXlOYW1lKS5zcGxpdChcIjo6XCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUFjdGlvbihwYXJ0c1swXSwgcGFydHNbMV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVBY3Rpb24odGhpcy5fcmVnaXN0ZXJlZEtleXMuZ2V0KGtleU5hbWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ29tcGxleCBmdW5jdGlvbiBjYWxsZWQgd2hlbiBkcmFnJ24nZHJvcHBpbmcuIEJhc2ljIGNoZWNrcyBvZiB3aG8gaXMgY2hpbGQgb2Ygd2hvLlxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmcgVGhlIGRyYWdnZWQgZWxlbWVudCBcbiAgICAgKiBAcGFyYW0gZGVzdERpciBTdHJpbmcgVGhlIGRyb3AgdGFyZ2V0IG5vZGUgcGF0aFxuICAgICAqIEBwYXJhbSBkZXN0Tm9kZU5hbWUgU3RyaW5nIFRoZSBkcm9wIHRhcmdldCBub2RlIG5hbWVcbiAgICAgKiBAcGFyYW0gY29weSBCb29sZWFuIENvcHkgb3IgTW92ZVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuYXBwbHlEcmFnTW92ZSA9IGZ1bmN0aW9uIGFwcGx5RHJhZ01vdmUoZmlsZU5hbWUsIGRlc3REaXIsIGRlc3ROb2RlTmFtZSwgY29weSkge1xuICAgICAgICBpZiAoIWNvcHkgJiYgKCF0aGlzLmRlZmF1bHRBY3Rpb25zLmhhcygnZHJhZ25kcm9wJykgfHwgdGhpcy5nZXREZWZhdWx0QWN0aW9uKCdkcmFnbmRyb3AnKS5kZW55KSB8fCBjb3B5ICYmICghdGhpcy5kZWZhdWx0QWN0aW9ucy5oYXMoJ2N0cmxkcmFnbmRyb3AnKSB8fCB0aGlzLmdldERlZmF1bHRBY3Rpb24oJ2N0cmxkcmFnbmRyb3AnKS5kZW55KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmaWxlTmFtZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChmaWxlTmFtZSA9PSBudWxsKSBmaWxlTmFtZXMgPSB0aGlzLl9kYXRhTW9kZWwuZ2V0RmlsZU5hbWVzKCk7ZWxzZSBmaWxlTmFtZXMgPSBbZmlsZU5hbWVdO1xuICAgICAgICAvLyBDaGVjayB0aGF0IGRlc3QgaXMgbm90IHRoZSBkaXJlY3QgcGFyZW50IG9mIHNvdXJjZSwgaWUgY3VycmVudCByZXAhXG4gICAgICAgIGlmIChkZXN0RGlyID09IHRoaXMuX2RhdGFNb2RlbC5nZXRDb250ZXh0Tm9kZSgpLmdldFBhdGgoKSkge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZGlzcGxheU1lc3NhZ2UoJ0VSUk9SJywgTWVzc2FnZUhhc2hbMjAzXSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2sgdGhhdCBkZXN0IGlzIG5vdCBjaGlsZCBvZiBzb3VyY2UgaXQgc2VsZlxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpbGVOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRlc3REaXIubGFzdEluZGV4T2YoZmlsZU5hbWVzW2ldLCAwKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmRpc3BsYXlNZXNzYWdlKCdFUlJPUicsIE1lc3NhZ2VIYXNoWzIwMl0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge307XG4gICAgICAgIHBhcmFtc1snZ2V0X2FjdGlvbiddID0gdGhpcy5kZWZhdWx0QWN0aW9ucy5nZXQoY29weSA/ICdjdHJsZHJhZ25kcm9wJyA6ICdkcmFnbmRyb3AnKTtcbiAgICAgICAgcGFyYW1zWydub2Rlc1tdJ10gPSBmaWxlTmFtZXM7XG4gICAgICAgIHBhcmFtc1snZGVzdCddID0gZGVzdERpcjtcbiAgICAgICAgcGFyYW1zWydkaXInXSA9IHRoaXMuX2RhdGFNb2RlbC5nZXRDb250ZXh0Tm9kZSgpLmdldFBhdGgoKTtcbiAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgIH0pLmJpbmQoX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKSkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGFjdGlvbiBkZWZpbmVkIGFzIGRlZmF1bHQgZm9yIGEgZ2l2ZW4gZGVmYXVsdCBzdHJpbmdcbiAgICAgKiBAcGFyYW0gZGVmYXVsdE5hbWUgU3RyaW5nXG4gICAgICogQHJldHVybnMgQWN0aW9uXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXREZWZhdWx0QWN0aW9uID0gZnVuY3Rpb24gZ2V0RGVmYXVsdEFjdGlvbihkZWZhdWx0TmFtZSkge1xuICAgICAgICBpZiAodGhpcy5kZWZhdWx0QWN0aW9ucy5oYXMoZGVmYXVsdE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hY3Rpb25zLmdldCh0aGlzLmRlZmF1bHRBY3Rpb25zLmdldChkZWZhdWx0TmFtZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTcHJlYWRzIGEgc2VsZWN0aW9uIGNoYW5nZSB0byBhbGwgYWN0aW9ucyBhbmQgdG8gcmVnaXN0ZXJlZCBjb21wb25lbnRzIFxuICAgICAqIGJ5IHRyaWdnZXJpbmcgYWpheHBsb3JlcjphY3Rpb25zX3JlZnJlc2hlZCBldmVudC5cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmZpcmVTZWxlY3Rpb25DaGFuZ2UgPSBmdW5jdGlvbiBmaXJlU2VsZWN0aW9uQ2hhbmdlKCkge1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgYWN0aW9uLmZpcmVTZWxlY3Rpb25DaGFuZ2UodGhpcy5fZGF0YU1vZGVsKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiYWN0aW9uc19yZWZyZXNoZWRcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNwcmVhZHMgYSBjb250ZXh0IGNoYW5nZSB0byBhbGwgYWN0aW9ucyBhbmQgdG8gcmVnaXN0ZXJlZCBjb21wb25lbnRzIFxuICAgICAqIGJ5IHRyaWdnZXJpbmcgYWpheHBsb3JlcjphY3Rpb25zX3JlZnJlc2hlZCBldmVudC5cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmZpcmVDb250ZXh0Q2hhbmdlID0gZnVuY3Rpb24gZmlyZUNvbnRleHRDaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBhY3Rpb24uZmlyZUNvbnRleHRDaGFuZ2UodGhpcy5fZGF0YU1vZGVsLCB0aGlzLnVzZXJzRW5hYmxlZCwgdGhpcy5vVXNlcik7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm5vdGlmeShcImFjdGlvbnNfcmVmcmVzaGVkXCIpO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5ub3RpZnkgPSBmdW5jdGlvbiBub3RpZnkoZXZlbnROYW1lLCBtZW1vKSB7XG4gICAgICAgIGlmICh0aGlzLmxvY2FsRGF0YU1vZGVsKSB7XG4gICAgICAgICAgICBfT2JzZXJ2YWJsZS5wcm90b3R5cGUubm90aWZ5LmNhbGwodGhpcywgXCJhY3Rpb25zX3JlZnJlc2hlZFwiLCBtZW1vKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmZpcmUoXCJhY3Rpb25zX3JlZnJlc2hlZFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIGFjdGlvbnNcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnJlbW92ZUFjdGlvbnMgPSBmdW5jdGlvbiByZW1vdmVBY3Rpb25zKCkge1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBhY3Rpb24ucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFjdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuY2xlYXJSZWdpc3RlcmVkS2V5cygpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYWN0aW9ucyBmcm9tIFhNTCBSZWdpc3RyeVxuICAgICAqIEBwYXJhbSByZWdpc3RyeSBET01Eb2N1bWVudFxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkgPSBmdW5jdGlvbiBsb2FkQWN0aW9uc0Zyb21SZWdpc3RyeSgpIHtcbiAgICAgICAgdmFyIHJlZ2lzdHJ5ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICBpZiAoIXJlZ2lzdHJ5KSB7XG4gICAgICAgICAgICByZWdpc3RyeSA9IHB5ZGlvLmdldFhtbFJlZ2lzdHJ5KCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW1vdmVBY3Rpb25zKCk7XG4gICAgICAgIHRoaXMucGFyc2VBY3Rpb25zKHJlZ2lzdHJ5KTtcbiAgICAgICAgdGhpcy5fZ3VpQWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAoYWN0KSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyQWN0aW9uKGFjdCk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm5vdGlmeShcImFjdGlvbnNfbG9hZGVkXCIpO1xuICAgICAgICB0aGlzLmZpcmVDb250ZXh0Q2hhbmdlKCk7XG4gICAgICAgIHRoaXMuZmlyZVNlbGVjdGlvbkNoYW5nZSgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYW4gYWN0aW9uIHRvIHRoaXMgbWFuYWdlciAoZGVmYXVsdCwgYWNjZXNza2V5KS5cbiAgICAgKiBAcGFyYW0gYWN0aW9uIEFjdGlvblxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucmVnaXN0ZXJBY3Rpb24gPSBmdW5jdGlvbiByZWdpc3RlckFjdGlvbihhY3Rpb24pIHtcbiAgICAgICAgdmFyIGFjdGlvbk5hbWUgPSBhY3Rpb24ub3B0aW9ucy5uYW1lO1xuICAgICAgICB0aGlzLmFjdGlvbnMuc2V0KGFjdGlvbk5hbWUsIGFjdGlvbik7XG4gICAgICAgIGlmIChhY3Rpb24uZGVmYXVsdHMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBhY3Rpb24uZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uLmRlZmF1bHRzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0QWN0aW9ucy5zZXQoa2V5LCBhY3Rpb25OYW1lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvbi5vcHRpb25zLmhhc0FjY2Vzc0tleSkge1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlcktleShhY3Rpb24ub3B0aW9ucy5hY2Nlc3NLZXksIGFjdGlvbk5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhY3Rpb24ub3B0aW9ucy5zcGVjaWFsQWNjZXNzS2V5KSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyS2V5KFwia2V5X1wiICsgYWN0aW9uLm9wdGlvbnMuc3BlY2lhbEFjY2Vzc0tleSwgYWN0aW9uTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgYWN0aW9uLnNldE1hbmFnZXIodGhpcyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBhcnNlIGFuIFhNTCBhY3Rpb24gbm9kZSBhbmQgcmVnaXN0ZXJzIHRoZSBhY3Rpb25cbiAgICAgKiBAcGFyYW0gZG9jdW1lbnRFbGVtZW50IERPTU5vZGUgVGhlIG5vZGUgdG8gcGFyc2VcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnBhcnNlQWN0aW9ucyA9IGZ1bmN0aW9uIHBhcnNlQWN0aW9ucyhkb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGFjdGlvbnMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoZG9jdW1lbnRFbGVtZW50LCBcImFjdGlvbnMvYWN0aW9uXCIpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFjdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zW2ldLm5vZGVOYW1lICE9ICdhY3Rpb24nKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zW2ldLmdldEF0dHJpYnV0ZSgnZW5hYmxlZCcpID09ICdmYWxzZScpIGNvbnRpbnVlO1xuICAgICAgICAgICAgdmFyIG5ld0FjdGlvbiA9IG5ldyBfQWN0aW9uMlsnZGVmYXVsdCddKCk7XG4gICAgICAgICAgICBuZXdBY3Rpb24uc2V0TWFuYWdlcih0aGlzKTtcbiAgICAgICAgICAgIG5ld0FjdGlvbi5jcmVhdGVGcm9tWE1MKGFjdGlvbnNbaV0pO1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlckFjdGlvbihuZXdBY3Rpb24pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYW4gYWN0aW9uIGJ5IGl0cyBuYW1lXG4gICAgICogQHBhcmFtIGFjdGlvbk5hbWUgU3RyaW5nXG4gICAgICogQHJldHVybnMgQWN0aW9uXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXRBY3Rpb25CeU5hbWUgPSBmdW5jdGlvbiBnZXRBY3Rpb25CeU5hbWUoYWN0aW9uTmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5hY3Rpb25zLmdldChhY3Rpb25OYW1lKTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuX3NvcnRUb29sYmFyc0FjdGlvbnMgPSBmdW5jdGlvbiBfc29ydFRvb2xiYXJzQWN0aW9ucyh0b29sYmFycykge1xuICAgICAgICAvLyBTb3J0XG4gICAgICAgIHRvb2xiYXJzLmZvckVhY2goZnVuY3Rpb24gKHYsIGspIHtcbiAgICAgICAgICAgIGlmICghdi5zb3J0KSByZXR1cm47XG4gICAgICAgICAgICB2LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgd0EgPSBhLndlaWdodCB8fCBhLm9wdGlvbnMgJiYgYS5vcHRpb25zLndlaWdodCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciB3QiA9IGIud2VpZ2h0IHx8IGIub3B0aW9ucyAmJiBiLm9wdGlvbnMud2VpZ2h0IHx8IDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdBID09PSB3QiA/IDAgOiB3QSA+IHdCID8gMSA6IC0xO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdG9vbGJhcnM7XG4gICAgfTtcblxuICAgIHJldHVybiBDb250cm9sbGVyO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ29udHJvbGxlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9BanhwTm9kZSA9IHJlcXVpcmUoJy4vQWp4cE5vZGUnKTtcblxudmFyIF9BanhwTm9kZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9BanhwTm9kZSk7XG5cbnZhciBfdXRpbExhbmdVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvTGFuZ1V0aWxzJyk7XG5cbnZhciBfdXRpbExhbmdVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsTGFuZ1V0aWxzKTtcblxudmFyIF91dGlsUGF0aFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9QYXRoVXRpbHMnKTtcblxudmFyIF91dGlsUGF0aFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxQYXRoVXRpbHMpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4uL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxuLyoqXG4gKiBGdWxsIGNvbnRhaW5lciBvZiB0aGUgZGF0YSB0cmVlLiBDb250YWlucyB0aGUgU2VsZWN0aW9uTW9kZWwgYXMgd2VsbC5cbiAqL1xuXG52YXIgUHlkaW9EYXRhTW9kZWwgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG5cdF9pbmhlcml0cyhQeWRpb0RhdGFNb2RlbCwgX09ic2VydmFibGUpO1xuXG5cdC8qKlxuICAqIENvbnN0cnVjdG9yXG4gICAgICogPiBXYXJuaW5nLCBldmVudHMgYXJlIG5vdyBMT0NBTCBieSBkZWZhdWx0XG4gICovXG5cblx0ZnVuY3Rpb24gUHlkaW9EYXRhTW9kZWwoKSB7XG5cdFx0dmFyIGxvY2FsRXZlbnRzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1swXTtcblxuXHRcdF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQeWRpb0RhdGFNb2RlbCk7XG5cblx0XHRfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuXHRcdHRoaXMuX2N1cnJlbnRSZXAgPSAnLyc7XG5cdFx0dGhpcy5fc2VsZWN0ZWROb2RlcyA9IFtdO1xuXHRcdHRoaXMuX2JFbXB0eSA9IHRydWU7XG5cdFx0dGhpcy5fZ2xvYmFsRXZlbnRzID0gIWxvY2FsRXZlbnRzO1xuXG5cdFx0dGhpcy5fYkZpbGUgPSBmYWxzZTtcblx0XHR0aGlzLl9iRGlyID0gZmFsc2U7XG5cdFx0dGhpcy5faXNSZWN5Y2xlID0gZmFsc2U7XG5cblx0XHR0aGlzLl9wZW5kaW5nU2VsZWN0aW9uID0gbnVsbDtcblx0XHR0aGlzLl9zZWxlY3Rpb25Tb3VyY2UgPSB7fTtcblxuXHRcdHRoaXMuX3Jvb3ROb2RlID0gbnVsbDtcblx0fVxuXG5cdFB5ZGlvRGF0YU1vZGVsLlJlbW90ZURhdGFNb2RlbEZhY3RvcnkgPSBmdW5jdGlvbiBSZW1vdGVEYXRhTW9kZWxGYWN0b3J5KHByb3ZpZGVyUHJvcGVydGllcykge1xuXHRcdHZhciByb290TGFiZWwgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdHZhciBkYXRhTW9kZWwgPSBuZXcgUHlkaW9EYXRhTW9kZWwodHJ1ZSk7XG5cdFx0dmFyIHJOb2RlUHJvdmlkZXIgPSBuZXcgUmVtb3RlTm9kZVByb3ZpZGVyKHByb3ZpZGVyUHJvcGVydGllcyk7XG5cdFx0ZGF0YU1vZGVsLnNldEFqeHBOb2RlUHJvdmlkZXIock5vZGVQcm92aWRlcik7XG5cdFx0dmFyIHJvb3ROb2RlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShcIi9cIiwgZmFsc2UsIHJvb3RMYWJlbCwgJycsIHJOb2RlUHJvdmlkZXIpO1xuXHRcdGRhdGFNb2RlbC5zZXRSb290Tm9kZShyb290Tm9kZSk7XG5cdFx0cmV0dXJuIGRhdGFNb2RlbDtcblx0fTtcblxuXHQvKipcbiAgKiBTZXRzIHRoZSBkYXRhIHNvdXJjZSB0aGF0IHdpbGwgZmVlZCB0aGUgbm9kZXMgd2l0aCBjaGlsZHJlbi5cbiAgKiBAcGFyYW0gaUFqeHBOb2RlUHJvdmlkZXIgSUFqeHBOb2RlUHJvdmlkZXJcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0QWp4cE5vZGVQcm92aWRlciA9IGZ1bmN0aW9uIHNldEFqeHBOb2RlUHJvdmlkZXIoaUFqeHBOb2RlUHJvdmlkZXIpIHtcblx0XHR0aGlzLl9pQWp4cE5vZGVQcm92aWRlciA9IGlBanhwTm9kZVByb3ZpZGVyO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybiB0aGUgY3VycmVudCBkYXRhIHNvdXJjZSBwcm92aWRlclxuICAqIEByZXR1cm4gSUFqeHBOb2RlUHJvdmlkZXJcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0QWp4cE5vZGVQcm92aWRlciA9IGZ1bmN0aW9uIGdldEFqeHBOb2RlUHJvdmlkZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgdGhlIGN1cnJlbnQgY29udGV4dCBub2RlLlxuICAqIEBwYXJhbSBhanhwTm9kZSBBanhwTm9kZSBUYXJnZXQgbm9kZSwgZWl0aGVyIGFuIGV4aXN0aW5nIG9uZSBvciBhIGZha2Ugb25lIGNvbnRhaW5pbmcgdGhlIHRhcmdldCBwYXJ0LlxuICAqIEBwYXJhbSBmb3JjZVJlbG9hZCBCb29sZWFuIElmIHNldCB0byB0cnVlLCB0aGUgbm9kZSB3aWxsIGJlIHJlbG9hZGVkIGV2ZW4gaWYgYWxyZWFkeSBsb2FkZWQuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnJlcXVpcmVDb250ZXh0Q2hhbmdlID0gZnVuY3Rpb24gcmVxdWlyZUNvbnRleHRDaGFuZ2UoYWp4cE5vZGUpIHtcblx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0dmFyIGZvcmNlUmVsb2FkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cblx0XHRpZiAoYWp4cE5vZGUgPT0gbnVsbCkgcmV0dXJuO1xuXHRcdHRoaXMuc2V0U2VsZWN0ZWROb2RlcyhbXSk7XG5cdFx0dmFyIHBhdGggPSBhanhwTm9kZS5nZXRQYXRoKCk7XG5cdFx0aWYgKChwYXRoID09IFwiXCIgfHwgcGF0aCA9PSBcIi9cIikgJiYgYWp4cE5vZGUgIT0gdGhpcy5fcm9vdE5vZGUpIHtcblx0XHRcdGFqeHBOb2RlID0gdGhpcy5fcm9vdE5vZGU7XG5cdFx0fVxuXHRcdHZhciBwYWdpbmF0aW9uUGFnZSA9IG51bGw7XG5cdFx0aWYgKGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuaGFzKCdwYWdpbmF0aW9uRGF0YScpICYmIGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpLmhhcygnbmV3X3BhZ2UnKSAmJiBhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKS5nZXQoJ25ld19wYWdlJykgIT0gYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykuZ2V0KCdjdXJyZW50JykpIHtcblx0XHRcdHBhZ2luYXRpb25QYWdlID0gYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykuZ2V0KCduZXdfcGFnZScpO1xuXHRcdFx0Zm9yY2VSZWxvYWQgPSB0cnVlO1xuXHRcdH1cblx0XHRpZiAoYWp4cE5vZGUgIT0gdGhpcy5fcm9vdE5vZGUgJiYgKCFhanhwTm9kZS5nZXRQYXJlbnQoKSB8fCBhanhwTm9kZS5mYWtlKSkge1xuXHRcdFx0Ly8gRmluZCBpbiBhcmJvIG9yIGJ1aWxkIGZha2UgYXJib1xuXHRcdFx0dmFyIGZha2VOb2RlcyA9IFtdO1xuXHRcdFx0YWp4cE5vZGUgPSBhanhwTm9kZS5maW5kSW5BcmJvKHRoaXMuX3Jvb3ROb2RlLCBmYWtlTm9kZXMpO1xuXHRcdFx0aWYgKGZha2VOb2Rlcy5sZW5ndGgpIHtcblx0XHRcdFx0dmFyIF9yZXQgPSAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHZhciBmaXJzdEZha2UgPSBmYWtlTm9kZXMuc2hpZnQoKTtcblx0XHRcdFx0XHRmaXJzdEZha2Uub2JzZXJ2ZU9uY2UoXCJmaXJzdF9sb2FkXCIsIChmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHRcdFx0dGhpcy5yZXF1aXJlQ29udGV4dENoYW5nZShhanhwTm9kZSk7XG5cdFx0XHRcdFx0fSkuYmluZChfdGhpcykpO1xuXHRcdFx0XHRcdGZpcnN0RmFrZS5vYnNlcnZlT25jZShcImVycm9yXCIsIChmdW5jdGlvbiAobWVzc2FnZSkge1xuXHRcdFx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IobWVzc2FnZSk7XG5cdFx0XHRcdFx0XHRmaXJzdEZha2Uubm90aWZ5KFwibm9kZV9yZW1vdmVkXCIpO1xuXHRcdFx0XHRcdFx0dmFyIHBhcmVudCA9IGZpcnN0RmFrZS5nZXRQYXJlbnQoKTtcblx0XHRcdFx0XHRcdHBhcmVudC5yZW1vdmVDaGlsZChmaXJzdEZha2UpO1xuXHRcdFx0XHRcdFx0Ly9kZWxldGUoZmlyc3RGYWtlKTtcblx0XHRcdFx0XHRcdHRoaXMucmVxdWlyZUNvbnRleHRDaGFuZ2UocGFyZW50KTtcblx0XHRcdFx0XHR9KS5iaW5kKF90aGlzKSk7XG5cdFx0XHRcdFx0X3RoaXMucHVibGlzaChcImNvbnRleHRfbG9hZGluZ1wiKTtcblx0XHRcdFx0XHRmaXJzdEZha2UubG9hZChfdGhpcy5faUFqeHBOb2RlUHJvdmlkZXIpO1xuXHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHR2OiB1bmRlZmluZWRcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9KSgpO1xuXG5cdFx0XHRcdGlmICh0eXBlb2YgX3JldCA9PT0gJ29iamVjdCcpIHJldHVybiBfcmV0LnY7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGFqeHBOb2RlLm9ic2VydmVPbmNlKFwibG9hZGVkXCIsIChmdW5jdGlvbiAoKSB7XG5cdFx0XHR0aGlzLnNldENvbnRleHROb2RlKGFqeHBOb2RlLCB0cnVlKTtcblx0XHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfbG9hZGVkXCIpO1xuXHRcdFx0aWYgKHRoaXMuZ2V0UGVuZGluZ1NlbGVjdGlvbigpKSB7XG5cdFx0XHRcdHZhciBzZWxQYXRoID0gYWp4cE5vZGUuZ2V0UGF0aCgpICsgKGFqeHBOb2RlLmdldFBhdGgoKSA9PSBcIi9cIiA/IFwiXCIgOiBcIi9cIikgKyB0aGlzLmdldFBlbmRpbmdTZWxlY3Rpb24oKTtcblx0XHRcdFx0dmFyIHNlbE5vZGUgPSBhanhwTm9kZS5maW5kQ2hpbGRCeVBhdGgoc2VsUGF0aCk7XG5cdFx0XHRcdGlmIChzZWxOb2RlKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKFtzZWxOb2RlXSwgdGhpcyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0aWYgKGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicGFnaW5hdGlvbkRhdGFcIikgJiYgYXJndW1lbnRzLmxlbmd0aCA8IDMpIHtcblx0XHRcdFx0XHRcdHZhciBuZXdQYWdlID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0dmFyIGN1cnJlbnRQYWdlID0gYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJwYWdpbmF0aW9uRGF0YVwiKS5nZXQoXCJjdXJyZW50XCIpO1xuXHRcdFx0XHRcdFx0dGhpcy5sb2FkUGF0aEluZm9TeW5jKHNlbFBhdGgsIGZ1bmN0aW9uIChmb3VuZE5vZGUpIHtcblx0XHRcdFx0XHRcdFx0bmV3UGFnZSA9IGZvdW5kTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInBhZ2VfcG9zaXRpb25cIik7XG5cdFx0XHRcdFx0XHR9LCB7IHBhZ2VfcG9zaXRpb246ICd0cnVlJyB9KTtcblx0XHRcdFx0XHRcdGlmIChuZXdQYWdlICYmIG5ld1BhZ2UgIT09IGN1cnJlbnRQYWdlKSB7XG5cdFx0XHRcdFx0XHRcdGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicGFnaW5hdGlvbkRhdGFcIikuc2V0KFwibmV3X3BhZ2VcIiwgbmV3UGFnZSk7XG5cdFx0XHRcdFx0XHRcdHRoaXMucmVxdWlyZUNvbnRleHRDaGFuZ2UoYWp4cE5vZGUsIHRydWUsIHRydWUpO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuY2xlYXJQZW5kaW5nU2VsZWN0aW9uKCk7XG5cdFx0XHR9XG5cdFx0fSkuYmluZCh0aGlzKSk7XG5cdFx0YWp4cE5vZGUub2JzZXJ2ZU9uY2UoXCJlcnJvclwiLCAoZnVuY3Rpb24gKG1lc3NhZ2UpIHtcblx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKG1lc3NhZ2UpO1xuXHRcdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9sb2FkZWRcIik7XG5cdFx0fSkuYmluZCh0aGlzKSk7XG5cdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9sb2FkaW5nXCIpO1xuXHRcdHRyeSB7XG5cdFx0XHRpZiAoZm9yY2VSZWxvYWQpIHtcblx0XHRcdFx0aWYgKHBhZ2luYXRpb25QYWdlKSB7XG5cdFx0XHRcdFx0YWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykuc2V0KCdjdXJyZW50JywgcGFnaW5hdGlvblBhZ2UpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGFqeHBOb2RlLnJlbG9hZCh0aGlzLl9pQWp4cE5vZGVQcm92aWRlcik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRhanhwTm9kZS5sb2FkKHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyKTtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2xvYWRlZFwiKTtcblx0XHR9XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnJlcXVpcmVOb2RlUmVsb2FkID0gZnVuY3Rpb24gcmVxdWlyZU5vZGVSZWxvYWQobm9kZU9yUGF0aCwgY29tcGxldGVDYWxsYmFjaykge1xuXHRcdGlmIChub2RlT3JQYXRoIGluc3RhbmNlb2YgU3RyaW5nKSB7XG5cdFx0XHRub2RlT3JQYXRoID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShub2RlT3JQYXRoKTtcblx0XHR9XG5cdFx0dmFyIG9uQ29tcGxldGUgPSBudWxsO1xuXHRcdGlmICh0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCkge1xuXHRcdFx0dmFyIGZvdW5kID0gLTE7XG5cdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzLm1hcChmdW5jdGlvbiAobm9kZSwga2V5KSB7XG5cdFx0XHRcdGlmIChub2RlLmdldFBhdGgoKSA9PSBub2RlT3JQYXRoLmdldFBhdGgoKSkgZm91bmQgPSBrZXk7XG5cdFx0XHR9KTtcblx0XHRcdGlmIChmb3VuZCAhPT0gLTEpIHtcblx0XHRcdFx0Ly8gTUFLRSBTVVJFIFNFTEVDVElPTiBJUyBPSyBBRlRFUiBSRUxPQURcblx0XHRcdFx0dGhpcy5fc2VsZWN0ZWROb2RlcyA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLmFycmF5V2l0aG91dCh0aGlzLl9zZWxlY3RlZE5vZGVzLCBmb3VuZCk7XG5cdFx0XHRcdHRoaXMucHVibGlzaChcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMpO1xuXHRcdFx0XHRvbkNvbXBsZXRlID0gKGZ1bmN0aW9uIChuZXdOb2RlKSB7XG5cdFx0XHRcdFx0dGhpcy5fc2VsZWN0ZWROb2Rlcy5wdXNoKG5ld05vZGUpO1xuXHRcdFx0XHRcdHRoaXMuX3NlbGVjdGlvblNvdXJjZSA9IHt9O1xuXHRcdFx0XHRcdHRoaXMucHVibGlzaChcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMpO1xuXHRcdFx0XHRcdGlmIChjb21wbGV0ZUNhbGxiYWNrKSBjb21wbGV0ZUNhbGxiYWNrKG5ld05vZGUpO1xuXHRcdFx0XHR9KS5iaW5kKHRoaXMpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLl9pQWp4cE5vZGVQcm92aWRlci5yZWZyZXNoTm9kZUFuZFJlcGxhY2Uobm9kZU9yUGF0aCwgb25Db21wbGV0ZSk7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmxvYWRQYXRoSW5mb1N5bmMgPSBmdW5jdGlvbiBsb2FkUGF0aEluZm9TeW5jKHBhdGgsIGNhbGxiYWNrKSB7XG5cdFx0dmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbMl07XG5cblx0XHR0aGlzLl9pQWp4cE5vZGVQcm92aWRlci5sb2FkTGVhZk5vZGVTeW5jKG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10ocGF0aCksIGNhbGxiYWNrLCBmYWxzZSwgYWRkaXRpb25hbFBhcmFtZXRlcnMpO1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5sb2FkUGF0aEluZm9Bc3luYyA9IGZ1bmN0aW9uIGxvYWRQYXRoSW5mb0FzeW5jKHBhdGgsIGNhbGxiYWNrKSB7XG5cdFx0dGhpcy5faUFqeHBOb2RlUHJvdmlkZXIubG9hZExlYWZOb2RlU3luYyhuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKHBhdGgpLCBjYWxsYmFjaywgdHJ1ZSk7XG5cdH07XG5cblx0LyoqXG4gICogU2V0cyB0aGUgcm9vdCBvZiB0aGUgZGF0YSBzdG9yZVxuICAqIEBwYXJhbSBhanhwUm9vdE5vZGUgQWp4cE5vZGUgVGhlIHBhcmVudCBub2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldFJvb3ROb2RlID0gZnVuY3Rpb24gc2V0Um9vdE5vZGUoYWp4cFJvb3ROb2RlKSB7XG5cdFx0dGhpcy5fcm9vdE5vZGUgPSBhanhwUm9vdE5vZGU7XG5cdFx0dGhpcy5fcm9vdE5vZGUuc2V0Um9vdCgpO1xuXHRcdHRoaXMuX3Jvb3ROb2RlLm9ic2VydmUoXCJjaGlsZF9hZGRlZFwiLCBmdW5jdGlvbiAoYykge1xuXHRcdFx0Ly9jb25zb2xlLmxvZyhjKTtcblx0XHR9KTtcblx0XHR0aGlzLnB1Ymxpc2goXCJyb290X25vZGVfY2hhbmdlZFwiLCB0aGlzLl9yb290Tm9kZSk7XG5cdFx0dGhpcy5zZXRDb250ZXh0Tm9kZSh0aGlzLl9yb290Tm9kZSk7XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgY3VycmVudCByb290IG5vZGVcbiAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRSb290Tm9kZSA9IGZ1bmN0aW9uIGdldFJvb3ROb2RlKCkge1xuXHRcdHJldHVybiB0aGlzLl9yb290Tm9kZTtcblx0fTtcblxuXHQvKipcbiAgKiBTZXRzIHRoZSBjdXJyZW50IGNvbnRleHQgbm9kZVxuICAqIEBwYXJhbSBhanhwRGF0YU5vZGUgQWp4cE5vZGVcbiAgKiBAcGFyYW0gZm9yY2VFdmVudCBCb29sZWFuIElmIHNldCB0byB0cnVlLCBldmVudCB3aWxsIGJlIHRyaWdnZXJlZCBldmVuIGlmIHRoZSBjdXJyZW50IG5vZGUgaXMgYWxyZWFkeSB0aGUgc2FtZS5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0Q29udGV4dE5vZGUgPSBmdW5jdGlvbiBzZXRDb250ZXh0Tm9kZShhanhwRGF0YU5vZGUsIGZvcmNlRXZlbnQpIHtcblx0XHRpZiAodGhpcy5fY29udGV4dE5vZGUgJiYgdGhpcy5fY29udGV4dE5vZGUgPT0gYWp4cERhdGFOb2RlICYmIHRoaXMuX2N1cnJlbnRSZXAgPT0gYWp4cERhdGFOb2RlLmdldFBhdGgoKSAmJiAhZm9yY2VFdmVudCkge1xuXHRcdFx0cmV0dXJuOyAvLyBObyBjaGFuZ2VzXG5cdFx0fVxuXHRcdGlmICghYWp4cERhdGFOb2RlKSByZXR1cm47XG5cdFx0aWYgKHRoaXMuX2NvbnRleHROb2RlUmVwbGFjZWRPYnNlcnZlciAmJiB0aGlzLl9jb250ZXh0Tm9kZSkge1xuXHRcdFx0dGhpcy5fY29udGV4dE5vZGUuc3RvcE9ic2VydmluZyhcIm5vZGVfcmVwbGFjZWRcIiwgdGhpcy5fY29udGV4dE5vZGVSZXBsYWNlZE9ic2VydmVyKTtcblx0XHR9XG5cdFx0dGhpcy5fY29udGV4dE5vZGUgPSBhanhwRGF0YU5vZGU7XG5cdFx0dGhpcy5fY3VycmVudFJlcCA9IGFqeHBEYXRhTm9kZS5nZXRQYXRoKCk7XG5cdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9jaGFuZ2VkXCIsIGFqeHBEYXRhTm9kZSk7XG5cdFx0aWYgKCF0aGlzLl9jb250ZXh0Tm9kZVJlcGxhY2VkT2JzZXJ2ZXIpIHRoaXMuX2NvbnRleHROb2RlUmVwbGFjZWRPYnNlcnZlciA9IHRoaXMuY29udGV4dE5vZGVSZXBsYWNlZC5iaW5kKHRoaXMpO1xuXHRcdGFqeHBEYXRhTm9kZS5vYnNlcnZlKFwibm9kZV9yZXBsYWNlZFwiLCB0aGlzLl9jb250ZXh0Tm9kZVJlcGxhY2VkT2JzZXJ2ZXIpO1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5jb250ZXh0Tm9kZVJlcGxhY2VkID0gZnVuY3Rpb24gY29udGV4dE5vZGVSZXBsYWNlZChuZXdOb2RlKSB7XG5cdFx0dGhpcy5zZXRDb250ZXh0Tm9kZShuZXdOb2RlKTtcblx0fTtcblxuXHQvKipcbiAgKlxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5wdWJsaXNoID0gZnVuY3Rpb24gcHVibGlzaChldmVudE5hbWUsIG9wdGlvbmFsRGF0YSkge1xuXHRcdHZhciBhcmdzID0gW107XG5cdFx0aWYgKHRoaXMuX2dsb2JhbEV2ZW50cykge1xuXHRcdFx0aWYgKHdpbmRvdy5weWRpbykge1xuXHRcdFx0XHRhcmdzLnB1c2goZXZlbnROYW1lKTtcblx0XHRcdFx0aWYgKG9wdGlvbmFsRGF0YSkgYXJncy5wdXNoKG9wdGlvbmFsRGF0YSk7XG5cdFx0XHRcdHdpbmRvdy5weWRpby5maXJlLmFwcGx5KHdpbmRvdy5weWRpbywgYXJncyk7XG5cdFx0XHR9IGVsc2UgaWYgKGRvY3VtZW50LmZpcmUpIHtcblx0XHRcdFx0YXJncy5wdXNoKFwiYWpheHBsb3JlcjpcIiArIGV2ZW50TmFtZSk7XG5cdFx0XHRcdGlmIChvcHRpb25hbERhdGEpIGFyZ3MucHVzaChvcHRpb25hbERhdGEpO1xuXHRcdFx0XHRkb2N1bWVudC5maXJlLmFwcGx5KGRvY3VtZW50LCBhcmdzKTtcblx0XHRcdH1cblx0XHRcdGlmIChvcHRpb25hbERhdGEpIHtcblx0XHRcdFx0YXJncyA9IFtldmVudE5hbWUsIHsgbWVtbzogb3B0aW9uYWxEYXRhIH1dO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXJncyA9IFtldmVudE5hbWVdO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5ub3RpZnkuYXBwbHkodGhpcywgYXJncyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmIChvcHRpb25hbERhdGEpIHtcblx0XHRcdFx0YXJncyA9IFtldmVudE5hbWUsIHsgbWVtbzogb3B0aW9uYWxEYXRhIH1dO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXJncyA9IFtldmVudE5hbWVdO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5ub3RpZnkuYXBwbHkodGhpcywgYXJncyk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEdldCB0aGUgY3VycmVudCBjb250ZXh0IG5vZGVcbiAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRDb250ZXh0Tm9kZSA9IGZ1bmN0aW9uIGdldENvbnRleHROb2RlKCkge1xuXHRcdHJldHVybiB0aGlzLl9jb250ZXh0Tm9kZTtcblx0fTtcblxuXHQvKipcbiAgKiBBZnRlciBhIGNvcHkgb3IgbW92ZSBvcGVyYXRpb24sIG1hbnkgbm9kZXMgbWF5IGhhdmUgdG8gYmUgcmVsb2FkZWRcbiAgKiBUaGlzIGZ1bmN0aW9uIHRyaWVzIHRvIHJlbG9hZCB0aGVtIGluIHRoZSByaWdodCBvcmRlciBhbmQgaWYgbmVjZXNzYXJ5LlxuICAqIEBwYXJhbSBub2RlcyBBanhwTm9kZXNbXSBBbiBhcnJheSBvZiBub2Rlc1xuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5tdWx0aXBsZU5vZGVzUmVsb2FkID0gZnVuY3Rpb24gbXVsdGlwbGVOb2Rlc1JlbG9hZChub2Rlcykge1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBub2RlUGF0aE9yTm9kZSA9IG5vZGVzW2ldO1xuXHRcdFx0dmFyIG5vZGU7XG5cdFx0XHRpZiAobm9kZVBhdGhPck5vZGUgaW5zdGFuY2VvZiBTdHJpbmcpIHtcblx0XHRcdFx0bm9kZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10obm9kZVBhdGhPck5vZGUpO1xuXHRcdFx0XHRpZiAobm9kZS5nZXRQYXRoKCkgPT0gdGhpcy5fcm9vdE5vZGUuZ2V0UGF0aCgpKSBub2RlID0gdGhpcy5fcm9vdE5vZGU7ZWxzZSBub2RlID0gbm9kZS5maW5kSW5BcmJvKHRoaXMuX3Jvb3ROb2RlLCBbXSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRub2RlID0gbm9kZVBhdGhPck5vZGU7XG5cdFx0XHR9XG5cdFx0XHRub2Rlc1tpXSA9IG5vZGU7XG5cdFx0fVxuXHRcdHZhciBjaGlsZHJlbiA9IFtdO1xuXHRcdG5vZGVzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcblx0XHRcdGlmIChhLmlzUGFyZW50T2YoYikpIHtcblx0XHRcdFx0Y2hpbGRyZW4ucHVzaChiKTtcblx0XHRcdFx0cmV0dXJuIC0xO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGEuaXNDaGlsZE9mKGIpKSB7XG5cdFx0XHRcdGNoaWxkcmVuLnB1c2goYSk7XG5cdFx0XHRcdHJldHVybiArMTtcblx0XHRcdH1cblx0XHRcdHJldHVybiAwO1xuXHRcdH0pO1xuXHRcdGNoaWxkcmVuLm1hcChmdW5jdGlvbiAoYykge1xuXHRcdFx0bm9kZXMgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5hcnJheVdpdGhvdXQobm9kZXMsIGMpO1xuXHRcdH0pO1xuXHRcdG5vZGVzLm1hcCh0aGlzLnF1ZXVlTm9kZVJlbG9hZC5iaW5kKHRoaXMpKTtcblx0XHR0aGlzLm5leHROb2RlUmVsb2FkZXIoKTtcblx0fTtcblxuXHQvKipcbiAgKiBBZGQgYSBub2RlIHRvIHRoZSBxdWV1ZSBvZiBub2RlcyB0byByZWxvYWQuXG4gICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUucXVldWVOb2RlUmVsb2FkID0gZnVuY3Rpb24gcXVldWVOb2RlUmVsb2FkKG5vZGUpIHtcblx0XHRpZiAoIXRoaXMucXVldWUpIHRoaXMucXVldWUgPSBbXTtcblx0XHRpZiAobm9kZSkge1xuXHRcdFx0dGhpcy5xdWV1ZS5wdXNoKG5vZGUpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBRdWV1ZSBwcm9jZXNzb3IgZm9yIHRoZSBub2RlcyB0byByZWxvYWRcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUubmV4dE5vZGVSZWxvYWRlciA9IGZ1bmN0aW9uIG5leHROb2RlUmVsb2FkZXIoKSB7XG5cdFx0aWYgKCF0aGlzLnF1ZXVlLmxlbmd0aCkge1xuXHRcdFx0d2luZG93LnNldFRpbWVvdXQoKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9jaGFuZ2VkXCIsIHRoaXMuX2NvbnRleHROb2RlKTtcblx0XHRcdH0pLmJpbmQodGhpcyksIDIwMCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHZhciBuZXh0ID0gdGhpcy5xdWV1ZS5zaGlmdCgpO1xuXHRcdHZhciBvYnNlcnZlciA9IHRoaXMubmV4dE5vZGVSZWxvYWRlci5iaW5kKHRoaXMpO1xuXHRcdG5leHQub2JzZXJ2ZU9uY2UoXCJsb2FkZWRcIiwgb2JzZXJ2ZXIpO1xuXHRcdG5leHQub2JzZXJ2ZU9uY2UoXCJlcnJvclwiLCBvYnNlcnZlcik7XG5cdFx0aWYgKG5leHQgPT0gdGhpcy5fY29udGV4dE5vZGUgfHwgbmV4dC5pc1BhcmVudE9mKHRoaXMuX2NvbnRleHROb2RlKSkge1xuXHRcdFx0dGhpcy5yZXF1aXJlQ29udGV4dENoYW5nZShuZXh0LCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bmV4dC5yZWxvYWQodGhpcy5faUFqeHBOb2RlUHJvdmlkZXIpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBJbnNlcnQgYSBub2RlIHNvbWV3aGVyZSBpbiB0aGUgZGF0YW1vZGVsXG4gICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgKiBAcGFyYW0gc2V0U2VsZWN0ZWRBZnRlckFkZCBib29sXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmFkZE5vZGUgPSBmdW5jdGlvbiBhZGROb2RlKG5vZGUpIHtcblx0XHR2YXIgc2V0U2VsZWN0ZWRBZnRlckFkZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0dmFyIHBhcmVudEZha2UgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpKTtcblx0XHR2YXIgcGFyZW50ID0gcGFyZW50RmFrZS5maW5kSW5BcmJvKHRoaXMuZ2V0Um9vdE5vZGUoKSwgdW5kZWZpbmVkKTtcblx0XHRpZiAoIXBhcmVudCAmJiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSA9PSBcIlwiKSBwYXJlbnQgPSB0aGlzLmdldFJvb3ROb2RlKCk7XG5cdFx0aWYgKHBhcmVudCkge1xuXHRcdFx0dmFyIGFkZGVkTm9kZSA9IHBhcmVudC5hZGRDaGlsZChub2RlKTtcblx0XHRcdGlmIChhZGRlZE5vZGUgJiYgc2V0U2VsZWN0ZWRBZnRlckFkZCAmJiB0aGlzLmdldENvbnRleHROb2RlKCkgPT0gcGFyZW50KSB7XG5cdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWROb2RlcyhbYWRkZWROb2RlXSwge30pO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBSZW1vdmUgYSBub2RlIGJ5IHBhdGggc29tZXdoZXJlXG4gICogQHBhcmFtIHBhdGggc3RyaW5nXG4gICogQHBhcmFtIGltVGltZSBpbnRlZ2VyfG51bGxcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUucmVtb3ZlTm9kZUJ5UGF0aCA9IGZ1bmN0aW9uIHJlbW92ZU5vZGVCeVBhdGgocGF0aCkge1xuXHRcdHZhciBpbVRpbWUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0dmFyIGZha2UgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKHBhdGgpO1xuXHRcdHZhciBuID0gZmFrZS5maW5kSW5BcmJvKHRoaXMuZ2V0Um9vdE5vZGUoKSwgdW5kZWZpbmVkKTtcblx0XHRpZiAobikge1xuXHRcdFx0aWYgKGltVGltZSAmJiBuLmdldE1ldGFkYXRhKCkgJiYgbi5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSAmJiBwYXJzZUludChuLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpKSA+PSBpbVRpbWUpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0bi5nZXRQYXJlbnQoKS5yZW1vdmVDaGlsZChuKTtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG5cblx0LyoqXG4gICogVXBkYXRlIGEgbm9kZSBzb21ld2hlcmUgaW4gdGhlIGRhdGFtb2RlbFxuICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICogQHBhcmFtIHNldFNlbGVjdGVkQWZ0ZXJVcGRhdGUgYm9vbFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS51cGRhdGVOb2RlID0gZnVuY3Rpb24gdXBkYXRlTm9kZShub2RlKSB7XG5cdFx0dmFyIHNldFNlbGVjdGVkQWZ0ZXJVcGRhdGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdHZhciBvcmlnaW5hbCA9IG5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJvcmlnaW5hbF9wYXRoXCIpO1xuXHRcdHZhciBmYWtlLCBuO1xuXHRcdGlmIChvcmlnaW5hbCAmJiBvcmlnaW5hbCAhPSBub2RlLmdldFBhdGgoKSAmJiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG9yaWdpbmFsKSAhPSBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSkge1xuXHRcdFx0Ly8gTm9kZSB3YXMgcmVhbGx5IG1vdmVkIHRvIGFub3RoZXIgZm9sZGVyXG5cdFx0XHRmYWtlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShvcmlnaW5hbCk7XG5cdFx0XHRuID0gZmFrZS5maW5kSW5BcmJvKHRoaXMuZ2V0Um9vdE5vZGUoKSwgdW5kZWZpbmVkKTtcblx0XHRcdGlmIChuKSB7XG5cdFx0XHRcdG4uZ2V0UGFyZW50KCkucmVtb3ZlQ2hpbGQobik7XG5cdFx0XHR9XG5cdFx0XHR2YXIgcGFyZW50RmFrZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10oX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSkpO1xuXHRcdFx0dmFyIHBhcmVudCA9IHBhcmVudEZha2UuZmluZEluQXJibyh0aGlzLmdldFJvb3ROb2RlKCksIHVuZGVmaW5lZCk7XG5cdFx0XHRpZiAoIXBhcmVudCAmJiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSA9PSBcIlwiKSBwYXJlbnQgPSB0aGlzLmdldFJvb3ROb2RlKCk7XG5cdFx0XHRpZiAocGFyZW50KSB7XG5cdFx0XHRcdG5vZGUuZ2V0TWV0YWRhdGEoKS5zZXQoXCJvcmlnaW5hbF9wYXRoXCIsIHVuZGVmaW5lZCk7XG5cdFx0XHRcdHBhcmVudC5hZGRDaGlsZChub2RlKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKG5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJvcmlnaW5hbF9wYXRoXCIpID09PSBcIi9cIiAmJiBub2RlLmdldFBhdGgoKSA9PT0gXCIvXCIpIHtcblx0XHRcdFx0biA9IHRoaXMuZ2V0Um9vdE5vZGUoKTtcblx0XHRcdFx0bi5yZXBsYWNlTWV0YWRhdGEobm9kZS5nZXRNZXRhZGF0YSgpKTtcblx0XHRcdFx0aWYgKHNldFNlbGVjdGVkQWZ0ZXJVcGRhdGUgJiYgdGhpcy5nZXRDb250ZXh0Tm9kZSgpID09IG4pIHtcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMoW25dLCB7fSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0ZmFrZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10ob3JpZ2luYWwpO1xuXHRcdFx0biA9IGZha2UuZmluZEluQXJibyh0aGlzLmdldFJvb3ROb2RlKCksIHVuZGVmaW5lZCk7XG5cdFx0XHRpZiAobiAmJiAhbi5pc01vcmVSZWNlbnRUaGFuKG5vZGUpKSB7XG5cdFx0XHRcdG5vZGUuX2lzTG9hZGVkID0gbi5faXNMb2FkZWQ7XG5cdFx0XHRcdG4ucmVwbGFjZUJ5KG5vZGUsIFwib3ZlcnJpZGVcIik7XG5cdFx0XHRcdGlmIChzZXRTZWxlY3RlZEFmdGVyVXBkYXRlICYmIHRoaXMuZ2V0Q29udGV4dE5vZGUoKSA9PSBuLmdldFBhcmVudCgpKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKFtuXSwge30pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFNldHMgYW4gYXJyYXkgb2Ygbm9kZXMgdG8gYmUgc2VsZWN0ZWQgYWZ0ZXIgdGhlIGNvbnRleHQgaXMgKHJlKWxvYWRlZFxuICAqIEBwYXJhbSBzZWxlY3Rpb24gQWp4cE5vZGVbXVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRQZW5kaW5nU2VsZWN0aW9uID0gZnVuY3Rpb24gc2V0UGVuZGluZ1NlbGVjdGlvbihzZWxlY3Rpb24pIHtcblx0XHR0aGlzLl9wZW5kaW5nU2VsZWN0aW9uID0gc2VsZWN0aW9uO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGFycmF5IG9mIG5vZGVzIHRvIGJlIHNlbGVjdGVkIGFmdGVyIHRoZSBjb250ZXh0IGlzIChyZSlsb2FkZWRcbiAgKiBAcmV0dXJucyBBanhwTm9kZVtdXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFBlbmRpbmdTZWxlY3Rpb24gPSBmdW5jdGlvbiBnZXRQZW5kaW5nU2VsZWN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLl9wZW5kaW5nU2VsZWN0aW9uO1xuXHR9O1xuXG5cdC8qKlxuICAqIENsZWFycyB0aGUgbm9kZXMgdG8gYmUgc2VsZWN0ZWRcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuY2xlYXJQZW5kaW5nU2VsZWN0aW9uID0gZnVuY3Rpb24gY2xlYXJQZW5kaW5nU2VsZWN0aW9uKCkge1xuXHRcdHRoaXMuX3BlbmRpbmdTZWxlY3Rpb24gPSBudWxsO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldCBhbiBhcnJheSBvZiBub2RlcyBhcyB0aGUgY3VycmVudCBzZWxlY3Rpb25cbiAgKiBAcGFyYW0gYWp4cERhdGFOb2RlcyBBanhwTm9kZVtdIFRoZSBub2RlcyB0byBzZWxlY3RcbiAgKiBAcGFyYW0gc291cmNlIFN0cmluZyBUaGUgc291cmNlIG9mIHRoaXMgc2VsZWN0aW9uIGFjdGlvblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRTZWxlY3RlZE5vZGVzID0gZnVuY3Rpb24gc2V0U2VsZWN0ZWROb2RlcyhhanhwRGF0YU5vZGVzLCBzb3VyY2UpIHtcblx0XHRpZiAodGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGggPT0gYWp4cERhdGFOb2Rlcy5sZW5ndGgpIHtcblx0XHRcdGlmIChhanhwRGF0YU5vZGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHR2YXIgZXF1YWwgPSB0cnVlO1xuXHRcdFx0Zm9yICh2YXIgayA9IDA7IGsgPCBhanhwRGF0YU5vZGVzLmxlbmd0aDsgaysrKSB7XG5cdFx0XHRcdGVxdWFsID0gZXF1YWwgJiYgYWp4cERhdGFOb2Rlc1trXSA9PSB0aGlzLl9zZWxlY3RlZE5vZGVzW2tdO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGVxdWFsKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCFzb3VyY2UpIHtcblx0XHRcdHRoaXMuX3NlbGVjdGlvblNvdXJjZSA9IHt9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9zZWxlY3Rpb25Tb3VyY2UgPSBzb3VyY2U7XG5cdFx0fVxuXHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMgPSBhanhwRGF0YU5vZGVzO1xuXHRcdHRoaXMuX2JFbXB0eSA9IGFqeHBEYXRhTm9kZXMgJiYgYWp4cERhdGFOb2Rlcy5sZW5ndGggPyBmYWxzZSA6IHRydWU7XG5cdFx0dGhpcy5fYkZpbGUgPSB0aGlzLl9iRGlyID0gdGhpcy5faXNSZWN5Y2xlID0gZmFsc2U7XG5cdFx0aWYgKCF0aGlzLl9iRW1wdHkpIHtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYWp4cERhdGFOb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHR2YXIgc2VsZWN0ZWROb2RlID0gYWp4cERhdGFOb2Rlc1tpXTtcblx0XHRcdFx0aWYgKHNlbGVjdGVkTm9kZS5pc0xlYWYoKSkgdGhpcy5fYkZpbGUgPSB0cnVlO2Vsc2UgdGhpcy5fYkRpciA9IHRydWU7XG5cdFx0XHRcdGlmIChzZWxlY3RlZE5vZGUuaXNSZWN5Y2xlKCkpIHRoaXMuX2lzUmVjeWNsZSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMucHVibGlzaChcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBub2Rlc1xuICAqIEByZXR1cm5zIEFqeHBOb2RlW11cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWROb2RlcyA9IGZ1bmN0aW9uIGdldFNlbGVjdGVkTm9kZXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXM7XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgc291cmNlIG9mIHRoZSBsYXN0IHNlbGVjdGlvbiBhY3Rpb25cbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0U2VsZWN0aW9uU291cmNlID0gZnVuY3Rpb24gZ2V0U2VsZWN0aW9uU291cmNlKCkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3Rpb25Tb3VyY2U7XG5cdH07XG5cblx0LyoqXG4gICogTWFudWFsbHkgc2V0cyB0aGUgc291cmNlIG9mIHRoZSBzZWxlY3Rpb25cbiAgKiBAcGFyYW0gb2JqZWN0XG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldFNlbGVjdGlvblNvdXJjZSA9IGZ1bmN0aW9uIHNldFNlbGVjdGlvblNvdXJjZShvYmplY3QpIHtcblx0XHR0aGlzLl9zZWxlY3Rpb25Tb3VyY2UgPSBvYmplY3Q7XG5cdH07XG5cblx0LyoqXG4gICogREVQUkVDQVRFRFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRTZWxlY3RlZEl0ZW1zID0gZnVuY3Rpb24gZ2V0U2VsZWN0ZWRJdGVtcygpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJEZXByZWNhdGVkIDogdXNlIGdldFNlbGVjdGVkTm9kZXMoKSBpbnN0ZWFkXCIpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNlbGVjdCBhbGwgdGhlIGNoaWxkcmVuIG9mIHRoZSBjdXJyZW50IGNvbnRleHQgbm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZWxlY3RBbGwgPSBmdW5jdGlvbiBzZWxlY3RBbGwoKSB7XG5cdFx0dmFyIG5vZGVzID0gW107XG5cdFx0dmFyIGNoaWxkcmVuTWFwID0gdGhpcy5fY29udGV4dE5vZGUuZ2V0Q2hpbGRyZW4oKTtcblx0XHRjaGlsZHJlbk1hcC5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xuXHRcdFx0bm9kZXMucHVzaChjaGlsZCk7XG5cdFx0fSk7XG5cdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKG5vZGVzLCBcImRhdGFNb2RlbFwiKTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaXMgZW1wdHlcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmlzRW1wdHkgPSBmdW5jdGlvbiBpc0VtcHR5KCkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzID8gdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGggPT0gMCA6IHRydWU7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmhhc1JlYWRPbmx5ID0gZnVuY3Rpb24gaGFzUmVhZE9ubHkoKSB7XG5cdFx0dmFyIHRlc3QgPSBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0dGhpcy5fc2VsZWN0ZWROb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG5cdFx0XHRcdGlmIChub2RlLmhhc01ldGFkYXRhSW5CcmFuY2goXCJhanhwX3JlYWRvbmx5XCIsIFwidHJ1ZVwiKSkge1xuXHRcdFx0XHRcdHRlc3QgPSB0cnVlO1xuXHRcdFx0XHRcdHRocm93ICRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBjYXRjaCAoZSkge31cblx0XHRyZXR1cm4gdGVzdDtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2VsZWN0aW9uSGFzUm9vdE5vZGUgPSBmdW5jdGlvbiBzZWxlY3Rpb25IYXNSb290Tm9kZSgpIHtcblx0XHR2YXIgZm91bmQgPSBmYWxzZTtcblx0XHR0cnkge1xuXHRcdFx0dGhpcy5fc2VsZWN0ZWROb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0XHRpZiAoZWwuaXNSb290KCkpIHtcblx0XHRcdFx0XHRmb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gY2F0Y2ggKGUpIHt9XG5cdFx0cmV0dXJuIGZvdW5kO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBpcyB1bmlxdWVcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmlzVW5pcXVlID0gZnVuY3Rpb24gaXNVbmlxdWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXMgJiYgdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGggPT09IDE7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGhhcyBhIGZpbGUgc2VsZWN0ZWQuXG4gICogU2hvdWxkIGJlIGhhc0xlYWZcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmhhc0ZpbGUgPSBmdW5jdGlvbiBoYXNGaWxlKCkge1xuXHRcdHJldHVybiB0aGlzLl9iRmlsZTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaGFzIGEgZGlyIHNlbGVjdGVkXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5oYXNEaXIgPSBmdW5jdGlvbiBoYXNEaXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2JEaXI7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgY3VycmVudCBjb250ZXh0IGlzIHRoZSByZWN5Y2xlIGJpblxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaXNSZWN5Y2xlID0gZnVuY3Rpb24gaXNSZWN5Y2xlKCkge1xuXHRcdHJldHVybiB0aGlzLl9pc1JlY3ljbGU7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGhhcyBtb3JlIHRoYW4gb25lIG5vZGUgc2VsZWN0ZWRcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmlzTXVsdGlwbGUgPSBmdW5jdGlvbiBpc011bHRpcGxlKCkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzICYmIHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoID4gMTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaGFzIGEgZmlsZSB3aXRoIG9uZSBvZiB0aGUgbWltZXNcbiAgKiBAcGFyYW0gbWltZVR5cGVzIEFycmF5IEFycmF5IG9mIG1pbWUgdHlwZXNcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmhhc01pbWUgPSBmdW5jdGlvbiBoYXNNaW1lKG1pbWVUeXBlcykge1xuXHRcdGlmIChtaW1lVHlwZXMubGVuZ3RoID09IDEgJiYgbWltZVR5cGVzWzBdID09IFwiKlwiKSByZXR1cm4gdHJ1ZTtcblx0XHR2YXIgaGFzID0gZmFsc2U7XG5cdFx0bWltZVR5cGVzLm1hcCgoZnVuY3Rpb24gKG1pbWUpIHtcblx0XHRcdGlmIChoYXMpIHJldHVybjtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRpZiAoX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QWp4cE1pbWVUeXBlKHRoaXMuX3NlbGVjdGVkTm9kZXNbaV0pID09PSBtaW1lKSB7XG5cdFx0XHRcdFx0aGFzID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pLmJpbmQodGhpcykpO1xuXHRcdHJldHVybiBoYXM7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IGFsbCBzZWxlY3RlZCBmaWxlbmFtZXMgYXMgYW4gYXJyYXkuXG4gICogQHBhcmFtIHNlcGFyYXRvciBTdHJpbmcgSXMgYSBzZXBhcmF0b3IsIHdpbGwgcmV0dXJuIGEgc3RyaW5nIGpvaW5lZFxuICAqIEByZXR1cm5zIEFycmF5fFN0cmluZ3xib29sXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldEZpbGVOYW1lcyA9IGZ1bmN0aW9uIGdldEZpbGVOYW1lcyhzZXBhcmF0b3IpIHtcblx0XHRpZiAoIXRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoKSB7XG5cdFx0XHRhbGVydCgnUGxlYXNlIHNlbGVjdCBhIGZpbGUhJyk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHZhciB0bXAgPSBuZXcgQXJyYXkodGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGgpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dG1wW2ldID0gdGhpcy5fc2VsZWN0ZWROb2Rlc1tpXS5nZXRQYXRoKCk7XG5cdFx0fVxuXHRcdGlmIChzZXBhcmF0b3IpIHtcblx0XHRcdHJldHVybiB0bXAuam9pbihzZXBhcmF0b3IpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdG1wO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBHZXQgYWxsIHRoZSBmaWxlbmFtZXMgb2YgdGhlIGN1cnJlbnQgY29udGV4dCBub2RlIGNoaWxkcmVuXG4gICogQHBhcmFtIHNlcGFyYXRvciBTdHJpbmcgSWYgcGFzc2VkLCB3aWxsIGpvaW4gdGhlIGFycmF5IGFzIGEgc3RyaW5nXG4gICogQHJldHVybiBBcnJheXxTdHJpbmd8Ym9vbFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRDb250ZXh0RmlsZU5hbWVzID0gZnVuY3Rpb24gZ2V0Q29udGV4dEZpbGVOYW1lcyhzZXBhcmF0b3IpIHtcblx0XHR2YXIgYWxsSXRlbXMgPSB0aGlzLl9jb250ZXh0Tm9kZS5nZXRDaGlsZHJlbigpO1xuXHRcdGlmICghYWxsSXRlbXMubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHZhciBuYW1lcyA9IFtdO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYWxsSXRlbXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdG5hbWVzLnB1c2goX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUoYWxsSXRlbXNbaV0uZ2V0UGF0aCgpKSk7XG5cdFx0fVxuXHRcdGlmIChzZXBhcmF0b3IpIHtcblx0XHRcdHJldHVybiBuYW1lcy5qb2luKHNlcGFyYXRvcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBuYW1lcztcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgY29udGV4dCBub2RlIGhhcyBhIGNoaWxkIHdpdGggdGhpcyBiYXNlbmFtZVxuICAqIEBwYXJhbSBuZXdGaWxlTmFtZSBTdHJpbmcgVGhlIG5hbWUgdG8gY2hlY2tcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICogQHBhcmFtIGxvY2FsXG4gICogQHBhcmFtIGNvbnRleHROb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmZpbGVOYW1lRXhpc3RzID0gZnVuY3Rpb24gZmlsZU5hbWVFeGlzdHMobmV3RmlsZU5hbWUsIGxvY2FsLCBjb250ZXh0Tm9kZSkge1xuXHRcdGlmICghY29udGV4dE5vZGUpIHtcblx0XHRcdGNvbnRleHROb2RlID0gdGhpcy5fY29udGV4dE5vZGU7XG5cdFx0fVxuXHRcdGlmIChsb2NhbCkge1xuXHRcdFx0dmFyIHRlc3QgPSAoY29udGV4dE5vZGUuZ2V0UGF0aCgpID09IFwiL1wiID8gXCJcIiA6IGNvbnRleHROb2RlLmdldFBhdGgoKSkgKyBcIi9cIiArIG5ld0ZpbGVOYW1lO1xuXHRcdFx0dmFyIGZvdW5kID0gZmFsc2U7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb250ZXh0Tm9kZS5nZXRDaGlsZHJlbigpLmZvckVhY2goZnVuY3Rpb24gKGMpIHtcblx0XHRcdFx0XHRpZiAoYy5nZXRQYXRoKCkgPT0gdGVzdCkge1xuXHRcdFx0XHRcdFx0Zm91bmQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0gY2F0Y2ggKGUpIHt9XG5cdFx0XHRyZXR1cm4gZm91bmQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHZhciBub2RlRXhpc3RzID0gZmFsc2U7XG5cdFx0XHR0aGlzLmxvYWRQYXRoSW5mb1N5bmMoY29udGV4dE5vZGUuZ2V0UGF0aCgpICsgXCIvXCIgKyBuZXdGaWxlTmFtZSwgZnVuY3Rpb24gKGZvdW5kTm9kZSkge1xuXHRcdFx0XHRub2RlRXhpc3RzID0gdHJ1ZTtcblx0XHRcdH0pO1xuXHRcdFx0cmV0dXJuIG5vZGVFeGlzdHM7XG5cdFx0fVxuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5hcHBseUNoZWNrSG9vayA9IGZ1bmN0aW9uIGFwcGx5Q2hlY2tIb29rKG5vZGUpIHtcblx0XHR2YXIgYWRkaXRpb25hbFBhcmFtcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cblx0XHR2YXIgY2xpZW50ID0gX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKTtcblx0XHR2YXIgcmVzdWx0O1xuXHRcdGNsaWVudC5hcHBseUNoZWNrSG9vayhub2RlLCBcImJlZm9yZV9jcmVhdGVcIiwgbm9kZS5nZXRNZXRhZGF0YSgpLmdldChcImZpbGVzaXplXCIpIHx8IC0xLCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG5cdFx0XHRyZXN1bHQgPSBjbGllbnQucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG5cdFx0fSwgYWRkaXRpb25hbFBhcmFtcyk7XG5cdFx0aWYgKHJlc3VsdCA9PT0gZmFsc2UpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIkNoZWNrIGZhaWxlZFwiKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgZmlyc3QgbmFtZSBvZiB0aGUgY3VycmVudCBzZWxlY3Rpb25cbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0VW5pcXVlRmlsZU5hbWUgPSBmdW5jdGlvbiBnZXRVbmlxdWVGaWxlTmFtZSgpIHtcblx0XHRpZiAodGhpcy5nZXRGaWxlTmFtZXMoKS5sZW5ndGgpIHJldHVybiB0aGlzLmdldEZpbGVOYW1lcygpWzBdO1xuXHRcdHJldHVybiBudWxsO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGZpcnN0IG5vZGUgb2YgdGhlIHNlbGVjdGlvbiwgb3IgTnVsbFxuICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFVuaXF1ZU5vZGUgPSBmdW5jdGlvbiBnZXRVbmlxdWVOb2RlKCkge1xuXHRcdGlmICh0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXNbMF07XG5cdFx0fVxuXHRcdHJldHVybiBudWxsO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgYSBub2RlIGZyb20gdGhlIGN1cnJlbnQgc2VsZWN0aW9uXG4gICogQHBhcmFtIGkgSW50ZWdlciB0aGUgbm9kZSBpbmRleFxuICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldE5vZGUgPSBmdW5jdGlvbiBnZXROb2RlKGkpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2Rlc1tpXTtcblx0fTtcblxuXHQvKipcbiAgKiBXaWxsIGFkZCB0aGUgY3VycmVudCBzZWxlY3Rpb24gbm9kZXMgYXMgc2VyaWFsaXphYmxlIGRhdGEgdG8gdGhlIGVsZW1lbnQgcGFzc2VkIDpcbiAgKiBlaXRoZXIgYXMgaGlkZGVuIGlucHV0IGVsZW1lbnRzIGlmIGl0J3MgYSBmb3JtLCBvciBhcyBxdWVyeSBwYXJhbWV0ZXJzIGlmIGl0J3MgYW4gdXJsXG4gICogQHBhcmFtIG9Gb3JtRWxlbWVudCBIVE1MRm9ybSBUaGUgZm9ybVxuICAqIEBwYXJhbSBzVXJsIFN0cmluZyBBbiB1cmwgdG8gY29tcGxldGVcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUudXBkYXRlRm9ybU9yVXJsID0gZnVuY3Rpb24gdXBkYXRlRm9ybU9yVXJsKG9Gb3JtRWxlbWVudCwgc1VybCkge1xuXHRcdC8vIENMRUFSIEZST00gUFJFVklPVVMgQUNUSU9OUyFcblx0XHRpZiAob0Zvcm1FbGVtZW50KSB7XG5cdFx0XHQkKG9Gb3JtRWxlbWVudCkuc2VsZWN0KCdpbnB1dFt0eXBlPVwiaGlkZGVuXCJdJykubWFwKGZ1bmN0aW9uIChlbGVtZW50KSB7XG5cdFx0XHRcdGlmIChlbGVtZW50Lm5hbWUgPT0gXCJub2Rlc1tdXCIgfHwgZWxlbWVudC5uYW1lID09IFwiZmlsZVwiKSBlbGVtZW50LnJlbW92ZSgpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHRcdC8vIFVQREFURSBUSEUgJ0RJUicgRklFTERTXG5cdFx0aWYgKG9Gb3JtRWxlbWVudCAmJiBvRm9ybUVsZW1lbnRbJ3JlcCddKSBvRm9ybUVsZW1lbnRbJ3JlcCddLnZhbHVlID0gdGhpcy5fY3VycmVudFJlcDtcblx0XHRzVXJsICs9ICcmZGlyPScgKyBlbmNvZGVVUklDb21wb25lbnQodGhpcy5fY3VycmVudFJlcCk7XG5cblx0XHQvLyBVUERBVEUgVEhFICdmaWxlJyBGSUVMRFNcblx0XHRpZiAodGhpcy5pc0VtcHR5KCkpIHJldHVybiBzVXJsO1xuXHRcdHZhciBmaWxlTmFtZXMgPSB0aGlzLmdldEZpbGVOYW1lcygpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgZmlsZU5hbWVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRzVXJsICs9ICcmJyArICdub2Rlc1tdPScgKyBlbmNvZGVVUklDb21wb25lbnQoZmlsZU5hbWVzW2ldKTtcblx0XHRcdGlmIChvRm9ybUVsZW1lbnQpIHRoaXMuX2FkZEhpZGRlbkZpZWxkKG9Gb3JtRWxlbWVudCwgJ25vZGVzW10nLCBmaWxlTmFtZXNbaV0pO1xuXHRcdH1cblx0XHRpZiAoZmlsZU5hbWVzLmxlbmd0aCA9PSAxKSB7XG5cdFx0XHRzVXJsICs9ICcmJyArICdmaWxlPScgKyBlbmNvZGVVUklDb21wb25lbnQoZmlsZU5hbWVzWzBdKTtcblx0XHRcdGlmIChvRm9ybUVsZW1lbnQpIHRoaXMuX2FkZEhpZGRlbkZpZWxkKG9Gb3JtRWxlbWVudCwgJ2ZpbGUnLCBmaWxlTmFtZXNbMF0pO1xuXHRcdH1cblx0XHRyZXR1cm4gc1VybDtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuX2FkZEhpZGRlbkZpZWxkID0gZnVuY3Rpb24gX2FkZEhpZGRlbkZpZWxkKG9Gb3JtRWxlbWVudCwgc0ZpZWxkTmFtZSwgc0ZpZWxkVmFsdWUpIHtcblx0XHRvRm9ybUVsZW1lbnQuaW5zZXJ0KG5ldyBFbGVtZW50KCdpbnB1dCcsIHsgdHlwZTogJ2hpZGRlbicsIG5hbWU6IHNGaWVsZE5hbWUsIHZhbHVlOiBzRmllbGRWYWx1ZSB9KSk7XG5cdH07XG5cblx0cmV0dXJuIFB5ZGlvRGF0YU1vZGVsO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUHlkaW9EYXRhTW9kZWw7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgRW1wdHlOb2RlUHJvdmlkZXIgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKEVtcHR5Tm9kZVByb3ZpZGVyLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICBmdW5jdGlvbiBFbXB0eU5vZGVQcm92aWRlcigpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEVtcHR5Tm9kZVByb3ZpZGVyKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuICAgIH1cblxuICAgIEVtcHR5Tm9kZVByb3ZpZGVyLnByb3RvdHlwZS5pbml0UHJvdmlkZXIgPSBmdW5jdGlvbiBpbml0UHJvdmlkZXIocHJvcGVydGllcykge1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIG5vZGVDYWxsYmFjayBGdW5jdGlvblxuICAgICAqIEBwYXJhbSBjaGlsZENhbGxiYWNrIEZ1bmN0aW9uXG4gICAgICovXG5cbiAgICBFbXB0eU5vZGVQcm92aWRlci5wcm90b3R5cGUubG9hZE5vZGUgPSBmdW5jdGlvbiBsb2FkTm9kZShub2RlLCBub2RlQ2FsbGJhY2ssIGNoaWxkQ2FsbGJhY2spIHt9O1xuXG4gICAgRW1wdHlOb2RlUHJvdmlkZXIucHJvdG90eXBlLmxvYWRMZWFmTm9kZVN5bmMgPSBmdW5jdGlvbiBsb2FkTGVhZk5vZGVTeW5jKG5vZGUsIGNhbGxiYWNrKSB7fTtcblxuICAgIHJldHVybiBFbXB0eU5vZGVQcm92aWRlcjtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEVtcHR5Tm9kZVByb3ZpZGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIF91dGlsUGF0aFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9QYXRoVXRpbHMnKTtcblxudmFyIF91dGlsUGF0aFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxQYXRoVXRpbHMpO1xuXG52YXIgQWp4cE5vZGUgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKEFqeHBOb2RlLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYXRoIFN0cmluZ1xuICAgICAqIEBwYXJhbSBpc0xlYWYgQm9vbGVhblxuICAgICAqIEBwYXJhbSBsYWJlbCBTdHJpbmdcbiAgICAgKiBAcGFyYW0gaWNvbiBTdHJpbmdcbiAgICAgKiBAcGFyYW0gaU5vZGVQcm92aWRlciBJQWp4cE5vZGVQcm92aWRlclxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gQWp4cE5vZGUocGF0aCkge1xuICAgICAgICB2YXIgaXNMZWFmID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBsYWJlbCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgaWNvbiA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzNdO1xuICAgICAgICB2YXIgaU5vZGVQcm92aWRlciA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNCB8fCBhcmd1bWVudHNbNF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbNF07XG5cbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEFqeHBOb2RlKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLl9wYXRoID0gcGF0aDtcbiAgICAgICAgaWYgKHRoaXMuX3BhdGggJiYgdGhpcy5fcGF0aC5sZW5ndGggJiYgdGhpcy5fcGF0aC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGF0aFt0aGlzLl9wYXRoLmxlbmd0aCAtIDFdID09IFwiL1wiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcGF0aCA9IHRoaXMuX3BhdGguc3Vic3RyaW5nKDAsIHRoaXMuX3BhdGgubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5faXNMZWFmID0gaXNMZWFmO1xuICAgICAgICB0aGlzLl9sYWJlbCA9IGxhYmVsO1xuICAgICAgICB0aGlzLl9pY29uID0gaWNvbjtcbiAgICAgICAgdGhpcy5faXNSb290ID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5fbWV0YWRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuX2NoaWxkcmVuID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMuX2lzTG9hZGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZmFrZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9pTm9kZVByb3ZpZGVyID0gaU5vZGVQcm92aWRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbm9kZSBpcyBsb2FkZWQgb3Igbm90XG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzTG9hZGVkID0gZnVuY3Rpb24gaXNMb2FkZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0xvYWRlZDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIG5vZGUgaXMgY3VycmVudGx5IGxvYWRpbmdcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNMb2FkaW5nID0gZnVuY3Rpb24gaXNMb2FkaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNMb2FkaW5nO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIGxvYWRlZCBzdGF0dXNcbiAgICAgKiBAcGFyYW0gYm9vbCBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuc2V0TG9hZGVkID0gZnVuY3Rpb24gc2V0TG9hZGVkKGJvb2wpIHtcbiAgICAgICAgdGhpcy5faXNMb2FkZWQgPSBib29sO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgbm9kZSBwcm92aWRlclxuICAgICAqIEBwYXJhbSBpQWp4cE5vZGVQcm92aWRlclxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnVwZGF0ZVByb3ZpZGVyID0gZnVuY3Rpb24gdXBkYXRlUHJvdmlkZXIoaUFqeHBOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgdGhpcy5faU5vZGVQcm92aWRlciA9IGlBanhwTm9kZVByb3ZpZGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyB0aGUgbm9kZSB1c2luZyBpdHMgb3duIHByb3ZpZGVyIG9yIHRoZSBvbmUgcGFzc2VkXG4gICAgICogQHBhcmFtIGlBanhwTm9kZVByb3ZpZGVyIElBanhwTm9kZVByb3ZpZGVyIE9wdGlvbm5hbFxuICAgICAqIEBwYXJhbSBhZGRpdGlvbmFsUGFyYW1ldGVycyBPYmplY3Qgb2Ygb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiBsb2FkKGlBanhwTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgIHZhciBhZGRpdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzTG9hZGluZykgcmV0dXJuO1xuICAgICAgICBpZiAoIWlBanhwTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faU5vZGVQcm92aWRlcikge1xuICAgICAgICAgICAgICAgIGlBanhwTm9kZVByb3ZpZGVyID0gdGhpcy5faU5vZGVQcm92aWRlcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaUFqeHBOb2RlUHJvdmlkZXIgPSBuZXcgUmVtb3RlTm9kZVByb3ZpZGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5faXNMb2FkaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJsb2FkaW5nXCIpO1xuICAgICAgICBpZiAodGhpcy5faXNMb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzTG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoXCJsb2FkZWRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaUFqeHBOb2RlUHJvdmlkZXIubG9hZE5vZGUodGhpcywgKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLl9pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KFwibG9hZGVkXCIpO1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoXCJmaXJzdF9sb2FkXCIpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpLCBudWxsLCBmYWxzZSwgLTEsIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGNoaWxkcmVuIGFuZCByZWxvYWQgbm9kZVxuICAgICAqIEBwYXJhbSBpQWp4cE5vZGVQcm92aWRlciBJQWp4cE5vZGVQcm92aWRlciBPcHRpb25uYWxcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5yZWxvYWQgPSBmdW5jdGlvbiByZWxvYWQoaUFqeHBOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgdmFyIHNpbGVudENsZWFyID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdGhpcy5faXNMb2FkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQsIGtleSkge1xuICAgICAgICAgICAgaWYgKCFzaWxlbnRDbGVhcikgY2hpbGQubm90aWZ5KFwibm9kZV9yZW1vdmVkXCIpO1xuICAgICAgICAgICAgY2hpbGQuX3BhcmVudE5vZGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5fY2hpbGRyZW5bJ2RlbGV0ZSddKGtleSk7XG4gICAgICAgICAgICBpZiAoIXNpbGVudENsZWFyKSB0aGlzLm5vdGlmeShcImNoaWxkX3JlbW92ZWRcIiwgY2hpbGQpO1xuICAgICAgICB9LCB0aGlzKTtcbiAgICAgICAgdGhpcy5sb2FkKGlBanhwTm9kZVByb3ZpZGVyKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVW5sb2FkIGNoaWxkIGFuZCBub3RpZnkgXCJmb3JjZV9jbGVhclwiXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgICAgdGhpcy5fY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQsIGtleSkge1xuICAgICAgICAgICAgY2hpbGQubm90aWZ5KFwibm9kZV9yZW1vdmVkXCIpO1xuICAgICAgICAgICAgY2hpbGQuX3BhcmVudE5vZGUgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5fY2hpbGRyZW5bJ2RlbGV0ZSddKGtleSk7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeShcImNoaWxkX3JlbW92ZWRcIiwgY2hpbGQpO1xuICAgICAgICB9LCB0aGlzKTtcbiAgICAgICAgdGhpcy5faXNMb2FkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJmb3JjZV9jbGVhclwiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGlzIEFqeHBOb2RlIGFzIGJlaW5nIHRoZSByb290IHBhcmVudFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnNldFJvb3QgPSBmdW5jdGlvbiBzZXRSb290KCkge1xuICAgICAgICB0aGlzLl9pc1Jvb3QgPSB0cnVlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIG5vZGUgY2hpbGRyZW4gYXMgYSBidW5jaFxuICAgICAqIEBwYXJhbSBhanhwTm9kZXMgQWp4cE5vZGVzW11cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5zZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIHNldENoaWxkcmVuKGFqeHBOb2Rlcykge1xuICAgICAgICB0aGlzLl9jaGlsZHJlbiA9IG5ldyBNYXAoKTtcbiAgICAgICAgYWp4cE5vZGVzLmZvckVhY2goKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fY2hpbGRyZW4uc2V0KHZhbHVlLmdldFBhdGgoKSwgdmFsdWUpO1xuICAgICAgICAgICAgdmFsdWUuc2V0UGFyZW50KHRoaXMpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBjaGlsZHJlbiBhcyBhIGJ1bmNoXG4gICAgICogQHJldHVybnMgQWp4cE5vZGVbXVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldENoaWxkcmVuID0gZnVuY3Rpb24gZ2V0Q2hpbGRyZW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaGlsZHJlbjtcbiAgICB9O1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldEZpcnN0Q2hpbGRJZkV4aXN0cyA9IGZ1bmN0aW9uIGdldEZpcnN0Q2hpbGRJZkV4aXN0cygpIHtcbiAgICAgICAgaWYgKHRoaXMuX2NoaWxkcmVuLnNpemUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jaGlsZHJlbi52YWx1ZXMoKS5uZXh0KCkudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc01vcmVSZWNlbnRUaGFuID0gZnVuY3Rpb24gaXNNb3JlUmVjZW50VGhhbihvdGhlck5vZGUpIHtcbiAgICAgICAgcmV0dXJuIG90aGVyTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSAmJiB0aGlzLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpICYmIHBhcnNlSW50KHRoaXMuZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikpID49IHBhcnNlSW50KG90aGVyTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBjaGlsZCB0byBjaGlsZHJlblxuICAgICAqIEBwYXJhbSBhanhwTm9kZSBBanhwTm9kZSBUaGUgY2hpbGRcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5hZGRDaGlsZCA9IGZ1bmN0aW9uIGFkZENoaWxkKGFqeHBOb2RlKSB7XG4gICAgICAgIGFqeHBOb2RlLnNldFBhcmVudCh0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuX2lOb2RlUHJvdmlkZXIpIGFqeHBOb2RlLl9pTm9kZVByb3ZpZGVyID0gdGhpcy5faU5vZGVQcm92aWRlcjtcbiAgICAgICAgdmFyIGV4aXN0aW5nTm9kZSA9IHRoaXMuZmluZENoaWxkQnlQYXRoKGFqeHBOb2RlLmdldFBhdGgoKSk7XG4gICAgICAgIGlmIChleGlzdGluZ05vZGUgJiYgIShleGlzdGluZ05vZGUgaW5zdGFuY2VvZiBTdHJpbmcpKSB7XG4gICAgICAgICAgICBpZiAoIWV4aXN0aW5nTm9kZS5pc01vcmVSZWNlbnRUaGFuKGFqeHBOb2RlKSkge1xuICAgICAgICAgICAgICAgIGV4aXN0aW5nTm9kZS5yZXBsYWNlQnkoYWp4cE5vZGUsIFwib3ZlcnJpZGVcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4aXN0aW5nTm9kZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fY2hpbGRyZW4uc2V0KGFqeHBOb2RlLmdldFBhdGgoKSwgYWp4cE5vZGUpO1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoXCJjaGlsZF9hZGRlZFwiLCBhanhwTm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhanhwTm9kZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgY2hpbGQgZnJvbSB0aGUgY2hpbGRyZW5cbiAgICAgKiBAcGFyYW0gYWp4cE5vZGUgQWp4cE5vZGVcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5yZW1vdmVDaGlsZCA9IGZ1bmN0aW9uIHJlbW92ZUNoaWxkKGFqeHBOb2RlKSB7XG4gICAgICAgIHZhciByZW1vdmVQYXRoID0gYWp4cE5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICBhanhwTm9kZS5ub3RpZnkoXCJub2RlX3JlbW92ZWRcIik7XG4gICAgICAgIGFqeHBOb2RlLl9wYXJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgdGhpcy5fY2hpbGRyZW5bJ2RlbGV0ZSddKGFqeHBOb2RlLmdldFBhdGgoKSk7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiY2hpbGRfcmVtb3ZlZFwiLCByZW1vdmVQYXRoKTtcbiAgICB9O1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnJlcGxhY2VNZXRhZGF0YSA9IGZ1bmN0aW9uIHJlcGxhY2VNZXRhZGF0YShuZXdNZXRhKSB7XG4gICAgICAgIHRoaXMuX21ldGFkYXRhID0gbmV3TWV0YTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJtZXRhX3JlcGxhY2VkXCIsIHRoaXMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgY3VycmVudCBub2RlIGJ5IGEgbmV3IG9uZS4gQ29weSBhbGwgcHJvcGVydGllcyBkZWVwbHlcbiAgICAgKiBAcGFyYW0gYWp4cE5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gbWV0YU1lcmdlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUucmVwbGFjZUJ5ID0gZnVuY3Rpb24gcmVwbGFjZUJ5KGFqeHBOb2RlLCBtZXRhTWVyZ2UpIHtcbiAgICAgICAgdGhpcy5faXNMZWFmID0gYWp4cE5vZGUuX2lzTGVhZjtcbiAgICAgICAgdmFyIHBhdGhDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChhanhwTm9kZS5nZXRQYXRoKCkgJiYgdGhpcy5fcGF0aCAhPSBhanhwTm9kZS5nZXRQYXRoKCkpIHtcbiAgICAgICAgICAgIHZhciBvcmlnaW5hbFBhdGggPSB0aGlzLl9wYXRoO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0UGFyZW50KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Q2hpbGRyZW5JbmRleCA9IHRoaXMuZ2V0UGFyZW50KCkuX2NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHBhcmVudENoaWxkcmVuSW5kZXguc2V0KGFqeHBOb2RlLmdldFBhdGgoKSwgdGhpcyk7XG4gICAgICAgICAgICAgICAgcGFyZW50Q2hpbGRyZW5JbmRleFsnZGVsZXRlJ10ob3JpZ2luYWxQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3BhdGggPSBhanhwTm9kZS5nZXRQYXRoKCk7XG4gICAgICAgICAgICBwYXRoQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFqeHBOb2RlLl9sYWJlbCkge1xuICAgICAgICAgICAgdGhpcy5fbGFiZWwgPSBhanhwTm9kZS5fbGFiZWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFqeHBOb2RlLl9pY29uKSB7XG4gICAgICAgICAgICB0aGlzLl9pY29uID0gYWp4cE5vZGUuX2ljb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFqeHBOb2RlLl9pTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgICAgICB0aGlzLl9pTm9kZVByb3ZpZGVyID0gYWp4cE5vZGUuX2lOb2RlUHJvdmlkZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy90aGlzLl9pc1Jvb3QgPSBhanhwTm9kZS5faXNSb290O1xuICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IGFqeHBOb2RlLl9pc0xvYWRlZDtcbiAgICAgICAgdGhpcy5mYWtlID0gYWp4cE5vZGUuZmFrZTtcbiAgICAgICAgdmFyIG1ldGEgPSBhanhwTm9kZS5nZXRNZXRhZGF0YSgpO1xuICAgICAgICBpZiAobWV0YU1lcmdlID09IFwib3ZlcnJpZGVcIikgdGhpcy5fbWV0YWRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgIG1ldGEuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIGlmIChtZXRhTWVyZ2UgPT0gXCJvdmVycmlkZVwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbWV0YWRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fbWV0YWRhdGEuaGFzKGtleSkgJiYgdmFsdWUgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9tZXRhZGF0YS5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICBpZiAocGF0aENoYW5nZWQgJiYgIXRoaXMuX2lzTGVhZiAmJiB0aGlzLmdldENoaWxkcmVuKCkuc2l6ZSkge1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbG9hZCh0aGlzLl9pTm9kZVByb3ZpZGVyKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyksIDEwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgYWp4cE5vZGUuZ2V0Q2hpbGRyZW4oKS5mb3JFYWNoKChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkQ2hpbGQoY2hpbGQpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJub2RlX3JlcGxhY2VkXCIsIHRoaXMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyBhIGNoaWxkIG5vZGUgYnkgaXRzIHBhdGhcbiAgICAgKiBAcGFyYW0gcGF0aCBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmZpbmRDaGlsZEJ5UGF0aCA9IGZ1bmN0aW9uIGZpbmRDaGlsZEJ5UGF0aChwYXRoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaGlsZHJlbi5nZXQocGF0aCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1ldGFkYXRhIGFzIGEgYnVuY2hcbiAgICAgKiBAcGFyYW0gZGF0YSBNYXAgQSBNYXBcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5zZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIHNldE1ldGFkYXRhKGRhdGEpIHtcbiAgICAgICAgdGhpcy5fbWV0YWRhdGEgPSBkYXRhO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBtZXRhZGF0XG4gICAgICogQHJldHVybnMgTWFwXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0TWV0YWRhdGEgPSBmdW5jdGlvbiBnZXRNZXRhZGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21ldGFkYXRhO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBJcyB0aGlzIG5vZGUgYSBsZWFmXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzTGVhZiA9IGZ1bmN0aW9uIGlzTGVhZigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzTGVhZjtcbiAgICB9O1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzQnJvd3NhYmxlID0gZnVuY3Rpb24gaXNCcm93c2FibGUoKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy5faXNMZWFmIHx8IHRoaXMuZ2V0QWp4cE1pbWUoKSA9PT0gJ2FqeHBfYnJvd3NhYmxlX2FyY2hpdmUnO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBTdHJpbmdcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRQYXRoID0gZnVuY3Rpb24gZ2V0UGF0aCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhdGg7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldExhYmVsID0gZnVuY3Rpb24gZ2V0TGFiZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYWJlbDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgU3RyaW5nXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0SWNvbiA9IGZ1bmN0aW9uIGdldEljb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pY29uO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNSZWN5Y2xlID0gZnVuY3Rpb24gaXNSZWN5Y2xlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRBanhwTWltZSgpID09ICdhanhwX3JlY3ljbGUnO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBTdHJpbmdcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRTdmdTb3VyY2UgPSBmdW5jdGlvbiBnZXRTdmdTb3VyY2UoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE1ldGFkYXRhKCkuZ2V0KFwiZm9udGljb25cIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlYXJjaCB0aGUgbWltZSB0eXBlIGluIHRoZSBwYXJlbnQgYnJhbmNoXG4gICAgICogQHBhcmFtIGFqeHBNaW1lIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5oYXNBanhwTWltZUluQnJhbmNoID0gZnVuY3Rpb24gaGFzQWp4cE1pbWVJbkJyYW5jaChhanhwTWltZSkge1xuICAgICAgICBpZiAodGhpcy5nZXRBanhwTWltZSgpID09IGFqeHBNaW1lLnRvTG93ZXJDYXNlKCkpIHJldHVybiB0cnVlO1xuICAgICAgICB2YXIgcGFyZW50ID0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3J0ID0gdGhpcztcbiAgICAgICAgd2hpbGUgKHBhcmVudCA9IGNydC5fcGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHBhcmVudC5nZXRBanhwTWltZSgpID09IGFqeHBNaW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNydCA9IHBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlYXJjaCB0aGUgbWltZSB0eXBlIGluIHRoZSBwYXJlbnQgYnJhbmNoXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqIEBwYXJhbSBtZXRhZGF0YUtleVxuICAgICAqIEBwYXJhbSBtZXRhZGF0YVZhbHVlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaGFzTWV0YWRhdGFJbkJyYW5jaCA9IGZ1bmN0aW9uIGhhc01ldGFkYXRhSW5CcmFuY2gobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2V0TWV0YWRhdGEoKS5oYXMobWV0YWRhdGFLZXkpKSB7XG4gICAgICAgICAgICBpZiAobWV0YWRhdGFWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldE1ldGFkYXRhKCkuZ2V0KG1ldGFkYXRhS2V5KSA9PSBtZXRhZGF0YVZhbHVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyZW50ID0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3J0ID0gdGhpcztcbiAgICAgICAgd2hpbGUgKHBhcmVudCA9IGNydC5fcGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHBhcmVudC5nZXRNZXRhZGF0YSgpLmhhcyhtZXRhZGF0YUtleSkpIHtcbiAgICAgICAgICAgICAgICBpZiAobWV0YWRhdGFWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50LmdldE1ldGFkYXRhKCkuZ2V0KG1ldGFkYXRhS2V5KSA9PSBtZXRhZGF0YVZhbHVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNydCA9IHBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCBub2RlXG4gICAgICogQHBhcmFtIHBhcmVudE5vZGUgQWp4cE5vZGVcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5zZXRQYXJlbnQgPSBmdW5jdGlvbiBzZXRQYXJlbnQocGFyZW50Tm9kZSkge1xuICAgICAgICB0aGlzLl9wYXJlbnROb2RlID0gcGFyZW50Tm9kZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcGFyZW50IE5vZGVcbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldFBhcmVudCA9IGZ1bmN0aW9uIGdldFBhcmVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcmVudE5vZGU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoaXMgbm9kZSBieSBwYXRoIGlmIGl0IGFscmVhZHkgZXhpc3RzIGluIGFyYm9yZXNjZW5jZVxuICAgICAqIEBwYXJhbSByb290Tm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSBmYWtlTm9kZXMgQWp4cE5vZGVbXVxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlfHVuZGVmaW5lZFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmZpbmRJbkFyYm8gPSBmdW5jdGlvbiBmaW5kSW5BcmJvKHJvb3ROb2RlLCBmYWtlTm9kZXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdldFBhdGgoKSkgcmV0dXJuO1xuICAgICAgICB2YXIgcGF0aFBhcnRzID0gdGhpcy5nZXRQYXRoKCkuc3BsaXQoXCIvXCIpO1xuICAgICAgICB2YXIgY3J0UGF0aCA9IFwiXCIsXG4gICAgICAgICAgICBjcnROb2RlID0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3J0UGFyZW50Tm9kZSA9IHJvb3ROb2RlO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGhQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHBhdGhQYXJ0c1tpXSA9PSBcIlwiKSBjb250aW51ZTtcbiAgICAgICAgICAgIGNydFBhdGggPSBjcnRQYXRoICsgXCIvXCIgKyBwYXRoUGFydHNbaV07XG4gICAgICAgICAgICB2YXIgbm9kZSA9IGNydFBhcmVudE5vZGUuZmluZENoaWxkQnlQYXRoKGNydFBhdGgpO1xuICAgICAgICAgICAgaWYgKG5vZGUgJiYgIShub2RlIGluc3RhbmNlb2YgU3RyaW5nKSkge1xuICAgICAgICAgICAgICAgIGNydE5vZGUgPSBub2RlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoZmFrZU5vZGVzID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgY3J0Tm9kZSA9IG5ldyBBanhwTm9kZShjcnRQYXRoLCBmYWxzZSwgX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUoY3J0UGF0aCkpO1xuICAgICAgICAgICAgICAgIGNydE5vZGUuZmFrZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgY3J0Tm9kZS5nZXRNZXRhZGF0YSgpLnNldChcInRleHRcIiwgX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUoY3J0UGF0aCkpO1xuICAgICAgICAgICAgICAgIGZha2VOb2Rlcy5wdXNoKGNydE5vZGUpO1xuICAgICAgICAgICAgICAgIGNydFBhcmVudE5vZGUuYWRkQ2hpbGQoY3J0Tm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjcnRQYXJlbnROb2RlID0gY3J0Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3J0Tm9kZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzUm9vdCA9IGZ1bmN0aW9uIGlzUm9vdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzUm9vdDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgaXQncyB0aGUgcGFyZW50IG9mIHRoZSBnaXZlbiBub2RlXG4gICAgICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNQYXJlbnRPZiA9IGZ1bmN0aW9uIGlzUGFyZW50T2Yobm9kZSkge1xuICAgICAgICB2YXIgY2hpbGRQYXRoID0gbm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIHZhciBwYXJlbnRQYXRoID0gdGhpcy5nZXRQYXRoKCk7XG4gICAgICAgIHJldHVybiBjaGlsZFBhdGguc3Vic3RyaW5nKDAsIHBhcmVudFBhdGgubGVuZ3RoKSA9PT0gcGFyZW50UGF0aDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgaXQncyBhIGNoaWxkIG9mIHRoZSBnaXZlbiBub2RlXG4gICAgICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNDaGlsZE9mID0gZnVuY3Rpb24gaXNDaGlsZE9mKG5vZGUpIHtcbiAgICAgICAgdmFyIGNoaWxkUGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICB2YXIgcGFyZW50UGF0aCA9IG5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICByZXR1cm4gY2hpbGRQYXRoLnN1YnN0cmluZygwLCBwYXJlbnRQYXRoLmxlbmd0aCkgPT09IHBhcmVudFBhdGg7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGN1cnJlbnQncyBub2RlIG1pbWUgdHlwZSwgZWl0aGVyIGJ5IGFqeHBfbWltZSBvciBieSBleHRlbnNpb24uXG4gICAgICogQHJldHVybnMgU3RyaW5nXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0QWp4cE1pbWUgPSBmdW5jdGlvbiBnZXRBanhwTWltZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX21ldGFkYXRhICYmIHRoaXMuX21ldGFkYXRhLmhhcyhcImFqeHBfbWltZVwiKSkgcmV0dXJuIHRoaXMuX21ldGFkYXRhLmdldChcImFqeHBfbWltZVwiKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAodGhpcy5fbWV0YWRhdGEgJiYgdGhpcy5pc0xlYWYoKSkgcmV0dXJuIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEFqeHBNaW1lVHlwZSh0aGlzLl9tZXRhZGF0YSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfTtcblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5idWlsZFJhbmRvbVNlZWQgPSBmdW5jdGlvbiBidWlsZFJhbmRvbVNlZWQoYWp4cE5vZGUpIHtcbiAgICAgICAgdmFyIG10aW1lU3RyaW5nID0gXCImdGltZV9zZWVkPVwiICsgdGhpcy5fbWV0YWRhdGEuZ2V0KFwiYWp4cF9tb2RpZnRpbWVcIik7XG4gICAgICAgIGlmICh0aGlzLmdldFBhcmVudCgpKSB7XG4gICAgICAgICAgICB2YXIgcHJldmlld19zZWVkID0gdGhpcy5nZXRQYXJlbnQoKS5nZXRNZXRhZGF0YSgpLmdldCgncHJldmlld19zZWVkJyk7XG4gICAgICAgICAgICBpZiAocHJldmlld19zZWVkKSB7XG4gICAgICAgICAgICAgICAgbXRpbWVTdHJpbmcgKz0gXCImcmFuZD1cIiArIHByZXZpZXdfc2VlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXRpbWVTdHJpbmc7XG4gICAgfTtcblxuICAgIHJldHVybiBBanhwTm9kZTtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEFqeHBOb2RlO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4uL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxudmFyIF9Vc2VyID0gcmVxdWlyZSgnLi9Vc2VyJyk7XG5cbnZhciBfVXNlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9Vc2VyKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi4vaHR0cC9SZXNvdXJjZXNNYW5hZ2VyJyk7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFJlc291cmNlc01hbmFnZXIpO1xuXG52YXIgUmVnaXN0cnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFJlZ2lzdHJ5KHB5ZGlvT2JqZWN0KSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSZWdpc3RyeSk7XG5cbiAgICAgICAgdGhpcy5fcmVnaXN0cnkgPSBudWxsO1xuICAgICAgICB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnkgPSB7IFwiZWRpdG9yXCI6IFtdLCBcInVwbG9hZGVyXCI6IFtdIH07XG4gICAgICAgIHRoaXMuX3Jlc291cmNlc1JlZ2lzdHJ5ID0ge307XG4gICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0ID0gcHlkaW9PYmplY3Q7XG4gICAgICAgIHRoaXMuX3hQYXRoTG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9nbG9iYWxMb2FkaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgWE1MIFN0cmluZyBkaXJlY3RseVxuICAgICAqIEBwYXJhbSBzXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUubG9hZEZyb21TdHJpbmcgPSBmdW5jdGlvbiBsb2FkRnJvbVN0cmluZyhzKSB7XG4gICAgICAgIHRoaXMuX3JlZ2lzdHJ5ID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5wYXJzZVhtbChzKS5kb2N1bWVudEVsZW1lbnQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgcmVnaXN0cnkgZnJvbSBzZXJ2ZXJcbiAgICAgKiBAcGFyYW0geFBhdGhcbiAgICAgKiBAcGFyYW0gY29tcGxldGVGdW5jXG4gICAgICogQHBhcmFtIHJlcG9zaXRvcnlJZFxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiBsb2FkKCkge1xuICAgICAgICB2YXIgeFBhdGggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzBdO1xuICAgICAgICB2YXIgY29tcGxldGVGdW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIHJlcG9zaXRvcnlJZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgaWYgKHhQYXRoID09PSBudWxsICYmIHRoaXMuX2dsb2JhbExvYWRpbmcgfHwgeFBhdGggJiYgdGhpcy5feFBhdGhMb2FkaW5nID09PSB4UGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4UGF0aCkgdGhpcy5feFBhdGhMb2FkaW5nID0geFBhdGg7ZWxzZSB0aGlzLl9nbG9iYWxMb2FkaW5nID0gdHJ1ZTtcbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHhQYXRoKSB0aGlzLl94UGF0aExvYWRpbmcgPSBmYWxzZTtlbHNlIHRoaXMuX2dsb2JhbExvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnQucmVzcG9uc2VYTUwgPT0gbnVsbCB8fCB0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50ID09IG51bGwpIHJldHVybjtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lID09IFwiYWp4cF9yZWdpc3RyeVwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVnaXN0cnkgPSB0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGlmICghY29tcGxldGVGdW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmZpcmUoXCJyZWdpc3RyeV9sb2FkZWRcIiwgdGhpcy5fcmVnaXN0cnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PSBcImFqeHBfcmVnaXN0cnlfcGFydFwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWZyZXNoWG1sUmVnaXN0cnlQYXJ0KHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbXBsZXRlRnVuYykgY29tcGxldGVGdW5jKHRoaXMuX3JlZ2lzdHJ5KTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHsgZ2V0X2FjdGlvbjogJ2dldF94bWxfcmVnaXN0cnknIH07XG4gICAgICAgIGlmICh4UGF0aCkge1xuICAgICAgICAgICAgcGFyYW1zWyd4UGF0aCddID0geFBhdGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgcGFyYW1zWyd3c19pZCddID0gcmVwb3NpdG9yeUlkOyAvLyBmb3IgY2FjaGluZyBvbmx5XG4gICAgICAgIH1cbiAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgb25Db21wbGV0ZSwgbnVsbCwgeyBtZXRob2Q6ICdnZXQnIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnRzIGEgZG9jdW1lbnQgZnJhZ21lbnQgcmV0cmlldmVkIGZyb20gc2VydmVyIGluc2lkZSB0aGUgZnVsbCB0cmVlLlxuICAgICAqIFRoZSBub2RlIG11c3QgY29udGFpbnMgdGhlIHhQYXRoIGF0dHJpYnV0ZSB0byBsb2NhdGUgaXQgaW5zaWRlIHRoZSByZWdpc3RyeS5cbiAgICAgKiBFdmVudCBhamF4cGxvcmVyOnJlZ2lzdHJ5X3BhcnRfbG9hZGVkIGlzIHRyaWdnZXJkIG9uY2UgdGhpcyBpcyBkb25lLlxuICAgICAqIEBwYXJhbSBkb2N1bWVudEVsZW1lbnQgRE9NTm9kZVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLnJlZnJlc2hYbWxSZWdpc3RyeVBhcnQgPSBmdW5jdGlvbiByZWZyZXNoWG1sUmVnaXN0cnlQYXJ0KGRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICB2YXIgeFBhdGggPSBkb2N1bWVudEVsZW1lbnQuZ2V0QXR0cmlidXRlKFwieFBhdGhcIik7XG4gICAgICAgIHZhciBleGlzdGluZ05vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgeFBhdGgpO1xuICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGV4aXN0aW5nTm9kZSAmJiBleGlzdGluZ05vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgcGFyZW50Tm9kZSA9IGV4aXN0aW5nTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChleGlzdGluZ05vZGUpO1xuICAgICAgICAgICAgaWYgKGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZC5jbG9uZU5vZGUodHJ1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHhQYXRoLmluZGV4T2YoXCIvXCIpID4gLTEpIHtcbiAgICAgICAgICAgIC8vIHRyeSBzZWxlY3RpbmcgcGFyZW50Tm9kZVxuICAgICAgICAgICAgdmFyIHBhcmVudFBhdGggPSB4UGF0aC5zdWJzdHJpbmcoMCwgeFBhdGgubGFzdEluZGV4T2YoXCIvXCIpKTtcbiAgICAgICAgICAgIHBhcmVudE5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgcGFyZW50UGF0aCk7XG4gICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQuY2xvbmVOb2RlKHRydWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZCkgdGhpcy5fcmVnaXN0cnkuYXBwZW5kQ2hpbGQoZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQuY2xvbmVOb2RlKHRydWUpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9weWRpb09iamVjdC5maXJlKFwicmVnaXN0cnlfcGFydF9sb2FkZWRcIiwgeFBhdGgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc2xhdGUgdGhlIFhNTCBhbnN3ZXIgdG8gYSBuZXcgVXNlciBvYmplY3RcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5wYXJzZVVzZXIgPSBmdW5jdGlvbiBwYXJzZVVzZXIoKSB7XG4gICAgICAgIHZhciB1c2VyID0gbnVsbCxcbiAgICAgICAgICAgIHVzZXJOb2RlID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAodGhpcy5fcmVnaXN0cnkpIHtcbiAgICAgICAgICAgIHVzZXJOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksIFwidXNlclwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXNlck5vZGUpIHtcbiAgICAgICAgICAgIHZhciB1c2VySWQgPSB1c2VyTm9kZS5nZXRBdHRyaWJ1dGUoJ2lkJyk7XG4gICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB1c2VyTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgaWYgKHVzZXJJZCkge1xuICAgICAgICAgICAgICAgIHVzZXIgPSBuZXcgX1VzZXIyWydkZWZhdWx0J10odXNlcklkLCBjaGlsZHJlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHJldHVybnMge0VsZW1lbnR8KnxudWxsfVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmdldFhNTCA9IGZ1bmN0aW9uIGdldFhNTCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlZ2lzdHJ5O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIEV4dGVuc2lvbiBpbml0aWFsaXNhdGlvbiBub2RlcyAoYWN0aXZlQ29uZGl0aW9uLCBvbkluaXQsIGV0YyksIHBhcnNlc1xuICAgICAqIHRoZSBYTUwgYW5kIGV4ZWN1dGUgSlMuXG4gICAgICogQHBhcmFtIHhtbE5vZGUge0VsZW1lbnR9IFRoZSBleHRlbnNpb24gbm9kZVxuICAgICAqIEBwYXJhbSBleHRlbnNpb25EZWZpbml0aW9uIE9iamVjdCBJbmZvcm1hdGlvbiBhbHJlYWR5IGNvbGxlY3RlZCBhYm91dCB0aGlzIGV4dGVuc2lvblxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5pbml0RXh0ZW5zaW9uID0gZnVuY3Rpb24gaW5pdEV4dGVuc2lvbih4bWxOb2RlLCBleHRlbnNpb25EZWZpbml0aW9uKSB7XG4gICAgICAgIHZhciBhY3RpdmVDb25kaXRpb24gPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9hY3RpdmVDb25kaXRpb24nKTtcbiAgICAgICAgaWYgKGFjdGl2ZUNvbmRpdGlvbiAmJiBhY3RpdmVDb25kaXRpb24uZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgZnVuYyA9IG5ldyBGdW5jdGlvbihhY3RpdmVDb25kaXRpb24uZmlyc3RDaGlsZC5ub2RlVmFsdWUudHJpbSgpKTtcbiAgICAgICAgICAgICAgICBpZiAoZnVuYygpID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuICAgICAgICBpZiAoeG1sTm9kZS5ub2RlTmFtZSA9PSAnZWRpdG9yJykge1xuXG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKGV4dGVuc2lvbkRlZmluaXRpb24sIHtcbiAgICAgICAgICAgICAgICBvcGVuYWJsZTogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJvcGVuYWJsZVwiKSA9PSBcInRydWVcIixcbiAgICAgICAgICAgICAgICBtb2RhbE9ubHk6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwibW9kYWxPbmx5XCIpID09IFwidHJ1ZVwiLFxuICAgICAgICAgICAgICAgIHByZXZpZXdQcm92aWRlcjogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJwcmV2aWV3UHJvdmlkZXJcIikgPT0gXCJ0cnVlXCIsXG4gICAgICAgICAgICAgICAgb3JkZXI6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwib3JkZXJcIikgPyBwYXJzZUludCh4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm9yZGVyXCIpKSA6IDAsXG4gICAgICAgICAgICAgICAgZm9ybUlkOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImZvcm1JZFwiKSB8fCBudWxsLFxuICAgICAgICAgICAgICAgIHRleHQ6IHRoaXMuX3B5ZGlvT2JqZWN0Lk1lc3NhZ2VIYXNoW3htbE5vZGUuZ2V0QXR0cmlidXRlKFwidGV4dFwiKV0sXG4gICAgICAgICAgICAgICAgdGl0bGU6IHRoaXMuX3B5ZGlvT2JqZWN0Lk1lc3NhZ2VIYXNoW3htbE5vZGUuZ2V0QXR0cmlidXRlKFwidGl0bGVcIildLFxuICAgICAgICAgICAgICAgIGljb246IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiaWNvblwiKSxcbiAgICAgICAgICAgICAgICBpY29uX2NsYXNzOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImljb25DbGFzc1wiKSxcbiAgICAgICAgICAgICAgICBlZGl0b3JBY3Rpb25zOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImFjdGlvbnNcIiksXG4gICAgICAgICAgICAgICAgZWRpdG9yQ2xhc3M6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpLFxuICAgICAgICAgICAgICAgIG1pbWVzOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm1pbWVzXCIpLnNwbGl0KFwiLFwiKSxcbiAgICAgICAgICAgICAgICB3cml0ZTogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJ3cml0ZVwiKSAmJiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIndyaXRlXCIpID09IFwidHJ1ZVwiID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNhbldyaXRlOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImNhbldyaXRlXCIpICYmIHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiY2FuV3JpdGVcIikgPT0gXCJ0cnVlXCIgPyB0cnVlIDogZmFsc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHhtbE5vZGUubm9kZU5hbWUgPT0gJ3VwbG9hZGVyJykge1xuXG4gICAgICAgICAgICB2YXIgdGggPSB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldCgndGhlbWUnKTtcbiAgICAgICAgICAgIHZhciBjbGllbnRGb3JtID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvY2xpZW50Rm9ybVtAdGhlbWU9XCInICsgdGggKyAnXCJdJyk7XG4gICAgICAgICAgICBpZiAoIWNsaWVudEZvcm0pIHtcbiAgICAgICAgICAgICAgICBjbGllbnRGb3JtID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvY2xpZW50Rm9ybScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNsaWVudEZvcm0gJiYgY2xpZW50Rm9ybS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5tb2R1bGVOYW1lID0gY2xpZW50Rm9ybS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwib3JkZXJcIikpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLm9yZGVyID0gcGFyc2VJbnQoeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJvcmRlclwiKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24ub3JkZXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGV4dGVuc2lvbk9uSW5pdCA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2V4dGVuc2lvbk9uSW5pdCcpO1xuICAgICAgICAgICAgaWYgKGV4dGVuc2lvbk9uSW5pdCAmJiBleHRlbnNpb25PbkluaXQuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEBUT0RPOiBUSElTIFdJTEwgTElLRUxZIFRSSUdHRVIgUFJPVE9UWVBFIENPREVcbiAgICAgICAgICAgICAgICAgICAgZXZhbChleHRlbnNpb25PbkluaXQuZmlyc3RDaGlsZC5ub2RlVmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoXCJJZ25vcmluZyBFcnJvciBpbiBleHRlbnNpb25PbkluaXQgY29kZTpcIik7XG4gICAgICAgICAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKGV4dGVuc2lvbk9uSW5pdC5maXJzdENoaWxkLm5vZGVWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKGUubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRpYWxvZ09uT3BlbiA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2RpYWxvZ09uT3BlbicpO1xuICAgICAgICAgICAgaWYgKGRpYWxvZ09uT3BlbiAmJiBkaWFsb2dPbk9wZW4uZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24uZGlhbG9nT25PcGVuID0gZGlhbG9nT25PcGVuLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRpYWxvZ09uQ29tcGxldGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9kaWFsb2dPbkNvbXBsZXRlJyk7XG4gICAgICAgICAgICBpZiAoZGlhbG9nT25Db21wbGV0ZSAmJiBkaWFsb2dPbkNvbXBsZXRlLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLmRpYWxvZ09uQ29tcGxldGUgPSBkaWFsb2dPbkNvbXBsZXRlLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWZyZXNoIHRoZSBjdXJyZW50bHkgYWN0aXZlIGV4dGVuc2lvbnNcbiAgICAgKiBFeHRlbnNpb25zIGFyZSBlZGl0b3JzIGFuZCB1cGxvYWRlcnMgZm9yIHRoZSBtb21lbnQuXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUucmVmcmVzaEV4dGVuc2lvbnNSZWdpc3RyeSA9IGZ1bmN0aW9uIHJlZnJlc2hFeHRlbnNpb25zUmVnaXN0cnkoKSB7XG5cbiAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5ID0geyBcImVkaXRvclwiOiBbXSwgXCJ1cGxvYWRlclwiOiBbXSB9O1xuICAgICAgICB2YXIgZXh0ZW5zaW9ucyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh0aGlzLl9yZWdpc3RyeSwgXCJwbHVnaW5zL2VkaXRvcnxwbHVnaW5zL3VwbG9hZGVyXCIpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV4dGVuc2lvbnMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgdmFyIGV4dGVuc2lvbkRlZmluaXRpb24gPSB7XG4gICAgICAgICAgICAgICAgaWQ6IGV4dGVuc2lvbnNbaV0uZ2V0QXR0cmlidXRlKFwiaWRcIiksXG4gICAgICAgICAgICAgICAgeG1sTm9kZTogZXh0ZW5zaW9uc1tpXSxcbiAgICAgICAgICAgICAgICByZXNvdXJjZXNNYW5hZ2VyOiBuZXcgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddKClcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLl9yZXNvdXJjZXNSZWdpc3RyeVtleHRlbnNpb25EZWZpbml0aW9uLmlkXSA9IGV4dGVuc2lvbkRlZmluaXRpb24ucmVzb3VyY2VzTWFuYWdlcjtcbiAgICAgICAgICAgIHZhciByZXNvdXJjZU5vZGVzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKGV4dGVuc2lvbnNbaV0sIFwiY2xpZW50X3NldHRpbmdzL3Jlc291cmNlc3xkZXBlbmRlbmNpZXN8Y2xpZW50Rm9ybVwiKTtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcmVzb3VyY2VOb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24ucmVzb3VyY2VzTWFuYWdlci5sb2FkRnJvbVhtbE5vZGUocmVzb3VyY2VOb2Rlc1tqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pbml0RXh0ZW5zaW9uKGV4dGVuc2lvbnNbaV0sIGV4dGVuc2lvbkRlZmluaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5W2V4dGVuc2lvbnNbaV0ubm9kZU5hbWVdLnB1c2goZXh0ZW5zaW9uRGVmaW5pdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLmxvYWRBdXRvTG9hZFJlc291cmNlcyh0aGlzLl9yZWdpc3RyeSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgdGhlIGN1cnJlbnRseSBhY3RpdmUgZXh0ZW5zaW9ucyBieSB0eXBlXG4gICAgICogQHBhcmFtIGV4dGVuc2lvblR5cGUgU3RyaW5nIFwiZWRpdG9yXCIgb3IgXCJ1cGxvYWRlclwiXG4gICAgICogQHJldHVybnMge2FycmF5fVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmdldEFjdGl2ZUV4dGVuc2lvbkJ5VHlwZSA9IGZ1bmN0aW9uIGdldEFjdGl2ZUV4dGVuc2lvbkJ5VHlwZShleHRlbnNpb25UeXBlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnlbZXh0ZW5zaW9uVHlwZV07XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgYSBnaXZlbiBlZGl0b3IgYnkgaXRzIGlkXG4gICAgICogQHBhcmFtIGVkaXRvcklkIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEFic3RyYWN0RWRpdG9yXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZmluZEVkaXRvckJ5SWQgPSBmdW5jdGlvbiBmaW5kRWRpdG9yQnlJZChlZGl0b3JJZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5LmVkaXRvci5maW5kKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgcmV0dXJuIGVsLmlkID09IGVkaXRvcklkO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCBFZGl0b3JzIHRoYXQgY2FuIGhhbmRsZSBhIGdpdmVuIG1pbWUgdHlwZVxuICAgICAqIEBwYXJhbSBtaW1lIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEFic3RyYWN0RWRpdG9yW11cbiAgICAgKiBAcGFyYW0gcmVzdHJpY3RUb1ByZXZpZXdQcm92aWRlcnNcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5maW5kRWRpdG9yc0Zvck1pbWUgPSBmdW5jdGlvbiBmaW5kRWRpdG9yc0Zvck1pbWUobWltZSwgcmVzdHJpY3RUb1ByZXZpZXdQcm92aWRlcnMpIHtcblxuICAgICAgICB2YXIgdXNlciA9IHRoaXMuX3B5ZGlvT2JqZWN0LnVzZXI7XG4gICAgICAgIHZhciBlZGl0b3JzID0gW10sXG4gICAgICAgICAgICBjaGVja1dyaXRlID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHVzZXIgIT0gbnVsbCAmJiAhdXNlci5jYW5Xcml0ZSgpKSB7XG4gICAgICAgICAgICBjaGVja1dyaXRlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnkuZWRpdG9yLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoZWwubWltZXMuaW5kZXhPZihtaW1lKSAhPT0gLTEgfHwgZWwubWltZXMuaW5kZXhPZignKicpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGlmIChyZXN0cmljdFRvUHJldmlld1Byb3ZpZGVycyAmJiAhZWwucHJldmlld1Byb3ZpZGVyKSByZXR1cm47XG4gICAgICAgICAgICAgICAgaWYgKCFjaGVja1dyaXRlIHx8ICFlbC53cml0ZSkgZWRpdG9ycy5wdXNoKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChlZGl0b3JzLmxlbmd0aCAmJiBlZGl0b3JzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGVkaXRvcnMgPSBlZGl0b3JzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGEub3JkZXIgfHwgMCkgLSAoYi5vcmRlciB8fCAwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlZGl0b3JzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIHRoZSBsb2FkIG1ldGhvZCBvZiB0aGUgcmVzb3VyY2VzTWFuYWdlci5cbiAgICAgKiBAcGFyYW0gcmVzb3VyY2VzTWFuYWdlciBSZXNvdXJjZXNNYW5hZ2VyXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIHRyaWdnZXJlZCBhZnRlciBKUyBsb2FkZWRcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5sb2FkRWRpdG9yUmVzb3VyY2VzID0gZnVuY3Rpb24gbG9hZEVkaXRvclJlc291cmNlcyhyZXNvdXJjZXNNYW5hZ2VyLCBjYWxsYmFjaykge1xuICAgICAgICByZXNvdXJjZXNNYW5hZ2VyLmxvYWQodGhpcy5fcmVzb3VyY2VzUmVnaXN0cnksIGZhbHNlLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHBsdWdpblF1ZXJ5XG4gICAgICogQHJldHVybnMge01hcH1cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXRQbHVnaW5Db25maWdzID0gZnVuY3Rpb24gZ2V0UGx1Z2luQ29uZmlncyhwbHVnaW5RdWVyeSkge1xuXG4gICAgICAgIHZhciB4cGF0aCA9ICdwbHVnaW5zLypbQGlkPVwiY29yZS4nICsgcGx1Z2luUXVlcnkgKyAnXCJdL3BsdWdpbl9jb25maWdzL3Byb3BlcnR5IHwgcGx1Z2lucy8qW0BpZD1cIicgKyBwbHVnaW5RdWVyeSArICdcIl0vcGx1Z2luX2NvbmZpZ3MvcHJvcGVydHknO1xuICAgICAgICBpZiAocGx1Z2luUXVlcnkuaW5kZXhPZignLicpID09IC0xKSB7XG4gICAgICAgICAgICB4cGF0aCA9ICdwbHVnaW5zLycgKyBwbHVnaW5RdWVyeSArICcvcGx1Z2luX2NvbmZpZ3MvcHJvcGVydHkgfCcgKyB4cGF0aDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJvcGVydGllcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh0aGlzLl9yZWdpc3RyeSwgeHBhdGgpO1xuICAgICAgICB2YXIgY29uZmlncyA9IG5ldyBNYXAoKTtcbiAgICAgICAgcHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wTm9kZSkge1xuICAgICAgICAgICAgY29uZmlncy5zZXQocHJvcE5vZGUuZ2V0QXR0cmlidXRlKFwibmFtZVwiKSwgSlNPTi5wYXJzZShwcm9wTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZSkpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZ3M7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHBsdWdpbklkXG4gICAgICogQHBhcmFtIHBhcmFtTmFtZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZ2V0RGVmYXVsdEltYWdlRnJvbVBhcmFtZXRlcnMgPSBmdW5jdGlvbiBnZXREZWZhdWx0SW1hZ2VGcm9tUGFyYW1ldGVycyhwbHVnaW5JZCwgcGFyYW1OYW1lKSB7XG4gICAgICAgIHZhciBub2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksIFwicGx1Z2lucy8qW0BpZD0nXCIgKyBwbHVnaW5JZCArIFwiJ10vc2VydmVyX3NldHRpbmdzL2dsb2JhbF9wYXJhbVtAbmFtZT0nXCIgKyBwYXJhbU5hbWUgKyBcIiddXCIpO1xuICAgICAgICBpZiAoIW5vZGUpIHJldHVybiAnJztcbiAgICAgICAgcmV0dXJuIG5vZGUuZ2V0QXR0cmlidXRlKFwiZGVmYXVsdEltYWdlXCIpIHx8ICcnO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSB0eXBlXG4gICAgICogQHBhcmFtIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbH1cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5oYXNQbHVnaW5PZlR5cGUgPSBmdW5jdGlvbiBoYXNQbHVnaW5PZlR5cGUodHlwZSwgbmFtZSkge1xuICAgICAgICB2YXIgbm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgbm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCAncGx1Z2lucy9hanhwX3BsdWdpbltjb250YWlucyhAaWQsIFwiJyArIHR5cGUgKyAnLlwiKV0gfCBwbHVnaW5zLycgKyB0eXBlICsgJ1tAaWRdJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBub2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksICdwbHVnaW5zL2FqeHBfcGx1Z2luW0BpZD1cIicgKyB0eXBlICsgJy4nICsgbmFtZSArICdcIl0gfCBwbHVnaW5zLycgKyB0eXBlICsgJ1tAaWQ9XCInICsgdHlwZSArICcuJyArIG5hbWUgKyAnXCJdJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGUgIT0gdW5kZWZpbmVkO1xuICAgIH07XG5cbiAgICByZXR1cm4gUmVnaXN0cnk7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSZWdpc3RyeTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfaHR0cE1ldGFDYWNoZVNlcnZpY2UgPSByZXF1aXJlKCcuLi9odHRwL01ldGFDYWNoZVNlcnZpY2UnKTtcblxudmFyIF9odHRwTWV0YUNhY2hlU2VydmljZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwTWV0YUNhY2hlU2VydmljZSk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1BhdGhVdGlscycpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFBhdGhVdGlscyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfQWp4cE5vZGUgPSByZXF1aXJlKCcuL0FqeHBOb2RlJyk7XG5cbnZhciBfQWp4cE5vZGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQWp4cE5vZGUpO1xuXG4vKipcbiAqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBJQWp4cE5vZGVQcm92aWRlciBpbnRlcmZhY2UgYmFzZWQgb24gYSByZW1vdGUgc2VydmVyIGFjY2Vzcy5cbiAqIERlZmF1bHQgZm9yIGFsbCByZXBvc2l0b3JpZXMuXG4gKi9cblxudmFyIFJlbW90ZU5vZGVQcm92aWRlciA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gUmVtb3RlTm9kZVByb3ZpZGVyKCkge1xuICAgICAgICB2YXIgcHJvcGVydGllcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlbW90ZU5vZGVQcm92aWRlcik7XG5cbiAgICAgICAgdGhpcy5kaXNjcmV0ZSA9IGZhbHNlO1xuICAgICAgICBpZiAocHJvcGVydGllcykgdGhpcy5pbml0UHJvdmlkZXIocHJvcGVydGllcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBwcm9wZXJ0aWVzXG4gICAgICogQHBhcmFtIHByb3BlcnRpZXMgT2JqZWN0XG4gICAgICovXG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLmluaXRQcm92aWRlciA9IGZ1bmN0aW9uIGluaXRQcm92aWRlcihwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwKSkgdGhpcy5wcm9wZXJ0aWVzLnNldChwLCBwcm9wZXJ0aWVzW3BdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzICYmIHRoaXMucHJvcGVydGllcy5oYXMoJ2Nvbm5leGlvbl9kaXNjcmV0ZScpKSB7XG4gICAgICAgICAgICB0aGlzLmRpc2NyZXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucHJvcGVydGllc1snZGVsZXRlJ10oJ2Nvbm5leGlvbl9kaXNjcmV0ZScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMgJiYgdGhpcy5wcm9wZXJ0aWVzLmhhcygnY2FjaGVfc2VydmljZScpKSB7XG4gICAgICAgICAgICB0aGlzLmNhY2hlU2VydmljZSA9IHRoaXMucHJvcGVydGllcy5nZXQoJ2NhY2hlX3NlcnZpY2UnKTtcbiAgICAgICAgICAgIHRoaXMucHJvcGVydGllc1snZGVsZXRlJ10oJ2NhY2hlX3NlcnZpY2UnKTtcbiAgICAgICAgICAgIF9odHRwTWV0YUNhY2hlU2VydmljZTJbJ2RlZmF1bHQnXS5nZXRJbnN0YW5jZSgpLnJlZ2lzdGVyTWV0YVN0cmVhbSh0aGlzLmNhY2hlU2VydmljZVsnbWV0YVN0cmVhbU5hbWUnXSwgdGhpcy5jYWNoZVNlcnZpY2VbJ2V4cGlyYXRpb25Qb2xpY3knXSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIG5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSBub2RlQ2FsbGJhY2sgRnVuY3Rpb24gT24gbm9kZSBsb2FkZWRcbiAgICAgKiBAcGFyYW0gY2hpbGRDYWxsYmFjayBGdW5jdGlvbiBPbiBjaGlsZCBhZGRlZFxuICAgICAqIEBwYXJhbSByZWN1cnNpdmVcbiAgICAgKiBAcGFyYW0gZGVwdGhcbiAgICAgKiBAcGFyYW0gb3B0aW9uYWxQYXJhbWV0ZXJzXG4gICAgICovXG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLmxvYWROb2RlID0gZnVuY3Rpb24gbG9hZE5vZGUobm9kZSkge1xuICAgICAgICB2YXIgbm9kZUNhbGxiYWNrID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGNoaWxkQ2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgcmVjdXJzaXZlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbM107XG4gICAgICAgIHZhciBkZXB0aCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNCB8fCBhcmd1bWVudHNbNF0gPT09IHVuZGVmaW5lZCA/IC0xIDogYXJndW1lbnRzWzRdO1xuICAgICAgICB2YXIgb3B0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSA1IHx8IGFyZ3VtZW50c1s1XSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1s1XTtcblxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ2xzJyxcbiAgICAgICAgICAgIG9wdGlvbnM6ICdhbCdcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHJlY3Vyc2l2ZSkge1xuICAgICAgICAgICAgcGFyYW1zWydyZWN1cnNpdmUnXSA9IHRydWU7XG4gICAgICAgICAgICBwYXJhbXNbJ2RlcHRoJ10gPSBkZXB0aDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGF0aCA9IG5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICAvLyBEb3VibGUgZW5jb2RlICMgY2hhcmFjdGVyXG4gICAgICAgIHZhciBwYWdpbmF0aW9uSGFzaCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKG5vZGUuZ2V0TWV0YWRhdGEoKS5oYXMoXCJwYWdpbmF0aW9uRGF0YVwiKSkge1xuICAgICAgICAgICAgcGFnaW5hdGlvbkhhc2ggPSBcIiUyM1wiICsgbm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInBhZ2luYXRpb25EYXRhXCIpLmdldChcImN1cnJlbnRcIik7XG4gICAgICAgICAgICBwYXRoICs9IHBhZ2luYXRpb25IYXNoO1xuICAgICAgICAgICAgcGFyYW1zWydyZW1vdGVfb3JkZXInXSA9ICd0cnVlJztcbiAgICAgICAgICAgIHZhciByZW1vdGVPcmRlckRhdGEgPSBub2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicmVtb3RlX29yZGVyXCIpO1xuICAgICAgICAgICAgaWYgKHJlbW90ZU9yZGVyRGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChyZW1vdGVPcmRlckRhdGEuX29iamVjdCkgcmVtb3RlT3JkZXJEYXRhID0gUHJvdG9Db21wYXQuaGFzaDJtYXAocmVtb3RlT3JkZXJEYXRhKTtcbiAgICAgICAgICAgICAgICByZW1vdGVPcmRlckRhdGEuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHBhcmFtc1snZGlyJ10gPSBwYXRoO1xuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgICAgIHBhcmFtc1trZXldID0gdmFsdWUgKyAoa2V5ID09ICdkaXInICYmIHBhZ2luYXRpb25IYXNoID8gcGFnaW5hdGlvbkhhc2ggOiAnJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9uYWxQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBfZXh0ZW5kcyh7fSwgcGFyYW1zLCBvcHRpb25hbFBhcmFtZXRlcnMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJzZXIgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdGhpcy5wYXJzZU5vZGVzKG5vZGUsIHRyYW5zcG9ydCwgbm9kZUNhbGxiYWNrLCBjaGlsZENhbGxiYWNrKTtcbiAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5jYWNoZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHZhciBsb2FkZXIgPSAoZnVuY3Rpb24gKGFqeHBOb2RlLCBjYWNoZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgY2FjaGVDYWxsYmFjaywgbnVsbCwgeyBkaXNjcmV0ZTogdGhpcy5kaXNjcmV0ZSB9KTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgICAgICB2YXIgY2FjaGVMb2FkZXIgPSAoZnVuY3Rpb24gKG5ld05vZGUpIHtcbiAgICAgICAgICAgICAgICBub2RlLnJlcGxhY2VCeShuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICBub2RlQ2FsbGJhY2sobm9kZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgX2h0dHBNZXRhQ2FjaGVTZXJ2aWNlMlsnZGVmYXVsdCddLmdldEluc3RhbmNlKCkubWV0YUZvck5vZGUodGhpcy5jYWNoZVNlcnZpY2VbJ21ldGFTdHJlYW1OYW1lJ10sIG5vZGUsIGxvYWRlciwgcGFyc2VyLCBjYWNoZUxvYWRlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCBwYXJzZXIsIG51bGwsIHsgZGlzY3JldGU6IHRoaXMuZGlzY3JldGUgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIG5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSBub2RlQ2FsbGJhY2sgRnVuY3Rpb24gT24gbm9kZSBsb2FkZWRcbiAgICAgKiBAcGFyYW0gYVN5bmMgYm9vbFxuICAgICAqIEBwYXJhbSBhZGRpdGlvbmFsUGFyYW1ldGVycyBvYmplY3RcbiAgICAgKi9cblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUubG9hZExlYWZOb2RlU3luYyA9IGZ1bmN0aW9uIGxvYWRMZWFmTm9kZVN5bmMobm9kZSwgbm9kZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBhU3luYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgYWRkaXRpb25hbFBhcmFtZXRlcnMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICB2YXIgcGFyYW1zID0gX2V4dGVuZHMoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ2xzJyxcbiAgICAgICAgICAgIG9wdGlvbnM6ICdhbCcsXG4gICAgICAgICAgICBkaXI6IF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpLFxuICAgICAgICAgICAgZmlsZTogX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUobm9kZS5nZXRQYXRoKCkpXG4gICAgICAgIH0sIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKTtcbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcykge1xuICAgICAgICAgICAgcGFyYW1zID0gX2V4dGVuZHMoe30sIHBhcmFtcywgdGhpcy5wcm9wZXJ0aWVzKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcGxldGUgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZS5pc1Jvb3QoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnNlTm9kZXMobm9kZSwgdHJhbnNwb3J0LCBub2RlQ2FsbGJhY2ssIG51bGwsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFyc2VOb2Rlcyhub2RlLCB0cmFuc3BvcnQsIG51bGwsIG5vZGVDYWxsYmFjaywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKCdMb2FkaW5nIGVycm9yIDonICsgZS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgY29tcGxldGUsIG51bGwsIHsgYXN5bmM6IGFTeW5jIH0pO1xuICAgIH07XG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLnJlZnJlc2hOb2RlQW5kUmVwbGFjZSA9IGZ1bmN0aW9uIHJlZnJlc2hOb2RlQW5kUmVwbGFjZShub2RlLCBvbkNvbXBsZXRlKSB7XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICdscycsXG4gICAgICAgICAgICBvcHRpb25zOiAnYWwnLFxuICAgICAgICAgICAgZGlyOiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSxcbiAgICAgICAgICAgIGZpbGU6IF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKG5vZGUuZ2V0UGF0aCgpKVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHBhcmFtcyA9IF9leHRlbmRzKHt9LCBwYXJhbXMsIHRoaXMucHJvcGVydGllcyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbm9kZUNhbGxiYWNrID0gZnVuY3Rpb24gbm9kZUNhbGxiYWNrKG5ld05vZGUpIHtcbiAgICAgICAgICAgIG5vZGUucmVwbGFjZUJ5KG5ld05vZGUsIFwib3ZlcnJpZGVcIik7XG4gICAgICAgICAgICBpZiAob25Db21wbGV0ZSkgb25Db21wbGV0ZShub2RlKTtcbiAgICAgICAgfTtcbiAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuaXNSb290KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJzZU5vZGVzKG5vZGUsIHRyYW5zcG9ydCwgbm9kZUNhbGxiYWNrLCBudWxsLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnNlTm9kZXMobm9kZSwgdHJhbnNwb3J0LCBudWxsLCBub2RlQ2FsbGJhY2ssIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBhcnNlIHRoZSBhbnN3ZXIgYW5kIGNyZWF0ZSBBanhwTm9kZXNcbiAgICAgKiBAcGFyYW0gb3JpZ05vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gdHJhbnNwb3J0IEFqYXguUmVzcG9uc2VcbiAgICAgKiBAcGFyYW0gbm9kZUNhbGxiYWNrIEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNoaWxkQ2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gY2hpbGRyZW5Pbmx5XG4gICAgICovXG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLnBhcnNlTm9kZXMgPSBmdW5jdGlvbiBwYXJzZU5vZGVzKG9yaWdOb2RlLCB0cmFuc3BvcnQsIG5vZGVDYWxsYmFjaywgY2hpbGRDYWxsYmFjaywgY2hpbGRyZW5Pbmx5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCF0cmFuc3BvcnQucmVzcG9uc2VYTUwgfHwgIXRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmRlYnVnKCdMb2FkaW5nIG5vZGUgJyArIG9yaWdOb2RlLmdldFBhdGgoKSArICcgaGFzIHdyb25nIHJlc3BvbnNlOiAnICsgdHJhbnNwb3J0LnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICBpZiAobm9kZUNhbGxiYWNrKSBub2RlQ2FsbGJhY2sob3JpZ05vZGUpO1xuICAgICAgICAgICAgb3JpZ05vZGUuc2V0TG9hZGVkKGZhbHNlKTtcbiAgICAgICAgICAgIGlmICghdHJhbnNwb3J0LnJlc3BvbnNlVGV4dCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRW1wdHkgcmVzcG9uc2UhJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgWE1MIERvY3VtZW50IChzZWUgY29uc29sZSknKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm9vdE5vZGUgPSB0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICBpZiAoIWNoaWxkcmVuT25seSkge1xuICAgICAgICAgICAgdmFyIGNvbnRleHROb2RlID0gdGhpcy5wYXJzZUFqeHBOb2RlKHJvb3ROb2RlKTtcbiAgICAgICAgICAgIG9yaWdOb2RlLnJlcGxhY2VCeShjb250ZXh0Tm9kZSwgXCJtZXJnZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENIRUNLIEZPUiBNRVNTQUdFIE9SIEVSUk9SU1xuICAgICAgICB2YXIgZXJyb3JOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocm9vdE5vZGUsIFwiZXJyb3J8bWVzc2FnZVwiKTtcbiAgICAgICAgaWYgKGVycm9yTm9kZSkge1xuICAgICAgICAgICAgdmFyIHR5cGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAoZXJyb3JOb2RlLm5vZGVOYW1lID09IFwibWVzc2FnZVwiKSB7XG4gICAgICAgICAgICAgICAgdHlwZSA9IGVycm9yTm9kZS5nZXRBdHRyaWJ1dGUoJ3R5cGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlID09IFwiRVJST1JcIikge1xuICAgICAgICAgICAgICAgIG9yaWdOb2RlLm5vdGlmeShcImVycm9yXCIsIGVycm9yTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZSArICcoU291cmNlOicgKyBvcmlnTm9kZS5nZXRQYXRoKCkgKyAnKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ0hFQ0sgRk9SIEFVVEggUFJPTVBUIFJFUVVJUkVEXG4gICAgICAgIHZhciBhdXRoTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHJvb3ROb2RlLCBcInByb21wdFwiKTtcbiAgICAgICAgaWYgKGF1dGhOb2RlICYmIHB5ZGlvICYmIHB5ZGlvLlVJICYmIHB5ZGlvLlVJLm9wZW5Qcm9tcHREaWFsb2cpIHtcbiAgICAgICAgICAgIHZhciBqc29uRGF0YSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKGF1dGhOb2RlLCBcImRhdGFcIikuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICBweWRpby5VSS5vcGVuUHJvbXB0RGlhbG9nKEpTT04ucGFyc2UoanNvbkRhdGEpKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENIRUNLIEZPUiBQQUdJTkFUSU9OIERBVEFcbiAgICAgICAgdmFyIHBhZ2luYXRpb25Ob2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocm9vdE5vZGUsIFwicGFnaW5hdGlvblwiKTtcbiAgICAgICAgaWYgKHBhZ2luYXRpb25Ob2RlKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBwYWdpbmF0aW9uRGF0YSA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgICAgICBBcnJheS5mcm9tKHBhZ2luYXRpb25Ob2RlLmF0dHJpYnV0ZXMpLmZvckVhY2goKGZ1bmN0aW9uIChhdHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFnaW5hdGlvbkRhdGEuc2V0KGF0dC5ub2RlTmFtZSwgYXR0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzKSk7XG4gICAgICAgICAgICAgICAgb3JpZ05vZGUuZ2V0TWV0YWRhdGEoKS5zZXQoJ3BhZ2luYXRpb25EYXRhJywgcGFnaW5hdGlvbkRhdGEpO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSBlbHNlIGlmIChvcmlnTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKSkge1xuICAgICAgICAgICAgb3JpZ05vZGUuZ2V0TWV0YWRhdGEoKVsnZGVsZXRlJ10oJ3BhZ2luYXRpb25EYXRhJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDSEVDSyBGT1IgQ09NUE9ORU5UIENPTkZJR1MgQ09OVEVYVFVBTCBEQVRBXG4gICAgICAgIHZhciBjb25maWdzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocm9vdE5vZGUsIFwiY2xpZW50X2NvbmZpZ3NcIik7XG4gICAgICAgIGlmIChjb25maWdzKSB7XG4gICAgICAgICAgICBvcmlnTm9kZS5nZXRNZXRhZGF0YSgpLnNldCgnY2xpZW50X2NvbmZpZ3MnLCBjb25maWdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5PVyBQQVJTRSBDSElMRFJFTlxuICAgICAgICB2YXIgY2hpbGRyZW4gPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMocm9vdE5vZGUsIFwidHJlZVwiKTtcbiAgICAgICAgY2hpbGRyZW4uZm9yRWFjaCgoZnVuY3Rpb24gKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgdmFyIGNoaWxkID0gdGhpcy5wYXJzZUFqeHBOb2RlKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICBpZiAoIWNoaWxkcmVuT25seSkge1xuICAgICAgICAgICAgICAgIG9yaWdOb2RlLmFkZENoaWxkKGNoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjTG9hZGVkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhjaGlsZE5vZGUsICd0cmVlJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKGNoaWxkTm9kZSwgJ3RyZWUnKS5mb3JFYWNoKChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGQgPSB0aGlzLnBhcnNlQWp4cE5vZGUoYyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdDaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuYWRkQ2hpbGQobmV3Q2hpbGQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgY0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2hpbGRDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNoaWxkQ2FsbGJhY2soY2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNMb2FkZWQpIGNoaWxkLnNldExvYWRlZCh0cnVlKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgaWYgKG5vZGVDYWxsYmFjaykge1xuICAgICAgICAgICAgbm9kZUNhbGxiYWNrKG9yaWdOb2RlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLnBhcnNlQWp4cE5vZGVzRGlmZnMgPSBmdW5jdGlvbiBwYXJzZUFqeHBOb2Rlc0RpZmZzKHhtbEVsZW1lbnQsIHRhcmdldERhdGFNb2RlbCwgdGFyZ2V0UmVwb3NpdG9yeUlkKSB7XG4gICAgICAgIHZhciBzZXRDb250ZXh0Q2hpbGRyZW5TZWxlY3RlZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIHZhciByZW1vdmVzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHhtbEVsZW1lbnQsIFwicmVtb3ZlL3RyZWVcIik7XG4gICAgICAgIHZhciBhZGRzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHhtbEVsZW1lbnQsIFwiYWRkL3RyZWVcIik7XG4gICAgICAgIHZhciB1cGRhdGVzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHhtbEVsZW1lbnQsIFwidXBkYXRlL3RyZWVcIik7XG4gICAgICAgIHZhciBub3RpZnlTZXJ2ZXJDaGFuZ2UgPSBbXTtcbiAgICAgICAgaWYgKHJlbW92ZXMgJiYgcmVtb3Zlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJlbW92ZXMuZm9yRWFjaChmdW5jdGlvbiAocikge1xuICAgICAgICAgICAgICAgIHZhciBwID0gci5nZXRBdHRyaWJ1dGUoXCJmaWxlbmFtZVwiKTtcbiAgICAgICAgICAgICAgICBpZiAoci5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgJiYgci5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgIT09IHRhcmdldFJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpbVRpbWUgPSBwYXJzZUludChyLmdldEF0dHJpYnV0ZShcImFqeHBfaW1fdGltZVwiKSk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RGF0YU1vZGVsLnJlbW92ZU5vZGVCeVBhdGgocCwgaW1UaW1lKTtcbiAgICAgICAgICAgICAgICBub3RpZnlTZXJ2ZXJDaGFuZ2UucHVzaChwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhZGRzICYmIGFkZHMubGVuZ3RoICYmIHRhcmdldERhdGFNb2RlbC5nZXRBanhwTm9kZVByb3ZpZGVyKCkucGFyc2VBanhwTm9kZSkge1xuICAgICAgICAgICAgYWRkcy5mb3JFYWNoKGZ1bmN0aW9uICh0cmVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRyZWUuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICYmIHRyZWUuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICE9PSB0YXJnZXRSZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHRhcmdldERhdGFNb2RlbC5nZXRBanhwTm9kZVByb3ZpZGVyKCkucGFyc2VBanhwTm9kZSh0cmVlKTtcbiAgICAgICAgICAgICAgICB0YXJnZXREYXRhTW9kZWwuYWRkTm9kZShuZXdOb2RlLCBzZXRDb250ZXh0Q2hpbGRyZW5TZWxlY3RlZCk7XG4gICAgICAgICAgICAgICAgbm90aWZ5U2VydmVyQ2hhbmdlLnB1c2gobmV3Tm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVwZGF0ZXMgJiYgdXBkYXRlcy5sZW5ndGggJiYgdGFyZ2V0RGF0YU1vZGVsLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2RlKSB7XG4gICAgICAgICAgICB1cGRhdGVzLmZvckVhY2goZnVuY3Rpb24gKHRyZWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodHJlZS5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgJiYgdHJlZS5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgIT09IHRhcmdldFJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gdGFyZ2V0RGF0YU1vZGVsLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2RlKHRyZWUpO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5hbCA9IG5ld05vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJvcmlnaW5hbF9wYXRoXCIpO1xuICAgICAgICAgICAgICAgIHRhcmdldERhdGFNb2RlbC51cGRhdGVOb2RlKG5ld05vZGUsIHNldENvbnRleHRDaGlsZHJlblNlbGVjdGVkKTtcbiAgICAgICAgICAgICAgICBub3RpZnlTZXJ2ZXJDaGFuZ2UucHVzaChuZXdOb2RlLmdldFBhdGgoKSk7XG4gICAgICAgICAgICAgICAgaWYgKG9yaWdpbmFsKSBub3RpZnlTZXJ2ZXJDaGFuZ2UucHVzaChvcmlnaW5hbCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm90aWZ5U2VydmVyQ2hhbmdlLmxlbmd0aCkge1xuICAgICAgICAgICAgdGFyZ2V0RGF0YU1vZGVsLm5vdGlmeShcInNlcnZlcl91cGRhdGVcIiwgbm90aWZ5U2VydmVyQ2hhbmdlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZXMgWE1MIE5vZGUgYW5kIGNyZWF0ZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSB4bWxOb2RlIFhNTE5vZGVcbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5wYXJzZUFqeHBOb2RlID0gZnVuY3Rpb24gcGFyc2VBanhwTm9kZSh4bWxOb2RlKSB7XG4gICAgICAgIHZhciBub2RlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXSh4bWxOb2RlLmdldEF0dHJpYnV0ZSgnZmlsZW5hbWUnKSwgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ2lzX2ZpbGUnKSA9PSBcIjFcIiB8fCB4bWxOb2RlLmdldEF0dHJpYnV0ZSgnaXNfZmlsZScpID09IFwidHJ1ZVwiLCB4bWxOb2RlLmdldEF0dHJpYnV0ZSgndGV4dCcpLCB4bWxOb2RlLmdldEF0dHJpYnV0ZSgnaWNvbicpKTtcbiAgICAgICAgdmFyIG1ldGFkYXRhID0gbmV3IE1hcCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHhtbE5vZGUuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbWV0YWRhdGEuc2V0KHhtbE5vZGUuYXR0cmlidXRlc1tpXS5ub2RlTmFtZSwgeG1sTm9kZS5hdHRyaWJ1dGVzW2ldLnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBub2RlLnNldE1ldGFkYXRhKG1ldGFkYXRhKTtcbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfTtcblxuICAgIHJldHVybiBSZW1vdGVOb2RlUHJvdmlkZXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSZW1vdGVOb2RlUHJvdmlkZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlciA9IHJlcXVpcmUoJy4uL2h0dHAvUmVzb3VyY2VzTWFuYWdlcicpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBSZXNvdXJjZXNNYW5hZ2VyKTtcblxuLyoqIFxuICogQ29udGFpbmVyIGZvciBhIFJlcG9zaXRvcnkuXG4gKi9cblxudmFyIFJlcG9zaXRvcnkgPSAoZnVuY3Rpb24gKCkge1xuXG5cdC8qKlxuICAqIENvbnN0cnVjdG9yXG4gICogQHBhcmFtIGlkIFN0cmluZ1xuICAqIEBwYXJhbSB4bWxEZWYgWE1MTm9kZVxuICAqL1xuXG5cdGZ1bmN0aW9uIFJlcG9zaXRvcnkoaWQsIHhtbERlZikge1xuXHRcdF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSZXBvc2l0b3J5KTtcblxuXHRcdHRoaXMubGFiZWwgPSAnJztcblx0XHR0aGlzLmlkID0gaWQ7XG5cdFx0dGhpcy5hY2Nlc3NUeXBlID0gJyc7XG5cdFx0dGhpcy5ub2RlUHJvdmlkZXJEZWYgPSB1bmRlZmluZWQ7XG5cdFx0dGhpcy5hbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHkgPSBmYWxzZTtcblx0XHR0aGlzLnVzZXJFZGl0YWJsZSA9IGZhbHNlO1xuXHRcdHRoaXMuc2x1ZyA9ICcnO1xuXHRcdHRoaXMub3duZXIgPSAnJztcblx0XHR0aGlzLmRlc2NyaXB0aW9uID0gJyc7XG5cdFx0dGhpcy5faGFzQ29udGVudEZpbHRlciA9IGZhbHNlO1xuXHRcdHRoaXMuX2hhc1VzZXJTY29wZSA9IGZhbHNlO1xuXHRcdHRoaXMuX3JlcG9zaXRvcnlUeXBlID0gJ2xvY2FsJztcblx0XHR0aGlzLl9hY2Nlc3NTdGF0dXMgPSBudWxsO1xuXHRcdHRoaXMuX2xhc3RDb25uZWN0aW9uID0gbnVsbDtcblx0XHR0aGlzLmljb24gPSAnJztcblx0XHR0aGlzLnJlc291cmNlc01hbmFnZXIgPSBuZXcgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddKCk7XG5cdFx0aWYgKHhtbERlZikgdGhpcy5sb2FkRnJvbVhtbCh4bWxEZWYpO1xuXHR9XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0SWQgPSBmdW5jdGlvbiBnZXRJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZDtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRTaGFyZUlkID0gZnVuY3Rpb24gZ2V0U2hhcmVJZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5pZC5yZXBsYWNlKC9vY3NfcmVtb3RlX3NoYXJlXy8sICcnKTtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRMYWJlbCA9IGZ1bmN0aW9uIGdldExhYmVsKCkge1xuXHRcdHJldHVybiB0aGlzLmxhYmVsO1xuXHR9O1xuXG5cdC8qKlxuICAqIEBwYXJhbSBsYWJlbCBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5zZXRMYWJlbCA9IGZ1bmN0aW9uIHNldExhYmVsKGxhYmVsKSB7XG5cdFx0dGhpcy5sYWJlbCA9IGxhYmVsO1xuXHR9O1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldExldHRlcnNCYWRnZSA9IGZ1bmN0aW9uIGdldExldHRlcnNCYWRnZSgpIHtcblx0XHRpZiAoIXRoaXMubGFiZWwpIHJldHVybiAnJztcblx0XHRyZXR1cm4gdGhpcy5sYWJlbC5zcGxpdChcIiBcIikubWFwKGZ1bmN0aW9uICh3b3JkKSB7XG5cdFx0XHRyZXR1cm4gd29yZC5zdWJzdHIoMCwgMSk7XG5cdFx0fSkuc2xpY2UoMCwgMikuam9pbihcIlwiKTtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJuIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldERlc2NyaXB0aW9uID0gZnVuY3Rpb24gZ2V0RGVzY3JpcHRpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGVzY3JpcHRpb247XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0SWNvbiA9IGZ1bmN0aW9uIGdldEljb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWNvbjtcblx0fTtcblxuXHQvKipcbiAgKiBAcGFyYW0gaWNvbiBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5zZXRJY29uID0gZnVuY3Rpb24gc2V0SWNvbihpY29uKSB7XG5cdFx0dGhpcy5pY29uID0gaWNvbjtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJuIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldE93bmVyID0gZnVuY3Rpb24gZ2V0T3duZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMub3duZXI7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0QWNjZXNzVHlwZSA9IGZ1bmN0aW9uIGdldEFjY2Vzc1R5cGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYWNjZXNzVHlwZTtcblx0fTtcblxuXHQvKipcbiAgKiBAcGFyYW0gYWNjZXNzIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLnNldEFjY2Vzc1R5cGUgPSBmdW5jdGlvbiBzZXRBY2Nlc3NUeXBlKGFjY2Vzcykge1xuXHRcdHRoaXMuYWNjZXNzVHlwZSA9IGFjY2Vzcztcblx0fTtcblxuXHQvKipcbiAgKiBUcmlnZ2VycyBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5sb2FkUmVzb3VyY2VzID0gZnVuY3Rpb24gbG9hZFJlc291cmNlcygpIHtcblx0XHR0aGlzLnJlc291cmNlc01hbmFnZXIubG9hZChudWxsLCB0cnVlKTtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBPYmplY3RcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXROb2RlUHJvdmlkZXJEZWYgPSBmdW5jdGlvbiBnZXROb2RlUHJvdmlkZXJEZWYoKSB7XG5cdFx0cmV0dXJuIHRoaXMubm9kZVByb3ZpZGVyRGVmO1xuXHR9O1xuXG5cdC8qKlxuICAqIEBwYXJhbSBzbHVnIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLnNldFNsdWcgPSBmdW5jdGlvbiBzZXRTbHVnKHNsdWcpIHtcblx0XHR0aGlzLnNsdWcgPSBzbHVnO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldFNsdWcgPSBmdW5jdGlvbiBnZXRTbHVnKCkge1xuXHRcdHJldHVybiB0aGlzLnNsdWc7XG5cdH07XG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0T3ZlcmxheSA9IGZ1bmN0aW9uIGdldE92ZXJsYXkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0T3duZXIoKSA/IF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5yZXNvbHZlSW1hZ2VTb3VyY2UoXCJzaGFyZWQucG5nXCIsIFwib3ZlcmxheXMvSUNPTl9TSVpFXCIsIDgpIDogXCJcIjtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5oYXNDb250ZW50RmlsdGVyID0gZnVuY3Rpb24gaGFzQ29udGVudEZpbHRlcigpIHtcblx0XHRyZXR1cm4gdGhpcy5faGFzQ29udGVudEZpbHRlcjtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5oYXNVc2VyU2NvcGUgPSBmdW5jdGlvbiBoYXNVc2VyU2NvcGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2hhc1VzZXJTY29wZTtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldFJlcG9zaXRvcnlUeXBlID0gZnVuY3Rpb24gZ2V0UmVwb3NpdG9yeVR5cGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3JlcG9zaXRvcnlUeXBlO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0QWNjZXNzU3RhdHVzID0gZnVuY3Rpb24gZ2V0QWNjZXNzU3RhdHVzKCkge1xuXHRcdHJldHVybiB0aGlzLl9hY2Nlc3NTdGF0dXM7XG5cdH07XG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuc2V0QWNjZXNzU3RhdHVzID0gZnVuY3Rpb24gc2V0QWNjZXNzU3RhdHVzKHN0YXR1cykge1xuXHRcdHRoaXMuX2FjY2Vzc1N0YXR1cyA9IHN0YXR1cztcblx0fTtcblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRMYXN0Q29ubmVjdGlvbiA9IGZ1bmN0aW9uIGdldExhc3RDb25uZWN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLl9sYXN0Q29ubmVjdGlvbjtcblx0fTtcblxuXHQvKipcbiAgKiBQYXJzZXMgWE1MIE5vZGVcbiAgKiBAcGFyYW0gcmVwb05vZGUgWE1MTm9kZVxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmxvYWRGcm9tWG1sID0gZnVuY3Rpb24gbG9hZEZyb21YbWwocmVwb05vZGUpIHtcblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHknKSAmJiByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weScpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHR0aGlzLmFsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2hhc0NvbnRlbnRGaWx0ZXInKSAmJiByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2hhc0NvbnRlbnRGaWx0ZXInKSA9PSBcInRydWVcIikge1xuXHRcdFx0dGhpcy5faGFzQ29udGVudEZpbHRlciA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3VzZXJTY29wZScpICYmIHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgndXNlclNjb3BlJykgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdHRoaXMuX2hhc1VzZXJTY29wZSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3JlcG9zaXRvcnlfdHlwZScpKSB7XG5cdFx0XHR0aGlzLl9yZXBvc2l0b3J5VHlwZSA9IHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgncmVwb3NpdG9yeV90eXBlJyk7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FjY2Vzc19zdGF0dXMnKSkge1xuXHRcdFx0dGhpcy5fYWNjZXNzU3RhdHVzID0gcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhY2Nlc3Nfc3RhdHVzJyk7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2xhc3RfY29ubmVjdGlvbicpKSB7XG5cdFx0XHR0aGlzLl9sYXN0Q29ubmVjdGlvbiA9IHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnbGFzdF9jb25uZWN0aW9uJyk7XG5cdFx0fVxuXG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgndXNlcl9lZGl0YWJsZV9yZXBvc2l0b3J5JykgJiYgcmVwb05vZGUuZ2V0QXR0cmlidXRlKCd1c2VyX2VkaXRhYmxlX3JlcG9zaXRvcnknKSA9PSBcInRydWVcIikge1xuXHRcdFx0dGhpcy51c2VyRWRpdGFibGUgPSB0cnVlO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhY2Nlc3NfdHlwZScpKSB7XG5cdFx0XHR0aGlzLnNldEFjY2Vzc1R5cGUocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhY2Nlc3NfdHlwZScpKTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgncmVwb3NpdG9yeVNsdWcnKSkge1xuXHRcdFx0dGhpcy5zZXRTbHVnKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgncmVwb3NpdG9yeVNsdWcnKSk7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ293bmVyJykpIHtcblx0XHRcdHRoaXMub3duZXIgPSByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ293bmVyJyk7XG5cdFx0fVxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcmVwb05vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIGNoaWxkTm9kZSA9IHJlcG9Ob2RlLmNoaWxkTm9kZXNbaV07XG5cdFx0XHRpZiAoY2hpbGROb2RlLm5vZGVOYW1lID09IFwibGFiZWxcIikge1xuXHRcdFx0XHR0aGlzLnNldExhYmVsKGNoaWxkTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZSk7XG5cdFx0XHR9IGVsc2UgaWYgKGNoaWxkTm9kZS5ub2RlTmFtZSA9PSBcImRlc2NyaXB0aW9uXCIpIHtcblx0XHRcdFx0dGhpcy5kZXNjcmlwdGlvbiA9IGNoaWxkTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcblx0XHRcdH0gZWxzZSBpZiAoY2hpbGROb2RlLm5vZGVOYW1lID09IFwiY2xpZW50X3NldHRpbmdzXCIpIHtcblx0XHRcdFx0aWYgKGNoaWxkTm9kZS5nZXRBdHRyaWJ1dGUoJ2ljb25fdHBsX2lkJykpIHtcblx0XHRcdFx0XHR0aGlzLnNldEljb24od2luZG93LnB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdzZXJ2ZXJBY2Nlc3NQYXRoJykgKyAnJmdldF9hY3Rpb249Z2V0X3VzZXJfdGVtcGxhdGVfbG9nbyZ0ZW1wbGF0ZV9pZD0nICsgY2hpbGROb2RlLmdldEF0dHJpYnV0ZSgnaWNvbl90cGxfaWQnKSArICcmaWNvbl9mb3JtYXQ9c21hbGwnKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnNldEljb24oY2hpbGROb2RlLmdldEF0dHJpYnV0ZSgnaWNvbicpKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IGNoaWxkTm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0dmFyIHN1YkNoID0gY2hpbGROb2RlLmNoaWxkTm9kZXNbal07XG5cdFx0XHRcdFx0aWYgKHN1YkNoLm5vZGVOYW1lID09ICdyZXNvdXJjZXMnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnJlc291cmNlc01hbmFnZXIubG9hZEZyb21YbWxOb2RlKHN1YkNoKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHN1YkNoLm5vZGVOYW1lID09ICdub2RlX3Byb3ZpZGVyJykge1xuXHRcdFx0XHRcdFx0dmFyIG5vZGVQcm92aWRlck5hbWUgPSBzdWJDaC5nZXRBdHRyaWJ1dGUoXCJhanhwQ2xhc3NcIik7XG5cdFx0XHRcdFx0XHR2YXIgbm9kZVByb3ZpZGVyT3B0aW9ucyA9IEpTT04ucGFyc2Uoc3ViQ2guZ2V0QXR0cmlidXRlKFwiYWp4cE9wdGlvbnNcIikpO1xuXHRcdFx0XHRcdFx0dGhpcy5ub2RlUHJvdmlkZXJEZWYgPSB7IG5hbWU6IG5vZGVQcm92aWRlck5hbWUsIG9wdGlvbnM6IG5vZGVQcm92aWRlck9wdGlvbnMgfTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0cmV0dXJuIFJlcG9zaXRvcnk7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSZXBvc2l0b3J5O1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbnZhciBfUmVwb3NpdG9yeSA9IHJlcXVpcmUoJy4vUmVwb3NpdG9yeScpO1xuXG52YXIgX1JlcG9zaXRvcnkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfUmVwb3NpdG9yeSk7XG5cbi8qKlxuICogQWJzdHJhY3Rpb24gb2YgdGhlIGN1cnJlbnRseSBsb2dnZWQgdXNlci4gQ2FuIGJlIGEgXCJmYWtlXCIgdXNlciB3aGVuIHVzZXJzIG1hbmFnZW1lbnRcbiAqIHN5c3RlbSBpcyBkaXNhYmxlZFxuICovXG5cbnZhciBVc2VyID0gKGZ1bmN0aW9uICgpIHtcblxuXHQvKipcbiAgKiBDb25zdHJ1Y3RvclxuICAqIEBwYXJhbSBpZCBTdHJpbmcgVGhlIHVzZXIgdW5pcXVlIGlkXG4gICogQHBhcmFtIHhtbERlZiBYTUxOb2RlIFJlZ2lzdHJ5IEZyYWdtZW50XG4gICovXG5cblx0ZnVuY3Rpb24gVXNlcihpZCwgeG1sRGVmKSB7XG5cdFx0X2NsYXNzQ2FsbENoZWNrKHRoaXMsIFVzZXIpO1xuXG5cdFx0LyoqXG4gICAqIEB2YXIgU3RyaW5nXG4gICAqL1xuXHRcdHRoaXMuaWQgPSBpZDtcblx0XHQvKipcbiAgICogQHZhciBTdHJpbmdcbiAgICovXG5cdFx0dGhpcy5hY3RpdmVSZXBvc2l0b3J5ID0gdW5kZWZpbmVkO1xuXHRcdC8qKlxuICAgKiBAdmFyIEJvb2xlYW5cbiAgICovXG5cdFx0dGhpcy5yZWFkID0gZmFsc2U7XG5cdFx0LyoqXG4gICAqIEB2YXIgQm9vbGVhblxuICAgKi9cblx0XHR0aGlzLndyaXRlID0gZmFsc2UsXG5cdFx0LyoqXG4gICAqIEB2YXIgQm9vbGVhblxuICAgKi9cblx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yeUNvcHkgPSBmYWxzZSxcblx0XHQvKipcbiAgICogQHZhciBNYXAoKVxuICAgKi9cblx0XHR0aGlzLnByZWZlcmVuY2VzID0gbmV3IE1hcCgpLFxuXHRcdC8qKlxuICAgKiBAdmFyIE1hcCgpXG4gICAqL1xuXHRcdHRoaXMucmVwb3NpdG9yaWVzID0gbmV3IE1hcCgpLFxuXHRcdC8qKlxuICAgKiBAdmFyIE1hcCgpXG4gICAqL1xuXHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXMgPSBuZXcgTWFwKCksXG5cdFx0LyoqXG4gICAqIEB2YXIgTWFwKClcbiAgICovXG5cdFx0dGhpcy5yZXBvSWNvbnMgPSBuZXcgTWFwKCksXG5cdFx0LyoqXG4gICAqIEB2YXIgTWFwKClcbiAgICovXG5cdFx0dGhpcy5yZXBvU2VhcmNoRW5naW5lcyA9IG5ldyBNYXAoKSxcblx0XHQvKipcbiAgICogQHZhciBCb29sZWFuXG4gICAqL1xuXHRcdHRoaXMuaXNBZG1pbiA9IGZhbHNlO1xuXHRcdC8qKlxuICAgKiBAdmFyIFN0cmluZ1xuICAgKi9cblx0XHR0aGlzLmxvY2sgPSBmYWxzZTtcblx0XHQvKipcbiAgICpcbiAgICogQHR5cGUgTWFwXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXHRcdHRoaXMuX3BhcnNlZEpTT05DYWNoZSA9IG5ldyBNYXAoKTtcblxuXHRcdGlmICh4bWxEZWYpIHRoaXMubG9hZEZyb21YbWwoeG1sRGVmKTtcblx0fVxuXG5cdC8qKlxuICAqIFNldCBjdXJyZW50IHJlcG9zaXRvcnlcbiAgKiBAcGFyYW0gaWQgU3RyaW5nXG4gICogQHBhcmFtIHJlYWQgQm9vbGVhblxuICAqIEBwYXJhbSB3cml0ZSBCb29sZWFuXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuc2V0QWN0aXZlUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIHNldEFjdGl2ZVJlcG9zaXRvcnkoaWQsIHJlYWQsIHdyaXRlKSB7XG5cdFx0dGhpcy5hY3RpdmVSZXBvc2l0b3J5ID0gaWQ7XG5cdFx0dGhpcy5yZWFkID0gcmVhZCA9PSBcIjFcIjtcblx0XHR0aGlzLndyaXRlID0gd3JpdGUgPT0gXCIxXCI7XG5cdFx0aWYgKHRoaXMucmVwb3NpdG9yaWVzLmhhcyhpZCkpIHtcblx0XHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3J5Q29weSA9IHRoaXMucmVwb3NpdG9yaWVzLmdldChpZCkuYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5O1xuXHRcdH1cblx0XHRpZiAodGhpcy5jcm9zc1JlcG9zaXRvcmllcy5oYXMoaWQpKSB7XG5cdFx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yaWVzWydkZWxldGUnXShpZCk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHJlcG9zaXRvcnlcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRBY3RpdmVSZXBvc2l0b3J5ID0gZnVuY3Rpb24gZ2V0QWN0aXZlUmVwb3NpdG9yeSgpIHtcblx0XHRyZXR1cm4gdGhpcy5hY3RpdmVSZXBvc2l0b3J5O1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgY3VycmVudCByZXBvIGlzIGFsbG93ZWQgdG8gYmUgcmVhZFxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5jYW5SZWFkID0gZnVuY3Rpb24gY2FuUmVhZCgpIHtcblx0XHRyZXR1cm4gdGhpcy5yZWFkO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgY3VycmVudCByZXBvIGlzIGFsbG93ZWQgdG8gYmUgd3JpdHRlblxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5jYW5Xcml0ZSA9IGZ1bmN0aW9uIGNhbldyaXRlKCkge1xuXHRcdHJldHVybiB0aGlzLndyaXRlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgY3VycmVudCByZXBvIGlzIGFsbG93ZWQgdG8gYmUgY3Jvc3MtY29waWVkXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmNhbkNyb3NzUmVwb3NpdG9yeUNvcHkgPSBmdW5jdGlvbiBjYW5Dcm9zc1JlcG9zaXRvcnlDb3B5KCkge1xuXHRcdHJldHVybiB0aGlzLmNyb3NzUmVwb3NpdG9yeUNvcHk7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IGEgdXNlciBwcmVmZXJlbmNlIGJ5IGl0cyBuYW1lXG4gICogQHJldHVybnMgTWl4ZWRcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRQcmVmZXJlbmNlID0gZnVuY3Rpb24gZ2V0UHJlZmVyZW5jZShwcmVmTmFtZSwgZnJvbUpTT04pIHtcblx0XHRpZiAoZnJvbUpTT04pIHtcblx0XHRcdHZhciB0ZXN0ID0gdGhpcy5fcGFyc2VkSlNPTkNhY2hlLmdldChwcmVmTmFtZSk7XG5cdFx0XHRpZiAodGVzdCkgcmV0dXJuIHRlc3Q7XG5cdFx0fVxuXHRcdHZhciB2YWx1ZSA9IHRoaXMucHJlZmVyZW5jZXMuZ2V0KHByZWZOYW1lKTtcblx0XHRpZiAoZnJvbUpTT04pIHtcblx0XHRcdGlmICh2YWx1ZSkge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGlmICh0eXBlb2YgdmFsdWUgPT0gXCJvYmplY3RcIikgcmV0dXJuIHZhbHVlO1xuXHRcdFx0XHRcdHZhciBwYXJzZWQgPSBKU09OLnBhcnNlKHZhbHVlKTtcblx0XHRcdFx0XHR0aGlzLl9wYXJzZWRKU09OQ2FjaGUuc2V0KHByZWZOYW1lLCBwYXJzZWQpO1xuXHRcdFx0XHRcdGlmICghcGFyc2VkKSByZXR1cm4ge307XG5cdFx0XHRcdFx0cmV0dXJuIHBhcnNlZDtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdGlmICh3aW5kb3cuY29uc29sZSkge1xuXHRcdFx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10ubG9nKFwiRXJyb3IgcGFyc2luZyBKU09OIGluIHByZWZlcmVuY2VzIChcIiArIHByZWZOYW1lICsgXCIpLiBZb3Ugc2hvdWxkIGNvbnRhY3Qgc3lzdGVtIGFkbWluIGFuZCBjbGVhciB1c2VyIHByZWZlcmVuY2VzLlwiKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0YWxlcnQoXCJFcnJvciBwYXJzaW5nIEpTT04gaW4gcHJlZmVyZW5jZXMuIFlvdSBzaG91bGQgY29udGFjdCBzeXN0ZW0gYWRtaW4gYW5kIGNsZWFyIHVzZXIgcHJlZmVyZW5jZXMuXCIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHt9O1xuXHRcdH1cblx0XHRyZXR1cm4gdmFsdWU7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IGFsbCByZXBvc2l0b3JpZXMgXG4gICogQHJldHVybnMgTWFwXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0UmVwb3NpdG9yaWVzTGlzdCA9IGZ1bmN0aW9uIGdldFJlcG9zaXRvcmllc0xpc3QoKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVwb3NpdG9yaWVzO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldCBhIHByZWZlcmVuY2UgdmFsdWVcbiAgKiBAcGFyYW0gcHJlZk5hbWUgU3RyaW5nXG4gICogQHBhcmFtIHByZWZWYWx1ZSBNaXhlZFxuICAqIEBwYXJhbSB0b0pTT04gQm9vbGVhbiBXaGV0aGVyIHRvIGNvbnZlcnQgdGhlIHZhbHVlIHRvIEpTT04gcmVwcmVzZW50YXRpb25cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5zZXRQcmVmZXJlbmNlID0gZnVuY3Rpb24gc2V0UHJlZmVyZW5jZShwcmVmTmFtZSwgcHJlZlZhbHVlKSB7XG5cdFx0dmFyIHRvSlNPTiA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzJdO1xuXG5cdFx0aWYgKHRvSlNPTikge1xuXHRcdFx0dGhpcy5fcGFyc2VkSlNPTkNhY2hlWydkZWxldGUnXShwcmVmTmFtZSk7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRwcmVmVmFsdWUgPSBKU09OLnN0cmluZ2lmeShwcmVmVmFsdWUpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRpZiAoY29uc29sZSkge1xuXHRcdFx0XHRcdHZhciBpc0N5Y2xpYyA9IGZ1bmN0aW9uIGlzQ3ljbGljKG9iaikge1xuXHRcdFx0XHRcdFx0dmFyIHNlZW5PYmplY3RzID0gW107XG5cblx0XHRcdFx0XHRcdGZ1bmN0aW9uIGRldGVjdChvYmopIHtcblx0XHRcdFx0XHRcdFx0aWYgKG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuXHRcdFx0XHRcdFx0XHRcdGlmIChzZWVuT2JqZWN0cy5pbmRleE9mKG9iaikgIT09IC0xKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0c2Vlbk9iamVjdHMucHVzaChvYmopO1xuXHRcdFx0XHRcdFx0XHRcdGZvciAodmFyIGtleSBpbiBvYmopIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSAmJiBkZXRlY3Qob2JqW2tleV0pKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKG9iaiwgJ2N5Y2xlIGF0ICcgKyBrZXkpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0cmV0dXJuIGRldGVjdChvYmopO1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRjb25zb2xlLmxvZyhcIkNhdWdodCB0b0pTT04gZXJyb3IgXCIgKyBlLm1lc3NhZ2UsIHByZWZWYWx1ZSwgaXNDeWNsaWMocHJlZlZhbHVlKSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLnByZWZlcmVuY2VzLnNldChwcmVmTmFtZSwgcHJlZlZhbHVlKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZXQgdGhlIHJlcG9zaXRvcmllcyBhcyBhIGJ1bmNoXG4gICogQHBhcmFtIHJlcG9IYXNoIE1hcFxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLnNldFJlcG9zaXRvcmllc0xpc3QgPSBmdW5jdGlvbiBzZXRSZXBvc2l0b3JpZXNMaXN0KHJlcG9IYXNoKSB7XG5cdFx0dGhpcy5yZXBvc2l0b3JpZXMgPSByZXBvSGFzaDtcblx0XHQvLyBmaWx0ZXIgcmVwb3NpdG9yaWVzIG9uY2UgZm9yIGFsbFxuXHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXMgPSBuZXcgTWFwKCk7XG5cdFx0dGhpcy5yZXBvc2l0b3JpZXMuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcblx0XHRcdGlmICh2YWx1ZS5hbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHkgJiYgdmFsdWUuYWNjZXNzVHlwZSAhPSAnaW5ib3gnKSB7XG5cdFx0XHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXMuc2V0KGtleSwgdmFsdWUpO1xuXHRcdFx0fVxuXHRcdH0pLmJpbmQodGhpcykpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlcmUgYXJlIGFueSByZXBvc2l0b3JpZXMgYWxsb3dpbmcgY3Jvc3NDb3B5XG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmhhc0Nyb3NzUmVwb3NpdG9yaWVzID0gZnVuY3Rpb24gaGFzQ3Jvc3NSZXBvc2l0b3JpZXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXMuc2l6ZTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgcmVwb3NpdG9yaWVzIGFsbG93aW5nIGNyb3NzIGNvcHlcbiAgKiBAcmV0dXJucyB7TWFwfVxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldENyb3NzUmVwb3NpdG9yaWVzID0gZnVuY3Rpb24gZ2V0Q3Jvc3NSZXBvc2l0b3JpZXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXM7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IHRoZSBjdXJyZW50IHJlcG9zaXRvcnkgSWNvblxuICAqIEBwYXJhbSByZXBvSWQgU3RyaW5nXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0UmVwb3NpdG9yeUljb24gPSBmdW5jdGlvbiBnZXRSZXBvc2l0b3J5SWNvbihyZXBvSWQpIHtcblx0XHRyZXR1cm4gdGhpcy5yZXBvSWNvbi5nZXQocmVwb0lkKTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgdGhlIHJlcG9zaXRvcnkgc2VhcmNoIGVuZ2luZVxuICAqIEBwYXJhbSByZXBvSWQgU3RyaW5nXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0UmVwb1NlYXJjaEVuZ2luZSA9IGZ1bmN0aW9uIGdldFJlcG9TZWFyY2hFbmdpbmUocmVwb0lkKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVwb1NlYXJjaEVuZ2luZXMuZ2V0KHJlcG9JZCk7XG5cdH07XG5cblx0LyoqXG4gICogU2VuZCB0aGUgcHJlZmVyZW5jZSB0byB0aGUgc2VydmVyIGZvciBzYXZpbmdcbiAgKiBAcGFyYW0gcHJlZk5hbWUgU3RyaW5nXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuc2F2ZVByZWZlcmVuY2UgPSBmdW5jdGlvbiBzYXZlUHJlZmVyZW5jZShwcmVmTmFtZSkge1xuXHRcdGlmICghdGhpcy5wcmVmZXJlbmNlcy5oYXMocHJlZk5hbWUpKSByZXR1cm47XG5cdFx0dmFyIHByZWZWYWx1ZSA9IHRoaXMucHJlZmVyZW5jZXMuZ2V0KHByZWZOYW1lKTtcblx0XHR3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnVzZXJTYXZlUHJlZmVyZW5jZShwcmVmTmFtZSwgcHJlZlZhbHVlKTtcblx0XHR9LCAyNTApO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNlbmQgYWxsIHByZWZlcmVuY2VzIHRvIHRoZSBzZXJ2ZXIuIElmIG9sZFBhc3MsIG5ld1Bhc3MgYW5kIHNlZWQgYXJlIHNldCwgYWxzbyBzYXZlIHBhc3MuXG4gICogQHBhcmFtIG9sZFBhc3MgU3RyaW5nXG4gICogQHBhcmFtIG5ld1Bhc3MgU3RyaW5nXG4gICogQHBhcmFtIHNlZWQgU3RyaW5nXG4gICogQHBhcmFtIG9uQ29tcGxldGVGdW5jIEZ1bmN0aW9uXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuc2F2ZVByZWZlcmVuY2VzID0gZnVuY3Rpb24gc2F2ZVByZWZlcmVuY2VzKG9sZFBhc3MsIG5ld1Bhc3MsIHNlZWQsIG9uQ29tcGxldGVGdW5jKSB7XG5cdFx0aWYgKG9sZFBhc3MgJiYgbmV3UGFzcykge1xuXHRcdFx0X2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS51c2VyU2F2ZVBhc3N3b3JkKG9sZFBhc3MsIG5ld1Bhc3MsIHNlZWQsIG9uQ29tcGxldGVGdW5jKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0X2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS51c2VyU2F2ZVByZWZlcmVuY2VzKHRoaXMucHJlZmVyZW5jZXMsIG9uQ29tcGxldGVGdW5jKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogUGFyc2UgdGhlIHJlZ2lzdHJ5IGZyYWdtZW50IHRvIGxvYWQgdGhpcyB1c2VyXG4gICogQHBhcmFtIHVzZXJOb2RlcyBET01Ob2RlXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUubG9hZEZyb21YbWwgPSBmdW5jdGlvbiBsb2FkRnJvbVhtbCh1c2VyTm9kZXMpIHtcblxuXHRcdHZhciByZXBvc2l0b3JpZXMgPSBuZXcgTWFwKCksXG5cdFx0ICAgIGFjdGl2ZU5vZGUgPSB1bmRlZmluZWQ7XG5cdFx0dmFyIGkgPSB1bmRlZmluZWQsXG5cdFx0ICAgIGogPSB1bmRlZmluZWQ7XG5cdFx0Zm9yIChpID0gMDsgaSA8IHVzZXJOb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKHVzZXJOb2Rlc1tpXS5ub2RlTmFtZSA9PSBcImFjdGl2ZV9yZXBvXCIpIHtcblx0XHRcdFx0YWN0aXZlTm9kZSA9IHVzZXJOb2Rlc1tpXTtcblx0XHRcdH0gZWxzZSBpZiAodXNlck5vZGVzW2ldLm5vZGVOYW1lID09IFwicmVwb3NpdG9yaWVzXCIpIHtcblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IHVzZXJOb2Rlc1tpXS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0dmFyIHJlcG9DaGlsZCA9IHVzZXJOb2Rlc1tpXS5jaGlsZE5vZGVzW2pdO1xuXHRcdFx0XHRcdGlmIChyZXBvQ2hpbGQubm9kZU5hbWUgPT0gXCJyZXBvXCIpIHtcblx0XHRcdFx0XHRcdHZhciByZXBvc2l0b3J5ID0gbmV3IF9SZXBvc2l0b3J5MlsnZGVmYXVsdCddKHJlcG9DaGlsZC5nZXRBdHRyaWJ1dGUoXCJpZFwiKSwgcmVwb0NoaWxkKTtcblx0XHRcdFx0XHRcdHJlcG9zaXRvcmllcy5zZXQocmVwb0NoaWxkLmdldEF0dHJpYnV0ZShcImlkXCIpLCByZXBvc2l0b3J5KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5zZXRSZXBvc2l0b3JpZXNMaXN0KHJlcG9zaXRvcmllcyk7XG5cdFx0XHR9IGVsc2UgaWYgKHVzZXJOb2Rlc1tpXS5ub2RlTmFtZSA9PSBcInByZWZlcmVuY2VzXCIpIHtcblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IHVzZXJOb2Rlc1tpXS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0dmFyIHByZWZDaGlsZCA9IHVzZXJOb2Rlc1tpXS5jaGlsZE5vZGVzW2pdO1xuXHRcdFx0XHRcdGlmIChwcmVmQ2hpbGQubm9kZU5hbWUgPT0gXCJwcmVmXCIpIHtcblx0XHRcdFx0XHRcdHZhciB2YWx1ZSA9IHByZWZDaGlsZC5nZXRBdHRyaWJ1dGUoXCJ2YWx1ZVwiKTtcblx0XHRcdFx0XHRcdGlmICghdmFsdWUgJiYgcHJlZkNoaWxkLmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0XHRcdFx0Ly8gUmV0cmlldmUgdmFsdWUgZnJvbSBDREFUQVxuXHRcdFx0XHRcdFx0XHR2YWx1ZSA9IHByZWZDaGlsZC5maXJzdENoaWxkLm5vZGVWYWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHRoaXMuc2V0UHJlZmVyZW5jZShwcmVmQ2hpbGQuZ2V0QXR0cmlidXRlKFwibmFtZVwiKSwgdmFsdWUpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICh1c2VyTm9kZXNbaV0ubm9kZU5hbWUgPT0gXCJzcGVjaWFsX3JpZ2h0c1wiKSB7XG5cdFx0XHRcdHZhciBhdHRyID0gdXNlck5vZGVzW2ldLmdldEF0dHJpYnV0ZShcImlzX2FkbWluXCIpO1xuXHRcdFx0XHRpZiAoYXR0ciAmJiBhdHRyID09PSBcIjFcIikgdGhpcy5pc0FkbWluID0gdHJ1ZTtcblx0XHRcdFx0aWYgKHVzZXJOb2Rlc1tpXS5nZXRBdHRyaWJ1dGUoXCJsb2NrXCIpKSB7XG5cdFx0XHRcdFx0dGhpcy5sb2NrID0gdXNlck5vZGVzW2ldLmdldEF0dHJpYnV0ZShcImxvY2tcIik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gTWFrZSBzdXJlIGl0IGhhcHBlbnMgYXQgdGhlIGVuZFxuXHRcdGlmIChhY3RpdmVOb2RlKSB7XG5cdFx0XHR0aGlzLnNldEFjdGl2ZVJlcG9zaXRvcnkoYWN0aXZlTm9kZS5nZXRBdHRyaWJ1dGUoJ2lkJyksIGFjdGl2ZU5vZGUuZ2V0QXR0cmlidXRlKCdyZWFkJyksIGFjdGl2ZU5vZGUuZ2V0QXR0cmlidXRlKCd3cml0ZScpKTtcblx0XHR9XG5cdH07XG5cblx0cmV0dXJuIFVzZXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBVc2VyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxuLyoqXG4gKiBBIG1vbml0b3IgZm9yIHVzZXIgXCJpZGxlXCIgc3RhdGUgdG8gcHJldmVudCBzZXNzaW9uIHRpbWluZyBvdXQuXG4gKi9cblxudmFyIEFjdGl2aXR5TW9uaXRvciA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoQWN0aXZpdHlNb25pdG9yLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSBweWRpbyBQeWRpb1xuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gQWN0aXZpdHlNb25pdG9yKHB5ZGlvKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEFjdGl2aXR5TW9uaXRvcik7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcblxuICAgICAgICB2YXIgc2VydmVyU2Vzc2lvblRpbWUgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnc2Vzc2lvbl90aW1lb3V0Jyk7XG4gICAgICAgIHZhciBjbGllbnRTZXNzaW9uVGltZSA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdjbGllbnRfdGltZW91dCcpO1xuICAgICAgICB2YXIgd2FybmluZ01pbnV0ZXMgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnY2xpZW50X3RpbWVvdXRfd2FybmluZycpO1xuXG4gICAgICAgIHRoaXMuX3B5ZGlvID0gcHlkaW87XG4gICAgICAgIHRoaXMuX3dhcm5pbmdNaW51dGVzID0gMztcbiAgICAgICAgdGhpcy5fcmVuZXdNaW51dGVzID0gMTA7XG4gICAgICAgIHRoaXMuX2xvZ291dE1pbnV0ZXMgPSAwO1xuXG4gICAgICAgIHRoaXMuX2xhc3RBY3RpdmUgPSAwO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICB0aGlzLl9sb25nVGFza1J1bm5pbmcgPSBmYWxzZTtcblxuICAgICAgICBpZiAoIXNlcnZlclNlc3Npb25UaW1lKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHNlcnZlclNlc3Npb25UaW1lIDw9IDYwICogdGhpcy5fcmVuZXdNaW51dGVzKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5ld01pbnV0ZXMgPSAyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjbGllbnRTZXNzaW9uVGltZSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmV3VGltZSA9IHNlcnZlclNlc3Npb25UaW1lIC0gdGhpcy5fcmVuZXdNaW51dGVzICogNjA7XG4gICAgICAgICAgICBpZiAodGhpcy5fcHlkaW8udXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRTZXJ2ZXJMb25nUG9sbGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCd1c2VyX2xvZ2dlZCcsIGZ1bmN0aW9uICh1KSB7XG4gICAgICAgICAgICAgICAgaWYgKHUpIF90aGlzLnN0YXJ0U2VydmVyTG9uZ1BvbGxlcigpO2Vsc2UgX3RoaXMuc3RvcFNlcnZlckxvbmdQb2xsZXIoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2VydmVyU2Vzc2lvblRpbWUgPSBzZXJ2ZXJTZXNzaW9uVGltZTtcbiAgICAgICAgaWYgKHdhcm5pbmdNaW51dGVzKSB7XG4gICAgICAgICAgICB0aGlzLl93YXJuaW5nTWludXRlcyA9IHdhcm5pbmdNaW51dGVzO1xuICAgICAgICAgICAgdGhpcy5fd2FybmluZ1RpbWUgPSBjbGllbnRTZXNzaW9uVGltZSAtIHRoaXMuX3dhcm5pbmdNaW51dGVzICogNjA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl93YXJuaW5nVGltZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2xvZ291dFRpbWUgPSBjbGllbnRTZXNzaW9uVGltZSAtIHRoaXMuX2xvZ291dE1pbnV0ZXMgKiA2MDtcbiAgICAgICAgdGhpcy5fcmVuZXdUaW1lID0gc2VydmVyU2Vzc2lvblRpbWUgLSB0aGlzLl9yZW5ld01pbnV0ZXMgKiA2MDtcbiAgICAgICAgdGhpcy5fbGFzdEFjdGl2ZSA9IHRoaXMuZ2V0Tm93KCk7XG5cbiAgICAgICAgdGhpcy5fYWN0aXZpdHlPYnNlcnZlciA9IG51bGw7XG5cbiAgICAgICAgaWYgKHRoaXMuX3B5ZGlvLnVzZXIpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXIoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCd1c2VyX2xvZ2dlZCcsIGZ1bmN0aW9uICh1KSB7XG4gICAgICAgICAgICBfdGhpcy51cGRhdGVMYXN0QWN0aXZlKCk7XG4gICAgICAgICAgICBpZiAodSkgX3RoaXMucmVnaXN0ZXIoKTtlbHNlIF90aGlzLnVucmVnaXN0ZXIoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgZG9jdW1lbnQub2JzZXJ2ZShcImFqYXhwbG9yZXI6dXNlcl9sb2dnZWRcIiwgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIC8vIEJlIHN1cmUgbm90IHRvIG11bHRpcGx5IHRoZSBzZXRJbnRlcnZhbFxuICAgICAgICAgICAgdGhpcy5fbGFzdEFjdGl2ZSA9IHRoaXMuZ2V0Tm93KCk7XG4gICAgICAgICAgICBpZih0aGlzLmludGVydmFsKSBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWwpO1xuICAgICAgICAgICAgaWYodGhpcy5zZXJ2ZXJJbnRlcnZhbCkgY2xlYXJJbnRlcnZhbCh0aGlzLnNlcnZlckludGVydmFsKTtcbiAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkuc3RvcE9ic2VydmluZyhcImtleXByZXNzXCIsIGFjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5zdG9wT2JzZXJ2aW5nKFwibW91c2VvdmVyXCIsIGFjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5zdG9wT2JzZXJ2aW5nKFwibW91c2Vtb3ZlXCIsIGFjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICAgICAgZG9jdW1lbnQuc3RvcE9ic2VydmluZyhcImFqYXhwbG9yZXI6c2VydmVyX2Fuc3dlclwiLCBhY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gJ2luYWN0aXZlJztcbiAgICAgICAgICAgIGlmKGFqYXhwbG9yZXIudXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gJ2FjdGl2ZSc7XG4gICAgICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5vYnNlcnZlKFwia2V5cHJlc3NcIiwgYWN0aXZpdHlPYnNlcnZlciApO1xuICAgICAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkub2JzZXJ2ZShcIm1vdXNlb3ZlclwiLCBhY3Rpdml0eU9ic2VydmVyICk7XG4gICAgICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5vYnNlcnZlKFwibW91c2Vtb3ZlXCIsIGFjdGl2aXR5T2JzZXJ2ZXIgKTtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5vYnNlcnZlKFwiYWpheHBsb3JlcjpzZXJ2ZXJfYW5zd2VyXCIsIGFjdGl2aXR5T2JzZXJ2ZXIgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmludGVydmFsID0gc2V0SW50ZXJ2YWwodGhpcy5pZGxlT2JzZXJ2ZXIuYmluZCh0aGlzKSwgNTAwMCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJJbnRlcnZhbCA9IHNldEludGVydmFsKHRoaXMuc2VydmVyT2JzZXJ2ZXIuYmluZCh0aGlzKSwgTWF0aC5taW4oKE1hdGgucG93KDIsMzEpLTEpLCB0aGlzLl9yZW5ld1RpbWUqMTAwMCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICBkb2N1bWVudC5vYnNlcnZlKFwiYWpheHBsb3Jlcjpsb25ndGFza19zdGFydGluZ1wiLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgdGhpcy5fbG9uZ1Rhc2tSdW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgZG9jdW1lbnQub2JzZXJ2ZShcImFqYXhwbG9yZXI6bG9uZ3Rhc2tfZmluaXNoZWRcIiwgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdUYXNrUnVubmluZyA9IGZhbHNlO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICAqL1xuICAgIH1cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc3RhcnRTZXJ2ZXJMb25nUG9sbGVyID0gZnVuY3Rpb24gc3RhcnRTZXJ2ZXJMb25nUG9sbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5fc2VydmVySW50ZXJ2YWwpIHJldHVybjtcbiAgICAgICAgdGhpcy5fc2VydmVySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLnNlcnZlclBvbGxlci5iaW5kKHRoaXMpLCBNYXRoLm1pbihNYXRoLnBvdygyLCAzMSkgLSAxLCB0aGlzLl9yZW5ld1RpbWUgKiAxMDAwKSk7XG4gICAgfTtcblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc3RvcFNlcnZlckxvbmdQb2xsZXIgPSBmdW5jdGlvbiBzdG9wU2VydmVyTG9uZ1BvbGxlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuX3NlcnZlckludGVydmFsKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMuX3NlcnZlckludGVydmFsKTtcbiAgICAgICAgICAgIHRoaXMuX3NlcnZlckludGVydmFsID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnN0YXJ0SWRsZVBvbGxlciA9IGZ1bmN0aW9uIHN0YXJ0SWRsZVBvbGxlcigpIHtcbiAgICAgICAgdmFyIHJlc3RhcnRBdCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgaWYgKHJlc3RhcnRBdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2lkbGVJbnRlcnZhbCkgY2xlYXJJbnRlcnZhbCh0aGlzLl9pZGxlSW50ZXJ2YWwpO1xuICAgICAgICAgICAgdGhpcy5faWRsZUludGVydmFsID0gc2V0SW50ZXJ2YWwodGhpcy5pZGxlT2JzZXJ2ZXIuYmluZCh0aGlzKSwgcmVzdGFydEF0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pZGxlSW50ZXJ2YWwpIHJldHVybjtcbiAgICAgICAgICAgIHRoaXMuX2lkbGVJbnRlcnZhbCA9IHNldEludGVydmFsKHRoaXMuaWRsZU9ic2VydmVyLmJpbmQodGhpcyksIDUwMDApO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc3RvcElkbGVQb2xsZXIgPSBmdW5jdGlvbiBzdG9wSWRsZVBvbGxlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuX2lkbGVJbnRlcnZhbCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLl9pZGxlSW50ZXJ2YWwpO1xuICAgICAgICAgICAgdGhpcy5faWRsZUludGVydmFsID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnJlZ2lzdGVyID0gZnVuY3Rpb24gcmVnaXN0ZXIoKSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9hY3Rpdml0eU9ic2VydmVyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBBbHJlYWR5IHJlZ2lzdGVyZWRcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICB0aGlzLl9hY3Rpdml0eU9ic2VydmVyID0gdGhpcy5hY3Rpdml0eU9ic2VydmVyLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ3VzZXJfYWN0aXZpdHknLCB0aGlzLl9hY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgnc2VydmVyX2Fuc3dlcicsIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCdsb25ndGFza19zdGFydGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzMi5fbG9uZ1Rhc2tSdW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ2xvbmd0YXNrX2ZpbmlzaGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMyLl9sb25nVGFza1J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3RhcnRJZGxlUG9sbGVyKCk7XG4gICAgICAgIHRoaXMuc3RhcnRTZXJ2ZXJMb25nUG9sbGVyKCk7XG4gICAgfTtcblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUudW5yZWdpc3RlciA9IGZ1bmN0aW9uIHVucmVnaXN0ZXIoKSB7XG4gICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgIGlmICh0aGlzLl9hY3Rpdml0eU9ic2VydmVyID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBBbHJlYWR5IGluYWN0aXZlXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdG9wSWRsZVBvbGxlcigpO1xuICAgICAgICB0aGlzLnN0b3BTZXJ2ZXJMb25nUG9sbGVyKCk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gJ2luYWN0aXZlJztcbiAgICAgICAgdGhpcy5fcHlkaW8uc3RvcE9ic2VydmluZygndXNlcl9hY3Rpdml0eScsIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLl9weWRpby5zdG9wT2JzZXJ2aW5nKCdzZXJ2ZXJfYW5zd2VyJywgdGhpcy5fYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgIHRoaXMuX3B5ZGlvLnN0b3BPYnNlcnZpbmcoJ2xvbmd0YXNrX3N0YXJ0aW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMzLl9sb25nVGFza1J1bm5pbmcgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fcHlkaW8uc3RvcE9ic2VydmluZygnbG9uZ3Rhc2tfZmluaXNoZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpczMuX2xvbmdUYXNrUnVubmluZyA9IGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fYWN0aXZpdHlPYnNlcnZlciA9IG51bGw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExpc3RlbmVyIHRvIGNsZWFyIHRoZSB0aW1lclxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5hY3Rpdml0eU9ic2VydmVyID0gZnVuY3Rpb24gYWN0aXZpdHlPYnNlcnZlcihldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQgJiYgKGV2ZW50Lm1lbW8gJiYgZXZlbnQubWVtby5kaXNjcmV0ZSB8fCBldmVudC5kaXNjcmV0ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fc3RhdGUgPT09ICd3YXJuaW5nJykge1xuICAgICAgICAgICAgdGhpcy5leGl0SWRsZVN0YXRlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2ludGVybmFsVGltZXIpIGNsZWFyVGltZW91dCh0aGlzLl9pbnRlcm5hbFRpbWVyKTtcbiAgICAgICAgdGhpcy5faW50ZXJuYWxUaW1lciA9IHNldFRpbWVvdXQodGhpcy51cGRhdGVMYXN0QWN0aXZlLmJpbmQodGhpcyksIDEwMDApO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXQgbGFzdCBhY3Rpdml0eSB0aW1lXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnVwZGF0ZUxhc3RBY3RpdmUgPSBmdW5jdGlvbiB1cGRhdGVMYXN0QWN0aXZlKCkge1xuICAgICAgICB0aGlzLl9sYXN0QWN0aXZlID0gdGhpcy5nZXROb3coKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGluZ3MgdGhlIHNlcnZlclxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zZXJ2ZXJQb2xsZXIgPSBmdW5jdGlvbiBzZXJ2ZXJQb2xsZXIoKSB7XG4gICAgICAgIFB5ZGlvQXBpLmdldENsaWVudCgpLnJlcXVlc3QoeyBnZXRfYWN0aW9uOiAncGluZycgfSwgbnVsbCwgbnVsbCwgeyBtZXRob2Q6ICdnZXQnLCBkaXNjcmV0ZTogdHJ1ZSB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTGlzdGVuZXIgZm9yIFwiaWRsZVwiIHN0YXRlIG9mIHRoZSB1c2VyXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLmlkbGVPYnNlcnZlciA9IGZ1bmN0aW9uIGlkbGVPYnNlcnZlcigpIHtcbiAgICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGlkbGVUaW1lID0gdGhpcy5nZXROb3coKSAtIHRoaXMuX2xhc3RBY3RpdmU7XG4gICAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gJ2luYWN0aXZlJykgcmV0dXJuO1xuICAgICAgICBpZiAodGhpcy5fbG9uZ1Rhc2tSdW5uaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUxhc3RBY3RpdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvL2NvbnNvbGUubG9nKGlkbGVUaW1lLCB0aGlzLl9sb2dvdXRUaW1lKTtcbiAgICAgICAgaWYgKGlkbGVUaW1lID49IHRoaXMuX2xvZ291dFRpbWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlV2FybmluZ1N0YXRlKCk7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICAgICAgdGhpcy5zdG9wSWRsZVBvbGxlcigpO1xuICAgICAgICAgICAgdGhpcy5zdG9wU2VydmVyTG9uZ1BvbGxlcigpO1xuICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXM0Ll9weWRpby5nZXRDb250cm9sbGVyKCkuZmlyZURlZmF1bHRBY3Rpb24oXCJleHBpcmVcIik7XG4gICAgICAgICAgICB9LCAxMDAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fd2FybmluZ1RpbWUgJiYgaWRsZVRpbWUgPj0gdGhpcy5fd2FybmluZ1RpbWUpIHtcbiAgICAgICAgICAgIHZhciB0aW1lclN0cmluZyA9IHRoaXMuZ2V0V2FybmluZ1RpbWVyKHRoaXMuX2xvZ291dFRpbWUgLSBpZGxlVGltZSk7XG4gICAgICAgICAgICB0aGlzLnNldFdhcm5pbmdTdGF0ZSh0aW1lclN0cmluZyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVhY3RpdmF0ZSB3aW5kb3dcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuZXhpdElkbGVTdGF0ZSA9IGZ1bmN0aW9uIGV4aXRJZGxlU3RhdGUoKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlV2FybmluZ1N0YXRlKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTGFzdEFjdGl2ZSgpO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICB0aGlzLnN0YXJ0SWRsZVBvbGxlcig1MDAwKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUHV0IHRoZSB3aW5kb3cgaW4gXCJ3YXJuaW5nXCIgc3RhdGUgOiBvdmVybGF5LCBzaGFraW5nIHRpbWVyLCBjaHJvbm9tZXRlci5cbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc2V0V2FybmluZ1N0YXRlID0gZnVuY3Rpb24gc2V0V2FybmluZ1N0YXRlKHdhcm5pbmdUaW1lclN0cmluZykge1xuICAgICAgICB0aGlzLl9zdGF0ZSA9ICd3YXJuaW5nJztcbiAgICAgICAgdGhpcy5zdGFydElkbGVQb2xsZXIoMTAwMCk7XG5cbiAgICAgICAgdGhpcy5fcHlkaW8ubm90aWZ5KCdhY3Rpdml0eV9zdGF0ZV9jaGFuZ2UnLCB7XG4gICAgICAgICAgICBhY3RpdmVTdGF0ZTogJ3dhcm5pbmcnLFxuICAgICAgICAgICAgbGFzdEFjdGl2ZVNpbmNlOiB0aGlzLl93YXJuaW5nVGltZSAvIDYwLFxuICAgICAgICAgICAgdGltZXJTdHJpbmc6IHdhcm5pbmdUaW1lclN0cmluZ1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hyb25vbWV0ZXIgZm9yIHdhcm5pbmcgYmVmb3JlIHRpbWVvdXRcbiAgICAgKiBAcGFyYW0gdGltZSBJbnRlZ2VyXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLmdldFdhcm5pbmdUaW1lciA9IGZ1bmN0aW9uIGdldFdhcm5pbmdUaW1lcih0aW1lKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKHRpbWUgLyA2MCkgKyAnbW4nICsgdGltZSAlIDYwICsgJ3MnO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBvdmVybGF5IG9mIHdhcm5pbmcgc3RhdGVcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUucmVtb3ZlV2FybmluZ1N0YXRlID0gZnVuY3Rpb24gcmVtb3ZlV2FybmluZ1N0YXRlKCkge1xuICAgICAgICB0aGlzLl9weWRpby5ub3RpZnkoJ2FjdGl2aXR5X3N0YXRlX2NoYW5nZScsIHtcbiAgICAgICAgICAgIGFjdGl2ZVN0YXRlOiAnYWN0aXZlJ1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXRpbGl0eSB0byBnZXQgdGhlIHRpbWVcbiAgICAgKiBAcmV0dXJucyBJbnRlZ2VyXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLmdldE5vdyA9IGZ1bmN0aW9uIGdldE5vdygpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIEFjdGl2aXR5TW9uaXRvcjtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEFjdGl2aXR5TW9uaXRvcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICogUHVyZSBKYXZhc2NyaXB0IChFUzYpIENvb2tpZSBNYW5hZ2VyIGluc3BpcmVkIGJ5IENvb2tpZUphciB0aGF0IHdhcyByZWx5aW5nIG9uIFByb3RvdHlwZUpTLlxuICpcbiAqIC0tLS1cbiAqIENvb2tpZUpBUiBPcmlnaW5hbCBIZWFkZXJcbiAqXG4gKiBKYXZhc2NyaXB0IGNvZGUgdG8gc3RvcmUgZGF0YSBhcyBKU09OIHN0cmluZ3MgaW4gY29va2llcy4gXG4gKiBJdCB1c2VzIHByb3RvdHlwZS5qcyAxLjUuMSAoaHR0cDovL3d3dy5wcm90b3R5cGVqcy5vcmcpXG4gKiBcbiAqIEF1dGhvciA6IExhbGl0IFBhdGVsXG4gKiBXZWJzaXRlOiBodHRwOi8vd3d3LmxhbGl0Lm9yZy9sYWIvanNvbmNvb2tpZXNcbiAqIExpY2Vuc2U6IENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSAyLjVcbiAqICAgICAgICAgIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzIuNS9cbiAqIFZlcnNpb246IDAuNFxuICogVXBkYXRlZDogQXVnIDExLCAyMDA3IDEwOjA5YW1cbiAqIFxuICogQ2huYWdlIExvZzpcbiAqICAgdiAwLjRcbiAqICAgLSAgUmVtb3ZlZCBhIGV4dHJhIGNvbW1hIGluIG9wdGlvbnMgKHdhcyBicmVha2luZyBpbiBJRSBhbmQgT3BlcmEpLiAoVGhhbmtzIEphc29uKVxuICogICAtICBSZW1vdmVkIHRoZSBwYXJhbWV0ZXIgbmFtZSBmcm9tIHRoZSBpbml0aWFsaXplIGZ1bmN0aW9uXG4gKiAgIC0gIENoYW5nZWQgdGhlIHdheSBleHBpcmVzIGRhdGUgd2FzIGJlaW5nIGNhbGN1bGF0ZWQuIChUaGFua3MgRGF2aWQpXG4gKiAgIHYgMC4zXG4gKiAgIC0gIFJlbW92ZWQgZGVwZW5kYW5jeSBvbiBqc29uLmpzIChodHRwOi8vd3d3Lmpzb24ub3JnL2pzb24uanMpXG4gKiAgIC0gIGVtcHR5KCkgZnVuY3Rpb24gb25seSBkZWxldGVzIHRoZSBjb29raWVzIHNldCBieSBDb29raWVKYXJcbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgQ29va2llc01hbmFnZXIgPSAoZnVuY3Rpb24gKCkge1xuXHRDb29raWVzTWFuYWdlci5zdXBwb3J0ZWQgPSBmdW5jdGlvbiBzdXBwb3J0ZWQoKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50ICYmIGRvY3VtZW50LmNvb2tpZSAhPT0gdW5kZWZpbmVkO1xuXHR9O1xuXG5cdC8qKlxuICAqIEluaXRpYWxpemVzIHRoZSBjb29raWUgamFyIHdpdGggdGhlIG9wdGlvbnMuXG4gICovXG5cblx0ZnVuY3Rpb24gQ29va2llc01hbmFnZXIob3B0aW9ucykge1xuXHRcdF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDb29raWVzTWFuYWdlcik7XG5cblx0XHQvKipcbiAgICogQXBwZW5kIGJlZm9yZSBhbGwgY29va2llIG5hbWVzIHRvIGRpZmZlcm50aWF0ZSB0aGVtLlxuICAgKi9cblx0XHR0aGlzLl9hcHBlbmRTdHJpbmcgPSBcIl9fUFlESU9fX1wiO1xuXG5cdFx0dGhpcy5vcHRpb25zID0ge1xuXHRcdFx0ZXhwaXJlczogMzYwMCwgLy8gc2Vjb25kcyAoMSBocilcblx0XHRcdHBhdGg6ICcnLCAvLyBjb29raWUgcGF0aFxuXHRcdFx0ZG9tYWluOiAnJywgLy8gY29va2llIGRvbWFpblxuXHRcdFx0c2VjdXJlOiAnJyAvLyBzZWN1cmUgP1xuXHRcdH07XG5cdFx0dGhpcy5vcHRpb25zID0gTGFuZ1V0aWxzLm9iamVjdE1lcmdlKHRoaXMub3B0aW9ucywgb3B0aW9ucyB8fCB7fSk7XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLmV4cGlyZXMgIT0gJycpIHtcblx0XHRcdHZhciBkYXRlID0gbmV3IERhdGUoKTtcblx0XHRcdGRhdGUgPSBuZXcgRGF0ZShkYXRlLmdldFRpbWUoKSArIHRoaXMub3B0aW9ucy5leHBpcmVzICogMTAwMCk7XG5cdFx0XHR0aGlzLm9wdGlvbnMuZXhwaXJlcyA9ICc7IGV4cGlyZXM9JyArIGRhdGUudG9HTVRTdHJpbmcoKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5wYXRoICE9ICcnKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMucGF0aCA9ICc7IHBhdGg9JyArIGVuY29kZVVSSSh0aGlzLm9wdGlvbnMucGF0aCk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMuZG9tYWluICE9ICcnKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuZG9tYWluID0gJzsgZG9tYWluPScgKyBlbmNvZGVVUkkodGhpcy5vcHRpb25zLmRvbWFpbik7XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMuc2VjdXJlID09ICdzZWN1cmUnKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuc2VjdXJlID0gJzsgc2VjdXJlJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vcHRpb25zLnNlY3VyZSA9ICcnO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuICAqIEFkZHMgYSBuYW1lIHZhbHVlcyBwYWlyLlxuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5wdXRDb29raWUgPSBmdW5jdGlvbiBwdXRDb29raWUobmFtZSwgdmFsdWUpIHtcblx0XHRuYW1lID0gdGhpcy5fYXBwZW5kU3RyaW5nICsgbmFtZTtcblx0XHR2YXIgY29va2llID0gdGhpcy5vcHRpb25zO1xuXHRcdHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuXHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0Y2FzZSAndW5kZWZpbmVkJzpcblx0XHRcdGNhc2UgJ2Z1bmN0aW9uJzpcblx0XHRcdGNhc2UgJ3Vua25vd24nOlxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRjYXNlICdib29sZWFuJzpcblx0XHRcdGNhc2UgJ3N0cmluZyc6XG5cdFx0XHRjYXNlICdudW1iZXInOlxuXHRcdFx0XHR2YWx1ZSA9IFN0cmluZyh2YWx1ZS50b1N0cmluZygpKTtcblx0XHR9XG5cdFx0dmFyIGNvb2tpZV9zdHIgPSBuYW1lICsgXCI9XCIgKyBlbmNvZGVVUkkoSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcblx0XHR0cnkge1xuXHRcdFx0ZG9jdW1lbnQuY29va2llID0gY29va2llX3N0ciArIGNvb2tpZS5leHBpcmVzICsgY29va2llLnBhdGggKyBjb29raWUuZG9tYWluICsgY29va2llLnNlY3VyZTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJlbW92ZXMgYSBwYXJ0aWN1bGFyIGNvb2tpZSAobmFtZSB2YWx1ZSBwYWlyKSBmb3JtIHRoZSBDb29raWUgSmFyLlxuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5yZW1vdmVDb29raWUgPSBmdW5jdGlvbiByZW1vdmVDb29raWUobmFtZSkge1xuXHRcdG5hbWUgPSB0aGlzLl9hcHBlbmRTdHJpbmcgKyBuYW1lO1xuXHRcdHZhciBjb29raWUgPSB0aGlzLm9wdGlvbnM7XG5cdFx0dHJ5IHtcblx0XHRcdHZhciBkYXRlID0gbmV3IERhdGUoKTtcblx0XHRcdGRhdGUuc2V0VGltZShkYXRlLmdldFRpbWUoKSAtIDM2MDAgKiAxMDAwKTtcblx0XHRcdHZhciBleHBpcmVzID0gJzsgZXhwaXJlcz0nICsgZGF0ZS50b0dNVFN0cmluZygpO1xuXHRcdFx0ZG9jdW1lbnQuY29va2llID0gbmFtZSArIFwiPVwiICsgZXhwaXJlcyArIGNvb2tpZS5wYXRoICsgY29va2llLmRvbWFpbiArIGNvb2tpZS5zZWN1cmU7XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm4gYSBwYXJ0aWN1bGFyIGNvb2tpZSBieSBuYW1lO1xuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5nZXRDb29raWUgPSBmdW5jdGlvbiBnZXRDb29raWUobmFtZSkge1xuXHRcdG5hbWUgPSB0aGlzLl9hcHBlbmRTdHJpbmcgKyBuYW1lO1xuXHRcdHZhciBjb29raWVzID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5hbWUgKyAnPSguKj8pKDt8JCknKTtcblx0XHRpZiAoY29va2llcykge1xuXHRcdFx0cmV0dXJuIEpTT04ucGFyc2UoZGVjb2RlVVJJKGNvb2tpZXNbMV0pKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEVtcHRpZXMgdGhlIENvb2tpZSBKYXIuIERlbGV0ZXMgYWxsIHRoZSBjb29raWVzLlxuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5lbXB0eUFsbCA9IGZ1bmN0aW9uIGVtcHR5QWxsKCkge1xuXHRcdHZhciBrZXlzID0gdGhpcy5nZXRLZXlzKCk7XG5cdFx0dmFyIHNpemUgPSBrZXlzLnNpemUoKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuXHRcdFx0dGhpcy5yZW1vdmVDb29raWUoa2V5c1tpXSk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybnMgYWxsIGNvb2tpZXMgYXMgYSBzaW5nbGUgb2JqZWN0XG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLmdldFBhY2sgPSBmdW5jdGlvbiBnZXRQYWNrKCkge1xuXHRcdHZhciBwYWNrID0ge307XG5cdFx0dmFyIGtleXMgPSB0aGlzLmdldEtleXMoKTtcblxuXHRcdHZhciBzaXplID0ga2V5cy5zaXplKCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcblx0XHRcdHBhY2tba2V5c1tpXV0gPSB0aGlzLmdldChrZXlzW2ldKTtcblx0XHR9XG5cdFx0cmV0dXJuIHBhY2s7XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJucyBhbGwga2V5cy5cbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUuZ2V0S2V5cyA9IGZ1bmN0aW9uIGdldEtleXMoKSB7XG5cdFx0dmFyIGtleXMgPSBbXTtcblx0XHR2YXIga2V5UmUgPSAvW149OyBdKyg/PVxcPSkvZztcblx0XHR2YXIgc3RyID0gZG9jdW1lbnQuY29va2llO1xuXHRcdHZhciBDSlJlID0gbmV3IFJlZ0V4cChcIl5cIiArIHRoaXMuX2FwcGVuZFN0cmluZyk7XG5cdFx0dmFyIG1hdGNoO1xuXHRcdHdoaWxlICgobWF0Y2ggPSBrZXlSZS5leGVjKHN0cikpICE9IHVuZGVmaW5lZCkge1xuXHRcdFx0aWYgKENKUmUudGVzdChtYXRjaFswXS5zdHJpcCgpKSkge1xuXHRcdFx0XHRrZXlzLnB1c2gobWF0Y2hbMF0uc3RyaXAoKS5nc3ViKFwiXlwiICsgdGhpcy5fYXBwZW5kU3RyaW5nLCBcIlwiKSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBrZXlzO1xuXHR9O1xuXG5cdHJldHVybiBDb29raWVzTWFuYWdlcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvb2tpZXNNYW5hZ2VyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBsYW5ndWFnZSBzcGVjaWZpYyBtZXRob2RzXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBET01VdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRE9NVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBET01VdGlscyk7XG4gICAgfVxuXG4gICAgRE9NVXRpbHMuZ2V0QmV6aWVyc1RyYW5zaXRpb24gPSBmdW5jdGlvbiBnZXRCZXppZXJzVHJhbnNpdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICdhbGwgNTUwbXMgY3ViaWMtYmV6aWVyKDAuMjMsIDEsIDAuMzIsIDEpIDBtcyc7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLmdldEJveFNoYWRvd0RlcHRoID0gZnVuY3Rpb24gZ2V0Qm94U2hhZG93RGVwdGgoKSB7XG4gICAgICAgIHZhciBkZXB0aCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IDEgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgcmV0dXJuICcwIDNweCA2cHggcmdiYSgwLCAwLCAwLCAwLjE2KSwgMCAzcHggNnB4IHJnYmEoMCwgMCwgMCwgMC4yMyknO1xuICAgIH07XG5cbiAgICBET01VdGlscy5nZXRVcmxGcm9tQmFzZSA9IGZ1bmN0aW9uIGdldFVybEZyb21CYXNlKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2Jhc2UnKS5sZW5ndGggPyBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnYmFzZScpWzBdLmhyZWYgOiAnJztcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuZ2V0Vmlld3BvcnRXaWR0aCA9IGZ1bmN0aW9uIGdldFZpZXdwb3J0V2lkdGgoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJXaWR0aCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGggfHwgZG9jdW1lbnQuYm9keS5jbGllbnRXaWR0aDtcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuZ2V0Vmlld3BvcnRIZWlnaHQgPSBmdW5jdGlvbiBnZXRWaWV3cG9ydEhlaWdodCgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0IHx8IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0O1xuICAgIH07XG5cbiAgICBET01VdGlscy5pbWFnZUxvYWRlciA9IGZ1bmN0aW9uIGltYWdlTG9hZGVyKGltYWdlVXJsLCBvbkxvYWQsIG9uRXJyb3IpIHtcbiAgICAgICAgdmFyIGxvYWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgICAgICBsb2FkZXIub25sb2FkID0gb25Mb2FkLmJpbmQobG9hZGVyKTtcbiAgICAgICAgbG9hZGVyLm9uZXJyb3IgPSBvbkVycm9yLmJpbmQobG9hZGVyKTtcbiAgICAgICAgbG9hZGVyLnNyYyA9IGltYWdlVXJsO1xuICAgIH07XG5cbiAgICBET01VdGlscy5vYnNlcnZlV2luZG93UmVzaXplID0gZnVuY3Rpb24gb2JzZXJ2ZVdpbmRvd1Jlc2l6ZShjYWxsYmFjaykge1xuICAgICAgICBpZiAod2luZG93LmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCBjYWxsYmFjayk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aW5kb3cuYXR0YWNoRXZlbnQoJ29ucmVzaXplJywgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIERPTVV0aWxzLnN0b3BPYnNlcnZpbmdXaW5kb3dSZXNpemUgPSBmdW5jdGlvbiBzdG9wT2JzZXJ2aW5nV2luZG93UmVzaXplKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICh3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5kZXRhY2hFdmVudCgnb25yZXNpemUnLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIERPTVV0aWxzO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRE9NVXRpbHM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIGxhbmd1YWdlIHNwZWNpZmljIG1ldGhvZHNcbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBGdW5jVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZ1bmNVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEZ1bmNVdGlscyk7XG4gICAgfVxuXG4gICAgRnVuY1V0aWxzLkVtcHR5ID0gZnVuY3Rpb24gRW1wdHkoKSB7fTtcblxuICAgIEZ1bmNVdGlscy5JZGVudGl0eSA9IGZ1bmN0aW9uIElkZW50aXR5KG9iamVjdCkge1xuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH07XG5cbiAgICBGdW5jVXRpbHMuZXhlY3V0ZUZ1bmN0aW9uQnlOYW1lID0gZnVuY3Rpb24gZXhlY3V0ZUZ1bmN0aW9uQnlOYW1lKGZ1bmN0aW9uTmFtZSwgY29udGV4dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgIHZhciBuYW1lc3BhY2VzID0gZnVuY3Rpb25OYW1lLnNwbGl0KFwiLlwiKTtcbiAgICAgICAgdmFyIGZ1bmMgPSBuYW1lc3BhY2VzLnBvcCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzcGFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnRleHQgPSBjb250ZXh0W25hbWVzcGFjZXNbaV1dO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb250ZXh0W2Z1bmNdLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICBGdW5jVXRpbHMuZ2V0RnVuY3Rpb25CeU5hbWUgPSBmdW5jdGlvbiBnZXRGdW5jdGlvbkJ5TmFtZShmdW5jdGlvbk5hbWUsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICB2YXIgbmFtZXNwYWNlcyA9IGZ1bmN0aW9uTmFtZS5zcGxpdChcIi5cIik7XG4gICAgICAgIHZhciBmdW5jID0gbmFtZXNwYWNlcy5wb3AoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lc3BhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoIWNvbnRleHRbbmFtZXNwYWNlc1tpXV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRleHQgPSBjb250ZXh0W25hbWVzcGFjZXNbaV1dO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb250ZXh0W2Z1bmNdO1xuICAgIH07XG5cbiAgICBGdW5jVXRpbHMuYnVmZmVyQ2FsbGJhY2sgPSBmdW5jdGlvbiBidWZmZXJDYWxsYmFjayhuYW1lLCB0aW1lLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAod2luZG93W25hbWVdKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHdpbmRvd1tuYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgd2luZG93W25hbWVdID0gd2luZG93LnNldFRpbWVvdXQoY2FsbGJhY2ssIHRpbWUpO1xuICAgIH07XG5cbiAgICByZXR1cm4gRnVuY1V0aWxzO1xufSkoKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBGdW5jVXRpbHM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgaGFzaGluZyBtZXRob2RzXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBIYXNoZXJVdGlscyA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKlxuICAgICAqIEEgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgUlNBIERhdGEgU2VjdXJpdHksIEluYy4gTUQ1IE1lc3NhZ2VcbiAgICAgKiBEaWdlc3QgQWxnb3JpdGhtLCBhcyBkZWZpbmVkIGluIFJGQyAxMzIxLlxuICAgICAqIFZlcnNpb24gMi4xIENvcHlyaWdodCAoQykgUGF1bCBKb2huc3RvbiAxOTk5IC0gMjAwMi5cbiAgICAgKiBPdGhlciBjb250cmlidXRvcnM6IEdyZWcgSG9sdCwgQW5kcmV3IEtlcGVydCwgWWRuYXIsIExvc3RpbmV0XG4gICAgICogRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIEJTRCBMaWNlbnNlXG4gICAgICogU2VlIGh0dHA6Ly9wYWpob21lLm9yZy51ay9jcnlwdC9tZDUgZm9yIG1vcmUgaW5mby5cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIEhhc2hlclV0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSGFzaGVyVXRpbHMpO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogQ29uZmlndXJhYmxlIHZhcmlhYmxlcy4gWW91IG1heSBuZWVkIHRvIHR3ZWFrIHRoZXNlIHRvIGJlIGNvbXBhdGlibGUgd2l0aFxuICAgICAqIHRoZSBzZXJ2ZXItc2lkZSwgYnV0IHRoZSBkZWZhdWx0cyB3b3JrIGluIG1vc3QgY2FzZXMuXG4gICAgICovXG5cbiAgICAvKlxuICAgICAqIFRoZXNlIGFyZSB0aGUgZnVuY3Rpb25zIHlvdSdsbCB1c3VhbGx5IHdhbnQgdG8gY2FsbFxuICAgICAqIFRoZXkgdGFrZSBzdHJpbmcgYXJndW1lbnRzIGFuZCByZXR1cm4gZWl0aGVyIGhleCBvciBiYXNlLTY0IGVuY29kZWQgc3RyaW5nc1xuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuaGV4X21kNSA9IGZ1bmN0aW9uIGhleF9tZDUocykge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJoZXgoSGFzaGVyVXRpbHMuY29yZV9tZDUoSGFzaGVyVXRpbHMuc3RyMmJpbmwocyksIHMubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3opKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuYjY0X21kNSA9IGZ1bmN0aW9uIGI2NF9tZDUocykge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJiNjQoSGFzaGVyVXRpbHMuY29yZV9tZDUoSGFzaGVyVXRpbHMuc3RyMmJpbmwocyksIHMubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3opKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuc3RyX21kNSA9IGZ1bmN0aW9uIHN0cl9tZDUocykge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJzdHIoSGFzaGVyVXRpbHMuY29yZV9tZDUoSGFzaGVyVXRpbHMuc3RyMmJpbmwocyksIHMubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3opKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuaGV4X2htYWNfbWQ1ID0gZnVuY3Rpb24gaGV4X2htYWNfbWQ1KGtleSwgZGF0YSkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJoZXgoSGFzaGVyVXRpbHMuY29yZV9obWFjX21kNShrZXksIGRhdGEpKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuYjY0X2htYWNfbWQ1ID0gZnVuY3Rpb24gYjY0X2htYWNfbWQ1KGtleSwgZGF0YSkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJiNjQoSGFzaGVyVXRpbHMuY29yZV9obWFjX21kNShrZXksIGRhdGEpKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuc3RyX2htYWNfbWQ1ID0gZnVuY3Rpb24gc3RyX2htYWNfbWQ1KGtleSwgZGF0YSkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuYmlubDJzdHIoSGFzaGVyVXRpbHMuY29yZV9obWFjX21kNShrZXksIGRhdGEpKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMuYmFzZTY0X2VuY29kZSA9IGZ1bmN0aW9uIGJhc2U2NF9lbmNvZGUoZGF0YSkge1xuICAgICAgICAvLyBodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldFxuICAgICAgICAvLyArICAgb3JpZ2luYWwgYnk6IFR5bGVyIEFraW5zIChodHRwOi8vcnVta2luLmNvbSlcbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBCYXlyb24gR3VldmFyYVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IFRodW5kZXIubVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IEtldmluIHZhbiBab25uZXZlbGQgKGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0KVxuICAgICAgICAvLyArICAgYnVnZml4ZWQgYnk6IFBlbGxlbnRlc3F1ZSBNYWxlc3VhZGFcbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBLZXZpbiB2YW4gWm9ubmV2ZWxkIChodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldClcbiAgICAgICAgLy8gLSAgICBkZXBlbmRzIG9uOiB1dGY4X2VuY29kZVxuICAgICAgICAvLyAqICAgICBleGFtcGxlIDE6IGJhc2U2NF9lbmNvZGUoJ0tldmluIHZhbiBab25uZXZlbGQnKTtcbiAgICAgICAgLy8gKiAgICAgcmV0dXJucyAxOiAnUzJWMmFXNGdkbUZ1SUZwdmJtNWxkbVZzWkE9PSdcblxuICAgICAgICAvLyBtb3ppbGxhIGhhcyB0aGlzIG5hdGl2ZVxuICAgICAgICAvLyAtIGJ1dCBicmVha3MgaW4gMi4wLjAuMTIhXG4gICAgICAgIC8vaWYgKHR5cGVvZiB3aW5kb3dbJ2F0b2InXSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vICAgIHJldHVybiBhdG9iKGRhdGEpO1xuICAgICAgICAvL31cblxuICAgICAgICB2YXIgYjY0ID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPVwiO1xuICAgICAgICB2YXIgbzEsXG4gICAgICAgICAgICBvMixcbiAgICAgICAgICAgIG8zLFxuICAgICAgICAgICAgaDEsXG4gICAgICAgICAgICBoMixcbiAgICAgICAgICAgIGgzLFxuICAgICAgICAgICAgaDQsXG4gICAgICAgICAgICBiaXRzLFxuICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICBhYyA9IDAsXG4gICAgICAgICAgICBlbmMsXG4gICAgICAgICAgICB0bXBfYXJyID0gW107XG5cbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGEgPSBIYXNoZXJVdGlscy51dGY4X2VuY29kZShkYXRhICsgJycpO1xuXG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIC8vIHBhY2sgdGhyZWUgb2N0ZXRzIGludG8gZm91ciBoZXhldHNcbiAgICAgICAgICAgIG8xID0gZGF0YS5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgICAgICBvMiA9IGRhdGEuY2hhckNvZGVBdChpKyspO1xuICAgICAgICAgICAgbzMgPSBkYXRhLmNoYXJDb2RlQXQoaSsrKTtcblxuICAgICAgICAgICAgYml0cyA9IG8xIDw8IDE2IHwgbzIgPDwgOCB8IG8zO1xuXG4gICAgICAgICAgICBoMSA9IGJpdHMgPj4gMTggJiAweDNmO1xuICAgICAgICAgICAgaDIgPSBiaXRzID4+IDEyICYgMHgzZjtcbiAgICAgICAgICAgIGgzID0gYml0cyA+PiA2ICYgMHgzZjtcbiAgICAgICAgICAgIGg0ID0gYml0cyAmIDB4M2Y7XG5cbiAgICAgICAgICAgIC8vIHVzZSBoZXhldHMgdG8gaW5kZXggaW50byBiNjQsIGFuZCBhcHBlbmQgcmVzdWx0IHRvIGVuY29kZWQgc3RyaW5nXG4gICAgICAgICAgICB0bXBfYXJyW2FjKytdID0gYjY0LmNoYXJBdChoMSkgKyBiNjQuY2hhckF0KGgyKSArIGI2NC5jaGFyQXQoaDMpICsgYjY0LmNoYXJBdChoNCk7XG4gICAgICAgIH0gd2hpbGUgKGkgPCBkYXRhLmxlbmd0aCk7XG5cbiAgICAgICAgZW5jID0gdG1wX2Fyci5qb2luKCcnKTtcblxuICAgICAgICBzd2l0Y2ggKGRhdGEubGVuZ3RoICUgMykge1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGVuYyA9IGVuYy5zbGljZSgwLCAtMikgKyAnPT0nO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGVuYyA9IGVuYy5zbGljZSgwLCAtMSkgKyAnPSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZW5jO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy51dGY4X2VuY29kZSA9IGZ1bmN0aW9uIHV0ZjhfZW5jb2RlKHN0cmluZykge1xuICAgICAgICAvLyBodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldFxuICAgICAgICAvLyArICAgb3JpZ2luYWwgYnk6IFdlYnRvb2xraXQuaW5mbyAoaHR0cDovL3d3dy53ZWJ0b29sa2l0LmluZm8vKVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IEtldmluIHZhbiBab25uZXZlbGQgKGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0KVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IHNvd2JlcnJ5XG4gICAgICAgIC8vICsgICAgdHdlYWtlZCBieTogSmFja1xuICAgICAgICAvLyArICAgYnVnZml4ZWQgYnk6IE9ubm8gTWFyc21hblxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IFl2ZXMgU3VjYWV0XG4gICAgICAgIC8vICsgICBidWdmaXhlZCBieTogT25ubyBNYXJzbWFuXG4gICAgICAgIC8vICogICAgIGV4YW1wbGUgMTogdXRmOF9lbmNvZGUoJ0tldmluIHZhbiBab25uZXZlbGQnKTtcbiAgICAgICAgLy8gKiAgICAgcmV0dXJucyAxOiAnS2V2aW4gdmFuIFpvbm5ldmVsZCdcblxuICAgICAgICBzdHJpbmcgPSAoc3RyaW5nICsgJycpLnJlcGxhY2UoL1xcclxcbi9nLCBcIlxcblwiKS5yZXBsYWNlKC9cXHIvZywgXCJcXG5cIik7XG5cbiAgICAgICAgdmFyIHV0ZnRleHQgPSBcIlwiO1xuICAgICAgICB2YXIgc3RhcnQsIGVuZDtcbiAgICAgICAgdmFyIHN0cmluZ2w7XG5cbiAgICAgICAgc3RhcnQgPSBlbmQgPSAwO1xuICAgICAgICBzdHJpbmdsID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgbiA9IDA7IG4gPCBzdHJpbmdsOyBuKyspIHtcbiAgICAgICAgICAgIHZhciBjMSA9IHN0cmluZy5jaGFyQ29kZUF0KG4pO1xuICAgICAgICAgICAgdmFyIGVuYyA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmIChjMSA8IDEyOCkge1xuICAgICAgICAgICAgICAgIGVuZCsrO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjMSA+IDEyNyAmJiBjMSA8IDIwNDgpIHtcbiAgICAgICAgICAgICAgICBlbmMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxID4+IDYgfCAxOTIpICsgU3RyaW5nLmZyb21DaGFyQ29kZShjMSAmIDYzIHwgMTI4KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZW5jID0gU3RyaW5nLmZyb21DaGFyQ29kZShjMSA+PiAxMiB8IDIyNCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxID4+IDYgJiA2MyB8IDEyOCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxICYgNjMgfCAxMjgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVuYyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVuZCA+IHN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgIHV0ZnRleHQgKz0gc3RyaW5nLnN1YnN0cmluZyhzdGFydCwgZW5kKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdXRmdGV4dCArPSBlbmM7XG4gICAgICAgICAgICAgICAgc3RhcnQgPSBlbmQgPSBuICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlbmQgPiBzdGFydCkge1xuICAgICAgICAgICAgdXRmdGV4dCArPSBzdHJpbmcuc3Vic3RyaW5nKHN0YXJ0LCBzdHJpbmcubGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1dGZ0ZXh0O1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIFBlcmZvcm0gYSBzaW1wbGUgc2VsZi10ZXN0IHRvIHNlZSBpZiB0aGUgVk0gaXMgd29ya2luZ1xuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X3ZtX3Rlc3QgPSBmdW5jdGlvbiBtZDVfdm1fdGVzdCgpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmhleF9tZDUoXCJhYmNcIikgPT0gXCI5MDAxNTA5ODNjZDI0ZmIwZDY5NjNmN2QyOGUxN2Y3MlwiO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgTUQ1IG9mIGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMsIGFuZCBhIGJpdCBsZW5ndGhcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmNvcmVfbWQ1ID0gZnVuY3Rpb24gY29yZV9tZDUoeCwgbGVuKSB7XG4gICAgICAgIC8qIGFwcGVuZCBwYWRkaW5nICovXG4gICAgICAgIHhbbGVuID4+IDVdIHw9IDB4ODAgPDwgbGVuICUgMzI7XG4gICAgICAgIHhbKGxlbiArIDY0ID4+PiA5IDw8IDQpICsgMTRdID0gbGVuO1xuXG4gICAgICAgIHZhciBhID0gMTczMjU4NDE5MztcbiAgICAgICAgdmFyIGIgPSAtMjcxNzMzODc5O1xuICAgICAgICB2YXIgYyA9IC0xNzMyNTg0MTk0O1xuICAgICAgICB2YXIgZCA9IDI3MTczMzg3ODtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHgubGVuZ3RoOyBpICs9IDE2KSB7XG4gICAgICAgICAgICB2YXIgb2xkYSA9IGE7XG4gICAgICAgICAgICB2YXIgb2xkYiA9IGI7XG4gICAgICAgICAgICB2YXIgb2xkYyA9IGM7XG4gICAgICAgICAgICB2YXIgb2xkZCA9IGQ7XG5cbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZmYoYSwgYiwgYywgZCwgeFtpICsgMF0sIDcsIC02ODA4NzY5MzYpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9mZihkLCBhLCBiLCBjLCB4W2kgKyAxXSwgMTIsIC0zODk1NjQ1ODYpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9mZihjLCBkLCBhLCBiLCB4W2kgKyAyXSwgMTcsIDYwNjEwNTgxOSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGIsIGMsIGQsIGEsIHhbaSArIDNdLCAyMiwgLTEwNDQ1MjUzMzApO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9mZihhLCBiLCBjLCBkLCB4W2kgKyA0XSwgNywgLTE3NjQxODg5Nyk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGQsIGEsIGIsIGMsIHhbaSArIDVdLCAxMiwgMTIwMDA4MDQyNik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGMsIGQsIGEsIGIsIHhbaSArIDZdLCAxNywgLTE0NzMyMzEzNDEpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9mZihiLCBjLCBkLCBhLCB4W2kgKyA3XSwgMjIsIC00NTcwNTk4Myk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGEsIGIsIGMsIGQsIHhbaSArIDhdLCA3LCAxNzcwMDM1NDE2KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZmYoZCwgYSwgYiwgYywgeFtpICsgOV0sIDEyLCAtMTk1ODQxNDQxNyk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGMsIGQsIGEsIGIsIHhbaSArIDEwXSwgMTcsIC00MjA2Myk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGIsIGMsIGQsIGEsIHhbaSArIDExXSwgMjIsIC0xOTkwNDA0MTYyKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZmYoYSwgYiwgYywgZCwgeFtpICsgMTJdLCA3LCAxODA0NjAzNjgyKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZmYoZCwgYSwgYiwgYywgeFtpICsgMTNdLCAxMiwgLTQwMzQxMTAxKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZmYoYywgZCwgYSwgYiwgeFtpICsgMTRdLCAxNywgLTE1MDIwMDIyOTApO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9mZihiLCBjLCBkLCBhLCB4W2kgKyAxNV0sIDIyLCAxMjM2NTM1MzI5KTtcblxuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9nZyhhLCBiLCBjLCBkLCB4W2kgKyAxXSwgNSwgLTE2NTc5NjUxMCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2dnKGQsIGEsIGIsIGMsIHhbaSArIDZdLCA5LCAtMTA2OTUwMTYzMik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2dnKGMsIGQsIGEsIGIsIHhbaSArIDExXSwgMTQsIDY0MzcxNzcxMyk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2dnKGIsIGMsIGQsIGEsIHhbaSArIDBdLCAyMCwgLTM3Mzg5NzMwMik7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2dnKGEsIGIsIGMsIGQsIHhbaSArIDVdLCA1LCAtNzAxNTU4NjkxKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZ2coZCwgYSwgYiwgYywgeFtpICsgMTBdLCA5LCAzODAxNjA4Myk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2dnKGMsIGQsIGEsIGIsIHhbaSArIDE1XSwgMTQsIC02NjA0NzgzMzUpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9nZyhiLCBjLCBkLCBhLCB4W2kgKyA0XSwgMjAsIC00MDU1Mzc4NDgpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9nZyhhLCBiLCBjLCBkLCB4W2kgKyA5XSwgNSwgNTY4NDQ2NDM4KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZ2coZCwgYSwgYiwgYywgeFtpICsgMTRdLCA5LCAtMTAxOTgwMzY5MCk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2dnKGMsIGQsIGEsIGIsIHhbaSArIDNdLCAxNCwgLTE4NzM2Mzk2MSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2dnKGIsIGMsIGQsIGEsIHhbaSArIDhdLCAyMCwgMTE2MzUzMTUwMSk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2dnKGEsIGIsIGMsIGQsIHhbaSArIDEzXSwgNSwgLTE0NDQ2ODE0NjcpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9nZyhkLCBhLCBiLCBjLCB4W2kgKyAyXSwgOSwgLTUxNDAzNzg0KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZ2coYywgZCwgYSwgYiwgeFtpICsgN10sIDE0LCAxNzM1MzI4NDczKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZ2coYiwgYywgZCwgYSwgeFtpICsgMTJdLCAyMCwgLTE5MjY2MDc3MzQpO1xuXG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2hoKGEsIGIsIGMsIGQsIHhbaSArIDVdLCA0LCAtMzc4NTU4KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaGgoZCwgYSwgYiwgYywgeFtpICsgOF0sIDExLCAtMjAyMjU3NDQ2Myk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2hoKGMsIGQsIGEsIGIsIHhbaSArIDExXSwgMTYsIDE4MzkwMzA1NjIpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9oaChiLCBjLCBkLCBhLCB4W2kgKyAxNF0sIDIzLCAtMzUzMDk1NTYpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9oaChhLCBiLCBjLCBkLCB4W2kgKyAxXSwgNCwgLTE1MzA5OTIwNjApO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9oaChkLCBhLCBiLCBjLCB4W2kgKyA0XSwgMTEsIDEyNzI4OTMzNTMpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9oaChjLCBkLCBhLCBiLCB4W2kgKyA3XSwgMTYsIC0xNTU0OTc2MzIpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9oaChiLCBjLCBkLCBhLCB4W2kgKyAxMF0sIDIzLCAtMTA5NDczMDY0MCk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2hoKGEsIGIsIGMsIGQsIHhbaSArIDEzXSwgNCwgNjgxMjc5MTc0KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaGgoZCwgYSwgYiwgYywgeFtpICsgMF0sIDExLCAtMzU4NTM3MjIyKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaGgoYywgZCwgYSwgYiwgeFtpICsgM10sIDE2LCAtNzIyNTIxOTc5KTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaGgoYiwgYywgZCwgYSwgeFtpICsgNl0sIDIzLCA3NjAyOTE4OSk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2hoKGEsIGIsIGMsIGQsIHhbaSArIDldLCA0LCAtNjQwMzY0NDg3KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaGgoZCwgYSwgYiwgYywgeFtpICsgMTJdLCAxMSwgLTQyMTgxNTgzNSk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2hoKGMsIGQsIGEsIGIsIHhbaSArIDE1XSwgMTYsIDUzMDc0MjUyMCk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2hoKGIsIGMsIGQsIGEsIHhbaSArIDJdLCAyMywgLTk5NTMzODY1MSk7XG5cbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaWkoYSwgYiwgYywgZCwgeFtpICsgMF0sIDYsIC0xOTg2MzA4NDQpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9paShkLCBhLCBiLCBjLCB4W2kgKyA3XSwgMTAsIDExMjY4OTE0MTUpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9paShjLCBkLCBhLCBiLCB4W2kgKyAxNF0sIDE1LCAtMTQxNjM1NDkwNSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2lpKGIsIGMsIGQsIGEsIHhbaSArIDVdLCAyMSwgLTU3NDM0MDU1KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaWkoYSwgYiwgYywgZCwgeFtpICsgMTJdLCA2LCAxNzAwNDg1NTcxKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaWkoZCwgYSwgYiwgYywgeFtpICsgM10sIDEwLCAtMTg5NDk4NjYwNik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2lpKGMsIGQsIGEsIGIsIHhbaSArIDEwXSwgMTUsIC0xMDUxNTIzKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaWkoYiwgYywgZCwgYSwgeFtpICsgMV0sIDIxLCAtMjA1NDkyMjc5OSk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2lpKGEsIGIsIGMsIGQsIHhbaSArIDhdLCA2LCAxODczMzEzMzU5KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaWkoZCwgYSwgYiwgYywgeFtpICsgMTVdLCAxMCwgLTMwNjExNzQ0KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaWkoYywgZCwgYSwgYiwgeFtpICsgNl0sIDE1LCAtMTU2MDE5ODM4MCk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2lpKGIsIGMsIGQsIGEsIHhbaSArIDEzXSwgMjEsIDEzMDkxNTE2NDkpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9paShhLCBiLCBjLCBkLCB4W2kgKyA0XSwgNiwgLTE0NTUyMzA3MCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2lpKGQsIGEsIGIsIGMsIHhbaSArIDExXSwgMTAsIC0xMTIwMjEwMzc5KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaWkoYywgZCwgYSwgYiwgeFtpICsgMl0sIDE1LCA3MTg3ODcyNTkpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9paShiLCBjLCBkLCBhLCB4W2kgKyA5XSwgMjEsIC0zNDM0ODU1NTEpO1xuXG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMuc2FmZV9hZGQoYSwgb2xkYSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMuc2FmZV9hZGQoYiwgb2xkYik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMuc2FmZV9hZGQoYywgb2xkYyk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMuc2FmZV9hZGQoZCwgb2xkZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFthLCBiLCBjLCBkXTtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBUaGVzZSBmdW5jdGlvbnMgaW1wbGVtZW50IHRoZSBmb3VyIGJhc2ljIG9wZXJhdGlvbnMgdGhlIGFsZ29yaXRobSB1c2VzLlxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X2NtbiA9IGZ1bmN0aW9uIG1kNV9jbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuc2FmZV9hZGQoSGFzaGVyVXRpbHMuYml0X3JvbChIYXNoZXJVdGlscy5zYWZlX2FkZChIYXNoZXJVdGlscy5zYWZlX2FkZChhLCBxKSwgSGFzaGVyVXRpbHMuc2FmZV9hZGQoeCwgdCkpLCBzKSwgYik7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLm1kNV9mZiA9IGZ1bmN0aW9uIG1kNV9mZihhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5tZDVfY21uKGIgJiBjIHwgfmIgJiBkLCBhLCBiLCB4LCBzLCB0KTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X2dnID0gZnVuY3Rpb24gbWQ1X2dnKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLm1kNV9jbW4oYiAmIGQgfCBjICYgfmQsIGEsIGIsIHgsIHMsIHQpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5tZDVfaGggPSBmdW5jdGlvbiBtZDVfaGgoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMubWQ1X2NtbihiIF4gYyBeIGQsIGEsIGIsIHgsIHMsIHQpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5tZDVfaWkgPSBmdW5jdGlvbiBtZDVfaWkoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMubWQ1X2NtbihjIF4gKGIgfCB+ZCksIGEsIGIsIHgsIHMsIHQpO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgSE1BQy1NRDUsIG9mIGEga2V5IGFuZCBzb21lIGRhdGFcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmNvcmVfaG1hY19tZDUgPSBmdW5jdGlvbiBjb3JlX2htYWNfbWQ1KGtleSwgZGF0YSkge1xuICAgICAgICB2YXIgYmtleSA9IEhhc2hlclV0aWxzLnN0cjJiaW5sKGtleSk7XG4gICAgICAgIGlmIChia2V5Lmxlbmd0aCA+IDE2KSBia2V5ID0gSGFzaGVyVXRpbHMuY29yZV9tZDUoYmtleSwga2V5Lmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6KTtcblxuICAgICAgICB2YXIgaXBhZCA9IG5ldyBBcnJheSgxNiksXG4gICAgICAgICAgICBvcGFkID0gbmV3IEFycmF5KDE2KTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICAgICAgICBpcGFkW2ldID0gYmtleVtpXSBeIDB4MzYzNjM2MzY7XG4gICAgICAgICAgICBvcGFkW2ldID0gYmtleVtpXSBeIDB4NUM1QzVDNUM7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaGFzaCA9IEhhc2hlclV0aWxzLmNvcmVfbWQ1KGlwYWQuY29uY2F0KEhhc2hlclV0aWxzLnN0cjJiaW5sKGRhdGEpKSwgNTEyICsgZGF0YS5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzeik7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5jb3JlX21kNShvcGFkLmNvbmNhdChoYXNoKSwgNTEyICsgMTI4KTtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBBZGQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeMzIuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9ucyBpbnRlcm5hbGx5XG4gICAgICogdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLnNhZmVfYWRkID0gZnVuY3Rpb24gc2FmZV9hZGQoeCwgeSkge1xuICAgICAgICB2YXIgbHN3ID0gKHggJiAweEZGRkYpICsgKHkgJiAweEZGRkYpO1xuICAgICAgICB2YXIgbXN3ID0gKHggPj4gMTYpICsgKHkgPj4gMTYpICsgKGxzdyA+PiAxNik7XG4gICAgICAgIHJldHVybiBtc3cgPDwgMTYgfCBsc3cgJiAweEZGRkY7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQml0d2lzZSByb3RhdGUgYSAzMi1iaXQgbnVtYmVyIHRvIHRoZSBsZWZ0LlxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuYml0X3JvbCA9IGZ1bmN0aW9uIGJpdF9yb2wobnVtLCBjbnQpIHtcbiAgICAgICAgcmV0dXJuIG51bSA8PCBjbnQgfCBudW0gPj4+IDMyIC0gY250O1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYSBzdHJpbmcgdG8gYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3Jkc1xuICAgICAqIElmIEhhc2hlclV0aWxzLmNocnN6IGlzIEFTQ0lJLCBjaGFyYWN0ZXJzID4yNTUgaGF2ZSB0aGVpciBoaS1ieXRlIHNpbGVudGx5IGlnbm9yZWQuXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5zdHIyYmlubCA9IGZ1bmN0aW9uIHN0cjJiaW5sKHN0cikge1xuICAgICAgICB2YXIgYmluID0gW107XG4gICAgICAgIHZhciBtYXNrID0gKDEgPDwgSGFzaGVyVXRpbHMuY2hyc3opIC0gMTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3o7IGkgKz0gSGFzaGVyVXRpbHMuY2hyc3opIGJpbltpID4+IDVdIHw9IChzdHIuY2hhckNvZGVBdChpIC8gSGFzaGVyVXRpbHMuY2hyc3opICYgbWFzaykgPDwgaSAlIDMyO1xuICAgICAgICByZXR1cm4gYmluO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3JkcyB0byBhIHN0cmluZ1xuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuYmlubDJzdHIgPSBmdW5jdGlvbiBiaW5sMnN0cihiaW4pIHtcbiAgICAgICAgdmFyIHN0ciA9IFwiXCI7XG4gICAgICAgIHZhciBtYXNrID0gKDEgPDwgSGFzaGVyVXRpbHMuY2hyc3opIC0gMTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiaW4ubGVuZ3RoICogMzI7IGkgKz0gSGFzaGVyVXRpbHMuY2hyc3opIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJpbltpID4+IDVdID4+PiBpICUgMzIgJiBtYXNrKTtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMgdG8gYSBoZXggc3RyaW5nLlxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuYmlubDJoZXggPSBmdW5jdGlvbiBiaW5sMmhleChiaW5hcnJheSkge1xuICAgICAgICB2YXIgaGV4X3RhYiA9IEhhc2hlclV0aWxzLmhleGNhc2UgPyBcIjAxMjM0NTY3ODlBQkNERUZcIiA6IFwiMDEyMzQ1Njc4OWFiY2RlZlwiO1xuICAgICAgICB2YXIgc3RyID0gXCJcIjtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiaW5hcnJheS5sZW5ndGggKiA0OyBpKyspIHtcbiAgICAgICAgICAgIHN0ciArPSBoZXhfdGFiLmNoYXJBdChiaW5hcnJheVtpID4+IDJdID4+IGkgJSA0ICogOCArIDQgJiAweEYpICsgaGV4X3RhYi5jaGFyQXQoYmluYXJyYXlbaSA+PiAyXSA+PiBpICUgNCAqIDggJiAweEYpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzIHRvIGEgYmFzZS02NCBzdHJpbmdcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmJpbmwyYjY0ID0gZnVuY3Rpb24gYmlubDJiNjQoYmluYXJyYXkpIHtcbiAgICAgICAgdmFyIHRhYiA9IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL1wiO1xuICAgICAgICB2YXIgc3RyID0gXCJcIjtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiaW5hcnJheS5sZW5ndGggKiA0OyBpICs9IDMpIHtcbiAgICAgICAgICAgIHZhciB0cmlwbGV0ID0gKGJpbmFycmF5W2kgPj4gMl0gPj4gOCAqIChpICUgNCkgJiAweEZGKSA8PCAxNiB8IChiaW5hcnJheVtpICsgMSA+PiAyXSA+PiA4ICogKChpICsgMSkgJSA0KSAmIDB4RkYpIDw8IDggfCBiaW5hcnJheVtpICsgMiA+PiAyXSA+PiA4ICogKChpICsgMikgJSA0KSAmIDB4RkY7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKykge1xuICAgICAgICAgICAgICAgIGlmIChpICogOCArIGogKiA2ID4gYmluYXJyYXkubGVuZ3RoICogMzIpIHN0ciArPSBIYXNoZXJVdGlscy5iNjRwYWQ7ZWxzZSBzdHIgKz0gdGFiLmNoYXJBdCh0cmlwbGV0ID4+IDYgKiAoMyAtIGopICYgMHgzRik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgcmV0dXJuIEhhc2hlclV0aWxzO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gSGFzaGVyVXRpbHM7XG5IYXNoZXJVdGlscy5oZXhjYXNlID0gMDsgLyogaGV4IG91dHB1dCBmb3JtYXQuIDAgLSBsb3dlcmNhc2U7IDEgLSB1cHBlcmNhc2UgICAgICAgICovXG5IYXNoZXJVdGlscy5iNjRwYWQgPSBcIlwiOyAvKiBiYXNlLTY0IHBhZCBjaGFyYWN0ZXIuIFwiPVwiIGZvciBzdHJpY3QgUkZDIGNvbXBsaWFuY2UgICAqL1xuSGFzaGVyVXRpbHMuY2hyc3ogPSA4OyAvKiBiaXRzIHBlciBpbnB1dCBjaGFyYWN0ZXIuIDggLSBBU0NJSTsgMTYgLSBVbmljb2RlICAgICAgKi9cbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgbGFuZ3VhZ2Ugc3BlY2lmaWMgbWV0aG9kc1xuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgTGFuZ1V0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMYW5nVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBMYW5nVXRpbHMpO1xuICAgIH1cblxuICAgIExhbmdVdGlscy5hcnJheVdpdGhvdXQgPSBmdW5jdGlvbiBhcnJheVdpdGhvdXQoYXJyYXksIGtleSkge1xuICAgICAgICBpZiAoIWFycmF5Lmxlbmd0aCkgcmV0dXJuIGFycmF5O1xuICAgICAgICBpZiAoa2V5ID49IGFycmF5Lmxlbmd0aCkgcmV0dXJuIGFycmF5O1xuICAgICAgICB2YXIgbmV3QXJyYXk7XG4gICAgICAgIGlmIChrZXkgPT0gMCkgbmV3QXJyYXkgPSBhcnJheS5zbGljZSgxKTtlbHNlIGlmIChrZXkgPT0gYXJyYXkubGVuZ3RoIC0gMSkgbmV3QXJyYXkgPSBhcnJheS5zbGljZSgwLCAtMSk7ZWxzZSBuZXdBcnJheSA9IGFycmF5LnNsaWNlKDAsIGtleSkuY29uY2F0KGFycmF5LnNsaWNlKGtleSArIDEpKTtcbiAgICAgICAgcmV0dXJuIG5ld0FycmF5O1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMub2JqZWN0TWVyZ2UgPSBmdW5jdGlvbiBvYmplY3RNZXJnZShvYmoxLCBvYmoyKSB7XG4gICAgICAgIHJldHVybiBfZXh0ZW5kcyh7fSwgb2JqMSwgb2JqMik7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5wYXJzZVVybCA9IGZ1bmN0aW9uIHBhcnNlVXJsKGRhdGEpIHtcbiAgICAgICAgdmFyIG1hdGNoZXMgPSBbXTtcbiAgICAgICAgLy92YXIgZT0vKChodHRwfGZ0cCk6XFwvKT9cXC8/KFteOlxcL1xcc10rKSgoXFwvXFx3KykqXFwvKShbXFx3XFwtXFwuXStcXC5bXiM/XFxzXSspKCNbXFx3XFwtXSspPy87XG4gICAgICAgIHZhciBkZXRlY3QgPSAvKHB5ZGlvOlxcLyk/XFwvPyhbXjpcXC9cXHNdKykoKFxcL1xcdyspKlxcLykoLiopKCNbXFx3XFwtXSspPy9nO1xuICAgICAgICB2YXIgcmVzdWx0cyA9IGRhdGEubWF0Y2goZGV0ZWN0KTtcbiAgICAgICAgaWYgKHJlc3VsdHMgJiYgcmVzdWx0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBlID0gL14oKHB5ZGlvKTpcXC8pP1xcLz8oW146XFwvXFxzXSspKChcXC9cXHcrKSpcXC8pKC4qKSgjW1xcd1xcLV0rKT8kLztcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChyZXN1bHRzW2ldLm1hdGNoKGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaCh7IHVybDogUmVnRXhwWyckJiddLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdG9jb2w6IFJlZ0V4cC4kMixcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvc3Q6IFJlZ0V4cC4kMyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGg6IFJlZ0V4cC4kNCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU6IFJlZ0V4cC4kNixcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc2g6IFJlZ0V4cC4kNyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hdGNoZXM7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5jb21wdXRlU3RyaW5nU2x1ZyA9IGZ1bmN0aW9uIGNvbXB1dGVTdHJpbmdTbHVnKHZhbHVlKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBMYW5nVXRpbHMuc2x1Z1RhYmxlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoTGFuZ1V0aWxzLnNsdWdUYWJsZVtpXS5yZSwgTGFuZ1V0aWxzLnNsdWdUYWJsZVtpXS5jaCk7XG5cbiAgICAgICAgLy8gMSkgbWV0IGVuIGJhcyBkZSBjYXNzZVxuICAgICAgICAvLyAyKSByZW1wbGFjZSBsZXMgZXNwYWNlIHBhciBkZXMgdGlyZXRzXG4gICAgICAgIC8vIDMpIGVubGV2ZSB0b3V0IGxlcyBjYXJhdMOocmVzIG5vbiBhbHBoYW51bWVyaXF1ZXNcbiAgICAgICAgLy8gNCkgZW5sw6h2ZSBsZXMgZG91YmxlcyB0aXJldHNcbiAgICAgICAgcmV0dXJuIHZhbHVlLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzKy9nLCAnLScpLnJlcGxhY2UoL1teYS16MC05LV0vZywgJycpLnJlcGxhY2UoL1xcLXsyLH0vZywgJy0nKTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLmZvcmNlSlNPTkFycmF5VG9PYmplY3QgPSBmdW5jdGlvbiBmb3JjZUpTT05BcnJheVRvT2JqZWN0KGNvbnRhaW5lciwgdmFsdWUpIHtcbiAgICAgICAgaWYgKGNvbnRhaW5lclt2YWx1ZV0gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgLy8gQ2xvbmVcbiAgICAgICAgICAgIHZhciBjb3B5ID0gY29udGFpbmVyW3ZhbHVlXS5zbGljZSgwKTtcbiAgICAgICAgICAgIGNvbnRhaW5lclt2YWx1ZV0gPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29weS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lclt2YWx1ZV1baV0gPSBjb3B5W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5kZWVwQ29weSA9IGZ1bmN0aW9uIGRlZXBDb3B5KHNvdXJjZSkge1xuICAgICAgICByZXR1cm4gTGFuZ1V0aWxzLm1lcmdlT2JqZWN0c1JlY3Vyc2l2ZSh7fSwgc291cmNlKTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLnNpbXBsZUNvcHkgPSBmdW5jdGlvbiBzaW1wbGVDb3B5KHNvdXJjZSkge1xuICAgICAgICB2YXIgY29weSA9IHt9O1xuICAgICAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiBzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgY29weVtwcm9wZXJ0eV0gPSBzb3VyY2VbcHJvcGVydHldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb3B5O1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMubWVyZ2VPYmplY3RzUmVjdXJzaXZlID0gZnVuY3Rpb24gbWVyZ2VPYmplY3RzUmVjdXJzaXZlKHNvdXJjZSwgZGVzdGluYXRpb24pIHtcbiAgICAgICAgdmFyIG5ld09iamVjdCA9IHt9LFxuICAgICAgICAgICAgcHJvcGVydHk7XG4gICAgICAgIGZvciAocHJvcGVydHkgaW4gc291cmNlKSB7XG4gICAgICAgICAgICBpZiAoc291cmNlLmhhc093blByb3BlcnR5KHByb3BlcnR5KSkge1xuICAgICAgICAgICAgICAgIC8vaWYgKHNvdXJjZVtwcm9wZXJ0eV0gPT09IG51bGwpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGlmIChkZXN0aW5hdGlvbi5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNvdXJjZVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBPYmplY3QgJiYgZGVzdGluYXRpb24gaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBMYW5nVXRpbHMubWVyZ2VPYmplY3RzUmVjdXJzaXZlKHNvdXJjZVtwcm9wZXJ0eV0sIGRlc3RpbmF0aW9uW3Byb3BlcnR5XSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gZGVzdGluYXRpb25bcHJvcGVydHldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNvdXJjZVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBMYW5nVXRpbHMubWVyZ2VPYmplY3RzUmVjdXJzaXZlKHNvdXJjZVtwcm9wZXJ0eV0sIHt9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBzb3VyY2VbcHJvcGVydHldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAocHJvcGVydHkgaW4gZGVzdGluYXRpb24pIHtcbiAgICAgICAgICAgIGlmIChkZXN0aW5hdGlvbi5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgJiYgIW5ld09iamVjdC5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgLyomJiBkZXN0aW5hdGlvbltwcm9wZXJ0eV0gIT09IG51bGwqLykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGVzdGluYXRpb25bcHJvcGVydHldIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gTGFuZ1V0aWxzLm1lcmdlT2JqZWN0c1JlY3Vyc2l2ZShkZXN0aW5hdGlvbltwcm9wZXJ0eV0sIHt9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBkZXN0aW5hdGlvbltwcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ld09iamVjdDtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLm9iamVjdFZhbHVlcyA9IGZ1bmN0aW9uIG9iamVjdFZhbHVlcyhvYmplY3QpIHtcbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgcHJvcGVydHkgaW4gb2JqZWN0KSBpZiAob2JqZWN0Lmhhc093blByb3BlcnR5KHByb3BlcnR5KSkge1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKG9iamVjdFtwcm9wZXJ0eV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMudHJpbUxlZnQgPSBmdW5jdGlvbiB0cmltTGVmdChzdHJpbmcsIGNoYXJsaXN0KSB7XG4gICAgICAgIGlmIChjaGFybGlzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjaGFybGlzdCA9IFwiXFxzXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKG5ldyBSZWdFeHAoXCJeW1wiICsgY2hhcmxpc3QgKyBcIl0rXCIpLCBcIlwiKTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLnRyaW1SaWdodCA9IGZ1bmN0aW9uIHRyaW1SaWdodChzdHJpbmcsIGNoYXJsaXN0KSB7XG4gICAgICAgIGlmIChjaGFybGlzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjaGFybGlzdCA9IFwiXFxzXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKG5ldyBSZWdFeHAoXCJbXCIgKyBjaGFybGlzdCArIFwiXSskXCIpLCBcIlwiKTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLnRyaW0gPSBmdW5jdGlvbiB0cmltKHN0cmluZywgY2hhcmxpc3QpIHtcbiAgICAgICAgcmV0dXJuIExhbmdVdGlscy50cmltTGVmdChMYW5nVXRpbHMudHJpbVJpZ2h0KHN0cmluZywgY2hhcmxpc3QpLCBjaGFybGlzdCk7XG4gICAgfTtcblxuICAgIHJldHVybiBMYW5nVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBMYW5nVXRpbHM7XG5cbkxhbmdVdGlscy5zbHVnVGFibGUgPSBbeyByZTogL1tcXHhDMC1cXHhDNl0vZywgY2g6ICdBJyB9LCB7IHJlOiAvW1xceEUwLVxceEU2XS9nLCBjaDogJ2EnIH0sIHsgcmU6IC9bXFx4QzgtXFx4Q0JdL2csIGNoOiAnRScgfSwgeyByZTogL1tcXHhFOC1cXHhFQl0vZywgY2g6ICdlJyB9LCB7IHJlOiAvW1xceENDLVxceENGXS9nLCBjaDogJ0knIH0sIHsgcmU6IC9bXFx4RUMtXFx4RUZdL2csIGNoOiAnaScgfSwgeyByZTogL1tcXHhEMi1cXHhENl0vZywgY2g6ICdPJyB9LCB7IHJlOiAvW1xceEYyLVxceEY2XS9nLCBjaDogJ28nIH0sIHsgcmU6IC9bXFx4RDktXFx4RENdL2csIGNoOiAnVScgfSwgeyByZTogL1tcXHhGOS1cXHhGQ10vZywgY2g6ICd1JyB9LCB7IHJlOiAvW1xceEM3LVxceEU3XS9nLCBjaDogJ2MnIH0sIHsgcmU6IC9bXFx4RDFdL2csIGNoOiAnTicgfSwgeyByZTogL1tcXHhGMV0vZywgY2g6ICduJyB9XTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIgPSByZXF1aXJlKCcuLi9odHRwL1Jlc291cmNlc01hbmFnZXInKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUmVzb3VyY2VzTWFuYWdlcik7XG5cbi8qKlxuICpcbiAqIFV0aWxzIHRvIGNvbXB1dGUgcGFzc3dvcmQgc3RyZW5ndGhcbiAqXG4gKi9cblxudmFyIFBhc3NVdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGFzc1V0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUGFzc1V0aWxzKTtcbiAgICB9XG5cbiAgICBQYXNzVXRpbHMuZ2V0U3RhdGUgPSBmdW5jdGlvbiBnZXRTdGF0ZSgpIHtcbiAgICAgICAgdmFyIHBhc3NWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzBdO1xuICAgICAgICB2YXIgY29uZmlybVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBjcnRTdGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IHsgdmFsaWQ6IGZhbHNlIH0gOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciBvbkNoYW5nZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uIChzdGF0dXMpIHt9IDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIHZhciBzdGF0ZSA9IHtcbiAgICAgICAgICAgIHZhbGlkOiB0cnVlLFxuICAgICAgICAgICAgcGFzc0Vycm9yVGV4dDogbnVsbCxcbiAgICAgICAgICAgIHBhc3NIaW50VGV4dDogbnVsbCxcbiAgICAgICAgICAgIGNvbmZpcm1FcnJvclRleHQ6IG51bGxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCFwYXNzVmFsdWUgJiYgIWNvbmZpcm1WYWx1ZSkge1xuICAgICAgICAgICAgc3RhdGUudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFBhc3NVdGlscy5jaGVja1Bhc3N3b3JkU3RyZW5ndGgocGFzc1ZhbHVlLCBmdW5jdGlvbiAodmFsaWQsIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZS52YWxpZCA9IHZhbGlkO1xuICAgICAgICAgICAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGUucGFzc0Vycm9yVGV4dCA9IG1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3RhdGUucGFzc0hpbnRUZXh0ID0gbWVzc2FnZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghY29uZmlybVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgc3RhdGUudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5jb25maXJtRXJyb3JUZXh0ID0gZ2xvYmFsLnB5ZGlvLk1lc3NhZ2VIYXNoWzYyMV07XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbmZpcm1WYWx1ZSAhPT0gcGFzc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgc3RhdGUudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBzdGF0ZS5jb25maXJtRXJyb3JUZXh0ID0gZ2xvYmFsLnB5ZGlvLk1lc3NhZ2VIYXNoWzIzOF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNydFN0YXRlLnZhbGlkICE9PSBzdGF0ZS52YWxpZCkge1xuICAgICAgICAgICAgb25DaGFuZ2Uoc3RhdGUudmFsaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdGF0ZTtcbiAgICB9O1xuXG4gICAgUGFzc1V0aWxzLmdldE9wdGlvbnMgPSBmdW5jdGlvbiBnZXRPcHRpb25zKCkge1xuICAgICAgICBpZiAoUGFzc1V0aWxzLk9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBQYXNzVXRpbHMuT3B0aW9ucztcbiAgICAgICAgfVxuICAgICAgICBQYXNzVXRpbHMuT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIHB5ZGlvTWVzc2FnZXM6IFszNzksIDM4MCwgMzgxLCAzODIsIDM4MywgMzg0LCAzODVdLFxuICAgICAgICAgICAgbWVzc2FnZXM6IFtcIlVuc2FmZSBwYXNzd29yZCB3b3JkIVwiLCBcIlRvbyBzaG9ydFwiLCBcIlZlcnkgd2Vha1wiLCBcIldlYWtcIiwgXCJNZWRpdW1cIiwgXCJTdHJvbmdcIiwgXCJWZXJ5IHN0cm9uZ1wiXSxcbiAgICAgICAgICAgIGNvbG9yczogW1wiI2YwMFwiLCBcIiM5OTlcIiwgXCIjQzcwRjBGXCIsIFwiI0M3MEYwRlwiLCBcIiNGRjg0MzJcIiwgXCIjMjc5RDAwXCIsIFwiIzI3OUQwMFwiXSxcbiAgICAgICAgICAgIHNjb3JlczogWzEwLCAxNSwgMzAsIDQwXSxcbiAgICAgICAgICAgIGNvbW1vbjogW1wicGFzc3dvcmRcIiwgXCIxMjM0NTZcIiwgXCIxMjNcIiwgXCIxMjM0XCIsIFwibXlwYXNzXCIsIFwicGFzc1wiLCBcImxldG1laW5cIiwgXCJxd2VydHlcIiwgXCJtb25rZXlcIiwgXCJhc2RmZ2hcIiwgXCJ6eGN2Ym5cIiwgXCJwYXNzXCJdLFxuICAgICAgICAgICAgbWluY2hhcjogOFxuICAgICAgICB9O1xuICAgICAgICB2YXIgcHlkaW9NaW4gPSBwYXJzZUludChnbG9iYWwucHlkaW8uZ2V0UGx1Z2luQ29uZmlncyhcImNvcmUuYXV0aFwiKS5nZXQoXCJQQVNTV09SRF9NSU5MRU5HVEhcIikpO1xuICAgICAgICBpZiAocHlkaW9NaW4pIHtcbiAgICAgICAgICAgIFBhc3NVdGlscy5PcHRpb25zLm1pbmNoYXIgPSBweWRpb01pbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUGFzc1V0aWxzLk9wdGlvbnM7XG4gICAgfTtcblxuICAgIFBhc3NVdGlscy5jaGVja1Bhc3N3b3JkU3RyZW5ndGggPSBmdW5jdGlvbiBjaGVja1Bhc3N3b3JkU3RyZW5ndGgodmFsdWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgUGFzc1BvbGljeUxpYiA9IF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5yZXF1aXJlTGliKFwiUGFzc3dvcmRQb2xpY3lcIiwgZmFsc2UpO1xuICAgICAgICAgICAgaWYgKFBhc3NQb2xpY3lMaWIgJiYgUGFzc1BvbGljeUxpYi5DaGVja2VyKSB7XG4gICAgICAgICAgICAgICAgdmFyIENoZWNrZXIgPSBQYXNzUG9saWN5TGliLkNoZWNrZXI7XG5cbiAgICAgICAgICAgICAgICBpZiAoQ2hlY2tlcikge1xuICAgICAgICAgICAgICAgICAgICBDaGVja2VyLmNoZWNrUGFzc3dvcmRTdHJlbmd0aCh2YWx1ZSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAvLyBVcGRhdGUgd2l0aCBQeWRpbyBvcHRpb25zXG4gICAgICAgIHZhciBvcHRpb25zID0gUGFzc1V0aWxzLmdldE9wdGlvbnMoKTtcbiAgICAgICAgaWYgKG9wdGlvbnMubWluY2hhciAmJiB2YWx1ZS5sZW5ndGggPCBvcHRpb25zLm1pbmNoYXIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlLCBnbG9iYWwucHlkaW8uTWVzc2FnZUhhc2hbMzgwXSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHdyYXBwZWRDYWxsYmFjayA9IGZ1bmN0aW9uIHdyYXBwZWRDYWxsYmFjayhtc2dJZCwgcGVyY2VudCkge1xuICAgICAgICAgICAgdmFyIHMgPSBvcHRpb25zLm1lc3NhZ2VzW21zZ0lkXTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcyA9IGdsb2JhbC5weWRpby5NZXNzYWdlSGFzaFtvcHRpb25zLnB5ZGlvTWVzc2FnZXNbbXNnSWRdXTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICBjYWxsYmFjayhwZXJjZW50ID4gMSwgcyk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBzdHJlbmd0aCA9IFBhc3NVdGlscy5nZXRQYXNzd29yZFNjb3JlKHZhbHVlLCBvcHRpb25zLm1pbmNoYXIpO1xuICAgICAgICBpZiAoc3RyZW5ndGggPT0gLTIwMCkge1xuICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDAsIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHN0cmVuZ3RoIDwgMCAmJiBzdHJlbmd0aCA+IC0xOTkpIHtcbiAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soMSwgMTApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RyZW5ndGggPD0gb3B0aW9ucy5zY29yZXNbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDIsIDEwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZW5ndGggPiBvcHRpb25zLnNjb3Jlc1swXSAmJiBzdHJlbmd0aCA8PSBvcHRpb25zLnNjb3Jlc1sxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDMsIDI1KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJlbmd0aCA+IG9wdGlvbnMuc2NvcmVzWzFdICYmIHN0cmVuZ3RoIDw9IG9wdGlvbnMuc2NvcmVzWzJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soNCwgNTUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmVuZ3RoID4gb3B0aW9ucy5zY29yZXNbMl0gJiYgc3RyZW5ndGggPD0gb3B0aW9ucy5zY29yZXNbM10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjayg1LCA4MCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soNiwgOTgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIFBhc3NVdGlscy5nZXRQYXNzd29yZFNjb3JlID0gZnVuY3Rpb24gZ2V0UGFzc3dvcmRTY29yZSh2YWx1ZSwgbWluY2hhcikge1xuXG4gICAgICAgIHZhciBzdHJlbmd0aCA9IDA7XG4gICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPCBtaW5jaGFyKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoIC0gMTAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+PSBtaW5jaGFyICYmIHZhbHVlLmxlbmd0aCA8PSBtaW5jaGFyICsgMikge1xuICAgICAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA2O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID49IG1pbmNoYXIgKyAzICYmIHZhbHVlLmxlbmd0aCA8PSBtaW5jaGFyICsgNCkge1xuICAgICAgICAgICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMTI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+PSBtaW5jaGFyICsgNSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDE4O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvW2Etel0vKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC9bQS1aXS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goL1xcZCsvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8oLipbMC05XS4qWzAtOV0uKlswLTldKS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNztcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLy5bISxAIyQlXiYqP19+XS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLyguKlshLEAjJCVeJio/X35dLipbISxAIyQlXiYqP19+XSkvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8oW2Etel0uKltBLVpdKXwoW0EtWl0uKlthLXpdKS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLyhbYS16QS1aXSkvKSAmJiB2YWx1ZS5tYXRjaCgvKFswLTldKS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMztcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLyhbYS16QS1aMC05XS4qWyEsQCMkJV4mKj9ffl0pfChbISxAIyQlXiYqP19+XS4qW2EtekEtWjAtOV0pLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb21tb24gPSBbXCJwYXNzd29yZFwiLCBcIjEyMzQ1NlwiLCBcIjEyM1wiLCBcIjEyMzRcIiwgXCJteXBhc3NcIiwgXCJwYXNzXCIsIFwibGV0bWVpblwiLCBcInF3ZXJ0eVwiLCBcIm1vbmtleVwiLCBcImFzZGZnaFwiLCBcInp4Y3ZiblwiLCBcInBhc3NcIl07XG4gICAgICAgIGlmIChjb21tb24uaW5kZXhPZih2YWx1ZS50b0xvd2VyQ2FzZSgpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gLTIwMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyZW5ndGg7XG4gICAgfTtcblxuICAgIHJldHVybiBQYXNzVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBQYXNzVXRpbHM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIG1hbmlwdWxhdGluZyBmaWxlL2ZvbGRlcnMgcGF0aGVzXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgUGF0aFV0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQYXRoVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQYXRoVXRpbHMpO1xuICAgIH1cblxuICAgIFBhdGhVdGlscy5nZXRCYXNlbmFtZSA9IGZ1bmN0aW9uIGdldEJhc2VuYW1lKGZpbGVOYW1lKSB7XG4gICAgICAgIGlmIChmaWxlTmFtZSA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICAgICAgdmFyIHNlcGFyYXRvciA9IFwiL1wiO1xuICAgICAgICBpZiAoZmlsZU5hbWUuaW5kZXhPZihcIlxcXFxcIikgIT0gLTEpIHNlcGFyYXRvciA9IFwiXFxcXFwiO1xuICAgICAgICByZXR1cm4gZmlsZU5hbWUuc3Vic3RyKGZpbGVOYW1lLmxhc3RJbmRleE9mKHNlcGFyYXRvcikgKyAxLCBmaWxlTmFtZS5sZW5ndGgpO1xuICAgIH07XG5cbiAgICBQYXRoVXRpbHMuZ2V0RGlybmFtZSA9IGZ1bmN0aW9uIGdldERpcm5hbWUoZmlsZU5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZpbGVOYW1lLnN1YnN0cigwLCBmaWxlTmFtZS5sYXN0SW5kZXhPZihcIi9cIikpO1xuICAgIH07XG5cbiAgICBQYXRoVXRpbHMuZ2V0QWp4cE1pbWVUeXBlID0gZnVuY3Rpb24gZ2V0QWp4cE1pbWVUeXBlKGl0ZW0pIHtcbiAgICAgICAgaWYgKCFpdGVtKSByZXR1cm4gXCJcIjtcbiAgICAgICAgaWYgKGl0ZW0gaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLmdldCgnYWp4cF9taW1lJykgfHwgUGF0aFV0aWxzLmdldEZpbGVFeHRlbnNpb24oaXRlbS5nZXQoJ2ZpbGVuYW1lJykpO1xuICAgICAgICB9IGVsc2UgaWYgKGl0ZW0uZ2V0TWV0YWRhdGEpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLmdldE1ldGFkYXRhKCkuZ2V0KCdhanhwX21pbWUnKSB8fCBQYXRoVXRpbHMuZ2V0RmlsZUV4dGVuc2lvbihpdGVtLmdldFBhdGgoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbS5nZXRBdHRyaWJ1dGUoJ2FqeHBfbWltZScpIHx8IFBhdGhVdGlscy5nZXRGaWxlRXh0ZW5zaW9uKGl0ZW0uZ2V0QXR0cmlidXRlKCdmaWxlbmFtZScpKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQYXRoVXRpbHMuZ2V0RmlsZUV4dGVuc2lvbiA9IGZ1bmN0aW9uIGdldEZpbGVFeHRlbnNpb24oZmlsZU5hbWUpIHtcbiAgICAgICAgaWYgKCFmaWxlTmFtZSB8fCBmaWxlTmFtZSA9PSBcIlwiKSByZXR1cm4gXCJcIjtcbiAgICAgICAgdmFyIHNwbGl0ID0gUGF0aFV0aWxzLmdldEJhc2VuYW1lKGZpbGVOYW1lKS5zcGxpdCgnLicpO1xuICAgICAgICBpZiAoc3BsaXQubGVuZ3RoID4gMSkgcmV0dXJuIHNwbGl0W3NwbGl0Lmxlbmd0aCAtIDFdLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuXG4gICAgUGF0aFV0aWxzLnJvdW5kRmlsZVNpemUgPSBmdW5jdGlvbiByb3VuZEZpbGVTaXplKGZpbGVzaXplKSB7XG4gICAgICAgIHZhciBzaXplX3VuaXQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBcIm9cIiA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAoZmlsZXNpemUgPj0gMTA3Mzc0MTgyNCkge1xuICAgICAgICAgICAgZmlsZXNpemUgPSBNYXRoLnJvdW5kKGZpbGVzaXplIC8gMTA3Mzc0MTgyNCAqIDEwMCkgLyAxMDAgKyBcIiBHXCIgKyBzaXplX3VuaXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoZmlsZXNpemUgPj0gMTA0ODU3Nikge1xuICAgICAgICAgICAgZmlsZXNpemUgPSBNYXRoLnJvdW5kKGZpbGVzaXplIC8gMTA0ODU3NiAqIDEwMCkgLyAxMDAgKyBcIiBNXCIgKyBzaXplX3VuaXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoZmlsZXNpemUgPj0gMTAyNCkge1xuICAgICAgICAgICAgZmlsZXNpemUgPSBNYXRoLnJvdW5kKGZpbGVzaXplIC8gMTAyNCAqIDEwMCkgLyAxMDAgKyBcIiBLXCIgKyBzaXplX3VuaXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmaWxlc2l6ZSA9IGZpbGVzaXplICsgXCIgXCIgKyBzaXplX3VuaXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZpbGVzaXplO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBkYXRlT2JqZWN0IERhdGVcbiAgICAgKiBAcGFyYW0gZm9ybWF0IFN0cmluZ1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuXG4gICAgUGF0aFV0aWxzLmZvcm1hdE1vZGlmRGF0ZSA9IGZ1bmN0aW9uIGZvcm1hdE1vZGlmRGF0ZShkYXRlT2JqZWN0LCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFmb3JtYXQgJiYgd2luZG93ICYmIHdpbmRvdy5weWRpbyAmJiBweWRpby5NZXNzYWdlSGFzaCkge1xuICAgICAgICAgICAgZm9ybWF0ID0gcHlkaW8uTWVzc2FnZUhhc2hbXCJkYXRlX2Zvcm1hdFwiXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvcm1hdCkgcmV0dXJuICdubyBmb3JtYXQnO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcImRcIiwgZGF0ZU9iamVjdC5nZXREYXRlKCkgPCAxMCA/ICcwJyArIGRhdGVPYmplY3QuZ2V0RGF0ZSgpIDogZGF0ZU9iamVjdC5nZXREYXRlKCkpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcIkRcIiwgZGF0ZU9iamVjdC5nZXREYXkoKSk7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiWVwiLCBkYXRlT2JqZWN0LmdldEZ1bGxZZWFyKCkpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcInlcIiwgZGF0ZU9iamVjdC5nZXRZZWFyKCkpO1xuICAgICAgICB2YXIgbW9udGggPSBkYXRlT2JqZWN0LmdldE1vbnRoKCkgKyAxO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcIm1cIiwgbW9udGggPCAxMCA/ICcwJyArIG1vbnRoIDogbW9udGgpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcIkhcIiwgKGRhdGVPYmplY3QuZ2V0SG91cnMoKSA8IDEwID8gJzAnIDogJycpICsgZGF0ZU9iamVjdC5nZXRIb3VycygpKTtcbiAgICAgICAgLy8gU3VwcG9ydCAxMiBob3VyIGZvcm1hdCBjb21wYXRpYmlsaXR5XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiaFwiLCBkYXRlT2JqZWN0LmdldEhvdXJzKCkgJSAxMiB8fCAxMik7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwicFwiLCBkYXRlT2JqZWN0LmdldEhvdXJzKCkgPCAxMiA/IFwiYW1cIiA6IFwicG1cIik7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiUFwiLCBkYXRlT2JqZWN0LmdldEhvdXJzKCkgPCAxMiA/IFwiQU1cIiA6IFwiUE1cIik7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiaVwiLCAoZGF0ZU9iamVjdC5nZXRNaW51dGVzKCkgPCAxMCA/ICcwJyA6ICcnKSArIGRhdGVPYmplY3QuZ2V0TWludXRlcygpKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJzXCIsIChkYXRlT2JqZWN0LmdldFNlY29uZHMoKSA8IDEwID8gJzAnIDogJycpICsgZGF0ZU9iamVjdC5nZXRTZWNvbmRzKCkpO1xuICAgICAgICByZXR1cm4gZm9ybWF0O1xuICAgIH07XG5cbiAgICByZXR1cm4gUGF0aFV0aWxzO1xufSkoKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBQYXRoVXRpbHM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFBlcmlvZGljYWxFeGVjdXRlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGVyaW9kaWNhbEV4ZWN1dGVyKGNhbGxiYWNrLCBmcmVxdWVuY3kpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFBlcmlvZGljYWxFeGVjdXRlcik7XG5cbiAgICAgICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgICAgICB0aGlzLmZyZXF1ZW5jeSA9IGZyZXF1ZW5jeTtcbiAgICAgICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLnJlZ2lzdGVyQ2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIucHJvdG90eXBlLnJlZ2lzdGVyQ2FsbGJhY2sgPSBmdW5jdGlvbiByZWdpc3RlckNhbGxiYWNrKCkge1xuICAgICAgICB0aGlzLnRpbWVyID0gc2V0SW50ZXJ2YWwodGhpcy5vblRpbWVyRXZlbnQuYmluZCh0aGlzKSwgdGhpcy5mcmVxdWVuY3kgKiAxMDAwKTtcbiAgICB9O1xuXG4gICAgUGVyaW9kaWNhbEV4ZWN1dGVyLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gZXhlY3V0ZSgpIHtcbiAgICAgICAgdGhpcy5jYWxsYmFjayh0aGlzKTtcbiAgICB9O1xuXG4gICAgUGVyaW9kaWNhbEV4ZWN1dGVyLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gc3RvcCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRpbWVyKSByZXR1cm47XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy50aW1lcik7XG4gICAgICAgIHRoaXMudGltZXIgPSBudWxsO1xuICAgIH07XG5cbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIucHJvdG90eXBlLm9uVGltZXJFdmVudCA9IGZ1bmN0aW9uIG9uVGltZXJFdmVudCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmN1cnJlbnRseUV4ZWN1dGluZykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRseUV4ZWN1dGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5leGVjdXRlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRseUV4ZWN1dGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIFBlcmlvZGljYWxFeGVjdXRlcjtcbn0pKCk7XG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gUGVyaW9kaWNhbEV4ZWN1dGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzW1wiZGVmYXVsdFwiXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX3dpY2tlZEdvb2RYcGF0aCA9IHJlcXVpcmUoJ3dpY2tlZC1nb29kLXhwYXRoJyk7XG5cbnZhciBfd2lja2VkR29vZFhwYXRoMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3dpY2tlZEdvb2RYcGF0aCk7XG5cbl93aWNrZWRHb29kWHBhdGgyWydkZWZhdWx0J10uaW5zdGFsbCgpO1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIG1hbmlwdWxhdGluZyBYTUxcbiAqL1xuXG52YXIgWE1MVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFhNTFV0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgWE1MVXRpbHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdHMgdGhlIGZpcnN0IFhtbE5vZGUgdGhhdCBtYXRjaGVzIHRoZSBYUGF0aCBleHByZXNzaW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsZW1lbnQge0VsZW1lbnQgfCBEb2N1bWVudH0gcm9vdCBlbGVtZW50IGZvciB0aGUgc2VhcmNoXG4gICAgICogQHBhcmFtIHF1ZXJ5IHtTdHJpbmd9IFhQYXRoIHF1ZXJ5XG4gICAgICogQHJldHVybiB7RWxlbWVudH0gZmlyc3QgbWF0Y2hpbmcgZWxlbWVudFxuICAgICAqIEBzaWduYXR1cmUgZnVuY3Rpb24oZWxlbWVudCwgcXVlcnkpXG4gICAgICovXG5cbiAgICBYTUxVdGlscy5YUGF0aFNlbGVjdFNpbmdsZU5vZGUgPSBmdW5jdGlvbiBYUGF0aFNlbGVjdFNpbmdsZU5vZGUoZWxlbWVudCwgcXVlcnkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50WydzZWxlY3RTaW5nbGVOb2RlJ10gJiYgdHlwZW9mIGVsZW1lbnQuc2VsZWN0U2luZ2xlTm9kZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IGVsZW1lbnQuc2VsZWN0U2luZ2xlTm9kZShxdWVyeSk7XG4gICAgICAgICAgICAgICAgaWYgKHJlcykgcmV0dXJuIHJlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge31cblxuICAgICAgICBpZiAoIVhNTFV0aWxzLl9feHBlICYmIHdpbmRvdy5YUGF0aEV2YWx1YXRvcikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBYTUxVdGlscy5fX3hwZSA9IG5ldyBYUGF0aEV2YWx1YXRvcigpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghWE1MVXRpbHMuX194cGUpIHtcbiAgICAgICAgICAgIHF1ZXJ5ID0gZG9jdW1lbnQuY3JlYXRlRXhwcmVzc2lvbihxdWVyeSwgbnVsbCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gcXVlcnkuZXZhbHVhdGUoZWxlbWVudCwgNywgbnVsbCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LnNuYXBzaG90TGVuZ3RoID8gcmVzdWx0LnNuYXBzaG90SXRlbSgwKSA6IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeHBlID0gWE1MVXRpbHMuX194cGU7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB4cGUuZXZhbHVhdGUocXVlcnksIGVsZW1lbnQsIHhwZS5jcmVhdGVOU1Jlc29sdmVyKGVsZW1lbnQpLCBYUGF0aFJlc3VsdC5GSVJTVF9PUkRFUkVEX05PREVfVFlQRSwgbnVsbCkuc2luZ2xlTm9kZVZhbHVlO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInNlbGVjdFNpbmdsZU5vZGU6IHF1ZXJ5OiBcIiArIHF1ZXJ5ICsgXCIsIGVsZW1lbnQ6IFwiICsgZWxlbWVudCArIFwiLCBlcnJvcjogXCIgKyBlcnIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlbGVjdHMgYSBsaXN0IG9mIG5vZGVzIG1hdGNoaW5nIHRoZSBYUGF0aCBleHByZXNzaW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsZW1lbnQge0VsZW1lbnQgfCBEb2N1bWVudH0gcm9vdCBlbGVtZW50IGZvciB0aGUgc2VhcmNoXG4gICAgICogQHBhcmFtIHF1ZXJ5IHtTdHJpbmd9IFhQYXRoIHF1ZXJ5XG4gICAgICogQHJldHVybiB7RWxlbWVudFtdfSBMaXN0IG9mIG1hdGNoaW5nIGVsZW1lbnRzXG4gICAgICogQHNpZ25hdHVyZSBmdW5jdGlvbihlbGVtZW50LCBxdWVyeSlcbiAgICAgKi9cblxuICAgIFhNTFV0aWxzLlhQYXRoU2VsZWN0Tm9kZXMgPSBmdW5jdGlvbiBYUGF0aFNlbGVjdE5vZGVzKGVsZW1lbnQsIHF1ZXJ5KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1lbnQuc2VsZWN0Tm9kZXMgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50Lm93bmVyRG9jdW1lbnQgJiYgZWxlbWVudC5vd25lckRvY3VtZW50LnNldFByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm93bmVyRG9jdW1lbnQuc2V0UHJvcGVydHkoXCJTZWxlY3Rpb25MYW5ndWFnZVwiLCBcIlhQYXRoXCIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGVsZW1lbnQuc2V0UHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0UHJvcGVydHkoXCJTZWxlY3Rpb25MYW5ndWFnZVwiLCBcIlhQYXRoXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gQXJyYXkuZnJvbShlbGVtZW50LnNlbGVjdE5vZGVzKHF1ZXJ5KSk7XG4gICAgICAgICAgICAgICAgaWYgKHJlcykgcmV0dXJuIHJlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge31cblxuICAgICAgICB2YXIgeHBlID0gWE1MVXRpbHMuX194cGU7XG5cbiAgICAgICAgaWYgKCF4cGUgJiYgd2luZG93LlhQYXRoRXZhbHVhdG9yKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIFhNTFV0aWxzLl9feHBlID0geHBlID0gbmV3IFhQYXRoRXZhbHVhdG9yKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQsXG4gICAgICAgICAgICBub2RlcyA9IFtdLFxuICAgICAgICAgICAgaTtcbiAgICAgICAgaWYgKCFYTUxVdGlscy5fX3hwZSkge1xuICAgICAgICAgICAgcXVlcnkgPSBkb2N1bWVudC5jcmVhdGVFeHByZXNzaW9uKHF1ZXJ5LCBudWxsKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IHF1ZXJ5LmV2YWx1YXRlKGVsZW1lbnQsIDcsIG51bGwpO1xuICAgICAgICAgICAgbm9kZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXN1bHQuc25hcHNob3RMZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChFbGVtZW50LmV4dGVuZCkge1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1tpXSA9IEVsZW1lbnQuZXh0ZW5kKHJlc3VsdC5zbmFwc2hvdEl0ZW0oaSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzW2ldID0gcmVzdWx0LnNuYXBzaG90SXRlbShpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmVzdWx0ID0geHBlLmV2YWx1YXRlKHF1ZXJ5LCBlbGVtZW50LCB4cGUuY3JlYXRlTlNSZXNvbHZlcihlbGVtZW50KSwgWFBhdGhSZXN1bHQuT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEUsIG51bGwpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInNlbGVjdE5vZGVzOiBxdWVyeTogXCIgKyBxdWVyeSArIFwiLCBlbGVtZW50OiBcIiArIGVsZW1lbnQgKyBcIiwgZXJyb3I6IFwiICsgZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCByZXN1bHQuc25hcHNob3RMZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbm9kZXNbaV0gPSByZXN1bHQuc25hcHNob3RJdGVtKGkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIHRoZSBmaXJzdCBYbWxOb2RlIHRoYXQgbWF0Y2hlcyB0aGUgWFBhdGggZXhwcmVzc2lvbiBhbmQgcmV0dXJucyB0aGUgdGV4dCBjb250ZW50IG9mIHRoZSBlbGVtZW50XG4gICAgICpcbiAgICAgKiBAcGFyYW0gZWxlbWVudCB7RWxlbWVudHxEb2N1bWVudH0gcm9vdCBlbGVtZW50IGZvciB0aGUgc2VhcmNoXG4gICAgICogQHBhcmFtIHF1ZXJ5IHtTdHJpbmd9ICBYUGF0aCBxdWVyeVxuICAgICAqIEByZXR1cm4ge1N0cmluZ30gdGhlIGpvaW5lZCB0ZXh0IGNvbnRlbnQgb2YgdGhlIGZvdW5kIGVsZW1lbnQgb3IgbnVsbCBpZiBub3QgYXBwcm9wcmlhdGUuXG4gICAgICogQHNpZ25hdHVyZSBmdW5jdGlvbihlbGVtZW50LCBxdWVyeSlcbiAgICAgKi9cblxuICAgIFhNTFV0aWxzLlhQYXRoR2V0U2luZ2xlTm9kZVRleHQgPSBmdW5jdGlvbiBYUGF0aEdldFNpbmdsZU5vZGVUZXh0KGVsZW1lbnQsIHF1ZXJ5KSB7XG4gICAgICAgIHZhciBub2RlID0gWE1MVXRpbHMuWFBhdGhTZWxlY3RTaW5nbGVOb2RlKGVsZW1lbnQsIHF1ZXJ5KTtcbiAgICAgICAgcmV0dXJuIFhNTFV0aWxzLmdldERvbU5vZGVUZXh0KG5vZGUpO1xuICAgIH07XG5cbiAgICBYTUxVdGlscy5nZXREb21Ob2RlVGV4dCA9IGZ1bmN0aW9uIGdldERvbU5vZGVUZXh0KG5vZGUpIHtcbiAgICAgICAgdmFyIGluY2x1ZGVDRGF0YSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIGlmICghbm9kZSB8fCAhbm9kZS5ub2RlVHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKG5vZGUubm9kZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAvLyBOT0RFX0VMRU1FTlRcbiAgICAgICAgICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgICAgICAgICAgYSA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGUuY2hpbGROb2RlcyxcbiAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID0gbm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhW2ldID0gWE1MVXRpbHMuZ2V0RG9tTm9kZVRleHQobm9kZXNbaV0sIGluY2x1ZGVDRGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGEuam9pbihcIlwiKTtcblxuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIC8vIE5PREVfQVRUUklCVVRFXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGUudmFsdWU7XG5cbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAvLyBOT0RFX1RFWFRcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZS5ub2RlVmFsdWU7XG5cbiAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAvLyBDREFUQVxuICAgICAgICAgICAgICAgIGlmIChpbmNsdWRlQ0RhdGEpIHJldHVybiBub2RlLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0geG1sU3RyXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG5cbiAgICBYTUxVdGlscy5wYXJzZVhtbCA9IGZ1bmN0aW9uIHBhcnNlWG1sKHhtbFN0cikge1xuXG4gICAgICAgIGlmICh0eXBlb2Ygd2luZG93LkRPTVBhcnNlciAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IHdpbmRvdy5ET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoeG1sU3RyLCBcInRleHQveG1sXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygd2luZG93LkFjdGl2ZVhPYmplY3QgIT0gXCJ1bmRlZmluZWRcIiAmJiBuZXcgd2luZG93LkFjdGl2ZVhPYmplY3QoXCJNU1hNTDIuRE9NRG9jdW1lbnQuNi4wXCIpKSB7XG4gICAgICAgICAgICB2YXIgeG1sRG9jID0gbmV3IHdpbmRvdy5BY3RpdmVYT2JqZWN0KFwiTVNYTUwyLkRPTURvY3VtZW50LjYuMFwiKTtcbiAgICAgICAgICAgIHhtbERvYy52YWxpZGF0ZU9uUGFyc2UgPSBmYWxzZTtcbiAgICAgICAgICAgIHhtbERvYy5hc3luYyA9IGZhbHNlO1xuICAgICAgICAgICAgeG1sRG9jLmxvYWRYTUwoeG1sU3RyKTtcbiAgICAgICAgICAgIHhtbERvYy5zZXRQcm9wZXJ0eSgnU2VsZWN0aW9uTGFuZ3VhZ2UnLCAnWFBhdGgnKTtcbiAgICAgICAgICAgIHJldHVybiB4bWxEb2M7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgcGFyc2UgWE1MIHN0cmluZycpO1xuICAgIH07XG5cbiAgICByZXR1cm4gWE1MVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBYTUxVdGlscztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbnZhciBfbW9kZWxSZWdpc3RyeSA9IHJlcXVpcmUoJy4vbW9kZWwvUmVnaXN0cnknKTtcblxudmFyIF9tb2RlbFJlZ2lzdHJ5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsUmVnaXN0cnkpO1xuXG52YXIgX21vZGVsQWp4cE5vZGUgPSByZXF1aXJlKCcuL21vZGVsL0FqeHBOb2RlJyk7XG5cbnZhciBfbW9kZWxBanhwTm9kZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbEFqeHBOb2RlKTtcblxudmFyIF9tb2RlbFB5ZGlvRGF0YU1vZGVsID0gcmVxdWlyZSgnLi9tb2RlbC9QeWRpb0RhdGFNb2RlbCcpO1xuXG52YXIgX21vZGVsUHlkaW9EYXRhTW9kZWwyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxQeWRpb0RhdGFNb2RlbCk7XG5cbnZhciBfbW9kZWxSZW1vdGVOb2RlUHJvdmlkZXIgPSByZXF1aXJlKCcuL21vZGVsL1JlbW90ZU5vZGVQcm92aWRlcicpO1xuXG52YXIgX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyKTtcblxudmFyIF9tb2RlbFJlcG9zaXRvcnkgPSByZXF1aXJlKCcuL21vZGVsL1JlcG9zaXRvcnknKTtcblxudmFyIF9tb2RlbFJlcG9zaXRvcnkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxSZXBvc2l0b3J5KTtcblxudmFyIF9tb2RlbENvbnRyb2xsZXIgPSByZXF1aXJlKCcuL21vZGVsL0NvbnRyb2xsZXInKTtcblxudmFyIF9tb2RlbENvbnRyb2xsZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxDb250cm9sbGVyKTtcblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIF91dGlsUGF0aFV0aWxzID0gcmVxdWlyZSgnLi91dGlsL1BhdGhVdGlscycpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFBhdGhVdGlscyk7XG5cbnZhciBfdXRpbExhbmdVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9MYW5nVXRpbHMnKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxMYW5nVXRpbHMpO1xuXG52YXIgX3V0aWxBY3Rpdml0eU1vbml0b3IgPSByZXF1aXJlKCcuL3V0aWwvQWN0aXZpdHlNb25pdG9yJyk7XG5cbnZhciBfdXRpbEFjdGl2aXR5TW9uaXRvcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsQWN0aXZpdHlNb25pdG9yKTtcblxuLyoqXG4gKiBUaGlzIGlzIHRoZSBtYWluIGNsYXNzIGZvciBsYXVuY2hpbmcgdGhlIHdob2xlIGZyYW1ld29yayxcbiAqIHdpdGggb3Igd2l0aG91dCBhIFVJLlxuICogSXQgY2FuIGJlIGxhdW5jaGVkIGJ5IFB5ZGlvQm9vdHN0cmFwIG9yIGRpcmVjdGx5IGJ5IGdpdmluZyB0aGUgcmlnaHQgcGFyYW1ldGVycy5cbiAqL1xuXG52YXIgUHlkaW8gPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKFB5ZGlvLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICAvKipcbiAgICAgKiBQeWRpbyBDb25zdHJ1Y3RvciB0YWtlcyBhIE1hcCBvZiBzdGFydCBwYXJhbWV0ZXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHBhcmFtZXRlcnMge01hcH1cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIFB5ZGlvKHBhcmFtZXRlcnMpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFB5ZGlvKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLlBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzO1xuICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IHBhcmFtZXRlcnMuZ2V0KCdpbml0TG9hZFJlcCcpIHx8IG51bGw7XG4gICAgICAgIHRoaXMudXNlcnNFbmFibGVkID0gcGFyYW1ldGVycy5nZXQoJ3VzZXJzRW5hYmxlZCcpIHx8IG51bGw7XG4gICAgICAgIHRoaXMuY3VycmVudExhbmd1YWdlID0gcGFyYW1ldGVycy5nZXQoJ2N1cnJlbnRMYW5ndWFnZScpIHx8IG51bGw7XG4gICAgICAgIHRoaXMuYXBwVGl0bGUgPSBcIlB5ZGlvXCI7XG4gICAgICAgIGlmICh0aGlzLlBhcmFtZXRlcnMuaGFzKFwiY3VzdG9tV29yZGluZ1wiKSkge1xuICAgICAgICAgICAgdGhpcy5hcHBUaXRsZSA9IHRoaXMuUGFyYW1ldGVycy5nZXQoXCJjdXN0b21Xb3JkaW5nXCIpLnRpdGxlIHx8IFwiUHlkaW9cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVzZXIgPSBudWxsO1xuICAgICAgICB0aGlzLk1lc3NhZ2VIYXNoID0ge307XG4gICAgICAgIGlmICh3aW5kb3cuTWVzc2FnZUhhc2gpIHRoaXMuTWVzc2FnZUhhc2ggPSB3aW5kb3cuTWVzc2FnZUhhc2g7XG4gICAgICAgIHRoaXMuQXBpQ2xpZW50ID0gX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKTtcbiAgICAgICAgdGhpcy5BcGlDbGllbnQuc2V0UHlkaW9PYmplY3QodGhpcyk7XG4gICAgICAgIHRoaXMuQWN0aXZpdHlNb25pdG9yID0gbmV3IF91dGlsQWN0aXZpdHlNb25pdG9yMlsnZGVmYXVsdCddKHRoaXMpO1xuICAgICAgICB0aGlzLlJlZ2lzdHJ5ID0gbmV3IF9tb2RlbFJlZ2lzdHJ5MlsnZGVmYXVsdCddKHRoaXMpO1xuICAgICAgICB0aGlzLl9yb290Tm9kZSA9IG5ldyBfbW9kZWxBanhwTm9kZTJbJ2RlZmF1bHQnXShcIi9cIiwgXCJSb290XCIpO1xuICAgICAgICB0aGlzLl9kYXRhTW9kZWwgPSB0aGlzLl9jb250ZXh0SG9sZGVyID0gbmV3IF9tb2RlbFB5ZGlvRGF0YU1vZGVsMlsnZGVmYXVsdCddKGZhbHNlKTtcbiAgICAgICAgdGhpcy5fZGF0YU1vZGVsLnNldEFqeHBOb2RlUHJvdmlkZXIobmV3IF9tb2RlbFJlbW90ZU5vZGVQcm92aWRlcjJbJ2RlZmF1bHQnXSgpKTtcbiAgICAgICAgdGhpcy5fZGF0YU1vZGVsLnNldFJvb3ROb2RlKHRoaXMuX3Jvb3ROb2RlKTtcbiAgICAgICAgLy8gTXVzdCBoYXBwZW4gQUZURVIgZGF0YW1vZGVsIGluaXRpemF0aW9uLlxuICAgICAgICB0aGlzLkNvbnRyb2xsZXIgPSBuZXcgX21vZGVsQ29udHJvbGxlcjJbJ2RlZmF1bHQnXSh0aGlzKTtcbiAgICB9XG5cbiAgICBQeWRpby5wcm90b3R5cGUuZmlyZSA9IGZ1bmN0aW9uIGZpcmUoZXZlbnROYW1lLCBkYXRhKSB7XG4gICAgICAgIHRoaXMubm90aWZ5KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHtVc2VyfG51bGx9IHVzZXJPYmplY3RcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS51cGRhdGVVc2VyID0gZnVuY3Rpb24gdXBkYXRlVXNlcih1c2VyT2JqZWN0KSB7XG4gICAgICAgIHZhciBza2lwRXZlbnQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICB0aGlzLnVzZXIgPSB1c2VyT2JqZWN0O1xuICAgICAgICBpZiAoIXNraXBFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoJ3VzZXJfbG9nZ2VkJywgdXNlck9iamVjdCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7bnVsbHxVc2VyfVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldFVzZXIgPSBmdW5jdGlvbiBnZXRVc2VyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy51c2VyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWZyZXNoIHVzZXIvcHJlZmVyZW5jZXMgcmVnaXN0cnkgcGFydFxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnJlZnJlc2hVc2VyRGF0YSA9IGZ1bmN0aW9uIHJlZnJlc2hVc2VyRGF0YSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICB0aGlzLm9ic2VydmVPbmNlKFwicmVnaXN0cnlfcGFydF9sb2FkZWRcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQgIT09IFwidXNlci9wcmVmZXJlbmNlc1wiKSByZXR1cm47XG4gICAgICAgICAgICBfdGhpcy51cGRhdGVVc2VyKF90aGlzLlJlZ2lzdHJ5LnBhcnNlVXNlcigpLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLlJlZ2lzdHJ5LmxvYWQoXCJ1c2VyL3ByZWZlcmVuY2VzXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWFsIGluaXRpYWxpc2F0aW9uIHNlcXVlbmNlLiBXaWxsIFRyaWdnZXIgdGhlIHdob2xlIEdVSSBidWlsZGluZy5cbiAgICAgKiBFdmVudCBhamF4cGxvcmVyOmxvYWRlZCBpcyBmaXJlZCBhdCB0aGUgZW5kLlxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICBpZiAoIXRoaXMuUGFyYW1ldGVycy5oYXMoJ1NFQ1VSRV9UT0tFTicpKSB7XG4gICAgICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLmdldEJvb3RDb25mKChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub2JzZXJ2ZShcInJlZ2lzdHJ5X2xvYWRlZFwiLCBmdW5jdGlvbiAoKSB7XG5cbiAgICAgICAgICAgIF90aGlzMi5SZWdpc3RyeS5yZWZyZXNoRXh0ZW5zaW9uc1JlZ2lzdHJ5KCk7XG4gICAgICAgICAgICBfdGhpczIudXBkYXRlVXNlcihfdGhpczIuUmVnaXN0cnkucGFyc2VVc2VyKCksIGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChfdGhpczIudXNlcikge1xuICAgICAgICAgICAgICAgIHZhciByZXBJZCA9IF90aGlzMi51c2VyLmdldEFjdGl2ZVJlcG9zaXRvcnkoKTtcbiAgICAgICAgICAgICAgICB2YXIgcmVwTGlzdCA9IF90aGlzMi51c2VyLmdldFJlcG9zaXRvcmllc0xpc3QoKTtcbiAgICAgICAgICAgICAgICB2YXIgcmVwb3NpdG9yeU9iamVjdCA9IHJlcExpc3QuZ2V0KHJlcElkKTtcbiAgICAgICAgICAgICAgICBpZiAocmVwb3NpdG9yeU9iamVjdCkgcmVwb3NpdG9yeU9iamVjdC5sb2FkUmVzb3VyY2VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMyLlVJLmd1aUxvYWRlZCkge1xuICAgICAgICAgICAgICAgIF90aGlzMi5VSS5yZWZyZXNoVGVtcGxhdGVQYXJ0cygpO1xuICAgICAgICAgICAgICAgIF90aGlzMi5SZWdpc3RyeS5yZWZyZXNoRXh0ZW5zaW9uc1JlZ2lzdHJ5KCk7XG4gICAgICAgICAgICAgICAgX3RoaXMyLkNvbnRyb2xsZXIubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoX3RoaXMyLmdldFhtbFJlZ2lzdHJ5KCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpczIub2JzZXJ2ZShcImd1aV9sb2FkZWRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIuVUkucmVmcmVzaFRlbXBsYXRlUGFydHMoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLlJlZ2lzdHJ5LnJlZnJlc2hFeHRlbnNpb25zUmVnaXN0cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLkNvbnRyb2xsZXIubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoX3RoaXMyLmdldFhtbFJlZ2lzdHJ5KCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMyLmxvYWRBY3RpdmVSZXBvc2l0b3J5KCk7XG4gICAgICAgICAgICBpZiAoX3RoaXMyLlBhcmFtZXRlcnMuaGFzKFwiVVNFUl9HVUlfQUNUSU9OXCIpKSB7XG4gICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSBfdGhpczIuUGFyYW1ldGVycy5nZXQoXCJVU0VSX0dVSV9BQ1RJT05cIik7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5QYXJhbWV0ZXJzWydkZWxldGUnXShcIlVTRVJfR1VJX0FDVElPTlwiKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpczIuQ29udHJvbGxlci5maXJlQWN0aW9uKGEpO1xuICAgICAgICAgICAgICAgICAgICB9LCAxMDAwKTtcbiAgICAgICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgc3RhcnRlckZ1bmMgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIubG9hZENsYXNzZXNBbmRBcHBseShbXCJSZWFjdFwiLCBcIlB5ZGlvUmVhY3RVSVwiXSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzMy5VSSA9IG5ldyB3aW5kb3cuUHlkaW9SZWFjdFVJLkJ1aWxkZXIoX3RoaXMzKTtcbiAgICAgICAgICAgICAgICBfdGhpczMuVUkuaW5pdFRlbXBsYXRlcygpO1xuICAgICAgICAgICAgICAgIF90aGlzMy5maXJlKFwicmVnaXN0cnlfbG9hZGVkXCIsIF90aGlzMy5SZWdpc3RyeS5nZXRYTUwoKSk7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMy5maXJlKCdsb2FkZWQnKTtcbiAgICAgICAgICAgICAgICB9LCAyMDApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG5cbiAgICAgICAgaWYgKHRoaXMuUGFyYW1ldGVycy5nZXQoXCJQUkVMT0FERURfUkVHSVNUUllcIikpIHtcblxuICAgICAgICAgICAgdGhpcy5SZWdpc3RyeS5sb2FkRnJvbVN0cmluZyh0aGlzLlBhcmFtZXRlcnMuZ2V0KFwiUFJFTE9BREVEX1JFR0lTVFJZXCIpKTtcbiAgICAgICAgICAgIHRoaXMuUGFyYW1ldGVyc1snZGVsZXRlJ10oXCJQUkVMT0FERURfUkVHSVNUUllcIik7XG4gICAgICAgICAgICBzdGFydGVyRnVuYygpO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICB0aGlzLmxvYWRYbWxSZWdpc3RyeShmYWxzZSwgbnVsbCwgc3RhcnRlckZ1bmMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vYnNlcnZlKFwic2VydmVyX21lc3NhZ2VcIiwgZnVuY3Rpb24gKHhtbCkge1xuICAgICAgICAgICAgdmFyIHJlbG9hZCA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbCwgXCJ0cmVlL3JlcXVpcmVfcmVnaXN0cnlfcmVsb2FkXCIpO1xuICAgICAgICAgICAgaWYgKHJlbG9hZCkge1xuICAgICAgICAgICAgICAgIGlmIChyZWxvYWQuZ2V0QXR0cmlidXRlKFwicmVwb3NpdG9yeUlkXCIpICE9IF90aGlzMi5yZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLmxvYWRYbWxSZWdpc3RyeShmYWxzZSwgbnVsbCwgbnVsbCwgcmVsb2FkLmdldEF0dHJpYnV0ZShcInJlcG9zaXRvcnlJZFwiKSk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5yZXBvc2l0b3J5SWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWRzIHRoZSBYTUwgUmVnaXN0cnksIGFuIGltYWdlIG9mIHRoZSBhcHBsaWNhdGlvbiBpbiBpdHMgY3VycmVudCBzdGF0ZVxuICAgICAqIHNlbnQgYnkgdGhlIHNlcnZlci5cbiAgICAgKiBAcGFyYW0gc3luYyBCb29sZWFuIFdoZXRoZXIgdG8gc2VuZCBzeW5jaHJvbm91c2x5IG9yIG5vdC5cbiAgICAgKiBAcGFyYW0geFBhdGggU3RyaW5nIEFuIFhQYXRoIHRvIGxvYWQgb25seSBhIHN1YnBhcnQgb2YgdGhlIHJlZ2lzdHJ5XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUubG9hZFhtbFJlZ2lzdHJ5ID0gZnVuY3Rpb24gbG9hZFhtbFJlZ2lzdHJ5KHN5bmMpIHtcbiAgICAgICAgdmFyIHhQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGNvbXBsZXRlRnVuYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciB0YXJnZXRSZXBvc2l0b3J5SWQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIHRoaXMuUmVnaXN0cnkubG9hZCh4UGF0aCwgY29tcGxldGVGdW5jLCB0YXJnZXRSZXBvc2l0b3J5SWQgPT09IG51bGwgPyBNYXRoLnJhbmRvbSgpIDogdGFyZ2V0UmVwb3NpdG9yeUlkKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBYTUwgUmVnaXN0cnlcbiAgICAgKiBAcmV0dXJucyBEb2N1bWVudFxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldFhtbFJlZ2lzdHJ5ID0gZnVuY3Rpb24gZ2V0WG1sUmVnaXN0cnkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLlJlZ2lzdHJ5LmdldFhNTCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBjdXJyZW50IHJlcG9zaXRvcnkgKGZyb20gdGhlIGN1cnJlbnQgdXNlcikgYW5kIGxvYWQgaXQuXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUubG9hZEFjdGl2ZVJlcG9zaXRvcnkgPSBmdW5jdGlvbiBsb2FkQWN0aXZlUmVwb3NpdG9yeSgpIHtcbiAgICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgICAgdmFyIHJlcG9zaXRvcnlPYmplY3QgPSBuZXcgX21vZGVsUmVwb3NpdG9yeTJbJ2RlZmF1bHQnXShudWxsKTtcbiAgICAgICAgaWYgKHRoaXMudXNlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5sb2FkUmVwb3NpdG9yeShyZXBvc2l0b3J5T2JqZWN0KTtcbiAgICAgICAgICAgIHRoaXMuZmlyZShcInJlcG9zaXRvcnlfbGlzdF9yZWZyZXNoZWRcIiwgeyBsaXN0OiBmYWxzZSwgYWN0aXZlOiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXBJZCA9IHRoaXMudXNlci5nZXRBY3RpdmVSZXBvc2l0b3J5KCk7XG4gICAgICAgIHZhciByZXBMaXN0ID0gdGhpcy51c2VyLmdldFJlcG9zaXRvcmllc0xpc3QoKTtcbiAgICAgICAgcmVwb3NpdG9yeU9iamVjdCA9IHJlcExpc3QuZ2V0KHJlcElkKTtcblxuICAgICAgICBpZiAoIXJlcG9zaXRvcnlPYmplY3QpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnVzZXIubG9jaykge1xuICAgICAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzNC5Db250cm9sbGVyLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KF90aGlzNC5nZXRYbWxSZWdpc3RyeSgpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvY2sgPSBfdGhpczQudXNlci5sb2NrLnNwbGl0KFwiLFwiKS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpczQuQ29udHJvbGxlci5maXJlQWN0aW9uKGxvY2spO1xuICAgICAgICAgICAgICAgICAgICB9LCA1MCk7XG4gICAgICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxlcnQoXCJObyBhY3RpdmUgcmVwb3NpdG9yeSBmb3VuZCBmb3IgdXNlciFcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy51c2VyLmdldFByZWZlcmVuY2UoXCJwZW5kaW5nX2ZvbGRlclwiKSAmJiB0aGlzLnVzZXIuZ2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIpICE9IFwiLTFcIikge1xuXG4gICAgICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IHRoaXMudXNlci5nZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIik7XG4gICAgICAgICAgICB0aGlzLnVzZXIuc2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIsIFwiLTFcIik7XG4gICAgICAgICAgICB0aGlzLnVzZXIuc2F2ZVByZWZlcmVuY2UoXCJwZW5kaW5nX2ZvbGRlclwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubG9hZFJlcG9zaXRvcnkocmVwb3NpdG9yeU9iamVjdCk7XG4gICAgICAgIHRoaXMuZmlyZShcInJlcG9zaXRvcnlfbGlzdF9yZWZyZXNoZWRcIiwgeyBsaXN0OiByZXBMaXN0LCBhY3RpdmU6IHJlcElkIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWZyZXNoIHRoZSByZXBvc2l0b3JpZXMgbGlzdCBmb3IgdGhlIGN1cnJlbnQgdXNlclxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnJlbG9hZFJlcG9zaXRvcmllc0xpc3QgPSBmdW5jdGlvbiByZWxvYWRSZXBvc2l0b3JpZXNMaXN0KCkge1xuICAgICAgICB2YXIgX3RoaXM1ID0gdGhpcztcblxuICAgICAgICBpZiAoIXRoaXMudXNlcikgcmV0dXJuO1xuICAgICAgICB0aGlzLm9ic2VydmVPbmNlKFwicmVnaXN0cnlfcGFydF9sb2FkZWRcIiwgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChkYXRhICE9IFwidXNlci9yZXBvc2l0b3JpZXNcIikgcmV0dXJuO1xuICAgICAgICAgICAgX3RoaXM1LnVwZGF0ZVVzZXIoX3RoaXM1LlJlZ2lzdHJ5LnBhcnNlVXNlcigpKTtcbiAgICAgICAgICAgIF90aGlzNS5maXJlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCB7XG4gICAgICAgICAgICAgICAgbGlzdDogX3RoaXM1LnVzZXIuZ2V0UmVwb3NpdG9yaWVzTGlzdCgpLFxuICAgICAgICAgICAgICAgIGFjdGl2ZTogX3RoaXM1LnVzZXIuZ2V0QWN0aXZlUmVwb3NpdG9yeSgpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBcInVzZXIvcmVwb3NpdG9yaWVzXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgUmVwb3NpdG9yeSBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSByZXBvc2l0b3J5IFJlcG9zaXRvcnlcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIGxvYWRSZXBvc2l0b3J5KHJlcG9zaXRvcnkpIHtcbiAgICAgICAgdmFyIF90aGlzNiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMucmVwb3NpdG9yeUlkICE9IG51bGwgJiYgdGhpcy5yZXBvc2l0b3J5SWQgPT0gcmVwb3NpdG9yeS5nZXRJZCgpKSB7XG4gICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5kZWJ1ZygnUmVwb3NpdG9yeSBhbHJlYWR5IGxvYWRlZCwgZG8gbm90aGluZycpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0U2VsZWN0ZWROb2RlcyhbXSk7XG4gICAgICAgIGlmIChyZXBvc2l0b3J5ID09IG51bGwpIHJldHVybjtcblxuICAgICAgICByZXBvc2l0b3J5LmxvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgdmFyIHJlcG9zaXRvcnlJZCA9IHJlcG9zaXRvcnkuZ2V0SWQoKTtcbiAgICAgICAgdmFyIG5ld0ljb24gPSByZXBvc2l0b3J5LmdldEljb24oKTtcblxuICAgICAgICB2YXIgcHJvdmlkZXJEZWYgPSByZXBvc2l0b3J5LmdldE5vZGVQcm92aWRlckRlZigpO1xuICAgICAgICB2YXIgcm9vdE5vZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChwcm92aWRlckRlZiAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgcHJvdmlkZXIgPSBldmFsKCduZXcgJyArIHByb3ZpZGVyRGVmLm5hbWUgKyAnKCknKTtcbiAgICAgICAgICAgIGlmIChwcm92aWRlckRlZi5vcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcHJvdmlkZXIuaW5pdFByb3ZpZGVyKHByb3ZpZGVyRGVmLm9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRBanhwTm9kZVByb3ZpZGVyKHByb3ZpZGVyKTtcbiAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKFwiL1wiLCBmYWxzZSwgcmVwb3NpdG9yeS5nZXRMYWJlbCgpLCBuZXdJY29uLCBwcm92aWRlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByb290Tm9kZSA9IG5ldyBfbW9kZWxBanhwTm9kZTJbJ2RlZmF1bHQnXShcIi9cIiwgZmFsc2UsIHJlcG9zaXRvcnkuZ2V0TGFiZWwoKSwgbmV3SWNvbik7XG4gICAgICAgICAgICAvLyBEZWZhdWx0XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnNldEFqeHBOb2RlUHJvdmlkZXIobmV3IF9tb2RlbFJlbW90ZU5vZGVQcm92aWRlcjJbJ2RlZmF1bHQnXSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpbml0TG9hZFJlcCA9IHRoaXMuX2luaXRMb2FkUmVwICYmIHRoaXMuX2luaXRMb2FkUmVwICE9PSAnLycgPyB0aGlzLl9pbml0TG9hZFJlcC52YWx1ZU9mKCkgOiBudWxsO1xuICAgICAgICB2YXIgZmlyc3RMb2FkT2JzID0gZnVuY3Rpb24gZmlyc3RMb2FkT2JzKCkge307XG4gICAgICAgIGlmIChpbml0TG9hZFJlcCkge1xuICAgICAgICAgICAgZmlyc3RMb2FkT2JzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzNi5nb1RvKGluaXRMb2FkUmVwKTtcbiAgICAgICAgICAgICAgICBfdGhpczYuX2luaXRMb2FkUmVwID0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnNldFJvb3ROb2RlKHJvb3ROb2RlKTtcbiAgICAgICAgcm9vdE5vZGUub2JzZXJ2ZU9uY2UoJ2ZpcnN0X2xvYWQnLCAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5ub3RpZnkoJ2NvbnRleHRfY2hhbmdlZCcsIHJvb3ROb2RlKTtcbiAgICAgICAgICAgIGZpcnN0TG9hZE9icygpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5yZXBvc2l0b3J5SWQgPSByZXBvc2l0b3J5SWQ7XG4gICAgICAgIHJvb3ROb2RlLmxvYWQoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVxdWlyZSBhIGNvbnRleHQgY2hhbmdlIHRvIHRoZSBnaXZlbiBwYXRoXG4gICAgICogQHBhcmFtIG5vZGVPclBhdGggQWp4cE5vZGV8U3RyaW5nIEEgbm9kZSBvciBhIHBhdGhcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nb1RvID0gZnVuY3Rpb24gZ29Ubyhub2RlT3JQYXRoKSB7XG4gICAgICAgIHZhciBnb3RvTm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIHBhdGggPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0eXBlb2Ygbm9kZU9yUGF0aCA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICBwYXRoID0gbm9kZU9yUGF0aDtcbiAgICAgICAgICAgIGdvdG9Ob2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKG5vZGVPclBhdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ290b05vZGUgPSBub2RlT3JQYXRoO1xuICAgICAgICAgICAgcGF0aCA9IGdvdG9Ob2RlLmdldFBhdGgoKTtcbiAgICAgICAgICAgIGlmIChub2RlT3JQYXRoLmdldE1ldGFkYXRhKCkuaGFzKFwicmVwb3NpdG9yeV9pZFwiKSAmJiBub2RlT3JQYXRoLmdldE1ldGFkYXRhKCkuZ2V0KFwicmVwb3NpdG9yeV9pZFwiKSAhPSB0aGlzLnJlcG9zaXRvcnlJZCAmJiBub2RlT3JQYXRoLmdldEFqeHBNaW1lKCkgIT0gXCJyZXBvc2l0b3J5XCIgJiYgbm9kZU9yUGF0aC5nZXRBanhwTWltZSgpICE9IFwicmVwb3NpdG9yeV9lZGl0YWJsZVwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudXNlcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVzZXIuc2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIsIG5vZGVPclBhdGguZ2V0UGF0aCgpKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5pdExvYWRSZXAgPSBub2RlT3JQYXRoLmdldFBhdGgoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyUmVwb3NpdG9yeUNoYW5nZShub2RlT3JQYXRoLmdldE1ldGFkYXRhKCkuZ2V0KFwicmVwb3NpdG9yeV9pZFwiKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9yZXBvc2l0b3J5Q3VycmVudGx5U3dpdGNoaW5nICYmIHRoaXMudXNlcikge1xuICAgICAgICAgICAgdGhpcy51c2VyLnNldFByZWZlcmVuY2UoXCJwZW5kaW5nX2ZvbGRlclwiLCBnb3RvTm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICAgICAgdGhpcy5faW5pdExvYWRSZXAgPSBnb3RvTm9kZS5nZXRQYXRoKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzLl9jb250ZXh0SG9sZGVyLmdldENvbnRleHROb2RlKCk7XG4gICAgICAgIGlmIChjdXJyZW50ICYmIGN1cnJlbnQuZ2V0UGF0aCgpID09IHBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGF0aCA9PT0gXCJcIiB8fCBwYXRoID09PSBcIi9cIikge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5yZXF1aXJlQ29udGV4dENoYW5nZSh0aGlzLl9jb250ZXh0SG9sZGVyLmdldFJvb3ROb2RlKCkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ290b05vZGUgPSBnb3RvTm9kZS5maW5kSW5BcmJvKHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Um9vdE5vZGUoKSk7XG4gICAgICAgICAgICBpZiAoZ290b05vZGUpIHtcbiAgICAgICAgICAgICAgICAvLyBOb2RlIGlzIGFscmVhZHkgaGVyZVxuICAgICAgICAgICAgICAgIGlmICghZ290b05vZGUuaXNCcm93c2FibGUoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnNldFBlbmRpbmdTZWxlY3Rpb24oX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUocGF0aCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnJlcXVpcmVDb250ZXh0Q2hhbmdlKGdvdG9Ob2RlLmdldFBhcmVudCgpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnJlcXVpcmVDb250ZXh0Q2hhbmdlKGdvdG9Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIG9uIHNlcnZlciBpZiBpdCBkb2VzIGV4aXN0LCB0aGVuIGxvYWRcbiAgICAgICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLmxvYWRQYXRoSW5mb0FzeW5jKHBhdGgsIChmdW5jdGlvbiAoZm91bmROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZm91bmROb2RlLmlzQnJvd3NhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0UGVuZGluZ1NlbGVjdGlvbihfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShwYXRoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBnb3RvTm9kZSA9IG5ldyBfbW9kZWxBanhwTm9kZTJbJ2RlZmF1bHQnXShfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKHBhdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdvdG9Ob2RlID0gZm91bmROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoZ290b05vZGUpO1xuICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoYW5nZSB0aGUgcmVwb3NpdG9yeSBvZiB0aGUgY3VycmVudCB1c2VyIGFuZCByZWxvYWQgbGlzdCBhbmQgY3VycmVudC5cbiAgICAgKiBAcGFyYW0gcmVwb3NpdG9yeUlkIFN0cmluZyBJZCBvZiB0aGUgbmV3IHJlcG9zaXRvcnlcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS50cmlnZ2VyUmVwb3NpdG9yeUNoYW5nZSA9IGZ1bmN0aW9uIHRyaWdnZXJSZXBvc2l0b3J5Q2hhbmdlKHJlcG9zaXRvcnlJZCwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzNyA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy5maXJlKFwidHJpZ2dlcl9yZXBvc2l0b3J5X3N3aXRjaFwiKTtcbiAgICAgICAgdGhpcy5fcmVwb3NpdG9yeUN1cnJlbnRseVN3aXRjaGluZyA9IHRydWU7XG4gICAgICAgIHZhciBvbkNvbXBsZXRlID0gZnVuY3Rpb24gb25Db21wbGV0ZSh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnQucmVzcG9uc2VYTUwpIHtcbiAgICAgICAgICAgICAgICBfdGhpczcuQXBpQ2xpZW50LnBhcnNlWG1sTWVzc2FnZSh0cmFuc3BvcnQucmVzcG9uc2VYTUwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXM3LmxvYWRYbWxSZWdpc3RyeShmYWxzZSwgbnVsbCwgbnVsbCwgcmVwb3NpdG9yeUlkKTtcbiAgICAgICAgICAgIF90aGlzNy5yZXBvc2l0b3J5SWQgPSBudWxsO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09IFwiZnVuY3Rpb25cIikgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIF90aGlzNy5fcmVwb3NpdG9yeUN1cnJlbnRseVN3aXRjaGluZyA9IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciByb290ID0gdGhpcy5fY29udGV4dEhvbGRlci5nZXRSb290Tm9kZSgpO1xuICAgICAgICBpZiAocm9vdCkge1xuICAgICAgICAgICAgcm9vdC5jbGVhcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuQXBpQ2xpZW50LnN3aXRjaFJlcG9zaXRvcnkocmVwb3NpdG9yeUlkLCBvbkNvbXBsZXRlKTtcbiAgICB9O1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldFBsdWdpbkNvbmZpZ3MgPSBmdW5jdGlvbiBnZXRQbHVnaW5Db25maWdzKHBsdWdpblF1ZXJ5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLlJlZ2lzdHJ5LmdldFBsdWdpbkNvbmZpZ3MocGx1Z2luUXVlcnkpO1xuICAgIH07XG5cbiAgICBQeWRpby5wcm90b3R5cGUubGlzdExhbmd1YWdlc1dpdGhDYWxsYmFjayA9IGZ1bmN0aW9uIGxpc3RMYW5ndWFnZXNXaXRoQ2FsbGJhY2soY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGxhbmdzID0gdGhpcy5QYXJhbWV0ZXJzLmdldChcImF2YWlsYWJsZUxhbmd1YWdlc1wiKSB8fCB7IFwiZW5cIjogXCJEZWZhdWx0XCIgfTtcbiAgICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzLmN1cnJlbnRMYW5ndWFnZTtcbiAgICAgICAgT2JqZWN0LmtleXMobGFuZ3MpLnNvcnQoKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgY2FsbGJhY2soa2V5LCBsYW5nc1trZXldLCBjdXJyZW50ID09PSBrZXkpO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVsb2FkIGFsbCBtZXNzYWdlcyBmcm9tIHNlcnZlciBhbmQgdHJpZ2dlciB1cGRhdGVJMThuVGFnc1xuICAgICAqIEBwYXJhbSBuZXdMYW5ndWFnZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkSTE4Tk1lc3NhZ2VzID0gZnVuY3Rpb24gbG9hZEkxOE5NZXNzYWdlcyhuZXdMYW5ndWFnZSkge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIHRoaXMuQXBpQ2xpZW50LnN3aXRjaExhbmd1YWdlKG5ld0xhbmd1YWdlLCAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pIHtcbiAgICAgICAgICAgICAgICB0aGlzLk1lc3NhZ2VIYXNoID0gdHJhbnNwb3J0LnJlc3BvbnNlSlNPTjtcbiAgICAgICAgICAgICAgICBpZiAod2luZG93ICYmIHdpbmRvdy5NZXNzYWdlSGFzaCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuTWVzc2FnZUhhc2ggPSB0aGlzLk1lc3NhZ2VIYXNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5NZXNzYWdlSGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5NZXNzYWdlSGFzaC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLk1lc3NhZ2VIYXNoW2tleV0gPSB0aGlzLk1lc3NhZ2VIYXNoW2tleV0ucmVwbGFjZShcIlxcXFxuXCIsIFwiXFxuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuQ29udHJvbGxlci5yZWZyZXNoR3VpQWN0aW9uc0kxOG4oKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRYbWxSZWdpc3RyeSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNvbnRleHRSZWZyZXNoKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TGFuZ3VhZ2UgPSBuZXdMYW5ndWFnZTtcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIG1haW4gY29udHJvbGxlclxuICAgICAqIEByZXR1cm5zIEFjdGlvbk1hbmFnZXJcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRDb250cm9sbGVyID0gZnVuY3Rpb24gZ2V0Q29udHJvbGxlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuQ29udHJvbGxlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRGlzcGxheSBhbiBpbmZvcm1hdGlvbiBvciBlcnJvciBtZXNzYWdlIHRvIHRoZSB1c2VyXG4gICAgICogQHBhcmFtIG1lc3NhZ2VUeXBlIFN0cmluZyBFUlJPUiBvciBTVUNDRVNTXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgU3RyaW5nIHRoZSBtZXNzYWdlXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZGlzcGxheU1lc3NhZ2UgPSBmdW5jdGlvbiBkaXNwbGF5TWVzc2FnZShtZXNzYWdlVHlwZSwgbWVzc2FnZSkge1xuICAgICAgICB2YXIgdXJscyA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLnBhcnNlVXJsKG1lc3NhZ2UpO1xuICAgICAgICBpZiAodXJscy5sZW5ndGggJiYgdGhpcy51c2VyICYmIHRoaXMudXNlci5yZXBvc2l0b3JpZXMpIHtcbiAgICAgICAgICAgIHVybHMuZm9yRWFjaCgoZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcG8gPSB0aGlzLnVzZXIucmVwb3NpdG9yaWVzLmdldChtYXRjaC5ob3N0KTtcbiAgICAgICAgICAgICAgICBpZiAoIXJlcG8pIHJldHVybjtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gbWVzc2FnZS5yZXBsYWNlKG1hdGNoLnVybCwgcmVwby5sYWJlbCArIFwiOlwiICsgbWF0Y2gucGF0aCArIG1hdGNoLmZpbGUpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lc3NhZ2VUeXBlID09ICdFUlJPUicpIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKG1lc3NhZ2UpO2Vsc2UgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10ubG9nKG1lc3NhZ2UpO1xuICAgICAgICBpZiAodGhpcy5VSSkge1xuICAgICAgICAgICAgdGhpcy5VSS5kaXNwbGF5TWVzc2FnZShtZXNzYWdlVHlwZSwgbWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgKlxuICAgICAqICAgICAgICAgIFBST1hZIE1FVEhPRFMgRk9SIERBVEFNT0RFTFxuICAgICAqXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICAgIC8qKlxuICAgICAqIEFjY2Vzc29yIGZvciB1cGRhdGluZyB0aGUgZGF0YW1vZGVsIGNvbnRleHRcbiAgICAgKiBAcGFyYW0gYWp4cENvbnRleHROb2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIGFqeHBTZWxlY3RlZE5vZGVzIEFqeHBOb2RlW11cbiAgICAgKiBAcGFyYW0gc2VsZWN0aW9uU291cmNlIFN0cmluZ1xuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnVwZGF0ZUNvbnRleHREYXRhID0gZnVuY3Rpb24gdXBkYXRlQ29udGV4dERhdGEoYWp4cENvbnRleHROb2RlLCBhanhwU2VsZWN0ZWROb2Rlcywgc2VsZWN0aW9uU291cmNlKSB7XG4gICAgICAgIGlmIChhanhwQ29udGV4dE5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoYWp4cENvbnRleHROb2RlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWp4cFNlbGVjdGVkTm9kZXMpIHtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0U2VsZWN0ZWROb2RlcyhhanhwU2VsZWN0ZWROb2Rlcywgc2VsZWN0aW9uU291cmNlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBBanhwRGF0YU1vZGVsXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0Q29udGV4dEhvbGRlciA9IGZ1bmN0aW9uIGdldENvbnRleHRIb2xkZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250ZXh0SG9sZGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldENvbnRleHROb2RlID0gZnVuY3Rpb24gZ2V0Q29udGV4dE5vZGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250ZXh0SG9sZGVyLmdldENvbnRleHROb2RlKCkgfHwgbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKFwiXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBBanhwRGF0YU1vZGVsXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0VXNlclNlbGVjdGlvbiA9IGZ1bmN0aW9uIGdldFVzZXJTZWxlY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb250ZXh0SG9sZGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBY2Nlc3NvciBmb3IgZGF0YW1vZGVsLnJlcXVpcmVDb250ZXh0Q2hhbmdlKClcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5maXJlQ29udGV4dFJlZnJlc2ggPSBmdW5jdGlvbiBmaXJlQ29udGV4dFJlZnJlc2goKSB7XG4gICAgICAgIHRoaXMuZ2V0Q29udGV4dEhvbGRlcigpLnJlcXVpcmVDb250ZXh0Q2hhbmdlKHRoaXMuZ2V0Q29udGV4dE5vZGUoKSwgdHJ1ZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFjY2Vzc29yIGZvciBkYXRhbW9kZWwucmVxdWlyZUNvbnRleHRDaGFuZ2UoKVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmZpcmVOb2RlUmVmcmVzaCA9IGZ1bmN0aW9uIGZpcmVOb2RlUmVmcmVzaChub2RlUGF0aE9yTm9kZSwgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB0aGlzLmdldENvbnRleHRIb2xkZXIoKS5yZXF1aXJlTm9kZVJlbG9hZChub2RlUGF0aE9yTm9kZSwgY29tcGxldGVDYWxsYmFjayk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFjY2Vzc29yIGZvciBkYXRhbW9kZWwucmVxdWlyZUNvbnRleHRDaGFuZ2UoKVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmZpcmVDb250ZXh0VXAgPSBmdW5jdGlvbiBmaXJlQ29udGV4dFVwKCkge1xuICAgICAgICBpZiAodGhpcy5nZXRDb250ZXh0Tm9kZSgpLmlzUm9vdCgpKSByZXR1cm47XG4gICAgICAgIHRoaXMudXBkYXRlQ29udGV4dERhdGEodGhpcy5nZXRDb250ZXh0Tm9kZSgpLmdldFBhcmVudCgpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUHJveHkgdG8gUmVzb3VyY2VzTWFuYWdlci5yZXF1aXJlTGliIGZvciBlYXNlIG9mIHdyaXRpbmdcbiAgICAgKiBAcGFyYW0gbW9kdWxlXG4gICAgICogQHBhcmFtIHByb21pc2VcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cblxuICAgIFB5ZGlvLnJlcXVpcmVMaWIgPSBmdW5jdGlvbiByZXF1aXJlTGliKG1vZHVsZSkge1xuICAgICAgICB2YXIgcHJvbWlzZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIHJldHVybiByZXF1aXJlKCdweWRpby9odHRwL3Jlc291cmNlcy1tYW5hZ2VyJykucmVxdWlyZUxpYihtb2R1bGUsIHByb21pc2UpO1xuICAgIH07XG5cbiAgICByZXR1cm4gUHlkaW87XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBQeWRpbztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIl19