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+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xuXG4ndXNlIHN0cmljdCdcblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJ2Jhc2U2NC1qcycpXG52YXIgaWVlZTc1NCA9IHJlcXVpcmUoJ2llZWU3NTQnKVxudmFyIGlzQXJyYXkgPSByZXF1aXJlKCdpc2FycmF5JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbnZhciByb290UGFyZW50ID0ge31cblxuLyoqXG4gKiBJZiBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgVXNlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiAobW9zdCBjb21wYXRpYmxlLCBldmVuIElFNilcbiAqXG4gKiBCcm93c2VycyB0aGF0IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssIENocm9tZSA3KywgU2FmYXJpIDUuMSssXG4gKiBPcGVyYSAxMS42KywgaU9TIDQuMisuXG4gKlxuICogRHVlIHRvIHZhcmlvdXMgYnJvd3NlciBidWdzLCBzb21ldGltZXMgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiB3aWxsIGJlIHVzZWQgZXZlblxuICogd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyB0eXBlZCBhcnJheXMuXG4gKlxuICogTm90ZTpcbiAqXG4gKiAgIC0gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLFxuICogICAgIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njk1NDM4LlxuICpcbiAqICAgLSBTYWZhcmkgNS03IGxhY2tzIHN1cHBvcnQgZm9yIGNoYW5naW5nIHRoZSBgT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3RvcmAgcHJvcGVydHlcbiAqICAgICBvbiBvYmplY3RzLlxuICpcbiAqICAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAgLSBJRTEwIGhhcyBhIGJyb2tlbiBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYXJyYXlzIG9mXG4gKiAgICAgaW5jb3JyZWN0IGxlbmd0aCBpbiBzb21lIHNpdHVhdGlvbnMuXG5cbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGAgdG8gYGZhbHNlYCBzbyB0aGV5XG4gKiBnZXQgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiwgd2hpY2ggaXMgc2xvd2VyIGJ1dCBiZWhhdmVzIGNvcnJlY3RseS5cbiAqL1xuQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgPSBnbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVCAhPT0gdW5kZWZpbmVkXG4gID8gZ2xvYmFsLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgOiB0eXBlZEFycmF5U3VwcG9ydCgpXG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgZnVuY3Rpb24gQmFyICgpIHt9XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgYXJyLmZvbyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH1cbiAgICBhcnIuY29uc3RydWN0b3IgPSBCYXJcbiAgICByZXR1cm4gYXJyLmZvbygpID09PSA0MiAmJiAvLyB0eXBlZCBhcnJheSBpbnN0YW5jZXMgY2FuIGJlIGF1Z21lbnRlZFxuICAgICAgICBhcnIuY29uc3RydWN0b3IgPT09IEJhciAmJiAvLyBjb25zdHJ1Y3RvciBjYW4gYmUgc2V0XG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgJiYgLy8gY2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gICAgICAgIGFyci5zdWJhcnJheSgxLCAxKS5ieXRlTGVuZ3RoID09PSAwIC8vIGllMTAgaGFzIGJyb2tlbiBgc3ViYXJyYXlgXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5mdW5jdGlvbiBrTWF4TGVuZ3RoICgpIHtcbiAgcmV0dXJuIEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUXG4gICAgPyAweDdmZmZmZmZmXG4gICAgOiAweDNmZmZmZmZmXG59XG5cbi8qKlxuICogQ2xhc3M6IEJ1ZmZlclxuICogPT09PT09PT09PT09PVxuICpcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgYXJlIGF1Z21lbnRlZFxuICogd2l0aCBmdW5jdGlvbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgQVBJIGZ1bmN0aW9ucy4gV2UgdXNlXG4gKiBgVWludDhBcnJheWAgc28gdGhhdCBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdCByZXR1cm5zXG4gKiBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBCeSBhdWdtZW50aW5nIHRoZSBpbnN0YW5jZXMsIHdlIGNhbiBhdm9pZCBtb2RpZnlpbmcgdGhlIGBVaW50OEFycmF5YFxuICogcHJvdG90eXBlLlxuICovXG5mdW5jdGlvbiBCdWZmZXIgKGFyZykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSkge1xuICAgIC8vIEF2b2lkIGdvaW5nIHRocm91Z2ggYW4gQXJndW1lbnRzQWRhcHRvclRyYW1wb2xpbmUgaW4gdGhlIGNvbW1vbiBjYXNlLlxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkgcmV0dXJuIG5ldyBCdWZmZXIoYXJnLCBhcmd1bWVudHNbMV0pXG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoYXJnKVxuICB9XG5cbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXMubGVuZ3RoID0gMFxuICAgIHRoaXMucGFyZW50ID0gdW5kZWZpbmVkXG4gIH1cblxuICAvLyBDb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGZyb21OdW1iZXIodGhpcywgYXJnKVxuICB9XG5cbiAgLy8gU2xpZ2h0bHkgbGVzcyBjb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZyb21TdHJpbmcodGhpcywgYXJnLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6ICd1dGY4JylcbiAgfVxuXG4gIC8vIFVudXN1YWwuXG4gIHJldHVybiBmcm9tT2JqZWN0KHRoaXMsIGFyZylcbn1cblxuZnVuY3Rpb24gZnJvbU51bWJlciAodGhhdCwgbGVuZ3RoKSB7XG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGggPCAwID8gMCA6IGNoZWNrZWQobGVuZ3RoKSB8IDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGF0W2ldID0gMFxuICAgIH1cbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nICh0aGF0LCBzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnIHx8IGVuY29kaW5nID09PSAnJykgZW5jb2RpbmcgPSAndXRmOCdcblxuICAvLyBBc3N1bXB0aW9uOiBieXRlTGVuZ3RoKCkgcmV0dXJuIHZhbHVlIGlzIGFsd2F5cyA8IGtNYXhMZW5ndGguXG4gIHZhciBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuXG4gIHRoYXQud3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdCAodGhhdCwgb2JqZWN0KSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqZWN0KSkgcmV0dXJuIGZyb21CdWZmZXIodGhhdCwgb2JqZWN0KVxuXG4gIGlmIChpc0FycmF5KG9iamVjdCkpIHJldHVybiBmcm9tQXJyYXkodGhhdCwgb2JqZWN0KVxuXG4gIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211c3Qgc3RhcnQgd2l0aCBudW1iZXIsIGJ1ZmZlciwgYXJyYXkgb3Igc3RyaW5nJylcbiAgfVxuXG4gIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKG9iamVjdC5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgcmV0dXJuIGZyb21UeXBlZEFycmF5KHRoYXQsIG9iamVjdClcbiAgICB9XG4gICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHRoYXQsIG9iamVjdClcbiAgICB9XG4gIH1cblxuICBpZiAob2JqZWN0Lmxlbmd0aCkgcmV0dXJuIGZyb21BcnJheUxpa2UodGhhdCwgb2JqZWN0KVxuXG4gIHJldHVybiBmcm9tSnNvbk9iamVjdCh0aGF0LCBvYmplY3QpXG59XG5cbmZ1bmN0aW9uIGZyb21CdWZmZXIgKHRoYXQsIGJ1ZmZlcikge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChidWZmZXIubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgYnVmZmVyLmNvcHkodGhhdCwgMCwgMCwgbGVuZ3RoKVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXkgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG4vLyBEdXBsaWNhdGUgb2YgZnJvbUFycmF5KCkgdG8ga2VlcCBmcm9tQXJyYXkoKSBtb25vbW9ycGhpYy5cbmZ1bmN0aW9uIGZyb21UeXBlZEFycmF5ICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICAvLyBUcnVuY2F0aW5nIHRoZSBlbGVtZW50cyBpcyBwcm9iYWJseSBub3Qgd2hhdCBwZW9wbGUgZXhwZWN0IGZyb20gdHlwZWRcbiAgLy8gYXJyYXlzIHdpdGggQllURVNfUEVSX0VMRU1FTlQgPiAxIGJ1dCBpdCdzIGNvbXBhdGlibGUgd2l0aCB0aGUgYmVoYXZpb3JcbiAgLy8gb2YgdGhlIG9sZCBCdWZmZXIgY29uc3RydWN0b3IuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIgKHRoYXQsIGFycmF5KSB7XG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIGFycmF5LmJ5dGVMZW5ndGhcbiAgICB0aGF0ID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGFycmF5KSlcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgdGhhdCA9IGZyb21UeXBlZEFycmF5KHRoYXQsIG5ldyBVaW50OEFycmF5KGFycmF5KSlcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlMaWtlICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuLy8gRGVzZXJpYWxpemUgeyB0eXBlOiAnQnVmZmVyJywgZGF0YTogWzEsMiwzLC4uLl0gfSBpbnRvIGEgQnVmZmVyIG9iamVjdC5cbi8vIFJldHVybnMgYSB6ZXJvLWxlbmd0aCBidWZmZXIgZm9yIGlucHV0cyB0aGF0IGRvbid0IGNvbmZvcm0gdG8gdGhlIHNwZWMuXG5mdW5jdGlvbiBmcm9tSnNvbk9iamVjdCAodGhhdCwgb2JqZWN0KSB7XG4gIHZhciBhcnJheVxuICB2YXIgbGVuZ3RoID0gMFxuXG4gIGlmIChvYmplY3QudHlwZSA9PT0gJ0J1ZmZlcicgJiYgaXNBcnJheShvYmplY3QuZGF0YSkpIHtcbiAgICBhcnJheSA9IG9iamVjdC5kYXRhXG4gICAgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB9XG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICBCdWZmZXIucHJvdG90eXBlLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXkucHJvdG90eXBlXG4gIEJ1ZmZlci5fX3Byb3RvX18gPSBVaW50OEFycmF5XG59IGVsc2Uge1xuICAvLyBwcmUtc2V0IGZvciB2YWx1ZXMgdGhhdCBtYXkgZXhpc3QgaW4gdGhlIGZ1dHVyZVxuICBCdWZmZXIucHJvdG90eXBlLmxlbmd0aCA9IHVuZGVmaW5lZFxuICBCdWZmZXIucHJvdG90eXBlLnBhcmVudCA9IHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBhbGxvY2F0ZSAodGhhdCwgbGVuZ3RoKSB7XG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoYXQgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkobGVuZ3RoKSlcbiAgICB0aGF0Ll9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgdGhhdC5sZW5ndGggPSBsZW5ndGhcbiAgICB0aGF0Ll9pc0J1ZmZlciA9IHRydWVcbiAgfVxuXG4gIHZhciBmcm9tUG9vbCA9IGxlbmd0aCAhPT0gMCAmJiBsZW5ndGggPD0gQnVmZmVyLnBvb2xTaXplID4+PiAxXG4gIGlmIChmcm9tUG9vbCkgdGhhdC5wYXJlbnQgPSByb290UGFyZW50XG5cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gY2hlY2tlZCAobGVuZ3RoKSB7XG4gIC8vIE5vdGU6IGNhbm5vdCB1c2UgYGxlbmd0aCA8IGtNYXhMZW5ndGhgIGhlcmUgYmVjYXVzZSB0aGF0IGZhaWxzIHdoZW5cbiAgLy8gbGVuZ3RoIGlzIE5hTiAod2hpY2ggaXMgb3RoZXJ3aXNlIGNvZXJjZWQgdG8gemVyby4pXG4gIGlmIChsZW5ndGggPj0ga01heExlbmd0aCgpKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemU6IDB4JyArIGtNYXhMZW5ndGgoKS50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcbiAgfVxuICByZXR1cm4gbGVuZ3RoIHwgMFxufVxuXG5mdW5jdGlvbiBTbG93QnVmZmVyIChzdWJqZWN0LCBlbmNvZGluZykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU2xvd0J1ZmZlcikpIHJldHVybiBuZXcgU2xvd0J1ZmZlcihzdWJqZWN0LCBlbmNvZGluZylcblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihzdWJqZWN0LCBlbmNvZGluZylcbiAgZGVsZXRlIGJ1Zi5wYXJlbnRcbiAgcmV0dXJuIGJ1ZlxufVxuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbiBpc0J1ZmZlciAoYikge1xuICByZXR1cm4gISEoYiAhPSBudWxsICYmIGIuX2lzQnVmZmVyKVxufVxuXG5CdWZmZXIuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGEsIGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYSkgfHwgIUJ1ZmZlci5pc0J1ZmZlcihiKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGEgPT09IGIpIHJldHVybiAwXG5cbiAgdmFyIHggPSBhLmxlbmd0aFxuICB2YXIgeSA9IGIubGVuZ3RoXG5cbiAgdmFyIGkgPSAwXG4gIHZhciBsZW4gPSBNYXRoLm1pbih4LCB5KVxuICB3aGlsZSAoaSA8IGxlbikge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSBicmVha1xuXG4gICAgKytpXG4gIH1cblxuICBpZiAoaSAhPT0gbGVuKSB7XG4gICAgeCA9IGFbaV1cbiAgICB5ID0gYltpXVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG5CdWZmZXIuaXNFbmNvZGluZyA9IGZ1bmN0aW9uIGlzRW5jb2RpbmcgKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICdyYXcnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gY29uY2F0IChsaXN0LCBsZW5ndGgpIHtcbiAgaWYgKCFpc0FycmF5KGxpc3QpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0IGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycy4nKVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgQnVmZmVyKDApXG4gIH1cblxuICB2YXIgaVxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBsZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxlbmd0aCArPSBsaXN0W2ldLmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKGxlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgaXRlbSA9IGxpc3RbaV1cbiAgICBpdGVtLmNvcHkoYnVmLCBwb3MpXG4gICAgcG9zICs9IGl0ZW0ubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykgc3RyaW5nID0gJycgKyBzdHJpbmdcblxuICB2YXIgbGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAobGVuID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIFVzZSBhIGZvciBsb29wIHRvIGF2b2lkIHJlY3Vyc2lvblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgIC8vIERlcHJlY2F0ZWRcbiAgICAgIGNhc2UgJ3Jhdyc6XG4gICAgICBjYXNlICdyYXdzJzpcbiAgICAgICAgcmV0dXJuIGxlblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIGxlbiAqIDJcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBsZW4gPj4+IDFcbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aCAvLyBhc3N1bWUgdXRmOFxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuQnVmZmVyLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICBzdGFydCA9IHN0YXJ0IHwgMFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPT09IEluZmluaXR5ID8gdGhpcy5sZW5ndGggOiBlbmQgfCAwXG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcbiAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKGVuZCA8PSBzdGFydCkgcmV0dXJuICcnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyAoKSB7XG4gIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCB8IDBcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgdmFyIHN0ciA9ICcnXG4gIHZhciBtYXggPSBleHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTXG4gIGlmICh0aGlzLmxlbmd0aCA+IDApIHtcbiAgICBzdHIgPSB0aGlzLnRvU3RyaW5nKCdoZXgnLCAwLCBtYXgpLm1hdGNoKC8uezJ9L2cpLmpvaW4oJyAnKVxuICAgIGlmICh0aGlzLmxlbmd0aCA+IG1heCkgc3RyICs9ICcgLi4uICdcbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiAwXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICBieXRlT2Zmc2V0ID4+PSAwXG5cbiAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gLTFcbiAgaWYgKGJ5dGVPZmZzZXQgPj0gdGhpcy5sZW5ndGgpIHJldHVybiAtMVxuXG4gIC8vIE5lZ2F0aXZlIG9mZnNldHMgc3RhcnQgZnJvbSB0aGUgZW5kIG9mIHRoZSBidWZmZXJcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwKSBieXRlT2Zmc2V0ID0gTWF0aC5tYXgodGhpcy5sZW5ndGggKyBieXRlT2Zmc2V0LCAwKVxuXG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIGlmICh2YWwubGVuZ3RoID09PSAwKSByZXR1cm4gLTEgLy8gc3BlY2lhbCBjYXNlOiBsb29raW5nIGZvciBlbXB0eSBzdHJpbmcgYWx3YXlzIGZhaWxzXG4gICAgcmV0dXJuIFN0cmluZy5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbCkpIHtcbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YodGhpcywgWyB2YWwgXSwgYnl0ZU9mZnNldClcbiAgfVxuXG4gIGZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgICB2YXIgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yICh2YXIgaSA9IDA7IGJ5dGVPZmZzZXQgKyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoYXJyW2J5dGVPZmZzZXQgKyBpXSA9PT0gdmFsW2ZvdW5kSW5kZXggPT09IC0xID8gMCA6IGkgLSBmb3VuZEluZGV4XSkge1xuICAgICAgICBpZiAoZm91bmRJbmRleCA9PT0gLTEpIGZvdW5kSW5kZXggPSBpXG4gICAgICAgIGlmIChpIC0gZm91bmRJbmRleCArIDEgPT09IHZhbC5sZW5ndGgpIHJldHVybiBieXRlT2Zmc2V0ICsgZm91bmRJbmRleFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmFsIG11c3QgYmUgc3RyaW5nLCBudW1iZXIgb3IgQnVmZmVyJylcbn1cblxuLy8gYGdldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQgKG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLmdldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMucmVhZFVJbnQ4KG9mZnNldClcbn1cblxuLy8gYHNldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiBzZXQgKHYsIG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMud3JpdGVVSW50OCh2LCBvZmZzZXQpXG59XG5cbmZ1bmN0aW9uIGhleFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgLy8gbXVzdCBiZSBhbiBldmVuIG51bWJlciBvZiBkaWdpdHNcbiAgdmFyIHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKHN0ckxlbiAlIDIgIT09IDApIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAoaXNOYU4ocGFyc2VkKSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmluYXJ5V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggfCAwXG4gICAgICBpZiAoZW5jb2RpbmcgPT09IHVuZGVmaW5lZCkgZW5jb2RpbmcgPSAndXRmOCdcbiAgICB9IGVsc2Uge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgLy8gbGVnYWN5IHdyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKSAtIHJlbW92ZSBpbiB2MC4xM1xuICB9IGVsc2Uge1xuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aCB8IDBcbiAgICBsZW5ndGggPSBzd2FwXG4gIH1cblxuICB2YXIgcmVtYWluaW5nID0gdGhpcy5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IGxlbmd0aCA+IHJlbWFpbmluZykgbGVuZ3RoID0gcmVtYWluaW5nXG5cbiAgaWYgKChzdHJpbmcubGVuZ3RoID4gMCAmJiAobGVuZ3RoIDwgMCB8fCBvZmZzZXQgPCAwKSkgfHwgb2Zmc2V0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignYXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGJpbmFyeVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgdmFyIHJlcyA9IFtdXG5cbiAgdmFyIGkgPSBzdGFydFxuICB3aGlsZSAoaSA8IGVuZCkge1xuICAgIHZhciBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICB2YXIgY29kZVBvaW50ID0gbnVsbFxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpID8gNFxuICAgICAgOiAoZmlyc3RCeXRlID4gMHhERikgPyAzXG4gICAgICA6IChmaXJzdEJ5dGUgPiAweEJGKSA/IDJcbiAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgdmFyIHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxudmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICB2YXIgbGVuID0gY29kZVBvaW50cy5sZW5ndGhcbiAgaWYgKGxlbiA8PSBNQVhfQVJHVU1FTlRTX0xFTkdUSCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY29kZVBvaW50cykgLy8gYXZvaWQgZXh0cmEgc2xpY2UoKVxuICB9XG5cbiAgLy8gRGVjb2RlIGluIGNodW5rcyB0byBhdm9pZCBcImNhbGwgc3RhY2sgc2l6ZSBleGNlZWRlZFwiLlxuICB2YXIgcmVzID0gJydcbiAgdmFyIGkgPSAwXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXG4gICAgICBTdHJpbmcsXG4gICAgICBjb2RlUG9pbnRzLnNsaWNlKGksIGkgKz0gTUFYX0FSR1VNRU5UU19MRU5HVEgpXG4gICAgKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0gJiAweDdGKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gYmluYXJ5U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIGJ5dGVzW2kgKyAxXSAqIDI1NilcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZSAoc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSB+fnN0YXJ0XG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuIDogfn5lbmRcblxuICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgKz0gbGVuXG4gICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApIGVuZCA9IDBcbiAgfSBlbHNlIGlmIChlbmQgPiBsZW4pIHtcbiAgICBlbmQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICB2YXIgbmV3QnVmXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIG5ld0J1ZiA9IEJ1ZmZlci5fYXVnbWVudCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpKVxuICB9IGVsc2Uge1xuICAgIHZhciBzbGljZUxlbiA9IGVuZCAtIHN0YXJ0XG4gICAgbmV3QnVmID0gbmV3IEJ1ZmZlcihzbGljZUxlbiwgdW5kZWZpbmVkKVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2xpY2VMZW47IGkrKykge1xuICAgICAgbmV3QnVmW2ldID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld0J1Zi5sZW5ndGgpIG5ld0J1Zi5wYXJlbnQgPSB0aGlzLnBhcmVudCB8fCB0aGlzXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gcmVhZFVJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gcmVhZFVJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgdmFyIG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKCh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSkgK1xuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10gKiAweDEwMDAwMDApXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gKiAweDEwMDAwMDApICtcbiAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgdGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50TEUgPSBmdW5jdGlvbiByZWFkSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkUgPSBmdW5jdGlvbiByZWFkSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGhcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIGlmICghKHRoaXNbb2Zmc2V0XSAmIDB4ODApKSByZXR1cm4gKHRoaXNbb2Zmc2V0XSlcbiAgcmV0dXJuICgoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTEpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiByZWFkSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0pIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSA8PCAyNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdExFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gcmVhZERvdWJsZUxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiByZWFkRG91YmxlQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdidWZmZXIgbXVzdCBiZSBhIEJ1ZmZlciBpbnN0YW5jZScpXG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uIHdyaXRlVUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCAyKTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSAmICgweGZmIDw8ICg4ICogKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkpKSkgPj4+XG4gICAgICAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSAqIDhcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50TEUgPSBmdW5jdGlvbiB3cml0ZUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludEJFID0gZnVuY3Rpb24gd3JpdGVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4N2YsIC0weDgwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0IDwgZW5kIC0gc3RhcnQpIHtcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgKyBzdGFydFxuICB9XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG4gIHZhciBpXG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiBzdGFydCA8IHRhcmdldFN0YXJ0ICYmIHRhcmdldFN0YXJ0IDwgZW5kKSB7XG4gICAgLy8gZGVzY2VuZGluZyBjb3B5IGZyb20gZW5kXG4gICAgZm9yIChpID0gbGVuIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2UgaWYgKGxlbiA8IDEwMDAgfHwgIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gYXNjZW5kaW5nIGNvcHkgZnJvbSBzdGFydFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0Ll9zZXQodGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLCB0YXJnZXRTdGFydClcbiAgfVxuXG4gIHJldHVybiBsZW5cbn1cblxuLy8gZmlsbCh2YWx1ZSwgc3RhcnQ9MCwgZW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiBmaWxsICh2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IDBcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kKSBlbmQgPSB0aGlzLmxlbmd0aFxuXG4gIGlmIChlbmQgPCBzdGFydCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCA8IHN0YXJ0JylcblxuICAvLyBGaWxsIDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDAgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdlbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJ5dGVzID0gdXRmOFRvQnl0ZXModmFsdWUudG9TdHJpbmcoKSlcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gdG9BcnJheUJ1ZmZlciAoKSB7XG4gIGlmICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKVxuICB9XG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxudmFyIEJQID0gQnVmZmVyLnByb3RvdHlwZVxuXG4vKipcbiAqIEF1Z21lbnQgYSBVaW50OEFycmF5ICppbnN0YW5jZSogKG5vdCB0aGUgVWludDhBcnJheSBjbGFzcyEpIHdpdGggQnVmZmVyIG1ldGhvZHNcbiAqL1xuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gX2F1Z21lbnQgKGFycikge1xuICBhcnIuY29uc3RydWN0b3IgPSBCdWZmZXJcbiAgYXJyLl9pc0J1ZmZlciA9IHRydWVcblxuICAvLyBzYXZlIHJlZmVyZW5jZSB0byBvcmlnaW5hbCBVaW50OEFycmF5IHNldCBtZXRob2QgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fc2V0ID0gYXJyLnNldFxuXG4gIC8vIGRlcHJlY2F0ZWRcbiAgYXJyLmdldCA9IEJQLmdldFxuICBhcnIuc2V0ID0gQlAuc2V0XG5cbiAgYXJyLndyaXRlID0gQlAud3JpdGVcbiAgYXJyLnRvU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvTG9jYWxlU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvSlNPTiA9IEJQLnRvSlNPTlxuICBhcnIuZXF1YWxzID0gQlAuZXF1YWxzXG4gIGFyci5jb21wYXJlID0gQlAuY29tcGFyZVxuICBhcnIuaW5kZXhPZiA9IEJQLmluZGV4T2ZcbiAgYXJyLmNvcHkgPSBCUC5jb3B5XG4gIGFyci5zbGljZSA9IEJQLnNsaWNlXG4gIGFyci5yZWFkVUludExFID0gQlAucmVhZFVJbnRMRVxuICBhcnIucmVhZFVJbnRCRSA9IEJQLnJlYWRVSW50QkVcbiAgYXJyLnJlYWRVSW50OCA9IEJQLnJlYWRVSW50OFxuICBhcnIucmVhZFVJbnQxNkxFID0gQlAucmVhZFVJbnQxNkxFXG4gIGFyci5yZWFkVUludDE2QkUgPSBCUC5yZWFkVUludDE2QkVcbiAgYXJyLnJlYWRVSW50MzJMRSA9IEJQLnJlYWRVSW50MzJMRVxuICBhcnIucmVhZFVJbnQzMkJFID0gQlAucmVhZFVJbnQzMkJFXG4gIGFyci5yZWFkSW50TEUgPSBCUC5yZWFkSW50TEVcbiAgYXJyLnJlYWRJbnRCRSA9IEJQLnJlYWRJbnRCRVxuICBhcnIucmVhZEludDggPSBCUC5yZWFkSW50OFxuICBhcnIucmVhZEludDE2TEUgPSBCUC5yZWFkSW50MTZMRVxuICBhcnIucmVhZEludDE2QkUgPSBCUC5yZWFkSW50MTZCRVxuICBhcnIucmVhZEludDMyTEUgPSBCUC5yZWFkSW50MzJMRVxuICBhcnIucmVhZEludDMyQkUgPSBCUC5yZWFkSW50MzJCRVxuICBhcnIucmVhZEZsb2F0TEUgPSBCUC5yZWFkRmxvYXRMRVxuICBhcnIucmVhZEZsb2F0QkUgPSBCUC5yZWFkRmxvYXRCRVxuICBhcnIucmVhZERvdWJsZUxFID0gQlAucmVhZERvdWJsZUxFXG4gIGFyci5yZWFkRG91YmxlQkUgPSBCUC5yZWFkRG91YmxlQkVcbiAgYXJyLndyaXRlVUludDggPSBCUC53cml0ZVVJbnQ4XG4gIGFyci53cml0ZVVJbnRMRSA9IEJQLndyaXRlVUludExFXG4gIGFyci53cml0ZVVJbnRCRSA9IEJQLndyaXRlVUludEJFXG4gIGFyci53cml0ZVVJbnQxNkxFID0gQlAud3JpdGVVSW50MTZMRVxuICBhcnIud3JpdGVVSW50MTZCRSA9IEJQLndyaXRlVUludDE2QkVcbiAgYXJyLndyaXRlVUludDMyTEUgPSBCUC53cml0ZVVJbnQzMkxFXG4gIGFyci53cml0ZVVJbnQzMkJFID0gQlAud3JpdGVVSW50MzJCRVxuICBhcnIud3JpdGVJbnRMRSA9IEJQLndyaXRlSW50TEVcbiAgYXJyLndyaXRlSW50QkUgPSBCUC53cml0ZUludEJFXG4gIGFyci53cml0ZUludDggPSBCUC53cml0ZUludDhcbiAgYXJyLndyaXRlSW50MTZMRSA9IEJQLndyaXRlSW50MTZMRVxuICBhcnIud3JpdGVJbnQxNkJFID0gQlAud3JpdGVJbnQxNkJFXG4gIGFyci53cml0ZUludDMyTEUgPSBCUC53cml0ZUludDMyTEVcbiAgYXJyLndyaXRlSW50MzJCRSA9IEJQLndyaXRlSW50MzJCRVxuICBhcnIud3JpdGVGbG9hdExFID0gQlAud3JpdGVGbG9hdExFXG4gIGFyci53cml0ZUZsb2F0QkUgPSBCUC53cml0ZUZsb2F0QkVcbiAgYXJyLndyaXRlRG91YmxlTEUgPSBCUC53cml0ZURvdWJsZUxFXG4gIGFyci53cml0ZURvdWJsZUJFID0gQlAud3JpdGVEb3VibGVCRVxuICBhcnIuZmlsbCA9IEJQLmZpbGxcbiAgYXJyLmluc3BlY3QgPSBCUC5pbnNwZWN0XG4gIGFyci50b0FycmF5QnVmZmVyID0gQlAudG9BcnJheUJ1ZmZlclxuXG4gIHJldHVybiBhcnJcbn1cblxudmFyIElOVkFMSURfQkFTRTY0X1JFID0gL1teK1xcLzAtOUEtWmEtei1fXS9nXG5cbmZ1bmN0aW9uIGJhc2U2NGNsZWFuIChzdHIpIHtcbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0cmluZ3RyaW0oc3RyKS5yZXBsYWNlKElOVkFMSURfQkFTRTY0X1JFLCAnJylcbiAgLy8gTm9kZSBjb252ZXJ0cyBzdHJpbmdzIHdpdGggbGVuZ3RoIDwgMiB0byAnJ1xuICBpZiAoc3RyLmxlbmd0aCA8IDIpIHJldHVybiAnJ1xuICAvLyBOb2RlIGFsbG93cyBmb3Igbm9uLXBhZGRlZCBiYXNlNjQgc3RyaW5ncyAobWlzc2luZyB0cmFpbGluZyA9PT0pLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgd2hpbGUgKHN0ci5sZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgc3RyID0gc3RyICsgJz0nXG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiBzdHJpbmd0cmltIChzdHIpIHtcbiAgaWYgKHN0ci50cmltKSByZXR1cm4gc3RyLnRyaW0oKVxuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKVxufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgdmFyIGNvZGVQb2ludFxuICB2YXIgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcbiAgdmFyIGJ5dGVzID0gW11cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICghbGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuICAgICAgICBpZiAoY29kZVBvaW50ID4gMHhEQkZGKSB7XG4gICAgICAgICAgLy8gdW5leHBlY3RlZCB0cmFpbFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgIC8vIHVucGFpcmVkIGxlYWRcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgY29kZVBvaW50ID0gKGxlYWRTdXJyb2dhdGUgLSAweEQ4MDAgPDwgMTAgfCBjb2RlUG9pbnQgLSAweERDMDApICsgMHgxMDAwMFxuICAgIH0gZWxzZSBpZiAobGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgLy8gdmFsaWQgYm1wIGNoYXIsIGJ1dCBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgfVxuXG4gICAgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcblxuICAgIC8vIGVuY29kZSB1dGY4XG4gICAgaWYgKGNvZGVQb2ludCA8IDB4ODApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMSkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChjb2RlUG9pbnQpXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDgwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2IHwgMHhDMCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyB8IDB4RTAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDQpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDEyIHwgMHhGMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2RlIHBvaW50JylcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnl0ZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0ciwgdW5pdHMpIHtcbiAgdmFyIGMsIGhpLCBsb1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcblxuICAgIGMgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGhpID0gYyA+PiA4XG4gICAgbG8gPSBjICUgMjU2XG4gICAgYnl0ZUFycmF5LnB1c2gobG8pXG4gICAgYnl0ZUFycmF5LnB1c2goaGkpXG4gIH1cblxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMgKHN0cikge1xuICByZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KGJhc2U2NGNsZWFuKHN0cikpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKSBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG4iLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChhcnIpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJyKSA9PSAnW29iamVjdCBBcnJheV0nO1xufTtcbiIsImV4cG9ydHMucmVhZCA9IGZ1bmN0aW9uIChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gKGUgKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gKG0gKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzXG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KVxuICB9IGVsc2Uge1xuICAgIG0gPSBtICsgTWF0aC5wb3coMiwgbUxlbilcbiAgICBlID0gZSAtIGVCaWFzXG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbilcbn1cblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uIChidWZmZXIsIHZhbHVlLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSwgY1xuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAoKHZhbHVlICogYykgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsIi8qXG4gKiBTeXN0ZW1KUyB2MC4yMC4xOSBEZXZcbiAqL1xuKGZ1bmN0aW9uICgpIHtcbid1c2Ugc3RyaWN0JztcblxuLypcbiAqIEVudmlyb25tZW50XG4gKi9cbnZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzTm9kZSA9IHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZTtcbnZhciBpc1dpbmRvd3MgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MucGxhdGZvcm0gPT09ICdzdHJpbmcnICYmIHByb2Nlc3MucGxhdGZvcm0ubWF0Y2goL153aW4vKTtcblxudmFyIGVudkdsb2JhbCA9IHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/IHNlbGYgOiBnbG9iYWw7XG4vKlxuICogU2ltcGxlIFN5bWJvbCgpIHNoaW1cbiAqL1xudmFyIGhhc1N5bWJvbCA9IHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnO1xuZnVuY3Rpb24gY3JlYXRlU3ltYm9sIChuYW1lKSB7XG4gIHJldHVybiBoYXNTeW1ib2wgPyBTeW1ib2woKSA6ICdAQCcgKyBuYW1lO1xufVxuXG5cblxuXG5cbi8qXG4gKiBFbnZpcm9ubWVudCBiYXNlVVJJXG4gKi9cbnZhciBiYXNlVVJJO1xuXG4vLyBlbnZpcm9uZW50IGJhc2VVUkkgZGV0ZWN0aW9uXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9ICd1bmRlZmluZWQnICYmIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKSB7XG4gIGJhc2VVUkkgPSBkb2N1bWVudC5iYXNlVVJJO1xuXG4gIGlmICghYmFzZVVSSSkge1xuICAgIHZhciBiYXNlcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdiYXNlJyk7XG4gICAgYmFzZVVSSSA9IGJhc2VzWzBdICYmIGJhc2VzWzBdLmhyZWYgfHwgd2luZG93LmxvY2F0aW9uLmhyZWY7XG4gIH1cbn1cbmVsc2UgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPSAndW5kZWZpbmVkJykge1xuICBiYXNlVVJJID0gbG9jYXRpb24uaHJlZjtcbn1cblxuLy8gc2FuaXRpemUgb3V0IHRoZSBoYXNoIGFuZCBxdWVyeXN0cmluZ1xuaWYgKGJhc2VVUkkpIHtcbiAgYmFzZVVSSSA9IGJhc2VVUkkuc3BsaXQoJyMnKVswXS5zcGxpdCgnPycpWzBdO1xuICB2YXIgc2xhc2hJbmRleCA9IGJhc2VVUkkubGFzdEluZGV4T2YoJy8nKTtcbiAgaWYgKHNsYXNoSW5kZXggIT09IC0xKVxuICAgIGJhc2VVUkkgPSBiYXNlVVJJLnN1YnN0cigwLCBzbGFzaEluZGV4ICsgMSk7XG59XG5lbHNlIGlmICh0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvY2Vzcy5jd2QpIHtcbiAgYmFzZVVSSSA9ICdmaWxlOi8vJyArIChpc1dpbmRvd3MgPyAnLycgOiAnJykgKyBwcm9jZXNzLmN3ZCgpO1xuICBpZiAoaXNXaW5kb3dzKVxuICAgIGJhc2VVUkkgPSBiYXNlVVJJLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbn1cbmVsc2Uge1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdObyBlbnZpcm9ubWVudCBiYXNlVVJJJyk7XG59XG5cbi8vIGVuc3VyZSBiYXNlVVJJIGhhcyB0cmFpbGluZyBcIi9cIlxuaWYgKGJhc2VVUklbYmFzZVVSSS5sZW5ndGggLSAxXSAhPT0gJy8nKVxuICBiYXNlVVJJICs9ICcvJztcblxuLypcbiAqIExvYWRlckVycm9yIHdpdGggY2hhaW5pbmcgZm9yIGxvYWRlciBzdGFja3NcbiAqL1xudmFyIGVyckFyZ3MgPSBuZXcgRXJyb3IoMCwgJ18nKS5maWxlTmFtZSA9PSAnXyc7XG5mdW5jdGlvbiBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrIChjaGlsZEVyciwgbmV3TWVzc2FnZSkge1xuICAvLyBDb252ZXJ0IGZpbGU6Ly8vIFVSTHMgdG8gcGF0aHMgaW4gTm9kZVxuICBpZiAoIWlzQnJvd3NlcilcbiAgICBuZXdNZXNzYWdlID0gbmV3TWVzc2FnZS5yZXBsYWNlKGlzV2luZG93cyA/IC9maWxlOlxcL1xcL1xcLy9nIDogL2ZpbGU6XFwvXFwvL2csICcnKTtcblxuICB2YXIgbWVzc2FnZSA9IChjaGlsZEVyci5tZXNzYWdlIHx8IGNoaWxkRXJyKSArICdcXG4gICcgKyBuZXdNZXNzYWdlO1xuXG4gIHZhciBlcnI7XG4gIGlmIChlcnJBcmdzICYmIGNoaWxkRXJyLmZpbGVOYW1lKVxuICAgIGVyciA9IG5ldyBFcnJvcihtZXNzYWdlLCBjaGlsZEVyci5maWxlTmFtZSwgY2hpbGRFcnIubGluZU51bWJlcik7XG4gIGVsc2VcbiAgICBlcnIgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG5cblxuICB2YXIgc3RhY2sgPSBjaGlsZEVyci5vcmlnaW5hbEVyciA/IGNoaWxkRXJyLm9yaWdpbmFsRXJyLnN0YWNrIDogY2hpbGRFcnIuc3RhY2s7XG5cbiAgaWYgKGlzTm9kZSlcbiAgICAvLyBub2RlIGRvZXNuJ3Qgc2hvdyB0aGUgbWVzc2FnZSBvdGhlcndpc2VcbiAgICBlcnIuc3RhY2sgPSBtZXNzYWdlICsgJ1xcbiAgJyArIHN0YWNrO1xuICBlbHNlXG4gICAgZXJyLnN0YWNrID0gc3RhY2s7XG5cbiAgZXJyLm9yaWdpbmFsRXJyID0gY2hpbGRFcnIub3JpZ2luYWxFcnIgfHwgY2hpbGRFcnI7XG5cbiAgcmV0dXJuIGVycjtcbn1cblxuLypcbiAqIE9wdGltaXplZCBVUkwgbm9ybWFsaXphdGlvbiBhc3N1bWluZyBhIHN5bnRheC12YWxpZCBVUkwgcGFyZW50XG4gKi9cbmZ1bmN0aW9uIHRocm93UmVzb2x2ZUVycm9yIChyZWxVcmwsIHBhcmVudFVybCkge1xuICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVW5hYmxlIHRvIHJlc29sdmUgXCInICsgcmVsVXJsICsgJ1wiIHRvICcgKyBwYXJlbnRVcmwpO1xufVxuZnVuY3Rpb24gcmVzb2x2ZUlmTm90UGxhaW4gKHJlbFVybCwgcGFyZW50VXJsKSB7XG4gIHJlbFVybCA9IHJlbFVybC50cmltKCk7XG4gIHZhciBwYXJlbnRQcm90b2NvbCA9IHBhcmVudFVybCAmJiBwYXJlbnRVcmwuc3Vic3RyKDAsIHBhcmVudFVybC5pbmRleE9mKCc6JykgKyAxKTtcblxuICB2YXIgZmlyc3RDaGFyID0gcmVsVXJsWzBdO1xuICB2YXIgc2Vjb25kQ2hhciA9IHJlbFVybFsxXTtcblxuICAvLyBwcm90b2NvbC1yZWxhdGl2ZVxuICBpZiAoZmlyc3RDaGFyID09PSAnLycgJiYgc2Vjb25kQ2hhciA9PT0gJy8nKSB7XG4gICAgaWYgKCFwYXJlbnRQcm90b2NvbClcbiAgICAgIHRocm93UmVzb2x2ZUVycm9yKHJlbFVybCwgcGFyZW50VXJsKTtcbiAgICByZXR1cm4gcGFyZW50UHJvdG9jb2wgKyByZWxVcmw7XG4gIH1cbiAgLy8gcmVsYXRpdmUtdXJsXG4gIGVsc2UgaWYgKGZpcnN0Q2hhciA9PT0gJy4nICYmIChzZWNvbmRDaGFyID09PSAnLycgfHwgc2Vjb25kQ2hhciA9PT0gJy4nICYmIChyZWxVcmxbMl0gPT09ICcvJyB8fCByZWxVcmwubGVuZ3RoID09PSAyICYmIChyZWxVcmwgKz0gJy8nKSkgfHxcbiAgICAgIHJlbFVybC5sZW5ndGggPT09IDEgICYmIChyZWxVcmwgKz0gJy8nKSkgfHxcbiAgICAgIGZpcnN0Q2hhciA9PT0gJy8nKSB7XG4gICAgdmFyIHBhcmVudElzUGxhaW4gPSAhcGFyZW50UHJvdG9jb2wgfHwgcGFyZW50VXJsW3BhcmVudFByb3RvY29sLmxlbmd0aF0gIT09ICcvJztcblxuICAgIC8vIHJlYWQgcGF0aG5hbWUgZnJvbSBwYXJlbnQgaWYgYSBVUkxcbiAgICAvLyBwYXRobmFtZSB0YWtlbiB0byBiZSBwYXJ0IGFmdGVyIGxlYWRpbmcgXCIvXCJcbiAgICB2YXIgcGF0aG5hbWU7XG4gICAgaWYgKHBhcmVudElzUGxhaW4pIHtcbiAgICAgIC8vIHJlc29sdmluZyB0byBhIHBsYWluIHBhcmVudCAtPiBza2lwIHN0YW5kYXJkIFVSTCBwcmVmaXgsIGFuZCB0cmVhdCBlbnRpcmUgcGFyZW50IGFzIHBhdGhuYW1lXG4gICAgICBpZiAocGFyZW50VXJsID09PSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93UmVzb2x2ZUVycm9yKHJlbFVybCwgcGFyZW50VXJsKTtcbiAgICAgIHBhdGhuYW1lID0gcGFyZW50VXJsO1xuICAgIH1cbiAgICBlbHNlIGlmIChwYXJlbnRVcmxbcGFyZW50UHJvdG9jb2wubGVuZ3RoICsgMV0gPT09ICcvJykge1xuICAgICAgLy8gcmVzb2x2aW5nIHRvIGEgOi8vIHNvIHdlIG5lZWQgdG8gcmVhZCBvdXQgdGhlIGF1dGggYW5kIGhvc3RcbiAgICAgIGlmIChwYXJlbnRQcm90b2NvbCAhPT0gJ2ZpbGU6Jykge1xuICAgICAgICBwYXRobmFtZSA9IHBhcmVudFVybC5zdWJzdHIocGFyZW50UHJvdG9jb2wubGVuZ3RoICsgMik7XG4gICAgICAgIHBhdGhuYW1lID0gcGF0aG5hbWUuc3Vic3RyKHBhdGhuYW1lLmluZGV4T2YoJy8nKSArIDEpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHBhdGhuYW1lID0gcGFyZW50VXJsLnN1YnN0cig4KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAvLyByZXNvbHZpbmcgdG8gOi8gc28gcGF0aG5hbWUgaXMgdGhlIC8uLi4gcGFydFxuICAgICAgcGF0aG5hbWUgPSBwYXJlbnRVcmwuc3Vic3RyKHBhcmVudFByb3RvY29sLmxlbmd0aCArIDEpO1xuICAgIH1cblxuICAgIGlmIChmaXJzdENoYXIgPT09ICcvJykge1xuICAgICAgaWYgKHBhcmVudElzUGxhaW4pXG4gICAgICAgIHRocm93UmVzb2x2ZUVycm9yKHJlbFVybCwgcGFyZW50VXJsKTtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIHBhcmVudFVybC5zdWJzdHIoMCwgcGFyZW50VXJsLmxlbmd0aCAtIHBhdGhuYW1lLmxlbmd0aCAtIDEpICsgcmVsVXJsO1xuICAgIH1cblxuICAgIC8vIGpvaW4gdG9nZXRoZXIgYW5kIHNwbGl0IGZvciByZW1vdmFsIG9mIC4uIGFuZCAuIHNlZ21lbnRzXG4gICAgLy8gbG9vcGluZyB0aGUgc3RyaW5nIGluc3RlYWQgb2YgYW55dGhpbmcgZmFuY3kgZm9yIHBlcmYgcmVhc29uc1xuICAgIC8vICcuLi8uLi8uLi8uLi8uLi96JyByZXNvbHZlZCB0byAneC95JyBpcyBqdXN0ICd6JyByZWdhcmRsZXNzIG9mIHBhcmVudElzUGxhaW5cbiAgICB2YXIgc2VnbWVudGVkID0gcGF0aG5hbWUuc3Vic3RyKDAsIHBhdGhuYW1lLmxhc3RJbmRleE9mKCcvJykgKyAxKSArIHJlbFVybDtcblxuICAgIHZhciBvdXRwdXQgPSBbXTtcbiAgICB2YXIgc2VnbWVudEluZGV4ID0gLTE7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlZ21lbnRlZC5sZW5ndGg7IGkrKykge1xuICAgICAgLy8gYnVzeSByZWFkaW5nIGEgc2VnbWVudCAtIG9ubHkgdGVybWluYXRlIG9uICcvJ1xuICAgICAgaWYgKHNlZ21lbnRJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgaWYgKHNlZ21lbnRlZFtpXSA9PT0gJy8nKSB7XG4gICAgICAgICAgb3V0cHV0LnB1c2goc2VnbWVudGVkLnN1YnN0cmluZyhzZWdtZW50SW5kZXgsIGkgKyAxKSk7XG4gICAgICAgICAgc2VnbWVudEluZGV4ID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIG5ldyBzZWdtZW50IC0gY2hlY2sgaWYgaXQgaXMgcmVsYXRpdmVcbiAgICAgIGlmIChzZWdtZW50ZWRbaV0gPT09ICcuJykge1xuICAgICAgICAvLyAuLi8gc2VnbWVudFxuICAgICAgICBpZiAoc2VnbWVudGVkW2kgKyAxXSA9PT0gJy4nICYmIChzZWdtZW50ZWRbaSArIDJdID09PSAnLycgfHwgaSArIDIgPT09IHNlZ21lbnRlZC5sZW5ndGgpKSB7XG4gICAgICAgICAgb3V0cHV0LnBvcCgpO1xuICAgICAgICAgIGkgKz0gMjtcbiAgICAgICAgfVxuICAgICAgICAvLyAuLyBzZWdtZW50XG4gICAgICAgIGVsc2UgaWYgKHNlZ21lbnRlZFtpICsgMV0gPT09ICcvJyB8fCBpICsgMSA9PT0gc2VnbWVudGVkLmxlbmd0aCkge1xuICAgICAgICAgIGkgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAvLyB0aGUgc3RhcnQgb2YgYSBuZXcgc2VnbWVudCBhcyBiZWxvd1xuICAgICAgICAgIHNlZ21lbnRJbmRleCA9IGk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGlzIGlzIHRoZSBwbGFpbiBVUkkgYmFja3RyYWNraW5nIGVycm9yICguLi8sIHBhY2thZ2U6eCAtPiBlcnJvcilcbiAgICAgICAgaWYgKHBhcmVudElzUGxhaW4gJiYgb3V0cHV0Lmxlbmd0aCA9PT0gMClcbiAgICAgICAgICB0aHJvd1Jlc29sdmVFcnJvcihyZWxVcmwsIHBhcmVudFVybCk7XG5cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIGl0IGlzIHRoZSBzdGFydCBvZiBhIG5ldyBzZWdtZW50XG4gICAgICBzZWdtZW50SW5kZXggPSBpO1xuICAgIH1cbiAgICAvLyBmaW5pc2ggcmVhZGluZyBvdXQgdGhlIGxhc3Qgc2VnbWVudFxuICAgIGlmIChzZWdtZW50SW5kZXggIT09IC0xKVxuICAgICAgb3V0cHV0LnB1c2goc2VnbWVudGVkLnN1YnN0cihzZWdtZW50SW5kZXgpKTtcblxuICAgIHJldHVybiBwYXJlbnRVcmwuc3Vic3RyKDAsIHBhcmVudFVybC5sZW5ndGggLSBwYXRobmFtZS5sZW5ndGgpICsgb3V0cHV0LmpvaW4oJycpO1xuICB9XG5cbiAgLy8gc2FuaXRpemVzIGFuZCB2ZXJpZmllcyAoYnkgcmV0dXJuaW5nIHVuZGVmaW5lZCBpZiBub3QgYSB2YWxpZCBVUkwtbGlrZSBmb3JtKVxuICAvLyBXaW5kb3dzIGZpbGVwYXRoIGNvbXBhdGliaWxpdHkgaXMgYW4gYWRkZWQgY29udmVuaWVuY2UgaGVyZVxuICB2YXIgcHJvdG9jb2xJbmRleCA9IHJlbFVybC5pbmRleE9mKCc6Jyk7XG4gIGlmIChwcm90b2NvbEluZGV4ICE9PSAtMSkge1xuICAgIGlmIChpc05vZGUpIHtcbiAgICAgIC8vIEM6XFx4IGJlY29tZXMgZmlsZTovLy9jOi94ICh3ZSBkb24ndCBzdXBwb3J0IEN8XFx4KVxuICAgICAgaWYgKHJlbFVybFsxXSA9PT0gJzonICYmIHJlbFVybFsyXSA9PT0gJ1xcXFwnICYmIHJlbFVybFswXS5tYXRjaCgvW2Etel0vaSkpXG4gICAgICAgIHJldHVybiAnZmlsZTovLy8nICsgcmVsVXJsLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlbFVybDtcbiAgfVxufVxuXG52YXIgcmVzb2x2ZWRQcm9taXNlJDEgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuLypcbiAqIFNpbXBsZSBBcnJheSB2YWx1ZXMgc2hpbVxuICovXG5mdW5jdGlvbiBhcnJheVZhbHVlcyAoYXJyKSB7XG4gIGlmIChhcnIudmFsdWVzKVxuICAgIHJldHVybiBhcnIudmFsdWVzKCk7XG5cbiAgaWYgKHR5cGVvZiBTeW1ib2wgPT09ICd1bmRlZmluZWQnIHx8ICFTeW1ib2wuaXRlcmF0b3IpXG4gICAgdGhyb3cgbmV3IEVycm9yKCdTeW1ib2wuaXRlcmF0b3Igbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKTtcblxuICB2YXIgaXRlcmFibGUgPSB7fTtcbiAgaXRlcmFibGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGFycik7XG4gICAgdmFyIGtleUluZGV4ID0gMDtcbiAgICByZXR1cm4ge1xuICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoa2V5SW5kZXggPCBrZXlzLmxlbmd0aClcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsdWU6IGFycltrZXlzW2tleUluZGV4KytdXSxcbiAgICAgICAgICAgIGRvbmU6IGZhbHNlXG4gICAgICAgICAgfTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZG9uZTogdHJ1ZVxuICAgICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcbiAgfTtcbiAgcmV0dXJuIGl0ZXJhYmxlO1xufVxuXG4vKlxuICogMy4gUmVmbGVjdC5Mb2FkZXJcbiAqXG4gKiBXZSBza2lwIHRoZSBlbnRpcmUgbmF0aXZlIGludGVybmFsIHBpcGVsaW5lLCBqdXN0IHByb3ZpZGluZyB0aGUgYmFyZSBBUElcbiAqL1xuLy8gMy4xLjFcbmZ1bmN0aW9uIExvYWRlciAoKSB7XG4gIHRoaXMucmVnaXN0cnkgPSBuZXcgUmVnaXN0cnkoKTtcbn1cbi8vIDMuMy4xXG5Mb2FkZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTG9hZGVyO1xuXG5mdW5jdGlvbiBlbnN1cmVJbnN0YW50aWF0ZWQgKG1vZHVsZSkge1xuICBpZiAoIShtb2R1bGUgaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ01vZHVsZSBpbnN0YW50aWF0aW9uIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbmFtZXNwYWNlIG9iamVjdC4nKTtcbiAgcmV0dXJuIG1vZHVsZTtcbn1cblxuLy8gMy4zLjJcbkxvYWRlci5wcm90b3R5cGUuaW1wb3J0ID0gZnVuY3Rpb24gKGtleSwgcGFyZW50KSB7XG4gIGlmICh0eXBlb2Yga2V5ICE9PSAnc3RyaW5nJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdMb2FkZXIgaW1wb3J0IG1ldGhvZCBtdXN0IGJlIHBhc3NlZCBhIG1vZHVsZSBrZXkgc3RyaW5nJyk7XG4gIC8vIGN1c3RvbSByZXNvbHZlSW5zdGFudGlhdGUgY29tYmluZWQgaG9vayBmb3IgYmV0dGVyIHBlcmZcbiAgdmFyIGxvYWRlciA9IHRoaXM7XG4gIHJldHVybiByZXNvbHZlZFByb21pc2UkMVxuICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGxvYWRlcltSRVNPTFZFX0lOU1RBTlRJQVRFXShrZXksIHBhcmVudCk7XG4gIH0pXG4gIC50aGVuKGVuc3VyZUluc3RhbnRpYXRlZClcbiAgLy8udGhlbihNb2R1bGUuZXZhbHVhdGUpXG4gIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgdGhyb3cgTG9hZGVyRXJyb3JfX0NoZWNrX2Vycm9yX21lc3NhZ2VfZm9yX2xvYWRlcl9zdGFjayhlcnIsICdMb2FkaW5nICcgKyBrZXkgKyAocGFyZW50ID8gJyBmcm9tICcgKyBwYXJlbnQgOiAnJykpO1xuICB9KTtcbn07XG4vLyAzLjMuM1xudmFyIFJFU09MVkUgPSBMb2FkZXIucmVzb2x2ZSA9IGNyZWF0ZVN5bWJvbCgncmVzb2x2ZScpO1xuXG4vKlxuICogQ29tYmluZWQgcmVzb2x2ZSAvIGluc3RhbnRpYXRlIGhvb2tcbiAqXG4gKiBOb3QgaW4gY3VycmVudCByZWR1Y2VkIHNwZWMsIGJ1dCBuZWNlc3NhcnkgdG8gc2VwYXJhdGUgUkVTT0xWRSBmcm9tIFJFU09MVkUgKyBJTlNUQU5USUFURSBhcyBkZXNjcmliZWRcbiAqIGluIHRoZSBzcGVjIG5vdGVzIG9mIHRoaXMgcmVwbyB0byBlbnN1cmUgdGhhdCBsb2FkZXIucmVzb2x2ZSBkb2Vzbid0IGluc3RhbnRpYXRlIHdoZW4gbm90IHdhbnRlZC5cbiAqXG4gKiBXZSBpbXBsZW1lbnQgUkVTT0xWRV9JTlNUQU5USUFURSBhcyBhIHNpbmdsZSBob29rIGluc3RlYWQgb2YgYSBzZXBhcmF0ZSBJTlNUQU5USUFURSBpbiBvcmRlciB0byBhdm9pZFxuICogdGhlIG5lZWQgZm9yIGRvdWJsZSByZWdpc3RyeSBsb29rdXBzIGFzIGEgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uLlxuICovXG52YXIgUkVTT0xWRV9JTlNUQU5USUFURSA9IExvYWRlci5yZXNvbHZlSW5zdGFudGlhdGUgPSBjcmVhdGVTeW1ib2woJ3Jlc29sdmVJbnN0YW50aWF0ZScpO1xuXG4vLyBkZWZhdWx0IHJlc29sdmVJbnN0YW50aWF0ZSBpcyBqdXN0IHRvIGNhbGwgcmVzb2x2ZSBhbmQgdGhlbiBnZXQgZnJvbSB0aGUgcmVnaXN0cnlcbi8vIHRoaXMgcHJvdmlkZXMgY29tcGF0aWJpbGl0eSBmb3IgdGhlIHJlc29sdmVJbnN0YW50aWF0ZSBvcHRpbWl6YXRpb25cbkxvYWRlci5wcm90b3R5cGVbUkVTT0xWRV9JTlNUQU5USUFURV0gPSBmdW5jdGlvbiAoa2V5LCBwYXJlbnQpIHtcbiAgdmFyIGxvYWRlciA9IHRoaXM7XG4gIHJldHVybiBsb2FkZXIucmVzb2x2ZShrZXksIHBhcmVudClcbiAgLnRoZW4oZnVuY3Rpb24gKHJlc29sdmVkKSB7XG4gICAgcmV0dXJuIGxvYWRlci5yZWdpc3RyeS5nZXQocmVzb2x2ZWQpO1xuICB9KTtcbn07XG5cbmZ1bmN0aW9uIGVuc3VyZVJlc29sdXRpb24gKHJlc29sdmVkS2V5KSB7XG4gIGlmIChyZXNvbHZlZEtleSA9PT0gdW5kZWZpbmVkKVxuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdObyByZXNvbHV0aW9uIGZvdW5kLicpO1xuICByZXR1cm4gcmVzb2x2ZWRLZXk7XG59XG5cbkxvYWRlci5wcm90b3R5cGUucmVzb2x2ZSA9IGZ1bmN0aW9uIChrZXksIHBhcmVudCkge1xuICB2YXIgbG9hZGVyID0gdGhpcztcbiAgcmV0dXJuIHJlc29sdmVkUHJvbWlzZSQxXG4gIC50aGVuKGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBsb2FkZXJbUkVTT0xWRV0oa2V5LCBwYXJlbnQpO1xuICB9KVxuICAudGhlbihlbnN1cmVSZXNvbHV0aW9uKVxuICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgIHRocm93IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnUmVzb2x2aW5nICcgKyBrZXkgKyAocGFyZW50ID8gJyB0byAnICsgcGFyZW50IDogJycpKTtcbiAgfSk7XG59O1xuXG4vLyAzLjMuNCAoaW1wb3J0IHdpdGhvdXQgZXZhbHVhdGUpXG4vLyB0aGlzIGlzIG5vdCBkb2N1bWVudGVkIGJlY2F1c2UgdGhlIHVzZSBvZiBkZWZlcnJlZCBldmFsdWF0aW9uIGFzIGluIE1vZHVsZS5ldmFsdWF0ZSBpcyBub3Rcbi8vIGRvY3VtZW50ZWQsIGFzIGl0IGlzIG5vdCBjb25zaWRlcmVkIGEgc3RhYmxlIGZlYXR1cmUgdG8gYmUgZW5jb3VyYWdlZFxuLy8gTG9hZGVyLnByb3RvdHlwZS5sb2FkIG1heSB3ZWxsIGJlIGRlcHJlY2F0ZWQgaWYgdGhpcyBzdGF5cyBkaXNhYmxlZFxuLyogTG9hZGVyLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKGtleSwgcGFyZW50KSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpc1tSRVNPTFZFX0lOU1RBTlRJQVRFXShrZXksIHBhcmVudCB8fCB0aGlzLmtleSkpXG4gIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgdGhyb3cgYWRkVG9FcnJvcihlcnIsICdMb2FkaW5nICcgKyBrZXkgKyAocGFyZW50ID8gJyBmcm9tICcgKyBwYXJlbnQgOiAnJykpO1xuICB9KTtcbn07ICovXG5cbi8qXG4gKiA0LiBSZWdpc3RyeVxuICpcbiAqIEluc3RlYWQgb2Ygc3RydWN0dXJpbmcgdGhyb3VnaCBhIE1hcCwganVzdCB1c2UgYSBkaWN0aW9uYXJ5IG9iamVjdFxuICogV2UgdGhyb3cgZm9yIGNvbnN0cnVjdGlvbiBhdHRlbXB0cyBzbyB0aGlzIGRvZXNuJ3QgYWZmZWN0IHRoZSBwdWJsaWMgQVBJXG4gKlxuICogUmVnaXN0cnkgaGFzIGJlZW4gYWRqdXN0ZWQgdG8gdXNlIE5hbWVzcGFjZSBvYmplY3RzIG92ZXIgTW9kdWxlU3RhdHVzIG9iamVjdHNcbiAqIGFzIHBhcnQgb2Ygc2ltcGxpZnlpbmcgbG9hZGVyIEFQSSBpbXBsZW1lbnRhdGlvblxuICovXG52YXIgaXRlcmF0b3JTdXBwb3J0ID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLml0ZXJhdG9yO1xudmFyIFJFR0lTVFJZID0gY3JlYXRlU3ltYm9sKCdyZWdpc3RyeScpO1xuZnVuY3Rpb24gUmVnaXN0cnkoKSB7XG4gIHRoaXNbUkVHSVNUUlldID0ge307XG59XG4vLyA0LjQuMVxuaWYgKGl0ZXJhdG9yU3VwcG9ydCkge1xuICAvLyA0LjQuMlxuICBSZWdpc3RyeS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5lbnRyaWVzKClbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9O1xuXG4gIC8vIDQuNC4zXG4gIFJlZ2lzdHJ5LnByb3RvdHlwZS5lbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZWdpc3RyeSA9IHRoaXNbUkVHSVNUUlldO1xuICAgIHJldHVybiBhcnJheVZhbHVlcyhPYmplY3Qua2V5cyhyZWdpc3RyeSkubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHJldHVybiBba2V5LCByZWdpc3RyeVtrZXldXTtcbiAgICB9KSk7XG4gIH07XG59XG5cbi8vIDQuNC40XG5SZWdpc3RyeS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGFycmF5VmFsdWVzKE9iamVjdC5rZXlzKHRoaXNbUkVHSVNUUlldKSk7XG59O1xuLy8gNC40LjVcblJlZ2lzdHJ5LnByb3RvdHlwZS52YWx1ZXMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciByZWdpc3RyeSA9IHRoaXNbUkVHSVNUUlldO1xuICByZXR1cm4gYXJyYXlWYWx1ZXMoT2JqZWN0LmtleXMocmVnaXN0cnkpLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIHJlZ2lzdHJ5W2tleV07XG4gIH0pKTtcbn07XG4vLyA0LjQuNlxuUmVnaXN0cnkucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHRoaXNbUkVHSVNUUlldW2tleV07XG59O1xuLy8gNC40LjdcblJlZ2lzdHJ5LnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCBuYW1lc3BhY2UpIHtcbiAgaWYgKCEobmFtZXNwYWNlIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlKSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlZ2lzdHJ5IG11c3QgYmUgc2V0IHdpdGggYW4gaW5zdGFuY2Ugb2YgTW9kdWxlIE5hbWVzcGFjZScpO1xuICB0aGlzW1JFR0lTVFJZXVtrZXldID0gbmFtZXNwYWNlO1xuICByZXR1cm4gdGhpcztcbn07XG4vLyA0LjQuOFxuUmVnaXN0cnkucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXNbUkVHSVNUUlldLCBrZXkpO1xufTtcbi8vIDQuNC45XG5SZWdpc3RyeS5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwodGhpc1tSRUdJU1RSWV0sIGtleSkpIHtcbiAgICBkZWxldGUgdGhpc1tSRUdJU1RSWV1ba2V5XTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKlxuICogU2ltcGxlIE1vZHVsZU5hbWVzcGFjZSBFeG90aWMgb2JqZWN0IGJhc2VkIG9uIGEgYmFzZU9iamVjdFxuICogV2UgZXhwb3J0IHRoaXMgZm9yIGFsbG93aW5nIGEgZmFzdC1wYXRoIGZvciBtb2R1bGUgbmFtZXNwYWNlIGNyZWF0aW9uIG92ZXIgTW9kdWxlIGRlc2NyaXB0b3JzXG4gKi9cbi8vIHZhciBFVkFMVUFURSA9IGNyZWF0ZVN5bWJvbCgnZXZhbHVhdGUnKTtcbnZhciBCQVNFX09CSkVDVCA9IGNyZWF0ZVN5bWJvbCgnYmFzZU9iamVjdCcpO1xuXG4vLyA4LjMuMSBSZWZsZWN0Lk1vZHVsZVxuLypcbiAqIEJlc3QtZWZmb3J0IHNpbXBsaWZpZWQgbm9uLXNwZWMgaW1wbGVtZW50YXRpb24gYmFzZWQgb25cbiAqIGEgYmFzZU9iamVjdCByZWZlcmVuY2VkIHZpYSBnZXR0ZXJzLlxuICpcbiAqIEFsbG93czpcbiAqXG4gKiAgIGxvYWRlci5yZWdpc3RyeS5zZXQoJ3gnLCBuZXcgTW9kdWxlKHsgZGVmYXVsdDogJ3gnIH0pKTtcbiAqXG4gKiBPcHRpb25hbCBldmFsdWF0aW9uIGZ1bmN0aW9uIHByb3ZpZGVzIGV4cGVyaW1lbnRhbCBNb2R1bGUuZXZhbHVhdGVcbiAqIHN1cHBvcnQgZm9yIG5vbi1leGVjdXRlZCBtb2R1bGVzIGluIHJlZ2lzdHJ5LlxuICovXG5mdW5jdGlvbiBNb2R1bGVOYW1lc3BhY2UgKGJhc2VPYmplY3QvKiwgZXZhbHVhdGUqLykge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgQkFTRV9PQkpFQ1QsIHtcbiAgICB2YWx1ZTogYmFzZU9iamVjdFxuICB9KTtcblxuICAvLyBldmFsdWF0ZSBkZWZlcnMgbmFtZXNwYWNlIHBvcHVsYXRpb25cbiAgLyogaWYgKGV2YWx1YXRlKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIEVWQUxVQVRFLCB7XG4gICAgICB2YWx1ZTogZXZhbHVhdGUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogdHJ1ZVxuICAgIH0pO1xuICB9XG4gIGVsc2UgeyAqL1xuICAgIE9iamVjdC5rZXlzKGJhc2VPYmplY3QpLmZvckVhY2goZXh0ZW5kTmFtZXNwYWNlLCB0aGlzKTtcbiAgLy99XG59XG4vLyA4LjQuMlxuTW9kdWxlTmFtZXNwYWNlLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbmlmICh0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShNb2R1bGVOYW1lc3BhY2UucHJvdG90eXBlLCBTeW1ib2wudG9TdHJpbmdUYWcsIHtcbiAgICB2YWx1ZTogJ01vZHVsZSdcbiAgfSk7XG5cbmZ1bmN0aW9uIGV4dGVuZE5hbWVzcGFjZSAoa2V5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBrZXksIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXNbQkFTRV9PQkpFQ1RdW2tleV07XG4gICAgfVxuICB9KTtcbn1cblxuLyogZnVuY3Rpb24gZG9FdmFsdWF0ZSAoZXZhbHVhdGUsIGNvbnRleHQpIHtcbiAgdHJ5IHtcbiAgICBldmFsdWF0ZS5jYWxsKGNvbnRleHQpO1xuICB9XG4gIGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGU7XG4gIH1cbn1cblxuLy8gOC40LjEgTW9kdWxlLmV2YWx1YXRlLi4uIG5vdCBkb2N1bWVudGVkIG9yIHVzZWQgYmVjYXVzZSB0aGlzIGlzIHBvdGVudGlhbGx5IHVuc3RhYmxlXG5Nb2R1bGUuZXZhbHVhdGUgPSBmdW5jdGlvbiAobnMpIHtcbiAgdmFyIGV2YWx1YXRlID0gbnNbRVZBTFVBVEVdO1xuICBpZiAoZXZhbHVhdGUpIHtcbiAgICBuc1tFVkFMVUFURV0gPSB1bmRlZmluZWQ7XG4gICAgdmFyIGVyciA9IGRvRXZhbHVhdGUoZXZhbHVhdGUpO1xuICAgIGlmIChlcnIpIHtcbiAgICAgIC8vIGNhY2hlIHRoZSBlcnJvclxuICAgICAgbnNbRVZBTFVBVEVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9O1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICBPYmplY3Qua2V5cyhuc1tCQVNFX09CSkVDVF0pLmZvckVhY2goZXh0ZW5kTmFtZXNwYWNlLCBucyk7XG4gIH1cbiAgLy8gbWFrZSBjaGFpbmFibGVcbiAgcmV0dXJuIG5zO1xufTsgKi9cblxuLypcbiAqIFJlZ2lzdGVyIExvYWRlclxuICpcbiAqIEJ1aWxkcyBkaXJlY3RseSBvbiB0b3Agb2YgbG9hZGVyIHBvbHlmaWxsIHRvIHByb3ZpZGU6XG4gKiAtIGxvYWRlci5yZWdpc3RlciBzdXBwb3J0XG4gKiAtIGhvb2thYmxlIGhpZ2hlci1sZXZlbCByZXNvbHZlXG4gKiAtIGluc3RhbnRpYXRlIGhvb2sgcmV0dXJuaW5nIGEgTW9kdWxlTmFtZXNwYWNlIG9yIHVuZGVmaW5lZCBmb3IgZXMgbW9kdWxlIGxvYWRpbmdcbiAqIC0gbG9hZGVyIGVycm9yIGJlaGF2aW91ciBhcyBpbiBIVE1MIGFuZCBsb2FkZXIgc3BlY3MsIGNhY2hpbmcgbG9hZCBhbmQgZXZhbCBlcnJvcnMgc2VwYXJhdGVseVxuICogLSBidWlsZCB0cmFjaW5nIHN1cHBvcnQgYnkgcHJvdmlkaW5nIGEgLnRyYWNlPXRydWUgYW5kIC5sb2FkcyBvYmplY3QgZm9ybWF0XG4gKi9cblxudmFyIFJFR0lTVEVSX0lOVEVSTkFMID0gY3JlYXRlU3ltYm9sKCdyZWdpc3Rlci1pbnRlcm5hbCcpO1xuXG5mdW5jdGlvbiBSZWdpc3RlckxvYWRlciQxICgpIHtcbiAgTG9hZGVyLmNhbGwodGhpcyk7XG5cbiAgdmFyIHJlZ2lzdHJ5RGVsZXRlID0gdGhpcy5yZWdpc3RyeS5kZWxldGU7XG4gIHRoaXMucmVnaXN0cnkuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciBkZWxldGVkID0gcmVnaXN0cnlEZWxldGUuY2FsbCh0aGlzLCBrZXkpO1xuXG4gICAgLy8gYWxzbyBkZWxldGUgZnJvbSByZWdpc3RlciByZWdpc3RyeSBpZiBsaW5rZWRcbiAgICBpZiAocmVjb3Jkcy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmICFyZWNvcmRzW2tleV0ubGlua1JlY29yZCkge1xuICAgICAgZGVsZXRlIHJlY29yZHNba2V5XTtcbiAgICAgIGRlbGV0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBkZWxldGVkO1xuICB9O1xuXG4gIHZhciByZWNvcmRzID0ge307XG5cbiAgdGhpc1tSRUdJU1RFUl9JTlRFUk5BTF0gPSB7XG4gICAgLy8gbGFzdCBhbm9ueW1vdXMgU3lzdGVtLnJlZ2lzdGVyIGNhbGxcbiAgICBsYXN0UmVnaXN0ZXI6IHVuZGVmaW5lZCxcbiAgICAvLyBpbi1mbGlnaHQgZXMgbW9kdWxlIGxvYWQgcmVjb3Jkc1xuICAgIHJlY29yZHM6IHJlY29yZHNcbiAgfTtcblxuICAvLyB0cmFjaW5nXG4gIHRoaXMudHJhY2UgPSBmYWxzZTtcbn1cblxuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKExvYWRlci5wcm90b3R5cGUpO1xuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBSZWdpc3RlckxvYWRlciQxO1xuXG52YXIgSU5TVEFOVElBVEUgPSBSZWdpc3RlckxvYWRlciQxLmluc3RhbnRpYXRlID0gY3JlYXRlU3ltYm9sKCdpbnN0YW50aWF0ZScpO1xuXG4vLyBkZWZhdWx0IG5vcm1hbGl6ZSBpcyB0aGUgV2hhdFdHIHN0eWxlIG5vcm1hbGl6ZXJcblJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlW1JlZ2lzdGVyTG9hZGVyJDEucmVzb2x2ZSA9IExvYWRlci5yZXNvbHZlXSA9IGZ1bmN0aW9uIChrZXksIHBhcmVudEtleSkge1xuICByZXR1cm4gcmVzb2x2ZUlmTm90UGxhaW4oa2V5LCBwYXJlbnRLZXkgfHwgYmFzZVVSSSk7XG59O1xuXG5SZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZVtJTlNUQU5USUFURV0gPSBmdW5jdGlvbiAoa2V5LCBwcm9jZXNzQW5vblJlZ2lzdGVyKSB7fTtcblxuLy8gb25jZSBldmFsdWF0ZWQsIHRoZSBsaW5rUmVjb3JkIGlzIHNldCB0byB1bmRlZmluZWQgbGVhdmluZyBqdXN0IHRoZSBvdGhlciBsb2FkIHJlY29yZCBwcm9wZXJ0aWVzXG4vLyB0aGlzIGFsbG93cyB0cmFja2luZyBuZXcgYmluZGluZyBsaXN0ZW5lcnMgZm9yIGVzIG1vZHVsZXMgdGhyb3VnaCBpbXBvcnRlclNldHRlcnNcbi8vIGZvciBkeW5hbWljIG1vZHVsZXMsIHRoZSBsb2FkIHJlY29yZCBpcyByZW1vdmVkIGVudGlyZWx5LlxuZnVuY3Rpb24gY3JlYXRlTG9hZFJlY29yZCAoc3RhdGUsIGtleSwgcmVnaXN0cmF0aW9uKSB7XG4gIHJldHVybiBzdGF0ZS5yZWNvcmRzW2tleV0gPSB7XG4gICAga2V5OiBrZXksXG5cbiAgICAvLyBkZWZpbmVkIFN5c3RlbS5yZWdpc3RlciBjYWNoZVxuICAgIHJlZ2lzdHJhdGlvbjogcmVnaXN0cmF0aW9uLFxuXG4gICAgLy8gbW9kdWxlIG5hbWVzcGFjZSBvYmplY3RcbiAgICBtb2R1bGU6IHVuZGVmaW5lZCxcblxuICAgIC8vIGVzLW9ubHlcbiAgICAvLyB0aGlzIHN0aWNrcyBhcm91bmQgc28gbmV3IG1vZHVsZSBsb2FkcyBjYW4gbGlzdGVuIHRvIGJpbmRpbmcgY2hhbmdlc1xuICAgIC8vIGZvciBhbHJlYWR5LWxvYWRlZCBtb2R1bGVzIGJ5IGFkZGluZyB0aGVtc2VsdmVzIHRvIHRoZWlyIGltcG9ydGVyU2V0dGVyc1xuICAgIGltcG9ydGVyU2V0dGVyczogdW5kZWZpbmVkLFxuXG4gICAgbG9hZEVycm9yOiB1bmRlZmluZWQsXG4gICAgZXZhbEVycm9yOiB1bmRlZmluZWQsXG5cbiAgICAvLyBpbi1mbGlnaHQgbGlua2luZyByZWNvcmRcbiAgICBsaW5rUmVjb3JkOiB7XG4gICAgICAvLyBwcm9taXNlIGZvciBpbnN0YW50aWF0ZWRcbiAgICAgIGluc3RhbnRpYXRlUHJvbWlzZTogdW5kZWZpbmVkLFxuICAgICAgZGVwZW5kZW5jaWVzOiB1bmRlZmluZWQsXG4gICAgICBleGVjdXRlOiB1bmRlZmluZWQsXG4gICAgICBleGVjdXRpbmdSZXF1aXJlOiBmYWxzZSxcblxuICAgICAgLy8gdW5kZXJseWluZyBtb2R1bGUgb2JqZWN0IGJpbmRpbmdzXG4gICAgICBtb2R1bGVPYmo6IHVuZGVmaW5lZCxcblxuICAgICAgLy8gZXMgb25seSwgYWxzbyBpbmRpY2F0ZXMgaWYgZXMgb3Igbm90XG4gICAgICBzZXR0ZXJzOiB1bmRlZmluZWQsXG5cbiAgICAgIC8vIHByb21pc2UgZm9yIGluc3RhbnRpYXRlZCBkZXBlbmRlbmNpZXMgKGRlcGVuZGVuY3lJbnN0YW50aWF0aW9ucyBwb3B1bGF0ZWQpXG4gICAgICBkZXBzSW5zdGFudGlhdGVQcm9taXNlOiB1bmRlZmluZWQsXG4gICAgICAvLyB3aWxsIGJlIHRoZSBhcnJheSBvZiBkZXBlbmRlbmN5IGxvYWQgcmVjb3JkIG9yIGEgbW9kdWxlIG5hbWVzcGFjZVxuICAgICAgZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zOiB1bmRlZmluZWQsXG5cbiAgICAgIC8vIE5CIG9wdGltaXphdGlvbiBhbmQgd2F5IG9mIGVuc3VyaW5nIG1vZHVsZSBvYmplY3RzIGluIHNldHRlcnNcbiAgICAgIC8vIGluZGljYXRlcyBzZXR0ZXJzIHdoaWNoIHNob3VsZCBydW4gcHJlLWV4ZWN1dGlvbiBvZiB0aGF0IGRlcGVuZGVuY3lcbiAgICAgIC8vIHNldHRlcnMgaXMgdGhlbiBqdXN0IGZvciBjb21wbGV0ZWx5IGV4ZWN1dGVkIG1vZHVsZSBvYmplY3RzXG4gICAgICAvLyBhbHRlcm5hdGl2ZWx5IHdlIGp1c3QgcGFzcyB0aGUgcGFydGlhbGx5IGZpbGxlZCBtb2R1bGUgb2JqZWN0cyBhc1xuICAgICAgLy8gYXJndW1lbnRzIGludG8gdGhlIGV4ZWN1dGUgZnVuY3Rpb25cbiAgICAgIC8vIGhvaXN0ZWQ6IHVuZGVmaW5lZFxuICAgIH1cbiAgfTtcbn1cblxuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGVbTG9hZGVyLnJlc29sdmVJbnN0YW50aWF0ZV0gPSBmdW5jdGlvbiAoa2V5LCBwYXJlbnRLZXkpIHtcbiAgdmFyIGxvYWRlciA9IHRoaXM7XG4gIHZhciBzdGF0ZSA9IHRoaXNbUkVHSVNURVJfSU5URVJOQUxdO1xuICB2YXIgcmVnaXN0cnkgPSB0aGlzLnJlZ2lzdHJ5W1JFR0lTVFJZXTtcblxuICByZXR1cm4gcmVzb2x2ZUluc3RhbnRpYXRlKGxvYWRlciwga2V5LCBwYXJlbnRLZXksIHJlZ2lzdHJ5LCBzdGF0ZSlcbiAgLnRoZW4oZnVuY3Rpb24gKGluc3RhbnRpYXRlZCkge1xuICAgIGlmIChpbnN0YW50aWF0ZWQgaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpXG4gICAgICByZXR1cm4gaW5zdGFudGlhdGVkO1xuXG4gICAgLy8gcmVzb2x2ZUluc3RhbnRpYXRlIGFsd2F5cyByZXR1cm5zIGEgbG9hZCByZWNvcmQgd2l0aCBhIGxpbmsgcmVjb3JkIGFuZCBubyBtb2R1bGUgdmFsdWVcbiAgICB2YXIgbGluayA9IGluc3RhbnRpYXRlZC5saW5rUmVjb3JkO1xuXG4gICAgLy8gaWYgYWxyZWFkeSBiZWF0ZW4gdG8gZG9uZSwgcmV0dXJuXG4gICAgaWYgKCFsaW5rKSB7XG4gICAgICBpZiAoaW5zdGFudGlhdGVkLm1vZHVsZSlcbiAgICAgICAgcmV0dXJuIGluc3RhbnRpYXRlZC5tb2R1bGU7XG4gICAgICB0aHJvdyBpbnN0YW50aWF0ZWQuZXZhbEVycm9yO1xuICAgIH1cblxuICAgIHJldHVybiBkZWVwSW5zdGFudGlhdGVEZXBzKGxvYWRlciwgaW5zdGFudGlhdGVkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUpXG4gICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGVuc3VyZUV2YWx1YXRlKGxvYWRlciwgaW5zdGFudGlhdGVkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUsIHVuZGVmaW5lZCk7XG4gICAgfSk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gcmVzb2x2ZUluc3RhbnRpYXRlIChsb2FkZXIsIGtleSwgcGFyZW50S2V5LCByZWdpc3RyeSwgc3RhdGUpIHtcbiAgLy8gbm9ybWFsaXphdGlvbiBzaG9ydHBhdGggZm9yIGFscmVhZHktbm9ybWFsaXplZCBrZXlcbiAgLy8gY291bGQgYWRkIGEgcGxhaW4gbmFtZSBmaWx0ZXIsIGJ1dCBkb2Vzbid0IHlldCBzZWVtIG5lY2Vzc2FyeSBmb3IgcGVyZlxuICB2YXIgbW9kdWxlID0gcmVnaXN0cnlba2V5XTtcbiAgaWYgKG1vZHVsZSlcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG1vZHVsZSk7XG5cbiAgdmFyIGxvYWQgPSBzdGF0ZS5yZWNvcmRzW2tleV07XG5cbiAgLy8gYWxyZWFkeSBsaW5rZWQgYnV0IG5vdCBpbiBtYWluIHJlZ2lzdHJ5IGlzIGlnbm9yZWRcbiAgaWYgKGxvYWQgJiYgIWxvYWQubW9kdWxlKSB7XG4gICAgaWYgKGxvYWQubG9hZEVycm9yKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGxvYWQubG9hZEVycm9yKTtcbiAgICByZXR1cm4gaW5zdGFudGlhdGUobG9hZGVyLCBsb2FkLCBsb2FkLmxpbmtSZWNvcmQsIHJlZ2lzdHJ5LCBzdGF0ZSk7XG4gIH1cblxuICByZXR1cm4gbG9hZGVyLnJlc29sdmUoa2V5LCBwYXJlbnRLZXkpXG4gIC50aGVuKGZ1bmN0aW9uIChyZXNvbHZlZEtleSkge1xuICAgIC8vIG1haW4gbG9hZGVyIHJlZ2lzdHJ5IGFsd2F5cyB0YWtlcyBwcmVmZXJlbmNlXG4gICAgbW9kdWxlID0gcmVnaXN0cnlbcmVzb2x2ZWRLZXldO1xuICAgIGlmIChtb2R1bGUpXG4gICAgICByZXR1cm4gbW9kdWxlO1xuXG4gICAgbG9hZCA9IHN0YXRlLnJlY29yZHNbcmVzb2x2ZWRLZXldO1xuXG4gICAgLy8gYWxyZWFkeSBoYXMgYSBtb2R1bGUgdmFsdWUgYnV0IG5vdCBhbHJlYWR5IGluIHRoZSByZWdpc3RyeSAobG9hZC5tb2R1bGUpXG4gICAgLy8gbWVhbnMgaXQgd2FzIHJlbW92ZWQgYnkgcmVnaXN0cnkuZGVsZXRlLCBzbyB3ZSBzaG91bGRcbiAgICAvLyBkaXNnYXJkIHRoZSBjdXJyZW50IGxvYWQgcmVjb3JkIGNyZWF0aW5nIGEgbmV3IG9uZSBvdmVyIGl0XG4gICAgLy8gYnV0IGtlZXAgYW55IGV4aXN0aW5nIHJlZ2lzdHJhdGlvblxuICAgIGlmICghbG9hZCB8fCBsb2FkLm1vZHVsZSlcbiAgICAgIGxvYWQgPSBjcmVhdGVMb2FkUmVjb3JkKHN0YXRlLCByZXNvbHZlZEtleSwgbG9hZCAmJiBsb2FkLnJlZ2lzdHJhdGlvbik7XG5cbiAgICBpZiAobG9hZC5sb2FkRXJyb3IpXG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobG9hZC5sb2FkRXJyb3IpO1xuXG4gICAgdmFyIGxpbmsgPSBsb2FkLmxpbmtSZWNvcmQ7XG4gICAgaWYgKCFsaW5rKVxuICAgICAgcmV0dXJuIGxvYWQ7XG5cbiAgICByZXR1cm4gaW5zdGFudGlhdGUobG9hZGVyLCBsb2FkLCBsaW5rLCByZWdpc3RyeSwgc3RhdGUpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlUHJvY2Vzc0Fub25SZWdpc3RlciAobG9hZGVyLCBsb2FkLCBzdGF0ZSkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBsYXN0UmVnaXN0ZXIgPSBzdGF0ZS5sYXN0UmVnaXN0ZXI7XG5cbiAgICBpZiAoIWxhc3RSZWdpc3RlcilcbiAgICAgIHJldHVybiAhIWxvYWQucmVnaXN0cmF0aW9uO1xuXG4gICAgc3RhdGUubGFzdFJlZ2lzdGVyID0gdW5kZWZpbmVkO1xuICAgIGxvYWQucmVnaXN0cmF0aW9uID0gbGFzdFJlZ2lzdGVyO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGluc3RhbnRpYXRlIChsb2FkZXIsIGxvYWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSkge1xuICByZXR1cm4gbGluay5pbnN0YW50aWF0ZVByb21pc2UgfHwgKGxpbmsuaW5zdGFudGlhdGVQcm9taXNlID1cbiAgLy8gaWYgdGhlcmUgaXMgYWxyZWFkeSBhbiBleGlzdGluZyByZWdpc3RyYXRpb24sIHNraXAgcnVubmluZyBpbnN0YW50aWF0ZVxuICAobG9hZC5yZWdpc3RyYXRpb24gPyBQcm9taXNlLnJlc29sdmUoKSA6IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIHN0YXRlLmxhc3RSZWdpc3RlciA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gbG9hZGVyW0lOU1RBTlRJQVRFXShsb2FkLmtleSwgbG9hZGVyW0lOU1RBTlRJQVRFXS5sZW5ndGggPiAxICYmIGNyZWF0ZVByb2Nlc3NBbm9uUmVnaXN0ZXIobG9hZGVyLCBsb2FkLCBzdGF0ZSkpO1xuICB9KSlcbiAgLnRoZW4oZnVuY3Rpb24gKGluc3RhbnRpYXRpb24pIHtcbiAgICAvLyBkaXJlY3QgbW9kdWxlIHJldHVybiBmcm9tIGluc3RhbnRpYXRlIC0+IHdlJ3JlIGRvbmVcbiAgICBpZiAoaW5zdGFudGlhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoIShpbnN0YW50aWF0aW9uIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlKSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW5zdGFudGlhdGUgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBNb2R1bGUgb2JqZWN0LicpO1xuXG4gICAgICBkZWxldGUgc3RhdGUucmVjb3Jkc1tsb2FkLmtleV07XG4gICAgICBpZiAobG9hZGVyLnRyYWNlKVxuICAgICAgICB0cmFjZUxvYWQobG9hZGVyLCBsb2FkLCBsaW5rKTtcbiAgICAgIHJldHVybiByZWdpc3RyeVtsb2FkLmtleV0gPSBpbnN0YW50aWF0aW9uO1xuICAgIH1cblxuICAgIC8vIHJ1biB0aGUgY2FjaGVkIGxvYWRlci5yZWdpc3RlciBkZWNsYXJhdGlvbiBpZiB0aGVyZSBpcyBvbmVcbiAgICB2YXIgcmVnaXN0cmF0aW9uID0gbG9hZC5yZWdpc3RyYXRpb247XG4gICAgLy8gY2xlYXIgdG8gYWxsb3cgbmV3IHJlZ2lzdHJhdGlvbnMgZm9yIGZ1dHVyZSBsb2FkcyAoY29tYmluZWQgd2l0aCByZWdpc3RyeSBkZWxldGUpXG4gICAgbG9hZC5yZWdpc3RyYXRpb24gPSB1bmRlZmluZWQ7XG4gICAgaWYgKCFyZWdpc3RyYXRpb24pXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdNb2R1bGUgaW5zdGFudGlhdGlvbiBkaWQgbm90IGNhbGwgYW4gYW5vbnltb3VzIG9yIGNvcnJlY3RseSBuYW1lZCBTeXN0ZW0ucmVnaXN0ZXIuJyk7XG5cbiAgICBsaW5rLmRlcGVuZGVuY2llcyA9IHJlZ2lzdHJhdGlvblswXTtcblxuICAgIGxvYWQuaW1wb3J0ZXJTZXR0ZXJzID0gW107XG5cbiAgICBsaW5rLm1vZHVsZU9iaiA9IHt9O1xuXG4gICAgLy8gcHJvY2VzcyBTeXN0ZW0ucmVnaXN0ZXJEeW5hbWljIGRlY2xhcmF0aW9uXG4gICAgaWYgKHJlZ2lzdHJhdGlvblsyXSkge1xuICAgICAgbGluay5tb2R1bGVPYmouZGVmYXVsdCA9IGxpbmsubW9kdWxlT2JqLl9fdXNlRGVmYXVsdCA9IHt9O1xuICAgICAgbGluay5leGVjdXRpbmdSZXF1aXJlID0gcmVnaXN0cmF0aW9uWzFdO1xuICAgICAgbGluay5leGVjdXRlID0gcmVnaXN0cmF0aW9uWzJdO1xuICAgIH1cblxuICAgIC8vIHByb2Nlc3MgU3lzdGVtLnJlZ2lzdGVyIGRlY2xhcmF0aW9uXG4gICAgZWxzZSB7XG4gICAgICByZWdpc3RlckRlY2xhcmF0aXZlKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cmF0aW9uWzFdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbG9hZDtcbiAgfSlcbiAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICBsb2FkLmxpbmtSZWNvcmQgPSB1bmRlZmluZWQ7XG4gICAgdGhyb3cgbG9hZC5sb2FkRXJyb3IgPSBsb2FkLmxvYWRFcnJvciB8fCBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrKGVyciwgJ0luc3RhbnRpYXRpbmcgJyArIGxvYWQua2V5KTtcbiAgfSkpO1xufVxuXG4vLyBsaWtlIHJlc29sdmVJbnN0YW50aWF0ZSwgYnV0IHJldHVybmluZyBsb2FkIHJlY29yZHMgZm9yIGxpbmtpbmdcbmZ1bmN0aW9uIHJlc29sdmVJbnN0YW50aWF0ZURlcCAobG9hZGVyLCBrZXksIHBhcmVudEtleSwgcmVnaXN0cnksIHN0YXRlLCB0cmFjZURlcE1hcCkge1xuICAvLyBub3JtYWxpemF0aW9uIHNob3J0cGF0aHMgZm9yIGFscmVhZHktbm9ybWFsaXplZCBrZXlcbiAgLy8gRElTQUJMRUQgdG8gcHJpb3JpdGlzZSBjb25zaXN0ZW50IHJlc29sdmVyIGNhbGxzXG4gIC8vIGNvdWxkIGFkZCBhIHBsYWluIG5hbWUgZmlsdGVyLCBidXQgZG9lc24ndCB5ZXQgc2VlbSBuZWNlc3NhcnkgZm9yIHBlcmZcbiAgLyogdmFyIGxvYWQgPSBzdGF0ZS5yZWNvcmRzW2tleV07XG4gIHZhciBtb2R1bGUgPSByZWdpc3RyeVtrZXldO1xuXG4gIGlmIChtb2R1bGUpIHtcbiAgICBpZiAodHJhY2VEZXBNYXApXG4gICAgICB0cmFjZURlcE1hcFtrZXldID0ga2V5O1xuXG4gICAgLy8gcmVnaXN0cnkgYXV0aG9yaXR5IGNoZWNrIGluIGNhc2UgbW9kdWxlIHdhcyBkZWxldGVkIG9yIHJlcGxhY2VkIGluIG1haW4gcmVnaXN0cnlcbiAgICBpZiAobG9hZCAmJiBsb2FkLm1vZHVsZSAmJiBsb2FkLm1vZHVsZSA9PT0gbW9kdWxlKVxuICAgICAgcmV0dXJuIGxvYWQ7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuIG1vZHVsZTtcbiAgfVxuXG4gIC8vIGFscmVhZHkgbGlua2VkIGJ1dCBub3QgaW4gbWFpbiByZWdpc3RyeSBpcyBpZ25vcmVkXG4gIGlmIChsb2FkICYmICFsb2FkLm1vZHVsZSkge1xuICAgIGlmICh0cmFjZURlcE1hcClcbiAgICAgIHRyYWNlRGVwTWFwW2tleV0gPSBrZXk7XG4gICAgcmV0dXJuIGluc3RhbnRpYXRlKGxvYWRlciwgbG9hZCwgbG9hZC5saW5rUmVjb3JkLCByZWdpc3RyeSwgc3RhdGUpO1xuICB9ICovXG4gIHJldHVybiBsb2FkZXIucmVzb2x2ZShrZXksIHBhcmVudEtleSlcbiAgLnRoZW4oZnVuY3Rpb24gKHJlc29sdmVkS2V5KSB7XG4gICAgaWYgKHRyYWNlRGVwTWFwKVxuICAgICAgdHJhY2VEZXBNYXBba2V5XSA9IHJlc29sdmVkS2V5O1xuXG4gICAgLy8gbm9ybWFsaXphdGlvbiBzaG9ydHBhdGhzIGZvciBhbHJlYWR5LW5vcm1hbGl6ZWQga2V5XG4gICAgdmFyIGxvYWQgPSBzdGF0ZS5yZWNvcmRzW3Jlc29sdmVkS2V5XTtcbiAgICB2YXIgbW9kdWxlID0gcmVnaXN0cnlbcmVzb2x2ZWRLZXldO1xuXG4gICAgLy8gbWFpbiBsb2FkZXIgcmVnaXN0cnkgYWx3YXlzIHRha2VzIHByZWZlcmVuY2VcbiAgICBpZiAobW9kdWxlICYmICghbG9hZCB8fCBsb2FkLm1vZHVsZSAmJiBtb2R1bGUgIT09IGxvYWQubW9kdWxlKSlcbiAgICAgIHJldHVybiBtb2R1bGU7XG5cbiAgICBpZiAobG9hZCAmJiBsb2FkLmxvYWRFcnJvcilcbiAgICAgIHRocm93IGxvYWQubG9hZEVycm9yO1xuXG4gICAgLy8gYWxyZWFkeSBoYXMgYSBtb2R1bGUgdmFsdWUgYnV0IG5vdCBhbHJlYWR5IGluIHRoZSByZWdpc3RyeSAobG9hZC5tb2R1bGUpXG4gICAgLy8gbWVhbnMgaXQgd2FzIHJlbW92ZWQgYnkgcmVnaXN0cnkuZGVsZXRlLCBzbyB3ZSBzaG91bGRcbiAgICAvLyBkaXNnYXJkIHRoZSBjdXJyZW50IGxvYWQgcmVjb3JkIGNyZWF0aW5nIGEgbmV3IG9uZSBvdmVyIGl0XG4gICAgLy8gYnV0IGtlZXAgYW55IGV4aXN0aW5nIHJlZ2lzdHJhdGlvblxuICAgIGlmICghbG9hZCB8fCAhbW9kdWxlICYmIGxvYWQubW9kdWxlKVxuICAgICAgbG9hZCA9IGNyZWF0ZUxvYWRSZWNvcmQoc3RhdGUsIHJlc29sdmVkS2V5LCBsb2FkICYmIGxvYWQucmVnaXN0cmF0aW9uKTtcblxuICAgIHZhciBsaW5rID0gbG9hZC5saW5rUmVjb3JkO1xuICAgIGlmICghbGluaylcbiAgICAgIHJldHVybiBsb2FkO1xuXG4gICAgcmV0dXJuIGluc3RhbnRpYXRlKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHRyYWNlTG9hZCAobG9hZGVyLCBsb2FkLCBsaW5rKSB7XG4gIGxvYWRlci5sb2FkcyA9IGxvYWRlci5sb2FkcyB8fCB7fTtcbiAgbG9hZGVyLmxvYWRzW2xvYWQua2V5XSA9IHtcbiAgICBrZXk6IGxvYWQua2V5LFxuICAgIGRlcHM6IGxpbmsuZGVwZW5kZW5jaWVzLFxuICAgIGR5bmFtaWNEZXBzOiBbXSxcbiAgICBkZXBNYXA6IGxpbmsuZGVwTWFwIHx8IHt9XG4gIH07XG59XG5cbi8qXG4gKiBDb252ZXJ0IGEgQ0pTIG1vZHVsZS5leHBvcnRzIGludG8gYSB2YWxpZCBvYmplY3QgZm9yIG5ldyBNb2R1bGU6XG4gKlxuICogICBuZXcgTW9kdWxlKGdldEVzTW9kdWxlKG1vZHVsZS5leHBvcnRzKSlcbiAqXG4gKiBTZXRzIHRoZSBkZWZhdWx0IHZhbHVlIHRvIHRoZSBtb2R1bGUsIHdoaWxlIGFsc28gcmVhZGluZyBvZmYgbmFtZWQgZXhwb3J0cyBjYXJlZnVsbHkuXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyRGVjbGFyYXRpdmUgKGxvYWRlciwgbG9hZCwgbGluaywgZGVjbGFyZSkge1xuICB2YXIgbW9kdWxlT2JqID0gbGluay5tb2R1bGVPYmo7XG4gIHZhciBpbXBvcnRlclNldHRlcnMgPSBsb2FkLmltcG9ydGVyU2V0dGVycztcblxuICB2YXIgZGVmaW5lZEV4cG9ydHMgPSBmYWxzZTtcblxuICAvLyBjbG9zdXJlIGVzcGVjaWFsbHkgbm90IGJhc2VkIG9uIGxpbmsgdG8gYWxsb3cgbGluayByZWNvcmQgZGlzcG9zYWxcbiAgdmFyIGRlY2xhcmVkID0gZGVjbGFyZS5jYWxsKGVudkdsb2JhbCwgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSAnb2JqZWN0Jykge1xuICAgICAgdmFyIGNoYW5nZWQgPSBmYWxzZTtcbiAgICAgIGZvciAodmFyIHAgaW4gbmFtZSkge1xuICAgICAgICB2YWx1ZSA9IG5hbWVbcF07XG4gICAgICAgIGlmIChwICE9PSAnX191c2VEZWZhdWx0JyAmJiAoIShwIGluIG1vZHVsZU9iaikgfHwgbW9kdWxlT2JqW3BdICE9PSB2YWx1ZSkpIHtcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICBtb2R1bGVPYmpbcF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGNoYW5nZWQgPT09IGZhbHNlKVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgaWYgKChkZWZpbmVkRXhwb3J0cyB8fCBuYW1lIGluIG1vZHVsZU9iaikgJiYgbW9kdWxlT2JqW25hbWVdID09PSB2YWx1ZSlcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgbW9kdWxlT2JqW25hbWVdID0gdmFsdWU7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbXBvcnRlclNldHRlcnMubGVuZ3RoOyBpKyspXG4gICAgICBpbXBvcnRlclNldHRlcnNbaV0obW9kdWxlT2JqKTtcblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfSwgbmV3IENvbnRleHR1YWxMb2FkZXIobG9hZGVyLCBsb2FkLmtleSkpO1xuXG4gIGxpbmsuc2V0dGVycyA9IGRlY2xhcmVkLnNldHRlcnM7XG4gIGxpbmsuZXhlY3V0ZSA9IGRlY2xhcmVkLmV4ZWN1dGU7XG4gIGlmIChkZWNsYXJlZC5leHBvcnRzKSB7XG4gICAgbGluay5tb2R1bGVPYmogPSBtb2R1bGVPYmogPSBkZWNsYXJlZC5leHBvcnRzO1xuICAgIGRlZmluZWRFeHBvcnRzID0gdHJ1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnN0YW50aWF0ZURlcHMgKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlKSB7XG4gIGlmIChsaW5rLmRlcHNJbnN0YW50aWF0ZVByb21pc2UpXG4gICAgcmV0dXJuIGxpbmsuZGVwc0luc3RhbnRpYXRlUHJvbWlzZTtcblxuICB2YXIgZGVwc0luc3RhbnRpYXRlUHJvbWlzZXMgPSBBcnJheShsaW5rLmRlcGVuZGVuY2llcy5sZW5ndGgpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGluay5kZXBlbmRlbmNpZXMubGVuZ3RoOyBpKyspXG4gICAgZGVwc0luc3RhbnRpYXRlUHJvbWlzZXNbaV0gPSByZXNvbHZlSW5zdGFudGlhdGVEZXAobG9hZGVyLCBsaW5rLmRlcGVuZGVuY2llc1tpXSwgbG9hZC5rZXksIHJlZ2lzdHJ5LCBzdGF0ZSwgbG9hZGVyLnRyYWNlICYmIGxpbmsuZGVwTWFwIHx8IChsaW5rLmRlcE1hcCA9IHt9KSk7XG5cbiAgdmFyIGRlcHNJbnN0YW50aWF0ZVByb21pc2UgPSBQcm9taXNlLmFsbChkZXBzSW5zdGFudGlhdGVQcm9taXNlcylcbiAgLnRoZW4oZnVuY3Rpb24gKGRlcGVuZGVuY3lJbnN0YW50aWF0aW9ucykge1xuICAgIGxpbmsuZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zID0gZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zO1xuXG4gICAgLy8gcnVuIHNldHRlcnMgdG8gc2V0IHVwIGJpbmRpbmdzIHRvIGluc3RhbnRpYXRlZCBkZXBlbmRlbmNpZXNcbiAgICBpZiAobGluay5zZXR0ZXJzKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRlcGVuZGVuY3lJbnN0YW50aWF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2V0dGVyID0gbGluay5zZXR0ZXJzW2ldO1xuICAgICAgICBpZiAoc2V0dGVyKSB7XG4gICAgICAgICAgdmFyIGluc3RhbnRpYXRpb24gPSBkZXBlbmRlbmN5SW5zdGFudGlhdGlvbnNbaV07XG5cbiAgICAgICAgICBpZiAoaW5zdGFudGlhdGlvbiBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSkge1xuICAgICAgICAgICAgc2V0dGVyKGluc3RhbnRpYXRpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChpbnN0YW50aWF0aW9uLmxvYWRFcnJvcilcbiAgICAgICAgICAgICAgdGhyb3cgaW5zdGFudGlhdGlvbi5sb2FkRXJyb3I7XG4gICAgICAgICAgICBzZXR0ZXIoaW5zdGFudGlhdGlvbi5tb2R1bGUgfHwgaW5zdGFudGlhdGlvbi5saW5rUmVjb3JkLm1vZHVsZU9iaik7XG4gICAgICAgICAgICAvLyB0aGlzIGFwcGxpZXMgdG8gYm90aCBlcyBhbmQgZHluYW1pYyByZWdpc3RyYXRpb25zXG4gICAgICAgICAgICBpZiAoaW5zdGFudGlhdGlvbi5pbXBvcnRlclNldHRlcnMpXG4gICAgICAgICAgICAgIGluc3RhbnRpYXRpb24uaW1wb3J0ZXJTZXR0ZXJzLnB1c2goc2V0dGVyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbG9hZDtcbiAgfSk7XG5cbiAgaWYgKGxvYWRlci50cmFjZSlcbiAgICBkZXBzSW5zdGFudGlhdGVQcm9taXNlID0gZGVwc0luc3RhbnRpYXRlUHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYWNlTG9hZChsb2FkZXIsIGxvYWQsIGxpbmspO1xuICAgICAgcmV0dXJuIGxvYWQ7XG4gICAgfSk7XG5cbiAgZGVwc0luc3RhbnRpYXRlUHJvbWlzZSA9IGRlcHNJbnN0YW50aWF0ZVByb21pc2UuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgIC8vIHRocm93IHVwIHRoZSBpbnN0YW50aWF0ZURlcHMgc3RhY2tcbiAgICBsaW5rLmRlcHNJbnN0YW50aWF0ZVByb21pc2UgPSB1bmRlZmluZWQ7XG4gICAgdGhyb3cgTG9hZGVyRXJyb3JfX0NoZWNrX2Vycm9yX21lc3NhZ2VfZm9yX2xvYWRlcl9zdGFjayhlcnIsICdMb2FkaW5nICcgKyBsb2FkLmtleSk7XG4gIH0pO1xuXG4gIGRlcHNJbnN0YW50aWF0ZVByb21pc2UuY2F0Y2goZnVuY3Rpb24gKCkge30pO1xuXG4gIHJldHVybiBsaW5rLmRlcHNJbnN0YW50aWF0ZVByb21pc2UgPSBkZXBzSW5zdGFudGlhdGVQcm9taXNlO1xufVxuXG5mdW5jdGlvbiBkZWVwSW5zdGFudGlhdGVEZXBzIChsb2FkZXIsIGxvYWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciBzZWVuID0gW107XG4gICAgdmFyIGxvYWRDbnQgPSAwO1xuICAgIGZ1bmN0aW9uIHF1ZXVlTG9hZCAobG9hZCkge1xuICAgICAgdmFyIGxpbmsgPSBsb2FkLmxpbmtSZWNvcmQ7XG4gICAgICBpZiAoIWxpbmspXG4gICAgICAgIHJldHVybjtcblxuICAgICAgaWYgKHNlZW4uaW5kZXhPZihsb2FkKSAhPT0gLTEpXG4gICAgICAgIHJldHVybjtcbiAgICAgIHNlZW4ucHVzaChsb2FkKTtcblxuICAgICAgbG9hZENudCsrO1xuICAgICAgaW5zdGFudGlhdGVEZXBzKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlKVxuICAgICAgLnRoZW4ocHJvY2Vzc0xvYWQsIHJlamVjdCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHByb2Nlc3NMb2FkIChsb2FkKSB7XG4gICAgICBsb2FkQ250LS07XG4gICAgICB2YXIgbGluayA9IGxvYWQubGlua1JlY29yZDtcbiAgICAgIGlmIChsaW5rKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluay5kZXBlbmRlbmNpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgZGVwTG9hZCA9IGxpbmsuZGVwZW5kZW5jeUluc3RhbnRpYXRpb25zW2ldO1xuICAgICAgICAgIGlmICghKGRlcExvYWQgaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpKVxuICAgICAgICAgICAgcXVldWVMb2FkKGRlcExvYWQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobG9hZENudCA9PT0gMClcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgIH1cbiAgICBxdWV1ZUxvYWQobG9hZCk7XG4gIH0pO1xufVxuXG4vKlxuICogU3lzdGVtLnJlZ2lzdGVyXG4gKi9cblJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlLnJlZ2lzdGVyID0gZnVuY3Rpb24gKGtleSwgZGVwcywgZGVjbGFyZSkge1xuICB2YXIgc3RhdGUgPSB0aGlzW1JFR0lTVEVSX0lOVEVSTkFMXTtcblxuICAvLyBhbm9ueW1vdXMgbW9kdWxlcyBnZXQgc3RvcmVkIGFzIGxhc3RBbm9uXG4gIGlmIChkZWNsYXJlID09PSB1bmRlZmluZWQpIHtcbiAgICBzdGF0ZS5sYXN0UmVnaXN0ZXIgPSBba2V5LCBkZXBzLCB1bmRlZmluZWRdO1xuICB9XG5cbiAgLy8gZXZlcnl0aGluZyBlbHNlIHJlZ2lzdGVycyBpbnRvIHRoZSByZWdpc3RlciBjYWNoZVxuICBlbHNlIHtcbiAgICB2YXIgbG9hZCA9IHN0YXRlLnJlY29yZHNba2V5XSB8fCBjcmVhdGVMb2FkUmVjb3JkKHN0YXRlLCBrZXksIHVuZGVmaW5lZCk7XG4gICAgbG9hZC5yZWdpc3RyYXRpb24gPSBbZGVwcywgZGVjbGFyZSwgdW5kZWZpbmVkXTtcbiAgfVxufTtcblxuLypcbiAqIFN5c3RlbS5yZWdpc3RlckR5YW5taWNcbiAqL1xuUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUucmVnaXN0ZXJEeW5hbWljID0gZnVuY3Rpb24gKGtleSwgZGVwcywgZXhlY3V0aW5nUmVxdWlyZSwgZXhlY3V0ZSkge1xuICB2YXIgc3RhdGUgPSB0aGlzW1JFR0lTVEVSX0lOVEVSTkFMXTtcblxuICAvLyBhbm9ueW1vdXMgbW9kdWxlcyBnZXQgc3RvcmVkIGFzIGxhc3RBbm9uXG4gIGlmICh0eXBlb2Yga2V5ICE9PSAnc3RyaW5nJykge1xuICAgIHN0YXRlLmxhc3RSZWdpc3RlciA9IFtrZXksIGRlcHMsIGV4ZWN1dGluZ1JlcXVpcmVdO1xuICB9XG5cbiAgLy8gZXZlcnl0aGluZyBlbHNlIHJlZ2lzdGVycyBpbnRvIHRoZSByZWdpc3RlciBjYWNoZVxuICBlbHNlIHtcbiAgICB2YXIgbG9hZCA9IHN0YXRlLnJlY29yZHNba2V5XSB8fCBjcmVhdGVMb2FkUmVjb3JkKHN0YXRlLCBrZXksIHVuZGVmaW5lZCk7XG4gICAgbG9hZC5yZWdpc3RyYXRpb24gPSBbZGVwcywgZXhlY3V0aW5nUmVxdWlyZSwgZXhlY3V0ZV07XG4gIH1cbn07XG5cbi8vIENvbnRleHR1YWxMb2FkZXIgY2xhc3Ncbi8vIGJhY2t3YXJkcy1jb21wYXRpYmxlIHdpdGggcHJldmlvdXMgU3lzdGVtLnJlZ2lzdGVyIGNvbnRleHQgYXJndW1lbnQgYnkgZXhwb3NpbmcgLmlkLCAua2V5XG5mdW5jdGlvbiBDb250ZXh0dWFsTG9hZGVyIChsb2FkZXIsIGtleSkge1xuICB0aGlzLmxvYWRlciA9IGxvYWRlcjtcbiAgdGhpcy5rZXkgPSB0aGlzLmlkID0ga2V5O1xuICB0aGlzLm1ldGEgPSB7XG4gICAgdXJsOiBrZXlcbiAgICAvLyBzY3JpcHRFbGVtZW50OiBudWxsXG4gIH07XG59XG4vKkNvbnRleHR1YWxMb2FkZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkge1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3Qgc3ViY2xhc3MgdGhlIGNvbnRleHR1YWwgbG9hZGVyIG9ubHkgUmVmbGVjdC5Mb2FkZXIuJyk7XG59OyovXG5Db250ZXh0dWFsTG9hZGVyLnByb3RvdHlwZS5pbXBvcnQgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIGlmICh0aGlzLmxvYWRlci50cmFjZSlcbiAgICB0aGlzLmxvYWRlci5sb2Fkc1t0aGlzLmtleV0uZHluYW1pY0RlcHMucHVzaChrZXkpO1xuICByZXR1cm4gdGhpcy5sb2FkZXIuaW1wb3J0KGtleSwgdGhpcy5rZXkpO1xufTtcbi8qQ29udGV4dHVhbExvYWRlci5wcm90b3R5cGUucmVzb2x2ZSA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHRoaXMubG9hZGVyLnJlc29sdmUoa2V5LCB0aGlzLmtleSk7XG59OyovXG5cbi8vIHRoaXMgaXMgdGhlIGV4ZWN1dGlvbiBmdW5jdGlvbiBib3VuZCB0byB0aGUgTW9kdWxlIG5hbWVzcGFjZSByZWNvcmRcbmZ1bmN0aW9uIGVuc3VyZUV2YWx1YXRlIChsb2FkZXIsIGxvYWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSwgc2Vlbikge1xuICBpZiAobG9hZC5tb2R1bGUpXG4gICAgcmV0dXJuIGxvYWQubW9kdWxlO1xuXG4gIGlmIChsb2FkLmV2YWxFcnJvcilcbiAgICB0aHJvdyBsb2FkLmV2YWxFcnJvcjtcblxuICBpZiAoc2VlbiAmJiBzZWVuLmluZGV4T2YobG9hZCkgIT09IC0xKVxuICAgIHJldHVybiBsb2FkLmxpbmtSZWNvcmQubW9kdWxlT2JqO1xuXG4gIC8vIGZvciBFUyBsb2FkcyB3ZSBhbHdheXMgcnVuIGVuc3VyZUV2YWx1YXRlIG9uIHRvcC1sZXZlbCwgc28gZW1wdHkgc2VlbiBpcyBwYXNzZWQgcmVnYXJkbGVzc1xuICAvLyBmb3IgZHluYW1pYyBsb2Fkcywgd2UgcGFzcyBzZWVuIGlmIGFsc28gZHluYW1pY1xuICB2YXIgZXJyID0gZG9FdmFsdWF0ZShsb2FkZXIsIGxvYWQsIGxpbmssIHJlZ2lzdHJ5LCBzdGF0ZSwgbGluay5zZXR0ZXJzID8gW10gOiBzZWVuIHx8IFtdKTtcbiAgaWYgKGVycilcbiAgICB0aHJvdyBlcnI7XG5cbiAgcmV0dXJuIGxvYWQubW9kdWxlO1xufVxuXG5mdW5jdGlvbiBtYWtlRHluYW1pY1JlcXVpcmUgKGxvYWRlciwga2V5LCBkZXBlbmRlbmNpZXMsIGRlcGVuZGVuY3lJbnN0YW50aWF0aW9ucywgcmVnaXN0cnksIHN0YXRlLCBzZWVuKSB7XG4gIC8vIHdlIGNhbiBvbmx5IHJlcXVpcmUgZnJvbSBhbHJlYWR5LWtub3duIGRlcGVuZGVuY2llc1xuICByZXR1cm4gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRlcGVuZGVuY2llcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGRlcGVuZGVuY2llc1tpXSA9PT0gbmFtZSkge1xuICAgICAgICB2YXIgZGVwTG9hZCA9IGRlcGVuZGVuY3lJbnN0YW50aWF0aW9uc1tpXTtcbiAgICAgICAgdmFyIG1vZHVsZTtcblxuICAgICAgICBpZiAoZGVwTG9hZCBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSlcbiAgICAgICAgICBtb2R1bGUgPSBkZXBMb2FkO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgbW9kdWxlID0gZW5zdXJlRXZhbHVhdGUobG9hZGVyLCBkZXBMb2FkLCBkZXBMb2FkLmxpbmtSZWNvcmQsIHJlZ2lzdHJ5LCBzdGF0ZSwgc2Vlbik7XG5cbiAgICAgICAgcmV0dXJuICdfX3VzZURlZmF1bHQnIGluIG1vZHVsZSA/IG1vZHVsZS5fX3VzZURlZmF1bHQgOiBtb2R1bGU7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignTW9kdWxlICcgKyBuYW1lICsgJyBub3QgZGVjbGFyZWQgYXMgYSBTeXN0ZW0ucmVnaXN0ZXJEeW5hbWljIGRlcGVuZGVuY3kgb2YgJyArIGtleSk7XG4gIH07XG59XG5cbi8vIGVuc3VyZXMgdGhlIGdpdmVuIGVzIGxvYWQgaXMgZXZhbHVhdGVkXG4vLyByZXR1cm5zIHRoZSBlcnJvciBpZiBhbnlcbmZ1bmN0aW9uIGRvRXZhbHVhdGUgKGxvYWRlciwgbG9hZCwgbGluaywgcmVnaXN0cnksIHN0YXRlLCBzZWVuKSB7XG4gIHNlZW4ucHVzaChsb2FkKTtcblxuICB2YXIgZXJyO1xuXG4gIC8vIGVzIG1vZHVsZXMgZXZhbHVhdGUgZGVwZW5kZW5jaWVzIGZpcnN0XG4gIC8vIG5vbiBlcyBtb2R1bGVzIGV4cGxpY2l0bHkgY2FsbCBtb2R1bGVFdmFsdWF0ZSB0aHJvdWdoIHJlcXVpcmVcbiAgaWYgKGxpbmsuc2V0dGVycykge1xuICAgIHZhciBkZXBMb2FkLCBkZXBMaW5rO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluay5kZXBlbmRlbmNpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGRlcExvYWQgPSBsaW5rLmRlcGVuZGVuY3lJbnN0YW50aWF0aW9uc1tpXTtcblxuICAgICAgaWYgKGRlcExvYWQgaW5zdGFuY2VvZiBNb2R1bGVOYW1lc3BhY2UpXG4gICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAvLyBjdXN0b20gTW9kdWxlIHJldHVybmVkIGZyb20gaW5zdGFudGlhdGVcbiAgICAgIGRlcExpbmsgPSBkZXBMb2FkLmxpbmtSZWNvcmQ7XG4gICAgICBpZiAoZGVwTGluayAmJiBzZWVuLmluZGV4T2YoZGVwTG9hZCkgPT09IC0xKSB7XG4gICAgICAgIGlmIChkZXBMb2FkLmV2YWxFcnJvcilcbiAgICAgICAgICBlcnIgPSBkZXBMb2FkLmV2YWxFcnJvcjtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIC8vIGR5bmFtaWMgLyBkZWNsYXJhdGl2ZSBib3VuZGFyaWVzIGNsZWFyIHRoZSBcInNlZW5cIiBsaXN0XG4gICAgICAgICAgLy8gd2UganVzdCBsZXQgY3Jvc3MgZm9ybWF0IGNpcmN1bGFyIHRocm93IGFzIHdvdWxkIGhhcHBlbiBpbiByZWFsIGltcGxlbWVudGF0aW9uc1xuICAgICAgICAgIGVyciA9IGRvRXZhbHVhdGUobG9hZGVyLCBkZXBMb2FkLCBkZXBMaW5rLCByZWdpc3RyeSwgc3RhdGUsIGRlcExpbmsuc2V0dGVycyA/IHNlZW4gOiBbXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgbG9hZC5saW5rUmVjb3JkID0gdW5kZWZpbmVkO1xuICAgICAgICBsb2FkLmV2YWxFcnJvciA9IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnRXZhbHVhdGluZyAnICsgbG9hZC5rZXkpO1xuICAgICAgICByZXR1cm4gbG9hZC5ldmFsRXJyb3I7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gbGluay5leGVjdXRlIHdvbid0IGV4aXN0IGZvciBNb2R1bGUgcmV0dXJucyBmcm9tIGluc3RhbnRpYXRlIG9uIHRvcC1sZXZlbCBsb2FkXG4gIGlmIChsaW5rLmV4ZWN1dGUpIHtcbiAgICAvLyBFUyBTeXN0ZW0ucmVnaXN0ZXIgZXhlY3V0ZVxuICAgIC8vIFwidGhpc1wiIGlzIG51bGwgaW4gRVNcbiAgICBpZiAobGluay5zZXR0ZXJzKSB7XG4gICAgICBlcnIgPSBkZWNsYXJhdGl2ZUV4ZWN1dGUobGluay5leGVjdXRlKTtcbiAgICB9XG4gICAgLy8gU3lzdGVtLnJlZ2lzdGVyRHluYW1pYyBleGVjdXRlXG4gICAgLy8gXCJ0aGlzXCIgaXMgXCJleHBvcnRzXCIgaW4gQ0pTXG4gICAgZWxzZSB7XG4gICAgICB2YXIgbW9kdWxlID0geyBpZDogbG9hZC5rZXkgfTtcbiAgICAgIHZhciBtb2R1bGVPYmogPSBsaW5rLm1vZHVsZU9iajtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUsICdleHBvcnRzJywge1xuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIHNldDogZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAgICAgICBtb2R1bGVPYmouZGVmYXVsdCA9IG1vZHVsZU9iai5fX3VzZURlZmF1bHQgPSBleHBvcnRzO1xuICAgICAgICB9LFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gbW9kdWxlT2JqLl9fdXNlRGVmYXVsdDtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHZhciByZXF1aXJlID0gbWFrZUR5bmFtaWNSZXF1aXJlKGxvYWRlciwgbG9hZC5rZXksIGxpbmsuZGVwZW5kZW5jaWVzLCBsaW5rLmRlcGVuZGVuY3lJbnN0YW50aWF0aW9ucywgcmVnaXN0cnksIHN0YXRlLCBzZWVuKTtcblxuICAgICAgLy8gZXZhbHVhdGUgZGVwcyBmaXJzdFxuICAgICAgaWYgKCFsaW5rLmV4ZWN1dGluZ1JlcXVpcmUpXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluay5kZXBlbmRlbmNpZXMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgcmVxdWlyZShsaW5rLmRlcGVuZGVuY2llc1tpXSk7XG5cbiAgICAgIGVyciA9IGR5bmFtaWNFeGVjdXRlKGxpbmsuZXhlY3V0ZSwgcmVxdWlyZSwgbW9kdWxlT2JqLmRlZmF1bHQsIG1vZHVsZSk7XG5cbiAgICAgIC8vIHBpY2sgdXAgZGVmaW5lUHJvcGVydHkgY2FsbHMgdG8gbW9kdWxlLmV4cG9ydHMgd2hlbiB3ZSBjYW5cbiAgICAgIGlmIChtb2R1bGUuZXhwb3J0cyAhPT0gbW9kdWxlT2JqLl9fdXNlRGVmYXVsdClcbiAgICAgICAgbW9kdWxlT2JqLmRlZmF1bHQgPSBtb2R1bGVPYmouX191c2VEZWZhdWx0ID0gbW9kdWxlLmV4cG9ydHM7XG5cbiAgICAgIHZhciBtb2R1bGVEZWZhdWx0ID0gbW9kdWxlT2JqLmRlZmF1bHQ7XG5cbiAgICAgIC8vIF9fZXNNb2R1bGUgZmxhZyBleHRlbnNpb24gc3VwcG9ydCB2aWEgbGlmdGluZ1xuICAgICAgaWYgKG1vZHVsZURlZmF1bHQgJiYgbW9kdWxlRGVmYXVsdC5fX2VzTW9kdWxlKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gbW9kdWxlRGVmYXVsdCkge1xuICAgICAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtb2R1bGVEZWZhdWx0LCBwKSlcbiAgICAgICAgICAgIG1vZHVsZU9ialtwXSA9IG1vZHVsZURlZmF1bHRbcF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBkaXNwb3NlIGxpbmsgcmVjb3JkXG4gIGxvYWQubGlua1JlY29yZCA9IHVuZGVmaW5lZDtcblxuICBpZiAoZXJyKVxuICAgIHJldHVybiBsb2FkLmV2YWxFcnJvciA9IExvYWRlckVycm9yX19DaGVja19lcnJvcl9tZXNzYWdlX2Zvcl9sb2FkZXJfc3RhY2soZXJyLCAnRXZhbHVhdGluZyAnICsgbG9hZC5rZXkpO1xuXG4gIHJlZ2lzdHJ5W2xvYWQua2V5XSA9IGxvYWQubW9kdWxlID0gbmV3IE1vZHVsZU5hbWVzcGFjZShsaW5rLm1vZHVsZU9iaik7XG5cbiAgLy8gaWYgbm90IGFuIGVzbSBtb2R1bGUsIHJ1biBpbXBvcnRlciBzZXR0ZXJzIGFuZCBjbGVhciB0aGVtXG4gIC8vIHRoaXMgYWxsb3dzIGR5bmFtaWMgbW9kdWxlcyB0byB1cGRhdGUgdGhlbXNlbHZlcyBpbnRvIGVzIG1vZHVsZXNcbiAgLy8gYXMgc29vbiBhcyBleGVjdXRpb24gaGFzIGNvbXBsZXRlZFxuICBpZiAoIWxpbmsuc2V0dGVycykge1xuICAgIGlmIChsb2FkLmltcG9ydGVyU2V0dGVycylcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZC5pbXBvcnRlclNldHRlcnMubGVuZ3RoOyBpKyspXG4gICAgICAgIGxvYWQuaW1wb3J0ZXJTZXR0ZXJzW2ldKGxvYWQubW9kdWxlKTtcbiAgICBsb2FkLmltcG9ydGVyU2V0dGVycyA9IHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vLyB7fSBpcyB0aGUgY2xvc2VzdCB3ZSBjYW4gZ2V0IHRvIGNhbGwodW5kZWZpbmVkKVxudmFyIG51bGxDb250ZXh0ID0ge307XG5pZiAoT2JqZWN0LmZyZWV6ZSlcbiAgT2JqZWN0LmZyZWV6ZShudWxsQ29udGV4dCk7XG5cbmZ1bmN0aW9uIGRlY2xhcmF0aXZlRXhlY3V0ZSAoZXhlY3V0ZSkge1xuICB0cnkge1xuICAgIGV4ZWN1dGUuY2FsbChudWxsQ29udGV4dCk7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBkeW5hbWljRXhlY3V0ZSAoZXhlY3V0ZSwgcmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gIHRyeSB7XG4gICAgdmFyIG91dHB1dCA9IGV4ZWN1dGUuY2FsbChlbnZHbG9iYWwsIHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSk7XG4gICAgaWYgKG91dHB1dCAhPT0gdW5kZWZpbmVkKVxuICAgICAgbW9kdWxlLmV4cG9ydHMgPSBvdXRwdXQ7XG4gIH1cbiAgY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZTtcbiAgfVxufVxuXG52YXIgcmVzb2x2ZWRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5mdW5jdGlvbiBub29wICgpIHt9XG5cbnZhciBlbXB0eU1vZHVsZSA9IG5ldyBNb2R1bGVOYW1lc3BhY2Uoe30pO1xuXG5mdW5jdGlvbiBwcm90ZWN0ZWRDcmVhdGVOYW1lc3BhY2UgKGJpbmRpbmdzKSB7XG4gIGlmIChiaW5kaW5ncyBpbnN0YW5jZW9mIE1vZHVsZU5hbWVzcGFjZSlcbiAgICByZXR1cm4gYmluZGluZ3M7XG5cbiAgaWYgKGJpbmRpbmdzICYmIGJpbmRpbmdzLl9fZXNNb2R1bGUpXG4gICAgcmV0dXJuIG5ldyBNb2R1bGVOYW1lc3BhY2UoYmluZGluZ3MpO1xuXG4gIHJldHVybiBuZXcgTW9kdWxlTmFtZXNwYWNlKHsgZGVmYXVsdDogYmluZGluZ3MsIF9fdXNlRGVmYXVsdDogYmluZGluZ3MgfSk7XG59XG5cbnZhciBoYXNTdHJpbmdUYWc7XG5mdW5jdGlvbiBpc01vZHVsZSAobSkge1xuICBpZiAoaGFzU3RyaW5nVGFnID09PSB1bmRlZmluZWQpXG4gICAgaGFzU3RyaW5nVGFnID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgISFTeW1ib2wudG9TdHJpbmdUYWc7XG4gIHJldHVybiBtIGluc3RhbmNlb2YgTW9kdWxlTmFtZXNwYWNlIHx8IGhhc1N0cmluZ1RhZyAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobSkgPT0gJ1tvYmplY3QgTW9kdWxlXSc7XG59XG5cbnZhciBDT05GSUcgPSBjcmVhdGVTeW1ib2woJ2xvYWRlci1jb25maWcnKTtcbnZhciBNRVRBREFUQSA9IGNyZWF0ZVN5bWJvbCgnbWV0YWRhdGEnKTtcblxuXG5cbnZhciBpc1dvcmtlciA9IHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgaW1wb3J0U2NyaXB0cyAhPT0gJ3VuZGVmaW5lZCc7XG5cbmZ1bmN0aW9uIHdhcm4gKG1zZywgZm9yY2UpIHtcbiAgaWYgKGZvcmNlIHx8IHRoaXMud2FybmluZ3MgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUud2FybilcbiAgICBjb25zb2xlLndhcm4obXNnKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnN0YW50aWF0ZVdhc20gKGxvYWRlciwgd2FzbUJ1ZmZlciwgcHJvY2Vzc0Fub25SZWdpc3Rlcikge1xuICB2YXIgYnl0ZXMgPSBuZXcgVWludDhBcnJheSh3YXNtQnVmZmVyKTtcblxuICAvLyBkZXRlY3QgYnkgbGVhZGluZyBieXRlc1xuICAvLyBDYW4gYmUgKG5ldyBVaW50MzJBcnJheShmZXRjaGVkKSlbMF0gPT09IDB4NkQ3MzYxMDAgd2hlbiB3b3JraW5nIGluIE5vZGVcbiAgaWYgKGJ5dGVzWzBdID09PSAwICYmIGJ5dGVzWzFdID09PSA5NyAmJiBieXRlc1syXSA9PT0gMTE1KSB7XG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LmNvbXBpbGUod2FzbUJ1ZmZlcikudGhlbihmdW5jdGlvbiAobSkge1xuICAgICAgdmFyIGRlcHMgPSBbXTtcbiAgICAgIHZhciBzZXR0ZXJzID0gW107XG4gICAgICB2YXIgaW1wb3J0T2JqID0ge307XG5cbiAgICAgIC8vIHdlIGNhbiBvbmx5IHNldCBpbXBvcnRzIGlmIHN1cHBvcnRlZCAoZWcgU2FmYXJpIGRvZXNudCBzdXBwb3J0KVxuICAgICAgaWYgKFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKVxuICAgICAgICBXZWJBc3NlbWJseS5Nb2R1bGUuaW1wb3J0cyhtKS5mb3JFYWNoKGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgdmFyIGtleSA9IGkubW9kdWxlO1xuICAgICAgICAgIHNldHRlcnMucHVzaChmdW5jdGlvbiAobSkge1xuICAgICAgICAgICAgaW1wb3J0T2JqW2tleV0gPSBtO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChkZXBzLmluZGV4T2Yoa2V5KSA9PT0gLTEpXG4gICAgICAgICAgICBkZXBzLnB1c2goa2V5KTtcbiAgICAgICAgfSk7XG4gICAgICBsb2FkZXIucmVnaXN0ZXIoZGVwcywgZnVuY3Rpb24gKF9leHBvcnQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzZXR0ZXJzOiBzZXR0ZXJzLFxuICAgICAgICAgIGV4ZWN1dGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF9leHBvcnQobmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKG0sIGltcG9ydE9iaikuZXhwb3J0cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICBwcm9jZXNzQW5vblJlZ2lzdGVyKCk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG59XG5cbnZhciBwYXJlbnRNb2R1bGVDb250ZXh0O1xuZnVuY3Rpb24gbG9hZE5vZGVNb2R1bGUgKGtleSwgYmFzZVVSTCkge1xuICBpZiAoa2V5WzBdID09PSAnLicpXG4gICAgdGhyb3cgbmV3IEVycm9yKCdOb2RlIG1vZHVsZSAnICsga2V5ICsgJyBjYW5cXCd0IGJlIGxvYWRlZCBhcyBpdCBpcyBub3QgYSBwYWNrYWdlIHJlcXVpcmUuJyk7XG5cbiAgaWYgKCFwYXJlbnRNb2R1bGVDb250ZXh0KSB7XG4gICAgdmFyIE1vZHVsZSA9IHRoaXMuX25vZGVSZXF1aXJlKCdtb2R1bGUnKTtcbiAgICB2YXIgYmFzZSA9IGRlY29kZVVSSShiYXNlVVJMLnN1YnN0cihpc1dpbmRvd3MgPyA4IDogNykpO1xuICAgIHBhcmVudE1vZHVsZUNvbnRleHQgPSBuZXcgTW9kdWxlKGJhc2UpO1xuICAgIHBhcmVudE1vZHVsZUNvbnRleHQucGF0aHMgPSBNb2R1bGUuX25vZGVNb2R1bGVQYXRocyhiYXNlKTtcbiAgfVxuICByZXR1cm4gcGFyZW50TW9kdWxlQ29udGV4dC5yZXF1aXJlKGtleSk7XG59XG5cbmZ1bmN0aW9uIGV4dGVuZCAoYSwgYikge1xuICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICBpZiAoIU9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKVxuICAgICAgY29udGludWU7XG4gICAgYVtwXSA9IGJbcF07XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbmZ1bmN0aW9uIHByZXBlbmQgKGEsIGIpIHtcbiAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgaWYgKCFPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSlcbiAgICAgIGNvbnRpbnVlO1xuICAgIGlmIChhW3BdID09PSB1bmRlZmluZWQpXG4gICAgICBhW3BdID0gYltwXTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuLy8gbWV0YSBmaXJzdC1sZXZlbCBleHRlbmRzIHdoZXJlOlxuLy8gYXJyYXkgKyBhcnJheSBhcHBlbmRzXG4vLyBvYmplY3QgKyBvYmplY3QgZXh0ZW5kc1xuLy8gb3RoZXIgcHJvcGVydGllcyByZXBsYWNlXG5mdW5jdGlvbiBleHRlbmRNZXRhIChhLCBiLCBfcHJlcGVuZCkge1xuICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICBpZiAoIU9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKVxuICAgICAgY29udGludWU7XG4gICAgdmFyIHZhbCA9IGJbcF07XG4gICAgaWYgKGFbcF0gPT09IHVuZGVmaW5lZClcbiAgICAgIGFbcF0gPSB2YWw7XG4gICAgZWxzZSBpZiAodmFsIGluc3RhbmNlb2YgQXJyYXkgJiYgYVtwXSBpbnN0YW5jZW9mIEFycmF5KVxuICAgICAgYVtwXSA9IFtdLmNvbmNhdChfcHJlcGVuZCA/IHZhbCA6IGFbcF0pLmNvbmNhdChfcHJlcGVuZCA/IGFbcF0gOiB2YWwpO1xuICAgIGVsc2UgaWYgKHR5cGVvZiB2YWwgPT0gJ29iamVjdCcgJiYgdmFsICE9PSBudWxsICYmIHR5cGVvZiBhW3BdID09ICdvYmplY3QnKVxuICAgICAgYVtwXSA9IChfcHJlcGVuZCA/IHByZXBlbmQgOiBleHRlbmQpKGV4dGVuZCh7fSwgYVtwXSksIHZhbCk7XG4gICAgZWxzZSBpZiAoIV9wcmVwZW5kKVxuICAgICAgYVtwXSA9IHZhbDtcbiAgfVxufVxuXG52YXIgc3VwcG9ydHNQcmVsb2FkID0gZmFsc2U7XG52YXIgc3VwcG9ydHNQcmVmZXRjaCA9IGZhbHNlO1xuaWYgKGlzQnJvd3NlcilcbiAgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVsTGlzdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKS5yZWxMaXN0O1xuICAgIGlmIChyZWxMaXN0ICYmIHJlbExpc3Quc3VwcG9ydHMpIHtcbiAgICAgIHN1cHBvcnRzUHJlZmV0Y2ggPSB0cnVlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgc3VwcG9ydHNQcmVsb2FkID0gcmVsTGlzdC5zdXBwb3J0cygncHJlbG9hZCcpO1xuICAgICAgfVxuICAgICAgY2F0Y2ggKGUpIHt9XG4gICAgfVxuICB9KSgpO1xuXG5mdW5jdGlvbiBwcmVsb2FkU2NyaXB0ICh1cmwpIHtcbiAgLy8gZmFsbGJhY2sgdG8gb2xkIGZhc2hpb25lZCBpbWFnZSB0ZWNobmlxdWUgd2hpY2ggc3RpbGwgd29ya3MgaW4gc2FmYXJpXG4gIGlmICghc3VwcG9ydHNQcmVsb2FkICYmICFzdXBwb3J0c1ByZWZldGNoKSB7XG4gICAgdmFyIHByZWxvYWRJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgIHByZWxvYWRJbWFnZS5zcmMgPSB1cmw7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaW5rJyk7XG4gIGlmIChzdXBwb3J0c1ByZWxvYWQpIHtcbiAgICBsaW5rLnJlbCA9ICdwcmVsb2FkJztcbiAgICBsaW5rLmFzID0gJ3NjcmlwdCc7XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gdGhpcyB3b3JrcyBmb3IgYWxsIGV4Y2VwdCBTYWZhcmkgKGRldGVjdGVkIGJ5IHJlbExpc3Quc3VwcG9ydHMgbGFja2luZylcbiAgICBsaW5rLnJlbCA9ICdwcmVmZXRjaCc7XG4gIH1cbiAgbGluay5ocmVmID0gdXJsO1xuICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGxpbmspO1xufVxuXG5mdW5jdGlvbiB3b3JrZXJJbXBvcnQgKHNyYywgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gIHRyeSB7XG4gICAgaW1wb3J0U2NyaXB0cyhzcmMpO1xuICB9XG4gIGNhdGNoIChlKSB7XG4gICAgcmVqZWN0KGUpO1xuICB9XG4gIHJlc29sdmUoKTtcbn1cblxuaWYgKGlzQnJvd3Nlcikge1xuICB2YXIgbG9hZGluZ1NjcmlwdHMgPSBbXTtcbiAgdmFyIG9uZXJyb3IgPSB3aW5kb3cub25lcnJvcjtcbiAgd2luZG93Lm9uZXJyb3IgPSBmdW5jdGlvbiBnbG9iYWxPbmVycm9yIChtc2csIHNyYykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbG9hZGluZ1NjcmlwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChsb2FkaW5nU2NyaXB0c1tpXS5zcmMgIT09IHNyYylcbiAgICAgICAgY29udGludWU7XG4gICAgICBsb2FkaW5nU2NyaXB0c1tpXS5lcnIobXNnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG9uZXJyb3IpXG4gICAgICBvbmVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHNjcmlwdExvYWQgKHNyYywgY3Jvc3NPcmlnaW4sIGludGVncml0eSwgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gIC8vIHBlcmNlbnQgZW5jb2RlIGp1c3QgXCIjXCIgZm9yIEhUVFAgcmVxdWVzdHNcbiAgc3JjID0gc3JjLnJlcGxhY2UoLyMvZywgJyUyMycpO1xuXG4gIC8vIHN1YnJlc291cmNlIGludGVncml0eSBpcyBub3Qgc3VwcG9ydGVkIGluIHdlYiB3b3JrZXJzXG4gIGlmIChpc1dvcmtlcilcbiAgICByZXR1cm4gd29ya2VySW1wb3J0KHNyYywgcmVzb2x2ZSwgcmVqZWN0KTtcblxuICB2YXIgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gIHNjcmlwdC50eXBlID0gJ3RleHQvamF2YXNjcmlwdCc7XG4gIHNjcmlwdC5jaGFyc2V0ID0gJ3V0Zi04JztcbiAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcblxuICBpZiAoY3Jvc3NPcmlnaW4pXG4gICAgc2NyaXB0LmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47XG4gIGlmIChpbnRlZ3JpdHkpXG4gICAgc2NyaXB0LmludGVncml0eSA9IGludGVncml0eTtcblxuICBzY3JpcHQuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGxvYWQsIGZhbHNlKTtcbiAgc2NyaXB0LmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZXJyb3IsIGZhbHNlKTtcblxuICBzY3JpcHQuc3JjID0gc3JjO1xuICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG5cbiAgZnVuY3Rpb24gbG9hZCAoKSB7XG4gICAgcmVzb2x2ZSgpO1xuICAgIGNsZWFudXAoKTtcbiAgfVxuXG4gIC8vIG5vdGUgdGhpcyBkb2VzIG5vdCBjYXRjaCBleGVjdXRpb24gZXJyb3JzXG4gIGZ1bmN0aW9uIGVycm9yIChlcnIpIHtcbiAgICBjbGVhbnVwKCk7XG4gICAgcmVqZWN0KG5ldyBFcnJvcignRmV0Y2hpbmcgJyArIHNyYykpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xlYW51cCAoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2FkaW5nU2NyaXB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGxvYWRpbmdTY3JpcHRzW2ldLmVyciA9PT0gZXJyb3IpIHtcbiAgICAgICAgbG9hZGluZ1NjcmlwdHMuc3BsaWNlKGksIDEpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgc2NyaXB0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBsb2FkLCBmYWxzZSk7XG4gICAgc2NyaXB0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZXJyb3IsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5oZWFkLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVhZE1lbWJlckV4cHJlc3Npb24gKHAsIHZhbHVlKSB7XG4gIHZhciBwUGFydHMgPSBwLnNwbGl0KCcuJyk7XG4gIHdoaWxlIChwUGFydHMubGVuZ3RoKVxuICAgIHZhbHVlID0gdmFsdWVbcFBhcnRzLnNoaWZ0KCldO1xuICByZXR1cm4gdmFsdWU7XG59XG5cbi8vIHNlcGFyYXRlIG91dCBwYXRocyBjYWNoZSBhcyBhIGJhc2VVUkwgbG9jayBwcm9jZXNzXG5mdW5jdGlvbiBhcHBseVBhdGhzIChiYXNlVVJMLCBwYXRocywga2V5KSB7XG4gIHZhciBtYXBNYXRjaCA9IGdldE1hcE1hdGNoKHBhdGhzLCBrZXkpO1xuICBpZiAobWFwTWF0Y2gpIHtcbiAgICB2YXIgdGFyZ2V0ID0gcGF0aHNbbWFwTWF0Y2hdICsga2V5LnN1YnN0cihtYXBNYXRjaC5sZW5ndGgpO1xuXG4gICAgdmFyIHJlc29sdmVkID0gcmVzb2x2ZUlmTm90UGxhaW4odGFyZ2V0LCBiYXNlVVJJKTtcbiAgICBpZiAocmVzb2x2ZWQgIT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiByZXNvbHZlZDtcblxuICAgIHJldHVybiBiYXNlVVJMICsgdGFyZ2V0O1xuICB9XG4gIGVsc2UgaWYgKGtleS5pbmRleE9mKCc6JykgIT09IC0xKSB7XG4gICAgcmV0dXJuIGtleTtcbiAgfVxuICBlbHNlIHtcbiAgICByZXR1cm4gYmFzZVVSTCArIGtleTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja01hcCAocCkge1xuICB2YXIgbmFtZSA9IHRoaXMubmFtZTtcbiAgLy8gY2FuIGFkZCAnOicgaGVyZSBpZiB3ZSB3YW50IHBhdGhzIHRvIG1hdGNoIHRoZSBiZWhhdmlvdXIgb2YgbWFwXG4gIGlmIChuYW1lLnN1YnN0cigwLCBwLmxlbmd0aCkgPT09IHAgJiYgKG5hbWUubGVuZ3RoID09PSBwLmxlbmd0aCB8fCBuYW1lW3AubGVuZ3RoXSA9PT0gJy8nIHx8IHBbcC5sZW5ndGggLSAxXSA9PT0gJy8nIHx8IHBbcC5sZW5ndGggLSAxXSA9PT0gJzonKSkge1xuICAgIHZhciBjdXJMZW4gPSBwLnNwbGl0KCcvJykubGVuZ3RoO1xuICAgIGlmIChjdXJMZW4gPiB0aGlzLmxlbikge1xuICAgICAgdGhpcy5tYXRjaCA9IHA7XG4gICAgICB0aGlzLmxlbiA9IGN1ckxlbjtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0TWFwTWF0Y2ggKG1hcCwgbmFtZSkge1xuICBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwobWFwLCBuYW1lKSlcbiAgICByZXR1cm4gbmFtZTtcblxuICB2YXIgYmVzdE1hdGNoID0ge1xuICAgIG5hbWU6IG5hbWUsXG4gICAgbWF0Y2g6IHVuZGVmaW5lZCxcbiAgICBsZW46IDBcbiAgfTtcblxuICBPYmplY3Qua2V5cyhtYXApLmZvckVhY2goY2hlY2tNYXAsIGJlc3RNYXRjaCk7XG5cbiAgcmV0dXJuIGJlc3RNYXRjaC5tYXRjaDtcbn1cblxuLy8gUmVnRXggYWRqdXN0ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vamJyYW50bHkveWFiYmxlL2Jsb2IvbWFzdGVyL2xpYi95YWJibGUuanMjTDMzOVxudmFyIGNqc1JlcXVpcmVSZWdFeCA9IC8oPzpeXFx1RkVGRj98W14kX2EtekEtWlxceEEwLVxcdUZGRkYuXCInXSlyZXF1aXJlXFxzKlxcKFxccyooXCJbXlwiXFxcXF0qKD86XFxcXC5bXlwiXFxcXF0qKSpcInwnW14nXFxcXF0qKD86XFxcXC5bXidcXFxcXSopKid8YFteYFxcXFxdKig/OlxcXFwuW15gXFxcXF0qKSpgKVxccypcXCkvZztcblxuLypcbiAqIFNvdXJjZSBsb2FkaW5nXG4gKi9cbmZ1bmN0aW9uIGZldGNoRmV0Y2ggKHVybCwgYXV0aG9yaXphdGlvbiwgaW50ZWdyaXR5LCBhc0J1ZmZlcikge1xuICAvLyBmZXRjaCBkb2Vzbid0IHN1cHBvcnQgZmlsZTovLy8gdXJsc1xuICBpZiAodXJsLnN1YnN0cigwLCA4KSA9PT0gJ2ZpbGU6Ly8vJykge1xuICAgIGlmIChoYXNYaHIpXG4gICAgICByZXR1cm4geGhyRmV0Y2godXJsLCBhdXRob3JpemF0aW9uLCBpbnRlZ3JpdHksIGFzQnVmZmVyKTtcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBmZXRjaCBmaWxlIFVSTHMgaW4gdGhpcyBlbnZpcm9ubWVudC4nKTtcbiAgfVxuXG4gIC8vIHBlcmNlbnQgZW5jb2RlIGp1c3QgXCIjXCIgZm9yIEhUVFAgcmVxdWVzdHNcbiAgdXJsID0gdXJsLnJlcGxhY2UoLyMvZywgJyUyMycpO1xuXG4gIHZhciBvcHRzID0ge1xuICAgIC8vIE5CIGRlcHJlY2F0ZVxuICAgIGhlYWRlcnM6IHsgQWNjZXB0OiAnYXBwbGljYXRpb24veC1lcy1tb2R1bGUsICovKicgfVxuICB9O1xuXG4gIGlmIChpbnRlZ3JpdHkpXG4gICAgb3B0cy5pbnRlZ3JpdHkgPSBpbnRlZ3JpdHk7XG5cbiAgaWYgKGF1dGhvcml6YXRpb24pIHtcbiAgICBpZiAodHlwZW9mIGF1dGhvcml6YXRpb24gPT0gJ3N0cmluZycpXG4gICAgICBvcHRzLmhlYWRlcnNbJ0F1dGhvcml6YXRpb24nXSA9IGF1dGhvcml6YXRpb247XG4gICAgb3B0cy5jcmVkZW50aWFscyA9ICdpbmNsdWRlJztcbiAgfVxuXG4gIHJldHVybiBmZXRjaCh1cmwsIG9wdHMpXG4gIC50aGVuKGZ1bmN0aW9uKHJlcykge1xuICAgIGlmIChyZXMub2spXG4gICAgICByZXR1cm4gYXNCdWZmZXIgPyByZXMuYXJyYXlCdWZmZXIoKSA6IHJlcy50ZXh0KCk7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGZXRjaCBlcnJvcjogJyArIHJlcy5zdGF0dXMgKyAnICcgKyByZXMuc3RhdHVzVGV4dCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB4aHJGZXRjaCAodXJsLCBhdXRob3JpemF0aW9uLCBpbnRlZ3JpdHksIGFzQnVmZmVyKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgLy8gcGVyY2VudCBlbmNvZGUganVzdCBcIiNcIiBmb3IgSFRUUCByZXF1ZXN0c1xuICAgIHVybCA9IHVybC5yZXBsYWNlKC8jL2csICclMjMnKTtcblxuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICBpZiAoYXNCdWZmZXIpXG4gICAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2FycmF5YnVmZmVyJztcbiAgICBmdW5jdGlvbiBsb2FkKCkge1xuICAgICAgcmVzb2x2ZShhc0J1ZmZlciA/IHhoci5yZXNwb25zZSA6IHhoci5yZXNwb25zZVRleHQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBlcnJvcigpIHtcbiAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1hIUiBlcnJvcjogJyArICh4aHIuc3RhdHVzID8gJyAoJyArIHhoci5zdGF0dXMgKyAoeGhyLnN0YXR1c1RleHQgPyAnICcgKyB4aHIuc3RhdHVzVGV4dCAgOiAnJykgKyAnKScgOiAnJykgKyAnIGxvYWRpbmcgJyArIHVybCkpO1xuICAgIH1cblxuICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgLy8gaW4gQ2hyb21lIG9uIGZpbGU6Ly8vIFVSTHMsIHN0YXR1cyBpcyAwXG4gICAgICAgIGlmICh4aHIuc3RhdHVzID09IDApIHtcbiAgICAgICAgICBpZiAoeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBsb2FkKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gd2hlbiByZXNwb25zZVRleHQgaXMgZW1wdHksIHdhaXQgZm9yIGxvYWQgb3IgZXJyb3IgZXZlbnRcbiAgICAgICAgICAgIC8vIHRvIGluZm9ybSBpZiBpdCBpcyBhIDQwNCBvciBlbXB0eSBmaWxlXG4gICAgICAgICAgICB4aHIuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCBlcnJvcik7XG4gICAgICAgICAgICB4aHIuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGxvYWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh4aHIuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICBsb2FkKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgZXJyb3IoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgeGhyLm9wZW4oXCJHRVRcIiwgdXJsLCB0cnVlKTtcblxuICAgIGlmICh4aHIuc2V0UmVxdWVzdEhlYWRlcikge1xuICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi94LWVzLW1vZHVsZSwgKi8qJyk7XG4gICAgICAvLyBjYW4gc2V0IFwiYXV0aG9yaXphdGlvbjogdHJ1ZVwiIHRvIGVuYWJsZSB3aXRoQ3JlZGVudGlhbHMgb25seVxuICAgICAgaWYgKGF1dGhvcml6YXRpb24pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBhdXRob3JpemF0aW9uID09ICdzdHJpbmcnKVxuICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdBdXRob3JpemF0aW9uJywgYXV0aG9yaXphdGlvbik7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHhoci5zZW5kKG51bGwpO1xuICB9KTtcbn1cblxudmFyIGZzO1xuZnVuY3Rpb24gbm9kZUZldGNoICh1cmwsIGF1dGhvcml6YXRpb24sIGludGVncml0eSwgYXNCdWZmZXIpIHtcbiAgaWYgKHVybC5zdWJzdHIoMCwgOCkgIT0gJ2ZpbGU6Ly8vJylcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdVbmFibGUgdG8gZmV0Y2ggXCInICsgdXJsICsgJ1wiLiBPbmx5IGZpbGUgVVJMcyBvZiB0aGUgZm9ybSBmaWxlOi8vLyBzdXBwb3J0ZWQgcnVubmluZyBpbiBOb2RlLicpKTtcblxuICBmcyA9IGZzIHx8IHJlcXVpcmUoJ2ZzJyk7XG4gIGlmIChpc1dpbmRvd3MpXG4gICAgdXJsID0gdXJsLnJlcGxhY2UoL1xcLy9nLCAnXFxcXCcpLnN1YnN0cig4KTtcbiAgZWxzZVxuICAgIHVybCA9IHVybC5zdWJzdHIoNyk7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmcy5yZWFkRmlsZSh1cmwsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgaWYgKGFzQnVmZmVyKSB7XG4gICAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAvLyBTdHJpcCBCeXRlIE9yZGVyIE1hcmsgb3V0IGlmIGl0J3MgdGhlIGxlYWRpbmcgY2hhclxuICAgICAgICAgIHZhciBkYXRhU3RyaW5nID0gZGF0YSArICcnO1xuICAgICAgICAgIGlmIChkYXRhU3RyaW5nWzBdID09PSAnXFx1ZmVmZicpXG4gICAgICAgICAgICBkYXRhU3RyaW5nID0gZGF0YVN0cmluZy5zdWJzdHIoMSk7XG5cbiAgICAgICAgICByZXNvbHZlKGRhdGFTdHJpbmcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBub0ZldGNoICgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdObyBmZXRjaCBtZXRob2QgaXMgZGVmaW5lZCBmb3IgdGhpcyBlbnZpcm9ubWVudC4nKTtcbn1cblxudmFyIGZldGNoRnVuY3Rpb247XG5cbnZhciBoYXNYaHIgPSB0eXBlb2YgWE1MSHR0cFJlcXVlc3QgIT09ICd1bmRlZmluZWQnO1xuXG5pZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBzZWxmLmZldGNoICE9PSAndW5kZWZpbmVkJylcbiBmZXRjaEZ1bmN0aW9uID0gZmV0Y2hGZXRjaDtcbmVsc2UgaWYgKGhhc1hocilcbiAgZmV0Y2hGdW5jdGlvbiA9IHhockZldGNoO1xuZWxzZSBpZiAodHlwZW9mIHJlcXVpcmUgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJylcbiAgZmV0Y2hGdW5jdGlvbiA9IG5vZGVGZXRjaDtcbmVsc2VcbiAgZmV0Y2hGdW5jdGlvbiA9IG5vRmV0Y2g7XG5cbnZhciBmZXRjaCQxID0gZmV0Y2hGdW5jdGlvbjtcblxuZnVuY3Rpb24gY3JlYXRlTWV0YWRhdGEgKCkge1xuICByZXR1cm4ge1xuICAgIHBsdWdpbktleTogdW5kZWZpbmVkLFxuICAgIHBsdWdpbkFyZ3VtZW50OiB1bmRlZmluZWQsXG4gICAgcGx1Z2luTW9kdWxlOiB1bmRlZmluZWQsXG4gICAgcGFja2FnZUtleTogdW5kZWZpbmVkLFxuICAgIHBhY2thZ2VDb25maWc6IHVuZGVmaW5lZCxcbiAgICBsb2FkOiB1bmRlZmluZWRcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyZW50TWV0YWRhdGEgKGxvYWRlciwgY29uZmlnLCBwYXJlbnRLZXkpIHtcbiAgdmFyIHBhcmVudE1ldGFkYXRhID0gY3JlYXRlTWV0YWRhdGEoKTtcblxuICBpZiAocGFyZW50S2V5KSB7XG4gICAgLy8gZGV0ZWN0IHBhcmVudCBwbHVnaW5cbiAgICAvLyB3ZSBqdXN0IG5lZWQgcGx1Z2luS2V5IHRvIGJlIHRydXRoeSBmb3IgcGFja2FnZSBjb25maWd1cmF0aW9uc1xuICAgIC8vIHNvIHdlIGR1cGxpY2F0ZSBpdCBhcyBwbHVnaW5Bcmd1bWVudCAtIGFsdGhvdWdoIG5vdCBjb3JyZWN0IGl0cyBub3QgdXNlZFxuICAgIHZhciBwYXJlbnRQbHVnaW5JbmRleDtcbiAgICBpZiAoY29uZmlnLnBsdWdpbkZpcnN0KSB7XG4gICAgICBpZiAoKHBhcmVudFBsdWdpbkluZGV4ID0gcGFyZW50S2V5Lmxhc3RJbmRleE9mKCchJykpICE9PSAtMSlcbiAgICAgICAgcGFyZW50TWV0YWRhdGEucGx1Z2luQXJndW1lbnQgPSBwYXJlbnRNZXRhZGF0YS5wbHVnaW5LZXkgPSBwYXJlbnRLZXkuc3Vic3RyKDAsIHBhcmVudFBsdWdpbkluZGV4KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBpZiAoKHBhcmVudFBsdWdpbkluZGV4ID0gcGFyZW50S2V5LmluZGV4T2YoJyEnKSkgIT09IC0xKVxuICAgICAgICBwYXJlbnRNZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCA9IHBhcmVudE1ldGFkYXRhLnBsdWdpbktleSA9IHBhcmVudEtleS5zdWJzdHIocGFyZW50UGx1Z2luSW5kZXggKyAxKTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3QgcGFyZW50IHBhY2thZ2VcbiAgICBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlS2V5ID0gZ2V0TWFwTWF0Y2goY29uZmlnLnBhY2thZ2VzLCBwYXJlbnRLZXkpO1xuICAgIGlmIChwYXJlbnRNZXRhZGF0YS5wYWNrYWdlS2V5KVxuICAgICAgcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZyA9IGNvbmZpZy5wYWNrYWdlc1twYXJlbnRNZXRhZGF0YS5wYWNrYWdlS2V5XTtcbiAgfVxuXG4gIHJldHVybiBwYXJlbnRNZXRhZGF0YTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplIChrZXksIHBhcmVudEtleSkge1xuICB2YXIgY29uZmlnID0gdGhpc1tDT05GSUddO1xuXG4gIHZhciBtZXRhZGF0YSA9IGNyZWF0ZU1ldGFkYXRhKCk7XG4gIHZhciBwYXJlbnRNZXRhZGF0YSA9IGdldFBhcmVudE1ldGFkYXRhKHRoaXMsIGNvbmZpZywgcGFyZW50S2V5KTtcblxuICB2YXIgbG9hZGVyID0gdGhpcztcblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcblxuICAvLyBib29sZWFuIGNvbmRpdGlvbmFsXG4gIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAvLyBmaXJzdCB3ZSBub3JtYWxpemUgdGhlIGNvbmRpdGlvbmFsXG4gICAgdmFyIGJvb2xlYW5JbmRleCA9IGtleS5sYXN0SW5kZXhPZignIz8nKTtcblxuICAgIGlmIChib29sZWFuSW5kZXggPT09IC0xKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShrZXkpO1xuXG4gICAgdmFyIGNvbmRpdGlvbk9iaiA9IHBhcnNlQ29uZGl0aW9uLmNhbGwobG9hZGVyLCBrZXkuc3Vic3RyKGJvb2xlYW5JbmRleCArIDIpKTtcblxuICAgIC8vIGluIGJ1aWxkcywgcmV0dXJuIG5vcm1hbGl6ZWQgY29uZGl0aW9uYWxcbiAgICAvKmlmICh0aGlzLmJ1aWxkZXIpXG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlKGNvbmRpdGlvbk9iai5tb2R1bGUsIHBhcmVudEtleSlcbiAgICAgIC50aGVuKGZ1bmN0aW9uIChjb25kaXRpb25Nb2R1bGUpIHtcbiAgICAgICAgY29uZGl0aW9uT2JqLm1vZHVsZSA9IGNvbmRpdGlvbk1vZHVsZTtcbiAgICAgICAgcmV0dXJuIGtleS5zdWJzdHIoMCwgYm9vbGVhbkluZGV4KSArICcjPycgKyBzZXJpYWxpemVDb25kaXRpb24oY29uZGl0aW9uT2JqKTtcbiAgICAgIH0pOyovXG5cbiAgICByZXR1cm4gcmVzb2x2ZUNvbmRpdGlvbi5jYWxsKGxvYWRlciwgY29uZGl0aW9uT2JqLCBwYXJlbnRLZXksIHRydWUpXG4gICAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvblZhbHVlKSB7XG4gICAgICByZXR1cm4gY29uZGl0aW9uVmFsdWUgPyBrZXkuc3Vic3RyKDAsIGJvb2xlYW5JbmRleCkgOiAnQGVtcHR5JztcbiAgICB9KTtcbiAgfSlcblxuICAvLyBwbHVnaW5cbiAgLnRoZW4oZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciBwYXJzZWQgPSBwYXJzZVBsdWdpbihjb25maWcucGx1Z2luRmlyc3QsIGtleSk7XG5cbiAgICBpZiAoIXBhcnNlZClcbiAgICAgIHJldHVybiBwYWNrYWdlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBrZXksIHBhcmVudE1ldGFkYXRhICYmIHBhcmVudE1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50IHx8IHBhcmVudEtleSwgbWV0YWRhdGEsIHBhcmVudE1ldGFkYXRhLCBmYWxzZSk7XG5cbiAgICBtZXRhZGF0YS5wbHVnaW5LZXkgPSBwYXJzZWQucGx1Z2luO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgIHBhY2thZ2VSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIHBhcnNlZC5hcmd1bWVudCwgcGFyZW50TWV0YWRhdGEgJiYgcGFyZW50TWV0YWRhdGEucGx1Z2luQXJndW1lbnQgfHwgcGFyZW50S2V5LCBtZXRhZGF0YSwgcGFyZW50TWV0YWRhdGEsIHRydWUpLFxuICAgICAgbG9hZGVyLnJlc29sdmUocGFyc2VkLnBsdWdpbiwgcGFyZW50S2V5KVxuICAgIF0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKG5vcm1hbGl6ZWQpIHtcbiAgICAgIG1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50ID0gbm9ybWFsaXplZFswXTtcbiAgICAgIG1ldGFkYXRhLnBsdWdpbktleSA9IG5vcm1hbGl6ZWRbMV07XG5cbiAgICAgIC8vIGRvbid0IGFsbG93IGEgcGx1Z2luIHRvIGxvYWQgaXRzZWxmXG4gICAgICBpZiAobWV0YWRhdGEucGx1Z2luQXJndW1lbnQgPT09IG1ldGFkYXRhLnBsdWdpbktleSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQbHVnaW4gJyArIG1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50ICsgJyBjYW5ub3QgbG9hZCBpdHNlbGYsIG1ha2Ugc3VyZSBpdCBpcyBleGNsdWRlZCBmcm9tIGFueSB3aWxkY2FyZCBtZXRhIGNvbmZpZ3VyYXRpb24gdmlhIGEgY3VzdG9tIGxvYWRlcjogZmFsc2UgcnVsZS4nKTtcblxuICAgICAgcmV0dXJuIGNvbWJpbmVQbHVnaW5QYXJ0cyhjb25maWcucGx1Z2luRmlyc3QsIG5vcm1hbGl6ZWRbMF0sIG5vcm1hbGl6ZWRbMV0pO1xuICAgIH0pO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAobm9ybWFsaXplZCkge1xuICAgIHJldHVybiBpbnRlcnBvbGF0ZUNvbmRpdGlvbmFsLmNhbGwobG9hZGVyLCBub3JtYWxpemVkLCBwYXJlbnRLZXksIHBhcmVudE1ldGFkYXRhKTtcbiAgfSlcbiAgLnRoZW4oZnVuY3Rpb24gKG5vcm1hbGl6ZWQpIHtcbiAgICBzZXRNZXRhLmNhbGwobG9hZGVyLCBjb25maWcsIG5vcm1hbGl6ZWQsIG1ldGFkYXRhKTtcblxuICAgIGlmIChtZXRhZGF0YS5wbHVnaW5LZXkgfHwgIW1ldGFkYXRhLmxvYWQubG9hZGVyKVxuICAgICAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG5cbiAgICAvLyBsb2FkZXIgYnkgY29uZmlndXJhdGlvblxuICAgIC8vIG5vcm1hbGl6ZXMgdG8gcGFyZW50IHRvIHN1cHBvcnQgcGFja2FnZSBsb2FkZXJzXG4gICAgcmV0dXJuIGxvYWRlci5yZXNvbHZlKG1ldGFkYXRhLmxvYWQubG9hZGVyLCBub3JtYWxpemVkKVxuICAgIC50aGVuKGZ1bmN0aW9uIChwbHVnaW5LZXkpIHtcbiAgICAgIG1ldGFkYXRhLnBsdWdpbktleSA9IHBsdWdpbktleTtcbiAgICAgIG1ldGFkYXRhLnBsdWdpbkFyZ3VtZW50ID0gbm9ybWFsaXplZDtcbiAgICAgIHJldHVybiBub3JtYWxpemVkO1xuICAgIH0pO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAobm9ybWFsaXplZCkge1xuICAgIGxvYWRlcltNRVRBREFUQV1bbm9ybWFsaXplZF0gPSBtZXRhZGF0YTtcbiAgICByZXR1cm4gbm9ybWFsaXplZDtcbiAgfSk7XG59XG5cbi8vIG5vcm1hbGl6YXRpb24gZnVuY3Rpb24gdXNlZCBmb3IgcmVnaXN0cnkga2V5c1xuLy8ganVzdCBkb2VzIGNvcmVSZXNvbHZlIHdpdGhvdXQgbWFwXG5mdW5jdGlvbiBkZWNhbm9uaWNhbGl6ZSAoY29uZmlnLCBrZXkpIHtcbiAgdmFyIHBhcnNlZCA9IHBhcnNlUGx1Z2luKGNvbmZpZy5wbHVnaW5GaXJzdCwga2V5KTtcblxuICAvLyBwbHVnaW5cbiAgaWYgKHBhcnNlZCkge1xuICAgIHZhciBwbHVnaW5LZXkgPSBkZWNhbm9uaWNhbGl6ZS5jYWxsKHRoaXMsIGNvbmZpZywgcGFyc2VkLnBsdWdpbik7XG4gICAgcmV0dXJuIGNvbWJpbmVQbHVnaW5QYXJ0cyhjb25maWcucGx1Z2luRmlyc3QsIGNvcmVSZXNvbHZlLmNhbGwodGhpcywgY29uZmlnLCBwYXJzZWQuYXJndW1lbnQsIHVuZGVmaW5lZCwgZmFsc2UsIGZhbHNlKSwgcGx1Z2luS2V5KTtcbiAgfVxuXG4gIHJldHVybiBjb3JlUmVzb2x2ZS5jYWxsKHRoaXMsIGNvbmZpZywga2V5LCB1bmRlZmluZWQsIGZhbHNlLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVN5bmMgKGtleSwgcGFyZW50S2V5KSB7XG4gIHZhciBjb25maWcgPSB0aGlzW0NPTkZJR107XG5cbiAgLy8gbm9ybWFsaXplU3luYyBpcyBtZXRhZGF0YWxlc3MsIHNvIGNyZWF0ZSBtZXRhZGF0YVxuICB2YXIgbWV0YWRhdGEgPSBjcmVhdGVNZXRhZGF0YSgpO1xuICB2YXIgcGFyZW50TWV0YWRhdGEgPSBwYXJlbnRNZXRhZGF0YSB8fCBnZXRQYXJlbnRNZXRhZGF0YSh0aGlzLCBjb25maWcsIHBhcmVudEtleSk7XG5cbiAgdmFyIHBhcnNlZCA9IHBhcnNlUGx1Z2luKGNvbmZpZy5wbHVnaW5GaXJzdCwga2V5KTtcblxuICAvLyBwbHVnaW5cbiAgaWYgKHBhcnNlZCkge1xuICAgIG1ldGFkYXRhLnBsdWdpbktleSA9IG5vcm1hbGl6ZVN5bmMuY2FsbCh0aGlzLCBwYXJzZWQucGx1Z2luLCBwYXJlbnRLZXkpO1xuICAgIHJldHVybiBjb21iaW5lUGx1Z2luUGFydHMoY29uZmlnLnBsdWdpbkZpcnN0LFxuICAgICAgICBwYWNrYWdlUmVzb2x2ZVN5bmMuY2FsbCh0aGlzLCBjb25maWcsIHBhcnNlZC5hcmd1bWVudCwgcGFyZW50TWV0YWRhdGEucGx1Z2luQXJndW1lbnQgfHwgcGFyZW50S2V5LCBtZXRhZGF0YSwgcGFyZW50TWV0YWRhdGEsICEhbWV0YWRhdGEucGx1Z2luS2V5KSxcbiAgICAgICAgbWV0YWRhdGEucGx1Z2luS2V5KTtcbiAgfVxuXG4gIHJldHVybiBwYWNrYWdlUmVzb2x2ZVN5bmMuY2FsbCh0aGlzLCBjb25maWcsIGtleSwgcGFyZW50TWV0YWRhdGEucGx1Z2luQXJndW1lbnQgfHwgcGFyZW50S2V5LCBtZXRhZGF0YSwgcGFyZW50TWV0YWRhdGEsICEhbWV0YWRhdGEucGx1Z2luS2V5KTtcbn1cblxuZnVuY3Rpb24gY29yZVJlc29sdmUgKGNvbmZpZywga2V5LCBwYXJlbnRLZXksIGRvTWFwLCBwYWNrYWdlTmFtZSkge1xuICB2YXIgcmVsYXRpdmVSZXNvbHZlZCA9IHJlc29sdmVJZk5vdFBsYWluKGtleSwgcGFyZW50S2V5IHx8IGJhc2VVUkkpO1xuXG4gIC8vIHN0YW5kYXJkIFVSTCByZXNvbHV0aW9uXG4gIGlmIChyZWxhdGl2ZVJlc29sdmVkKVxuICAgIHJldHVybiBhcHBseVBhdGhzKGNvbmZpZy5iYXNlVVJMLCBjb25maWcucGF0aHMsIHJlbGF0aXZlUmVzb2x2ZWQpO1xuXG4gIC8vIHBsYWluIGtleXMgbm90IHN0YXJ0aW5nIHdpdGggJy4vJywgJ3g6Ly8nIGFuZCAnLycgZ28gdGhyb3VnaCBjdXN0b20gcmVzb2x1dGlvblxuICBpZiAoZG9NYXApIHtcbiAgICB2YXIgbWFwTWF0Y2ggPSBnZXRNYXBNYXRjaChjb25maWcubWFwLCBrZXkpO1xuXG4gICAgaWYgKG1hcE1hdGNoKSB7XG4gICAgICBrZXkgPSBjb25maWcubWFwW21hcE1hdGNoXSArIGtleS5zdWJzdHIobWFwTWF0Y2gubGVuZ3RoKTtcblxuICAgICAgcmVsYXRpdmVSZXNvbHZlZCA9IHJlc29sdmVJZk5vdFBsYWluKGtleSwgYmFzZVVSSSk7XG4gICAgICBpZiAocmVsYXRpdmVSZXNvbHZlZClcbiAgICAgICAgcmV0dXJuIGFwcGx5UGF0aHMoY29uZmlnLmJhc2VVUkwsIGNvbmZpZy5wYXRocywgcmVsYXRpdmVSZXNvbHZlZCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRoaXMucmVnaXN0cnkuaGFzKGtleSkpXG4gICAgcmV0dXJuIGtleTtcblxuICBpZiAoa2V5LnN1YnN0cigwLCA2KSA9PT0gJ0Bub2RlLycpXG4gICAgcmV0dXJuIGtleTtcblxuICB2YXIgdHJhaWxpbmdTbGFzaCA9IHBhY2thZ2VOYW1lICYmIGtleVtrZXkubGVuZ3RoIC0gMV0gIT09ICcvJztcbiAgdmFyIHJlc29sdmVkID0gYXBwbHlQYXRocyhjb25maWcuYmFzZVVSTCwgY29uZmlnLnBhdGhzLCB0cmFpbGluZ1NsYXNoID8ga2V5ICsgJy8nIDoga2V5KTtcbiAgaWYgKHRyYWlsaW5nU2xhc2gpXG4gICAgcmV0dXJuIHJlc29sdmVkLnN1YnN0cigwLCByZXNvbHZlZC5sZW5ndGggLSAxKTtcbiAgcmV0dXJuIHJlc29sdmVkO1xufVxuXG5mdW5jdGlvbiBwYWNrYWdlUmVzb2x2ZVN5bmMgKGNvbmZpZywga2V5LCBwYXJlbnRLZXksIG1ldGFkYXRhLCBwYXJlbnRNZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpIHtcbiAgLy8gaWdub3JlIC4gc2luY2UgaW50ZXJuYWwgbWFwcyBoYW5kbGVkIGJ5IHN0YW5kYXJkIHBhY2thZ2UgcmVzb2x1dGlvblxuICBpZiAocGFyZW50TWV0YWRhdGEgJiYgcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZyAmJiBrZXlbMF0gIT09ICcuJykge1xuICAgIHZhciBwYXJlbnRNYXAgPSBwYXJlbnRNZXRhZGF0YS5wYWNrYWdlQ29uZmlnLm1hcDtcbiAgICB2YXIgcGFyZW50TWFwTWF0Y2ggPSBwYXJlbnRNYXAgJiYgZ2V0TWFwTWF0Y2gocGFyZW50TWFwLCBrZXkpO1xuXG4gICAgaWYgKHBhcmVudE1hcE1hdGNoICYmIHR5cGVvZiBwYXJlbnRNYXBbcGFyZW50TWFwTWF0Y2hdID09PSAnc3RyaW5nJykge1xuICAgICAgdmFyIG1hcHBlZCA9IGRvTWFwU3luYyh0aGlzLCBjb25maWcsIHBhcmVudE1ldGFkYXRhLnBhY2thZ2VDb25maWcsIHBhcmVudE1ldGFkYXRhLnBhY2thZ2VLZXksIHBhcmVudE1hcE1hdGNoLCBrZXksIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucyk7XG4gICAgICBpZiAobWFwcGVkKVxuICAgICAgICByZXR1cm4gbWFwcGVkO1xuICAgIH1cbiAgfVxuXG4gIHZhciBub3JtYWxpemVkID0gY29yZVJlc29sdmUuY2FsbCh0aGlzLCBjb25maWcsIGtleSwgcGFyZW50S2V5LCB0cnVlLCB0cnVlKTtcblxuICB2YXIgcGtnQ29uZmlnTWF0Y2ggPSBnZXRQYWNrYWdlQ29uZmlnTWF0Y2goY29uZmlnLCBub3JtYWxpemVkKTtcbiAgbWV0YWRhdGEucGFja2FnZUtleSA9IHBrZ0NvbmZpZ01hdGNoICYmIHBrZ0NvbmZpZ01hdGNoLnBhY2thZ2VLZXkgfHwgZ2V0TWFwTWF0Y2goY29uZmlnLnBhY2thZ2VzLCBub3JtYWxpemVkKTtcblxuICBpZiAoIW1ldGFkYXRhLnBhY2thZ2VLZXkpXG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG5cbiAgaWYgKGNvbmZpZy5wYWNrYWdlQ29uZmlnS2V5cy5pbmRleE9mKG5vcm1hbGl6ZWQpICE9PSAtMSkge1xuICAgIG1ldGFkYXRhLnBhY2thZ2VLZXkgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG4gIH1cblxuICBtZXRhZGF0YS5wYWNrYWdlQ29uZmlnID0gY29uZmlnLnBhY2thZ2VzW21ldGFkYXRhLnBhY2thZ2VLZXldIHx8IChjb25maWcucGFja2FnZXNbbWV0YWRhdGEucGFja2FnZUtleV0gPSBjcmVhdGVQYWNrYWdlKCkpO1xuXG4gIHZhciBzdWJQYXRoID0gbm9ybWFsaXplZC5zdWJzdHIobWV0YWRhdGEucGFja2FnZUtleS5sZW5ndGggKyAxKTtcblxuICByZXR1cm4gYXBwbHlQYWNrYWdlQ29uZmlnU3luYyh0aGlzLCBjb25maWcsIG1ldGFkYXRhLnBhY2thZ2VDb25maWcsIG1ldGFkYXRhLnBhY2thZ2VLZXksIHN1YlBhdGgsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucyk7XG59XG5cbmZ1bmN0aW9uIHBhY2thZ2VSZXNvbHZlIChjb25maWcsIGtleSwgcGFyZW50S2V5LCBtZXRhZGF0YSwgcGFyZW50TWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKSB7XG4gIHZhciBsb2FkZXIgPSB0aGlzO1xuXG4gIHJldHVybiByZXNvbHZlZFByb21pc2VcbiAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIC8vIGlnbm9yZSAuIHNpbmNlIGludGVybmFsIG1hcHMgaGFuZGxlZCBieSBzdGFuZGFyZCBwYWNrYWdlIHJlc29sdXRpb25cbiAgICBpZiAocGFyZW50TWV0YWRhdGEgJiYgcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZyAmJiBrZXkuc3Vic3RyKDAsIDIpICE9PSAnLi8nKSB7XG4gICAgICB2YXIgcGFyZW50TWFwID0gcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZy5tYXA7XG4gICAgICB2YXIgcGFyZW50TWFwTWF0Y2ggPSBwYXJlbnRNYXAgJiYgZ2V0TWFwTWF0Y2gocGFyZW50TWFwLCBrZXkpO1xuXG4gICAgICBpZiAocGFyZW50TWFwTWF0Y2gpXG4gICAgICAgIHJldHVybiBkb01hcChsb2FkZXIsIGNvbmZpZywgcGFyZW50TWV0YWRhdGEucGFja2FnZUNvbmZpZywgcGFyZW50TWV0YWRhdGEucGFja2FnZUtleSwgcGFyZW50TWFwTWF0Y2gsIGtleSwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAobWFwcGVkKSB7XG4gICAgaWYgKG1hcHBlZClcbiAgICAgIHJldHVybiBtYXBwZWQ7XG5cbiAgICAvLyBhcHBseSBtYXAsIGNvcmUsIHBhdGhzLCBjb250ZXh0dWFsIHBhY2thZ2UgbWFwXG4gICAgdmFyIG5vcm1hbGl6ZWQgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBrZXksIHBhcmVudEtleSwgdHJ1ZSwgdHJ1ZSk7XG5cbiAgICB2YXIgcGtnQ29uZmlnTWF0Y2ggPSBnZXRQYWNrYWdlQ29uZmlnTWF0Y2goY29uZmlnLCBub3JtYWxpemVkKTtcbiAgICBtZXRhZGF0YS5wYWNrYWdlS2V5ID0gcGtnQ29uZmlnTWF0Y2ggJiYgcGtnQ29uZmlnTWF0Y2gucGFja2FnZUtleSB8fCBnZXRNYXBNYXRjaChjb25maWcucGFja2FnZXMsIG5vcm1hbGl6ZWQpO1xuXG4gICAgaWYgKCFtZXRhZGF0YS5wYWNrYWdlS2V5KVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShub3JtYWxpemVkKTtcblxuICAgIGlmIChjb25maWcucGFja2FnZUNvbmZpZ0tleXMuaW5kZXhPZihub3JtYWxpemVkKSAhPT0gLTEpIHtcbiAgICAgIG1ldGFkYXRhLnBhY2thZ2VLZXkgPSB1bmRlZmluZWQ7XG4gICAgICBtZXRhZGF0YS5sb2FkID0gY3JlYXRlTWV0YSgpO1xuICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSAnanNvbic7XG4gICAgICAvLyBlbnN1cmUgbm8gbG9hZGVyXG4gICAgICBtZXRhZGF0YS5sb2FkLmxvYWRlciA9ICcnO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShub3JtYWxpemVkKTtcbiAgICB9XG5cbiAgICBtZXRhZGF0YS5wYWNrYWdlQ29uZmlnID0gY29uZmlnLnBhY2thZ2VzW21ldGFkYXRhLnBhY2thZ2VLZXldIHx8IChjb25maWcucGFja2FnZXNbbWV0YWRhdGEucGFja2FnZUtleV0gPSBjcmVhdGVQYWNrYWdlKCkpO1xuXG4gICAgLy8gbG9hZCBjb25maWd1cmF0aW9uIHdoZW4gaXQgbWF0Y2hlcyBwYWNrYWdlQ29uZmlnUGF0aHMsIG5vdCBhbHJlYWR5IGNvbmZpZ3VyZWQsIGFuZCBub3QgdGhlIGNvbmZpZyBpdHNlbGZcbiAgICB2YXIgbG9hZENvbmZpZyA9IHBrZ0NvbmZpZ01hdGNoICYmICFtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLmNvbmZpZ3VyZWQ7XG5cbiAgICByZXR1cm4gKGxvYWRDb25maWcgPyBsb2FkUGFja2FnZUNvbmZpZ1BhdGgobG9hZGVyLCBjb25maWcsIHBrZ0NvbmZpZ01hdGNoLmNvbmZpZ1BhdGgsIG1ldGFkYXRhKSA6IHJlc29sdmVkUHJvbWlzZSlcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgc3ViUGF0aCA9IG5vcm1hbGl6ZWQuc3Vic3RyKG1ldGFkYXRhLnBhY2thZ2VLZXkubGVuZ3RoICsgMSk7XG5cbiAgICAgIHJldHVybiBhcHBseVBhY2thZ2VDb25maWcobG9hZGVyLCBjb25maWcsIG1ldGFkYXRhLnBhY2thZ2VDb25maWcsIG1ldGFkYXRhLnBhY2thZ2VLZXksIHN1YlBhdGgsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVNZXRhICgpIHtcbiAgcmV0dXJuIHtcbiAgICBleHRlbnNpb246ICcnLFxuICAgIGRlcHM6IHVuZGVmaW5lZCxcbiAgICBmb3JtYXQ6IHVuZGVmaW5lZCxcbiAgICBsb2FkZXI6IHVuZGVmaW5lZCxcbiAgICBzY3JpcHRMb2FkOiB1bmRlZmluZWQsXG4gICAgZ2xvYmFsczogdW5kZWZpbmVkLFxuICAgIG5vbmNlOiB1bmRlZmluZWQsXG4gICAgaW50ZWdyaXR5OiB1bmRlZmluZWQsXG4gICAgc291cmNlTWFwOiB1bmRlZmluZWQsXG4gICAgZXhwb3J0czogdW5kZWZpbmVkLFxuICAgIGVuY2Fwc3VsYXRlR2xvYmFsOiBmYWxzZSxcbiAgICBjcm9zc09yaWdpbjogdW5kZWZpbmVkLFxuICAgIGNqc1JlcXVpcmVEZXRlY3Rpb246IHRydWUsXG4gICAgY2pzRGVmZXJEZXBzRXhlY3V0ZTogZmFsc2UsXG4gICAgZXNNb2R1bGU6IGZhbHNlXG4gIH07XG59XG5cbmZ1bmN0aW9uIHNldE1ldGEgKGNvbmZpZywga2V5LCBtZXRhZGF0YSkge1xuICBtZXRhZGF0YS5sb2FkID0gbWV0YWRhdGEubG9hZCB8fCBjcmVhdGVNZXRhKCk7XG5cbiAgLy8gYXBwbHkgd2lsZGNhcmQgbWV0YXNcbiAgdmFyIGJlc3REZXB0aCA9IDA7XG4gIHZhciB3aWxkY2FyZEluZGV4O1xuICBmb3IgKHZhciBtb2R1bGUgaW4gY29uZmlnLm1ldGEpIHtcbiAgICB3aWxkY2FyZEluZGV4ID0gbW9kdWxlLmluZGV4T2YoJyonKTtcbiAgICBpZiAod2lsZGNhcmRJbmRleCA9PT0gLTEpXG4gICAgICBjb250aW51ZTtcbiAgICBpZiAobW9kdWxlLnN1YnN0cigwLCB3aWxkY2FyZEluZGV4KSA9PT0ga2V5LnN1YnN0cigwLCB3aWxkY2FyZEluZGV4KVxuICAgICAgICAmJiBtb2R1bGUuc3Vic3RyKHdpbGRjYXJkSW5kZXggKyAxKSA9PT0ga2V5LnN1YnN0cihrZXkubGVuZ3RoIC0gbW9kdWxlLmxlbmd0aCArIHdpbGRjYXJkSW5kZXggKyAxKSkge1xuICAgICAgdmFyIGRlcHRoID0gbW9kdWxlLnNwbGl0KCcvJykubGVuZ3RoO1xuICAgICAgaWYgKGRlcHRoID4gYmVzdERlcHRoKVxuICAgICAgICBiZXN0RGVwdGggPSBkZXB0aDtcbiAgICAgIGV4dGVuZE1ldGEobWV0YWRhdGEubG9hZCwgY29uZmlnLm1ldGFbbW9kdWxlXSwgYmVzdERlcHRoICE9PSBkZXB0aCk7XG4gICAgfVxuICB9XG5cbiAgLy8gYXBwbHkgZXhhY3QgbWV0YVxuICBpZiAoY29uZmlnLm1ldGFba2V5XSlcbiAgICBleHRlbmRNZXRhKG1ldGFkYXRhLmxvYWQsIGNvbmZpZy5tZXRhW2tleV0sIGZhbHNlKTtcblxuICAvLyBhcHBseSBwYWNrYWdlIG1ldGFcbiAgaWYgKG1ldGFkYXRhLnBhY2thZ2VLZXkpIHtcbiAgICB2YXIgc3ViUGF0aCA9IGtleS5zdWJzdHIobWV0YWRhdGEucGFja2FnZUtleS5sZW5ndGggKyAxKTtcblxuICAgIHZhciBtZXRhID0ge307XG4gICAgaWYgKG1ldGFkYXRhLnBhY2thZ2VDb25maWcubWV0YSkge1xuICAgICAgdmFyIGJlc3REZXB0aCA9IDA7XG4gICAgICBnZXRNZXRhTWF0Y2hlcyhtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLm1ldGEsIHN1YlBhdGgsIGZ1bmN0aW9uIChtZXRhUGF0dGVybiwgbWF0Y2hNZXRhLCBtYXRjaERlcHRoKSB7XG4gICAgICAgIGlmIChtYXRjaERlcHRoID4gYmVzdERlcHRoKVxuICAgICAgICAgIGJlc3REZXB0aCA9IG1hdGNoRGVwdGg7XG4gICAgICAgIGV4dGVuZE1ldGEobWV0YSwgbWF0Y2hNZXRhLCBtYXRjaERlcHRoICYmIGJlc3REZXB0aCA+IG1hdGNoRGVwdGgpO1xuICAgICAgfSk7XG5cbiAgICAgIGV4dGVuZE1ldGEobWV0YWRhdGEubG9hZCwgbWV0YSwgZmFsc2UpO1xuICAgIH1cblxuICAgIC8vIGZvcm1hdFxuICAgIGlmIChtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLmZvcm1hdCAmJiAhbWV0YWRhdGEucGx1Z2luS2V5ICYmICFtZXRhZGF0YS5sb2FkLmxvYWRlcilcbiAgICAgIG1ldGFkYXRhLmxvYWQuZm9ybWF0ID0gbWV0YWRhdGEubG9hZC5mb3JtYXQgfHwgbWV0YWRhdGEucGFja2FnZUNvbmZpZy5mb3JtYXQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VQbHVnaW4gKHBsdWdpbkZpcnN0LCBrZXkpIHtcbiAgdmFyIGFyZ3VtZW50S2V5O1xuICB2YXIgcGx1Z2luS2V5O1xuXG4gIHZhciBwbHVnaW5JbmRleCA9IHBsdWdpbkZpcnN0ID8ga2V5LmluZGV4T2YoJyEnKSA6IGtleS5sYXN0SW5kZXhPZignIScpO1xuXG4gIGlmIChwbHVnaW5JbmRleCA9PT0gLTEpXG4gICAgcmV0dXJuO1xuXG4gIGlmIChwbHVnaW5GaXJzdCkge1xuICAgIGFyZ3VtZW50S2V5ID0ga2V5LnN1YnN0cihwbHVnaW5JbmRleCArIDEpO1xuICAgIHBsdWdpbktleSA9IGtleS5zdWJzdHIoMCwgcGx1Z2luSW5kZXgpO1xuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3VtZW50S2V5ID0ga2V5LnN1YnN0cigwLCBwbHVnaW5JbmRleCk7XG4gICAgcGx1Z2luS2V5ID0ga2V5LnN1YnN0cihwbHVnaW5JbmRleCArIDEpIHx8IGFyZ3VtZW50S2V5LnN1YnN0cihhcmd1bWVudEtleS5sYXN0SW5kZXhPZignLicpICsgMSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFyZ3VtZW50OiBhcmd1bWVudEtleSxcbiAgICBwbHVnaW46IHBsdWdpbktleVxuICB9O1xufVxuXG4vLyBwdXQga2V5IGJhY2sgdG9nZXRoZXIgYWZ0ZXIgcGFydHMgaGF2ZSBiZWVuIG5vcm1hbGl6ZWRcbmZ1bmN0aW9uIGNvbWJpbmVQbHVnaW5QYXJ0cyAocGx1Z2luRmlyc3QsIGFyZ3VtZW50S2V5LCBwbHVnaW5LZXkpIHtcbiAgaWYgKHBsdWdpbkZpcnN0KVxuICAgIHJldHVybiBwbHVnaW5LZXkgKyAnIScgKyBhcmd1bWVudEtleTtcbiAgZWxzZVxuICAgIHJldHVybiBhcmd1bWVudEtleSArICchJyArIHBsdWdpbktleTtcbn1cblxuLypcbiAqIFBhY2thZ2UgQ29uZmlndXJhdGlvbiBFeHRlbnNpb25cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqIFN5c3RlbUpTLnBhY2thZ2VzID0ge1xuICogICBqcXVlcnk6IHtcbiAqICAgICBtYWluOiAnaW5kZXguanMnLCAvLyB3aGVuIG5vdCBzZXQsIHBhY2thZ2Uga2V5IGlzIHJlcXVlc3RlZCBkaXJlY3RseVxuICogICAgIGZvcm1hdDogJ2FtZCcsXG4gKiAgICAgZGVmYXVsdEV4dGVuc2lvbjogJ3RzJywgLy8gZGVmYXVsdHMgdG8gJ2pzJywgY2FuIGJlIHNldCB0byBmYWxzZVxuICogICAgIG1vZHVsZXM6IHtcbiAqICAgICAgICcqLnRzJzoge1xuICogICAgICAgICBsb2FkZXI6ICd0eXBlc2NyaXB0J1xuICogICAgICAgfSxcbiAqICAgICAgICd2ZW5kb3Ivc2l6emxlLmpzJzoge1xuICogICAgICAgICBmb3JtYXQ6ICdnbG9iYWwnXG4gKiAgICAgICB9XG4gKiAgICAgfSxcbiAqICAgICBtYXA6IHtcbiAqICAgICAgICAvLyBtYXAgaW50ZXJuYWwgcmVxdWlyZSgnc2l6emxlJykgdG8gbG9jYWwgcmVxdWlyZSgnLi92ZW5kb3Ivc2l6emxlJylcbiAqICAgICAgICBzaXp6bGU6ICcuL3ZlbmRvci9zaXp6bGUuanMnLFxuICogICAgICAgIC8vIG1hcCBhbnkgaW50ZXJuYWwgb3IgZXh0ZXJuYWwgcmVxdWlyZSBvZiAnanF1ZXJ5L3ZlbmRvci9hbm90aGVyJyB0byAnYW5vdGhlci9pbmRleC5qcydcbiAqICAgICAgICAnLi92ZW5kb3IvYW5vdGhlci5qcyc6ICcuL2Fub3RoZXIvaW5kZXguanMnLFxuICogICAgICAgIC8vIHRlc3QuanMgLyB0ZXN0IC0+IGxpYi90ZXN0LmpzXG4gKiAgICAgICAgJy4vdGVzdC5qcyc6ICcuL2xpYi90ZXN0LmpzJyxcbiAqXG4gKiAgICAgICAgLy8gZW52aXJvbm1lbnQtc3BlY2lmaWMgbWFwIGNvbmZpZ3VyYXRpb25zXG4gKiAgICAgICAgJy4vaW5kZXguanMnOiB7XG4gKiAgICAgICAgICAnfmJyb3dzZXInOiAnLi9pbmRleC1ub2RlLmpzJyxcbiAqICAgICAgICAgICcuL2N1c3RvbS1jb25kaXRpb24uanN8fmV4cG9ydCc6ICcuL2luZGV4LWN1c3RvbS5qcydcbiAqICAgICAgICB9XG4gKiAgICAgfSxcbiAqICAgICAvLyBhbGxvd3MgZm9yIHNldHRpbmcgcGFja2FnZS1wcmVmaXhlZCBkZXBDYWNoZVxuICogICAgIC8vIGtleXMgYXJlIG5vcm1hbGl6ZWQgbW9kdWxlIGtleXMgcmVsYXRpdmUgdG8gdGhlIHBhY2thZ2UgaXRzZWxmXG4gKiAgICAgZGVwQ2FjaGU6IHtcbiAqICAgICAgIC8vIGltcG9ydCAncGFja2FnZS9pbmRleC5qcycgbG9hZHMgaW4gcGFyYWxsZWwgcGFja2FnZS9saWIvdGVzdC5qcyxwYWNrYWdlL3ZlbmRvci9zaXp6bGUuanNcbiAqICAgICAgICcuL2luZGV4LmpzJzogWycuL3Rlc3QnXSxcbiAqICAgICAgICcuL3Rlc3QuanMnOiBbJ2V4dGVybmFsLWRlcCddLFxuICogICAgICAgJ2V4dGVybmFsLWRlcC9wYXRoLmpzJzogWycuL2Fub3RoZXIuanMnXVxuICogICAgIH1cbiAqICAgfVxuICogfTtcbiAqXG4gKiBUaGVuOlxuICogICBpbXBvcnQgJ2pxdWVyeScgICAgICAgICAgICAgICAgICAgICAgIC0+IGpxdWVyeS9pbmRleC5qc1xuICogICBpbXBvcnQgJ2pxdWVyeS9zdWJtb2R1bGUnICAgICAgICAgICAgIC0+IGpxdWVyeS9zdWJtb2R1bGUuanNcbiAqICAgaW1wb3J0ICdqcXVlcnkvc3VibW9kdWxlLnRzJyAgICAgICAgICAtPiBqcXVlcnkvc3VibW9kdWxlLnRzIGxvYWRlZCBhcyB0eXBlc2NyaXB0XG4gKiAgIGltcG9ydCAnanF1ZXJ5L3ZlbmRvci9hbm90aGVyJyAgICAgICAgLT4gYW5vdGhlci9pbmRleC5qc1xuICpcbiAqIERldGFpbGVkIEJlaGF2aW91cnNcbiAqIC0gbWFpbiBjYW4gaGF2ZSBhIGxlYWRpbmcgXCIuL1wiIGNhbiBiZSBhZGRlZCBvcHRpb25hbGx5XG4gKiAtIG1hcCBhbmQgZGVmYXVsdEV4dGVuc2lvbiBhcmUgYXBwbGllZCB0byB0aGUgbWFpblxuICogLSBkZWZhdWx0RXh0ZW5zaW9uIGFkZHMgdGhlIGV4dGVuc2lvbiBvbmx5IGlmIHRoZSBleGFjdCBleHRlbnNpb24gaXMgbm90IHByZXNlbnRcblxuICogLSBpZiBhIG1ldGEgdmFsdWUgaXMgYXZhaWxhYmxlIGZvciBhIG1vZHVsZSwgbWFwIGFuZCBkZWZhdWx0RXh0ZW5zaW9uIGFyZSBza2lwcGVkXG4gKiAtIGxpa2UgZ2xvYmFsIG1hcCwgcGFja2FnZSBtYXAgYWxzbyBhcHBsaWVzIHRvIHN1YnBhdGhzIChzaXp6bGUveCwgLi92ZW5kb3IvYW5vdGhlci9zdWIpXG4gKiAtIGNvbmRpdGlvbiBtb2R1bGUgbWFwIGlzICdAZW52JyBtb2R1bGUgaW4gcGFja2FnZSBvciAnQHN5c3RlbS1lbnYnIGdsb2JhbGx5XG4gKiAtIG1hcCB0YXJnZXRzIHN1cHBvcnQgY29uZGl0aW9uYWwgaW50ZXJwb2xhdGlvbiAoJy4veCc6ICcuL3guI3t8ZW52fS5qcycpXG4gKiAtIGludGVybmFsIHBhY2thZ2UgbWFwIHRhcmdldHMgY2Fubm90IHVzZSBib29sZWFuIGNvbmRpdGlvbmFsc1xuICpcbiAqIFBhY2thZ2UgQ29uZmlndXJhdGlvbiBMb2FkaW5nXG4gKlxuICogTm90IGFsbCBwYWNrYWdlcyBtYXkgYWxyZWFkeSBoYXZlIHRoZWlyIGNvbmZpZ3VyYXRpb24gcHJlc2VudCBpbiB0aGUgU3lzdGVtIGNvbmZpZ1xuICogRm9yIHRoZXNlIGNhc2VzLCBhIGxpc3Qgb2YgcGFja2FnZUNvbmZpZ1BhdGhzIGNhbiBiZSBwcm92aWRlZCwgd2hpY2ggd2hlbiBtYXRjaGVkIGFnYWluc3RcbiAqIGEgcmVxdWVzdCwgd2lsbCBmaXJzdCByZXF1ZXN0IGEgXCIuanNvblwiIGZpbGUgYnkgdGhlIHBhY2thZ2Uga2V5IHRvIGRlcml2ZSB0aGUgcGFja2FnZVxuICogY29uZmlndXJhdGlvbiBmcm9tLiBUaGlzIGFsbG93cyBkeW5hbWljIGxvYWRpbmcgb2Ygbm9uLXByZWRldGVybWluZWQgY29kZSwgYSBrZXkgdXNlXG4gKiBjYXNlIGluIFN5c3RlbUpTLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogICBTeXN0ZW1KUy5wYWNrYWdlQ29uZmlnUGF0aHMgPSBbJ3BhY2thZ2VzL3Rlc3QvcGFja2FnZS5qc29uJywgJ3BhY2thZ2VzLyouanNvbiddO1xuICpcbiAqICAgLy8gd2lsbCBmaXJzdCByZXF1ZXN0ICdwYWNrYWdlcy9uZXctcGFja2FnZS9wYWNrYWdlLmpzb24nIGZvciB0aGUgcGFja2FnZSBjb25maWdcbiAqICAgLy8gYmVmb3JlIGNvbXBsZXRpbmcgdGhlIHBhY2thZ2UgcmVxdWVzdCB0byAncGFja2FnZXMvbmV3LXBhY2thZ2UvcGF0aCdcbiAqICAgU3lzdGVtSlMuaW1wb3J0KCdwYWNrYWdlcy9uZXctcGFja2FnZS9wYXRoJyk7XG4gKlxuICogICAvLyB3aWxsIGZpcnN0IHJlcXVlc3QgJ3BhY2thZ2VzL3Rlc3QvcGFja2FnZS5qc29uJyBiZWZvcmUgdGhlIG1haW5cbiAqICAgU3lzdGVtSlMuaW1wb3J0KCdwYWNrYWdlcy90ZXN0Jyk7XG4gKlxuICogV2hlbiBhIHBhY2thZ2UgbWF0Y2hlcyBwYWNrYWdlQ29uZmlnUGF0aHMsIGl0IHdpbGwgYWx3YXlzIHNlbmQgYSBjb25maWcgcmVxdWVzdCBmb3JcbiAqIHRoZSBwYWNrYWdlIGNvbmZpZ3VyYXRpb24uXG4gKiBUaGUgcGFja2FnZSBrZXkgaXRzZWxmIGlzIHRha2VuIHRvIGJlIHRoZSBtYXRjaCB1cCB0byBhbmQgaW5jbHVkaW5nIHRoZSBsYXN0IHdpbGRjYXJkXG4gKiBvciB0cmFpbGluZyBzbGFzaC5cbiAqIFRoZSBtb3N0IHNwZWNpZmljIHBhY2thZ2UgY29uZmlnIHBhdGggd2lsbCBiZSB1c2VkLlxuICogQW55IGV4aXN0aW5nIHBhY2thZ2UgY29uZmlndXJhdGlvbnMgZm9yIHRoZSBwYWNrYWdlIHdpbGwgZGVlcGx5IG1lcmdlIHdpdGggdGhlXG4gKiBwYWNrYWdlIGNvbmZpZywgd2l0aCB0aGUgZXhpc3RpbmcgcGFja2FnZSBjb25maWd1cmF0aW9ucyB0YWtpbmcgcHJlZmVyZW5jZS5cbiAqIFRvIG9wdC1vdXQgb2YgdGhlIHBhY2thZ2UgY29uZmlndXJhdGlvbiByZXF1ZXN0IGZvciBhIHBhY2thZ2UgdGhhdCBtYXRjaGVzXG4gKiBwYWNrYWdlQ29uZmlnUGF0aHMsIHVzZSB0aGUgeyBjb25maWd1cmVkOiB0cnVlIH0gcGFja2FnZSBjb25maWcgb3B0aW9uLlxuICpcbiAqL1xuXG5mdW5jdGlvbiBhZGREZWZhdWx0RXh0ZW5zaW9uIChjb25maWcsIHBrZywgcGtnS2V5LCBzdWJQYXRoLCBza2lwRXh0ZW5zaW9ucykge1xuICAvLyBkb24ndCBhcHBseSBleHRlbnNpb25zIHRvIGZvbGRlcnMgb3IgaWYgZGVmYXVsdEV4dGVuc2lvbiA9IGZhbHNlXG4gIGlmICghc3ViUGF0aCB8fCAhcGtnLmRlZmF1bHRFeHRlbnNpb24gfHwgc3ViUGF0aFtzdWJQYXRoLmxlbmd0aCAtIDFdID09PSAnLycgfHwgc2tpcEV4dGVuc2lvbnMpXG4gICAgcmV0dXJuIHN1YlBhdGg7XG5cbiAgdmFyIG1ldGFNYXRjaCA9IGZhbHNlO1xuXG4gIC8vIGV4YWN0IG1ldGEgb3IgbWV0YSB3aXRoIGFueSBjb250ZW50IGFmdGVyIHRoZSBsYXN0IHdpbGRjYXJkIHNraXBzIGV4dGVuc2lvblxuICBpZiAocGtnLm1ldGEpXG4gICAgZ2V0TWV0YU1hdGNoZXMocGtnLm1ldGEsIHN1YlBhdGgsIGZ1bmN0aW9uIChtZXRhUGF0dGVybiwgbWF0Y2hNZXRhLCBtYXRjaERlcHRoKSB7XG4gICAgICBpZiAobWF0Y2hEZXB0aCA9PT0gMCB8fCBtZXRhUGF0dGVybi5sYXN0SW5kZXhPZignKicpICE9PSBtZXRhUGF0dGVybi5sZW5ndGggLSAxKVxuICAgICAgICByZXR1cm4gbWV0YU1hdGNoID0gdHJ1ZTtcbiAgICB9KTtcblxuICAvLyBleGFjdCBnbG9iYWwgbWV0YSBvciBtZXRhIHdpdGggYW55IGNvbnRlbnQgYWZ0ZXIgdGhlIGxhc3Qgd2lsZGNhcmQgc2tpcHMgZXh0ZW5zaW9uXG4gIGlmICghbWV0YU1hdGNoICYmIGNvbmZpZy5tZXRhKVxuICAgIGdldE1ldGFNYXRjaGVzKGNvbmZpZy5tZXRhLCBwa2dLZXkgKyAnLycgKyBzdWJQYXRoLCBmdW5jdGlvbiAobWV0YVBhdHRlcm4sIG1hdGNoTWV0YSwgbWF0Y2hEZXB0aCkge1xuICAgICAgaWYgKG1hdGNoRGVwdGggPT09IDAgfHwgbWV0YVBhdHRlcm4ubGFzdEluZGV4T2YoJyonKSAhPT0gbWV0YVBhdHRlcm4ubGVuZ3RoIC0gMSlcbiAgICAgICAgcmV0dXJuIG1ldGFNYXRjaCA9IHRydWU7XG4gICAgfSk7XG5cbiAgaWYgKG1ldGFNYXRjaClcbiAgICByZXR1cm4gc3ViUGF0aDtcblxuICAvLyB3b3JrIG91dCB3aGF0IHRoZSBkZWZhdWx0RXh0ZW5zaW9uIGlzIGFuZCBhZGQgaWYgbm90IHRoZXJlIGFscmVhZHlcbiAgdmFyIGRlZmF1bHRFeHRlbnNpb24gPSAnLicgKyBwa2cuZGVmYXVsdEV4dGVuc2lvbjtcbiAgaWYgKHN1YlBhdGguc3Vic3RyKHN1YlBhdGgubGVuZ3RoIC0gZGVmYXVsdEV4dGVuc2lvbi5sZW5ndGgpICE9PSBkZWZhdWx0RXh0ZW5zaW9uKVxuICAgIHJldHVybiBzdWJQYXRoICsgZGVmYXVsdEV4dGVuc2lvbjtcbiAgZWxzZVxuICAgIHJldHVybiBzdWJQYXRoO1xufVxuXG5mdW5jdGlvbiBhcHBseVBhY2thZ2VDb25maWdTeW5jIChsb2FkZXIsIGNvbmZpZywgcGtnLCBwa2dLZXksIHN1YlBhdGgsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucykge1xuICAvLyBtYWluXG4gIGlmICghc3ViUGF0aCkge1xuICAgIGlmIChwa2cubWFpbilcbiAgICAgIHN1YlBhdGggPSBwa2cubWFpbi5zdWJzdHIoMCwgMikgPT09ICcuLycgPyBwa2cubWFpbi5zdWJzdHIoMikgOiBwa2cubWFpbjtcbiAgICBlbHNlXG4gICAgICAvLyBhbHNvIG5vIHN1Ym1hcCBpZiBrZXkgaXMgcGFja2FnZSBpdHNlbGYgKGltcG9ydCAncGtnJyAtPiAncGF0aC90by9wa2cuanMnKVxuICAgICAgLy8gTkIgY2FuIGFkZCBhIGRlZmF1bHQgcGFja2FnZSBtYWluIGNvbnZlbnRpb24gaGVyZVxuICAgICAgLy8gaWYgaXQgYmVjb21lcyBpbnRlcm5hbCB0byB0aGUgcGFja2FnZSB0aGVuIGl0IHdvdWxkIG5vIGxvbmdlciBiZSBhbiBleGl0IHBhdGhcbiAgICAgIHJldHVybiBwa2dLZXk7XG4gIH1cblxuICAvLyBtYXAgY29uZmlnIGNoZWNraW5nIHdpdGhvdXQgdGhlbiB3aXRoIGV4dGVuc2lvbnNcbiAgaWYgKHBrZy5tYXApIHtcbiAgICB2YXIgbWFwUGF0aCA9ICcuLycgKyBzdWJQYXRoO1xuXG4gICAgdmFyIG1hcE1hdGNoID0gZ2V0TWFwTWF0Y2gocGtnLm1hcCwgbWFwUGF0aCk7XG5cbiAgICAvLyB3ZSB0aGVuIGNoZWNrIG1hcCB3aXRoIHRoZSBkZWZhdWx0IGV4dGVuc2lvbiBhZGRpbmdcbiAgICBpZiAoIW1hcE1hdGNoKSB7XG4gICAgICBtYXBQYXRoID0gJy4vJyArIGFkZERlZmF1bHRFeHRlbnNpb24oY29uZmlnLCBwa2csIHBrZ0tleSwgc3ViUGF0aCwgc2tpcEV4dGVuc2lvbnMpO1xuICAgICAgaWYgKG1hcFBhdGggIT09ICcuLycgKyBzdWJQYXRoKVxuICAgICAgICBtYXBNYXRjaCA9IGdldE1hcE1hdGNoKHBrZy5tYXAsIG1hcFBhdGgpO1xuICAgIH1cbiAgICBpZiAobWFwTWF0Y2gpIHtcbiAgICAgIHZhciBtYXBwZWQgPSBkb01hcFN5bmMobG9hZGVyLCBjb25maWcsIHBrZywgcGtnS2V5LCBtYXBNYXRjaCwgbWFwUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKTtcbiAgICAgIGlmIChtYXBwZWQpXG4gICAgICAgIHJldHVybiBtYXBwZWQ7XG4gICAgfVxuICB9XG5cbiAgLy8gbm9ybWFsIHBhY2thZ2UgcmVzb2x1dGlvblxuICByZXR1cm4gcGtnS2V5ICsgJy8nICsgYWRkRGVmYXVsdEV4dGVuc2lvbihjb25maWcsIHBrZywgcGtnS2V5LCBzdWJQYXRoLCBza2lwRXh0ZW5zaW9ucyk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkTWFwcGluZyAobWFwTWF0Y2gsIG1hcHBlZCwgcGF0aCkge1xuICAvLyBhbGxvdyBpbnRlcm5hbCAuL3ggLT4gLi94L3kgb3IgLi94LyAtPiAuL3gveSByZWN1cnNpdmUgbWFwc1xuICAvLyBidXQgb25seSBpZiB0aGUgcGF0aCBpcyBleGFjdGx5IC4veCBhbmQgbm90IC4veC96XG4gIGlmIChtYXBwZWQuc3Vic3RyKDAsIG1hcE1hdGNoLmxlbmd0aCkgPT09IG1hcE1hdGNoICYmIHBhdGgubGVuZ3RoID4gbWFwTWF0Y2gubGVuZ3RoKVxuICAgIHJldHVybiBmYWxzZTtcblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZG9NYXBTeW5jIChsb2FkZXIsIGNvbmZpZywgcGtnLCBwa2dLZXksIG1hcE1hdGNoLCBwYXRoLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpIHtcbiAgaWYgKHBhdGhbcGF0aC5sZW5ndGggLSAxXSA9PT0gJy8nKVxuICAgIHBhdGggPSBwYXRoLnN1YnN0cigwLCBwYXRoLmxlbmd0aCAtIDEpO1xuICB2YXIgbWFwcGVkID0gcGtnLm1hcFttYXBNYXRjaF07XG5cbiAgaWYgKHR5cGVvZiBtYXBwZWQgPT09ICdvYmplY3QnKVxuICAgIHRocm93IG5ldyBFcnJvcignU3luY2hyb25vdXMgY29uZGl0aW9uYWwgbm9ybWFsaXphdGlvbiBub3Qgc3VwcG9ydGVkIHN5bmMgbm9ybWFsaXppbmcgJyArIG1hcE1hdGNoICsgJyBpbiAnICsgcGtnS2V5KTtcblxuICBpZiAoIXZhbGlkTWFwcGluZyhtYXBNYXRjaCwgbWFwcGVkLCBwYXRoKSB8fCB0eXBlb2YgbWFwcGVkICE9PSAnc3RyaW5nJylcbiAgICByZXR1cm47XG5cbiAgcmV0dXJuIHBhY2thZ2VSZXNvbHZlU3luYy5jYWxsKGxvYWRlciwgY29uZmlnLCBtYXBwZWQgKyBwYXRoLnN1YnN0cihtYXBNYXRjaC5sZW5ndGgpLCBwa2dLZXkgKyAnLycsIG1ldGFkYXRhLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpO1xufVxuXG5mdW5jdGlvbiBhcHBseVBhY2thZ2VDb25maWcgKGxvYWRlciwgY29uZmlnLCBwa2csIHBrZ0tleSwgc3ViUGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKSB7XG4gIC8vIG1haW5cbiAgaWYgKCFzdWJQYXRoKSB7XG4gICAgaWYgKHBrZy5tYWluKVxuICAgICAgc3ViUGF0aCA9IHBrZy5tYWluLnN1YnN0cigwLCAyKSA9PT0gJy4vJyA/IHBrZy5tYWluLnN1YnN0cigyKSA6IHBrZy5tYWluO1xuICAgIC8vIGFsc28gbm8gc3VibWFwIGlmIGtleSBpcyBwYWNrYWdlIGl0c2VsZiAoaW1wb3J0ICdwa2cnIC0+ICdwYXRoL3RvL3BrZy5qcycpXG4gICAgZWxzZVxuICAgICAgLy8gTkIgY2FuIGFkZCBhIGRlZmF1bHQgcGFja2FnZSBtYWluIGNvbnZlbnRpb24gaGVyZVxuICAgICAgLy8gaWYgaXQgYmVjb21lcyBpbnRlcm5hbCB0byB0aGUgcGFja2FnZSB0aGVuIGl0IHdvdWxkIG5vIGxvbmdlciBiZSBhbiBleGl0IHBhdGhcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGtnS2V5KTtcbiAgfVxuXG4gIC8vIG1hcCBjb25maWcgY2hlY2tpbmcgd2l0aG91dCB0aGVuIHdpdGggZXh0ZW5zaW9uc1xuICB2YXIgbWFwUGF0aCwgbWFwTWF0Y2g7XG5cbiAgaWYgKHBrZy5tYXApIHtcbiAgICBtYXBQYXRoID0gJy4vJyArIHN1YlBhdGg7XG4gICAgbWFwTWF0Y2ggPSBnZXRNYXBNYXRjaChwa2cubWFwLCBtYXBQYXRoKTtcblxuICAgIC8vIHdlIHRoZW4gY2hlY2sgbWFwIHdpdGggdGhlIGRlZmF1bHQgZXh0ZW5zaW9uIGFkZGluZ1xuICAgIGlmICghbWFwTWF0Y2gpIHtcbiAgICAgIG1hcFBhdGggPSAnLi8nICsgYWRkRGVmYXVsdEV4dGVuc2lvbihjb25maWcsIHBrZywgcGtnS2V5LCBzdWJQYXRoLCBza2lwRXh0ZW5zaW9ucyk7XG4gICAgICBpZiAobWFwUGF0aCAhPT0gJy4vJyArIHN1YlBhdGgpXG4gICAgICAgIG1hcE1hdGNoID0gZ2V0TWFwTWF0Y2gocGtnLm1hcCwgbWFwUGF0aCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIChtYXBNYXRjaCA/IGRvTWFwKGxvYWRlciwgY29uZmlnLCBwa2csIHBrZ0tleSwgbWFwTWF0Y2gsIG1hcFBhdGgsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucykgOiByZXNvbHZlZFByb21pc2UpXG4gIC50aGVuKGZ1bmN0aW9uIChtYXBwZWQpIHtcbiAgICBpZiAobWFwcGVkKVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtYXBwZWQpO1xuXG4gICAgLy8gbm9ybWFsIHBhY2thZ2UgcmVzb2x1dGlvbiAvIGZhbGxiYWNrIHJlc29sdXRpb24gZm9yIG5vIGNvbmRpdGlvbmFsIG1hdGNoXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwa2dLZXkgKyAnLycgKyBhZGREZWZhdWx0RXh0ZW5zaW9uKGNvbmZpZywgcGtnLCBwa2dLZXksIHN1YlBhdGgsIHNraXBFeHRlbnNpb25zKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkb01hcCAobG9hZGVyLCBjb25maWcsIHBrZywgcGtnS2V5LCBtYXBNYXRjaCwgcGF0aCwgbWV0YWRhdGEsIHNraXBFeHRlbnNpb25zKSB7XG4gIGlmIChwYXRoW3BhdGgubGVuZ3RoIC0gMV0gPT09ICcvJylcbiAgICBwYXRoID0gcGF0aC5zdWJzdHIoMCwgcGF0aC5sZW5ndGggLSAxKTtcblxuICB2YXIgbWFwcGVkID0gcGtnLm1hcFttYXBNYXRjaF07XG5cbiAgaWYgKHR5cGVvZiBtYXBwZWQgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKCF2YWxpZE1hcHBpbmcobWFwTWF0Y2gsIG1hcHBlZCwgcGF0aCkpXG4gICAgICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlO1xuICAgIHJldHVybiBwYWNrYWdlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBtYXBwZWQgKyBwYXRoLnN1YnN0cihtYXBNYXRjaC5sZW5ndGgpLCBwa2dLZXkgKyAnLycsIG1ldGFkYXRhLCBtZXRhZGF0YSwgc2tpcEV4dGVuc2lvbnMpXG4gICAgLnRoZW4oZnVuY3Rpb24gKG5vcm1hbGl6ZWQpIHtcbiAgICAgIHJldHVybiBpbnRlcnBvbGF0ZUNvbmRpdGlvbmFsLmNhbGwobG9hZGVyLCBub3JtYWxpemVkLCBwa2dLZXkgKyAnLycsIG1ldGFkYXRhKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIHdlIHVzZSBhIHNwZWNpYWwgY29uZGl0aW9uYWwgc3ludGF4IHRvIGFsbG93IHRoZSBidWlsZGVyIHRvIGhhbmRsZSBjb25kaXRpb25hbCBicmFuY2ggcG9pbnRzIGZ1cnRoZXJcbiAgLyppZiAobG9hZGVyLmJ1aWxkZXIpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwa2dLZXkgKyAnLyM6JyArIHBhdGgpOyovXG5cbiAgLy8gd2UgbG9hZCBhbGwgY29uZGl0aW9ucyB1cGZyb250XG4gIHZhciBjb25kaXRpb25Qcm9taXNlcyA9IFtdO1xuICB2YXIgY29uZGl0aW9ucyA9IFtdO1xuICBmb3IgKHZhciBlIGluIG1hcHBlZCkge1xuICAgIHZhciBjID0gcGFyc2VDb25kaXRpb24oZSk7XG4gICAgY29uZGl0aW9ucy5wdXNoKHtcbiAgICAgIGNvbmRpdGlvbjogYyxcbiAgICAgIG1hcDogbWFwcGVkW2VdXG4gICAgfSk7XG4gICAgY29uZGl0aW9uUHJvbWlzZXMucHVzaChSZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5pbXBvcnQuY2FsbChsb2FkZXIsIGMubW9kdWxlLCBwa2dLZXkpKTtcbiAgfVxuXG4gIC8vIG1hcCBvYmplY3QgLT4gY29uZGl0aW9uYWwgbWFwXG4gIHJldHVybiBQcm9taXNlLmFsbChjb25kaXRpb25Qcm9taXNlcylcbiAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvblZhbHVlcykge1xuICAgIC8vIGZpcnN0IG1hcCBjb25kaXRpb24gdG8gbWF0Y2ggaXMgdXNlZFxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29uZGl0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGMgPSBjb25kaXRpb25zW2ldLmNvbmRpdGlvbjtcbiAgICAgIHZhciB2YWx1ZSA9IHJlYWRNZW1iZXJFeHByZXNzaW9uKGMucHJvcCwgJ19fdXNlRGVmYXVsdCcgaW4gY29uZGl0aW9uVmFsdWVzW2ldID8gY29uZGl0aW9uVmFsdWVzW2ldLl9fdXNlRGVmYXVsdCA6IGNvbmRpdGlvblZhbHVlc1tpXSk7XG4gICAgICBpZiAoIWMubmVnYXRlICYmIHZhbHVlIHx8IGMubmVnYXRlICYmICF2YWx1ZSlcbiAgICAgICAgcmV0dXJuIGNvbmRpdGlvbnNbaV0ubWFwO1xuICAgIH1cbiAgfSlcbiAgLnRoZW4oZnVuY3Rpb24gKG1hcHBlZCkge1xuICAgIGlmIChtYXBwZWQpIHtcbiAgICAgIGlmICghdmFsaWRNYXBwaW5nKG1hcE1hdGNoLCBtYXBwZWQsIHBhdGgpKVxuICAgICAgICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlO1xuICAgICAgcmV0dXJuIHBhY2thZ2VSZXNvbHZlLmNhbGwobG9hZGVyLCBjb25maWcsIG1hcHBlZCArIHBhdGguc3Vic3RyKG1hcE1hdGNoLmxlbmd0aCksIHBrZ0tleSArICcvJywgbWV0YWRhdGEsIG1ldGFkYXRhLCBza2lwRXh0ZW5zaW9ucylcbiAgICAgIC50aGVuKGZ1bmN0aW9uIChub3JtYWxpemVkKSB7XG4gICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZUNvbmRpdGlvbmFsLmNhbGwobG9hZGVyLCBub3JtYWxpemVkLCBwa2dLZXkgKyAnLycsIG1ldGFkYXRhKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIG5vIGVudmlyb25tZW50IG1hdGNoIC0+IGZhbGxiYWNrIHRvIG9yaWdpbmFsIHN1YlBhdGggYnkgcmV0dXJuaW5nIHVuZGVmaW5lZFxuICB9KTtcbn1cblxuLy8gY2hlY2sgaWYgdGhlIGdpdmVuIG5vcm1hbGl6ZWQga2V5IG1hdGNoZXMgYSBwYWNrYWdlQ29uZmlnUGF0aFxuLy8gaWYgc28sIGxvYWRzIHRoZSBjb25maWdcbnZhciBwYWNrYWdlQ29uZmlnUGF0aHMgPSB7fTtcblxuLy8gZGF0YSBvYmplY3QgZm9yIHF1aWNrIGNoZWNrcyBhZ2FpbnN0IHBhY2thZ2UgcGF0aHNcbmZ1bmN0aW9uIGNyZWF0ZVBrZ0NvbmZpZ1BhdGhPYmogKHBhdGgpIHtcbiAgdmFyIGxhc3RXaWxkY2FyZCA9IHBhdGgubGFzdEluZGV4T2YoJyonKTtcbiAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KGxhc3RXaWxkY2FyZCArIDEsIHBhdGgubGFzdEluZGV4T2YoJy8nKSk7XG4gIHJldHVybiB7XG4gICAgbGVuZ3RoOiBsZW5ndGgsXG4gICAgcmVnRXg6IG5ldyBSZWdFeHAoJ14oJyArIHBhdGguc3Vic3RyKDAsIGxlbmd0aCkucmVwbGFjZSgvWy4rP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpLnJlcGxhY2UoL1xcKi9nLCAnW15cXFxcL10rJykgKyAnKShcXFxcL3wkKScpLFxuICAgIHdpbGRjYXJkOiBsYXN0V2lsZGNhcmQgIT09IC0xXG4gIH07XG59XG5cbi8vIG1vc3Qgc3BlY2lmaWMgbWF0Y2ggd2luc1xuZnVuY3Rpb24gZ2V0UGFja2FnZUNvbmZpZ01hdGNoIChjb25maWcsIG5vcm1hbGl6ZWQpIHtcbiAgdmFyIHBrZ0tleSwgZXhhY3RNYXRjaCA9IGZhbHNlLCBjb25maWdQYXRoO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbmZpZy5wYWNrYWdlQ29uZmlnUGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFja2FnZUNvbmZpZ1BhdGggPSBjb25maWcucGFja2FnZUNvbmZpZ1BhdGhzW2ldO1xuICAgIHZhciBwID0gcGFja2FnZUNvbmZpZ1BhdGhzW3BhY2thZ2VDb25maWdQYXRoXSB8fCAocGFja2FnZUNvbmZpZ1BhdGhzW3BhY2thZ2VDb25maWdQYXRoXSA9IGNyZWF0ZVBrZ0NvbmZpZ1BhdGhPYmoocGFja2FnZUNvbmZpZ1BhdGgpKTtcbiAgICBpZiAobm9ybWFsaXplZC5sZW5ndGggPCBwLmxlbmd0aClcbiAgICAgIGNvbnRpbnVlO1xuICAgIHZhciBtYXRjaCA9IG5vcm1hbGl6ZWQubWF0Y2gocC5yZWdFeCk7XG4gICAgaWYgKG1hdGNoICYmICghcGtnS2V5IHx8ICghKGV4YWN0TWF0Y2ggJiYgcC53aWxkY2FyZCkgJiYgcGtnS2V5Lmxlbmd0aCA8IG1hdGNoWzFdLmxlbmd0aCkpKSB7XG4gICAgICBwa2dLZXkgPSBtYXRjaFsxXTtcbiAgICAgIGV4YWN0TWF0Y2ggPSAhcC53aWxkY2FyZDtcbiAgICAgIGNvbmZpZ1BhdGggPSBwa2dLZXkgKyBwYWNrYWdlQ29uZmlnUGF0aC5zdWJzdHIocC5sZW5ndGgpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghcGtnS2V5KVxuICAgIHJldHVybjtcblxuICByZXR1cm4ge1xuICAgIHBhY2thZ2VLZXk6IHBrZ0tleSxcbiAgICBjb25maWdQYXRoOiBjb25maWdQYXRoXG4gIH07XG59XG5cbmZ1bmN0aW9uIGxvYWRQYWNrYWdlQ29uZmlnUGF0aCAobG9hZGVyLCBjb25maWcsIHBrZ0NvbmZpZ1BhdGgsIG1ldGFkYXRhLCBub3JtYWxpemVkKSB7XG4gIHZhciBjb25maWdMb2FkZXIgPSBsb2FkZXIucGx1Z2luTG9hZGVyIHx8IGxvYWRlcjtcblxuICAvLyBlbnN1cmUgd2Ugbm90ZSB0aGlzIGlzIGEgcGFja2FnZSBjb25maWcgZmlsZSBwYXRoXG4gIC8vIGl0IHdpbGwgdGhlbiBiZSBza2lwcGVkIGZyb20gZ2V0dGluZyBvdGhlciBub3JtYWxpemF0aW9ucyBpdHNlbGYgdG8gZW5zdXJlIGlkZW1wb3RlbmN5XG4gIGlmIChjb25maWcucGFja2FnZUNvbmZpZ0tleXMuaW5kZXhPZihwa2dDb25maWdQYXRoKSA9PT0gLTEpXG4gICAgY29uZmlnLnBhY2thZ2VDb25maWdLZXlzLnB1c2gocGtnQ29uZmlnUGF0aCk7XG5cbiAgcmV0dXJuIGNvbmZpZ0xvYWRlci5pbXBvcnQocGtnQ29uZmlnUGF0aClcbiAgLnRoZW4oZnVuY3Rpb24gKHBrZ0NvbmZpZykge1xuICAgIHNldFBrZ0NvbmZpZyhtZXRhZGF0YS5wYWNrYWdlQ29uZmlnLCBwa2dDb25maWcsIG1ldGFkYXRhLnBhY2thZ2VLZXksIHRydWUsIGNvbmZpZyk7XG4gICAgbWV0YWRhdGEucGFja2FnZUNvbmZpZy5jb25maWd1cmVkID0gdHJ1ZTtcbiAgfSlcbiAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICB0aHJvdyBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrKGVyciwgJ1VuYWJsZSB0byBmZXRjaCBwYWNrYWdlIGNvbmZpZ3VyYXRpb24gZmlsZSAnICsgcGtnQ29uZmlnUGF0aCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRNZXRhTWF0Y2hlcyAocGtnTWV0YSwgc3ViUGF0aCwgbWF0Y2hGbikge1xuICAvLyB3aWxkY2FyZCBtZXRhXG4gIHZhciB3aWxkY2FyZEluZGV4O1xuICBmb3IgKHZhciBtb2R1bGUgaW4gcGtnTWV0YSkge1xuICAgIC8vIGFsbG93IG1ldGEgdG8gc3RhcnQgd2l0aCAuLyBmb3IgZmxleGliaWxpdHlcbiAgICB2YXIgZG90UmVsID0gbW9kdWxlLnN1YnN0cigwLCAyKSA9PT0gJy4vJyA/ICcuLycgOiAnJztcbiAgICBpZiAoZG90UmVsKVxuICAgICAgbW9kdWxlID0gbW9kdWxlLnN1YnN0cigyKTtcblxuICAgIHdpbGRjYXJkSW5kZXggPSBtb2R1bGUuaW5kZXhPZignKicpO1xuICAgIGlmICh3aWxkY2FyZEluZGV4ID09PSAtMSlcbiAgICAgIGNvbnRpbnVlO1xuXG4gICAgaWYgKG1vZHVsZS5zdWJzdHIoMCwgd2lsZGNhcmRJbmRleCkgPT09IHN1YlBhdGguc3Vic3RyKDAsIHdpbGRjYXJkSW5kZXgpXG4gICAgICAgICYmIG1vZHVsZS5zdWJzdHIod2lsZGNhcmRJbmRleCArIDEpID09PSBzdWJQYXRoLnN1YnN0cihzdWJQYXRoLmxlbmd0aCAtIG1vZHVsZS5sZW5ndGggKyB3aWxkY2FyZEluZGV4ICsgMSkpIHtcbiAgICAgIC8vIGFsb3cgbWF0Y2ggZnVuY3Rpb24gdG8gcmV0dXJuIHRydWUgZm9yIGFuIGV4aXQgcGF0aFxuICAgICAgaWYgKG1hdGNoRm4obW9kdWxlLCBwa2dNZXRhW2RvdFJlbCArIG1vZHVsZV0sIG1vZHVsZS5zcGxpdCgnLycpLmxlbmd0aCkpXG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbiAgLy8gZXhhY3QgbWV0YVxuICB2YXIgZXhhY3RNZXRhID0gcGtnTWV0YVtzdWJQYXRoXSAmJiBPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChwa2dNZXRhLCBzdWJQYXRoKSA/IHBrZ01ldGFbc3ViUGF0aF0gOiBwa2dNZXRhWycuLycgKyBzdWJQYXRoXTtcbiAgaWYgKGV4YWN0TWV0YSlcbiAgICBtYXRjaEZuKGV4YWN0TWV0YSwgZXhhY3RNZXRhLCAwKTtcbn1cblxuXG4vKlxuICogQ29uZGl0aW9ucyBFeHRlbnNpb25cbiAqXG4gKiAgIEFsbG93cyBhIGNvbmRpdGlvbiBtb2R1bGUgdG8gYWx0ZXIgdGhlIHJlc29sdXRpb24gb2YgYW4gaW1wb3J0IHZpYSBzeW50YXg6XG4gKlxuICogICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeS8je2Jyb3dzZXJ9JztcbiAqXG4gKiAgIFdpbGwgZmlyc3QgbG9hZCB0aGUgbW9kdWxlICdicm93c2VyJyB2aWEgYFN5c3RlbUpTLmltcG9ydCgnYnJvd3NlcicpYCBhbmRcbiAqICAgdGFrZSB0aGUgZGVmYXVsdCBleHBvcnQgb2YgdGhhdCBtb2R1bGUuXG4gKiAgIElmIHRoZSBkZWZhdWx0IGV4cG9ydCBpcyBub3QgYSBzdHJpbmcsIGFuIGVycm9yIGlzIHRocm93bi5cbiAqXG4gKiAgIFdlIHRoZW4gc3Vic3RpdHV0ZSB0aGUgc3RyaW5nIGludG8gdGhlIHJlcXVpcmUgdG8gZ2V0IHRoZSBjb25kaXRpb25hbCByZXNvbHV0aW9uXG4gKiAgIGVuYWJsaW5nIGVudmlyb25tZW50LXNwZWNpZmljIHZhcmlhdGlvbnMgbGlrZTpcbiAqXG4gKiAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5L2llJ1xuICogICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeS9maXJlZm94J1xuICogICAgIGltcG9ydCAkIGZyb20gJ2pxdWVyeS9jaHJvbWUnXG4gKiAgICAgaW1wb3J0ICQgZnJvbSAnanF1ZXJ5L3NhZmFyaSdcbiAqXG4gKiAgIEl0IGNhbiBiZSB1c2VmdWwgZm9yIGEgY29uZGl0aW9uIG1vZHVsZSB0byBkZWZpbmUgbXVsdGlwbGUgY29uZGl0aW9ucy5cbiAqICAgVGhpcyBjYW4gYmUgZG9uZSB2aWEgdGhlIGB8YCBtb2RpZmllciB0byBzcGVjaWZ5IGFuIGV4cG9ydCBtZW1iZXIgZXhwcmVzc2lvbjpcbiAqXG4gKiAgICAgaW1wb3J0ICdqcXVlcnkvI3suL2Jyb3dzZXIuanN8Z3JhZGUudmVyc2lvbn0nXG4gKlxuICogICBXaGVyZSB0aGUgYGdyYWRlYCBleHBvcnQgYHZlcnNpb25gIG1lbWJlciBpbiB0aGUgYGJyb3dzZXIuanNgIG1vZHVsZSAgaXMgc3Vic3RpdHV0ZWQuXG4gKlxuICpcbiAqIEJvb2xlYW4gQ29uZGl0aW9uYWxzXG4gKlxuICogICBGb3IgcG9seWZpbGwgbW9kdWxlcywgdGhhdCBhcmUgdXNlZCBhcyBpbXBvcnRzIGJ1dCBoYXZlIG5vIG1vZHVsZSB2YWx1ZSxcbiAqICAgYSBiaW5hcnkgY29uZGl0aW9uYWwgYWxsb3dzIGEgbW9kdWxlIG5vdCB0byBiZSBsb2FkZWQgYXQgYWxsIGlmIG5vdCBuZWVkZWQ6XG4gKlxuICogICAgIGltcG9ydCAnZXM1LXNoaW0jPy4vY29uZGl0aW9ucy5qc3xuZWVkcy1lczVzaGltJ1xuICpcbiAqICAgVGhlc2UgY29uZGl0aW9ucyBjYW4gYWxzbyBiZSBuZWdhdGVkIHZpYTpcbiAqXG4gKiAgICAgaW1wb3J0ICdlczUtc2hpbSM/Li9jb25kaXRpb25zLmpzfH5lczYnXG4gKlxuICovXG5cbnZhciBzeXNDb25kaXRpb25zID0gWydicm93c2VyJywgJ25vZGUnLCAnZGV2JywgJ2J1aWxkJywgJ3Byb2R1Y3Rpb24nLCAnZGVmYXVsdCddO1xuXG5mdW5jdGlvbiBwYXJzZUNvbmRpdGlvbiAoY29uZGl0aW9uKSB7XG4gIHZhciBjb25kaXRpb25FeHBvcnQsIGNvbmRpdGlvbk1vZHVsZSwgbmVnYXRpb247XG5cbiAgdmFyIG5lZ2F0aW9uO1xuICB2YXIgY29uZGl0aW9uRXhwb3J0SW5kZXggPSBjb25kaXRpb24ubGFzdEluZGV4T2YoJ3wnKTtcbiAgaWYgKGNvbmRpdGlvbkV4cG9ydEluZGV4ICE9PSAtMSkge1xuICAgIGNvbmRpdGlvbkV4cG9ydCA9IGNvbmRpdGlvbi5zdWJzdHIoY29uZGl0aW9uRXhwb3J0SW5kZXggKyAxKTtcbiAgICBjb25kaXRpb25Nb2R1bGUgPSBjb25kaXRpb24uc3Vic3RyKDAsIGNvbmRpdGlvbkV4cG9ydEluZGV4KTtcblxuICAgIGlmIChjb25kaXRpb25FeHBvcnRbMF0gPT09ICd+Jykge1xuICAgICAgbmVnYXRpb24gPSB0cnVlO1xuICAgICAgY29uZGl0aW9uRXhwb3J0ID0gY29uZGl0aW9uRXhwb3J0LnN1YnN0cigxKTtcbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgbmVnYXRpb24gPSBjb25kaXRpb25bMF0gPT09ICd+JztcbiAgICBjb25kaXRpb25FeHBvcnQgPSAnZGVmYXVsdCc7XG4gICAgY29uZGl0aW9uTW9kdWxlID0gY29uZGl0aW9uLnN1YnN0cihuZWdhdGlvbik7XG4gICAgaWYgKHN5c0NvbmRpdGlvbnMuaW5kZXhPZihjb25kaXRpb25Nb2R1bGUpICE9PSAtMSkge1xuICAgICAgY29uZGl0aW9uRXhwb3J0ID0gY29uZGl0aW9uTW9kdWxlO1xuICAgICAgY29uZGl0aW9uTW9kdWxlID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG1vZHVsZTogY29uZGl0aW9uTW9kdWxlIHx8ICdAc3lzdGVtLWVudicsXG4gICAgcHJvcDogY29uZGl0aW9uRXhwb3J0LFxuICAgIG5lZ2F0ZTogbmVnYXRpb25cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNvbmRpdGlvbiAoY29uZGl0aW9uT2JqLCBwYXJlbnRLZXksIGJvb2wpIHtcbiAgLy8gaW1wb3J0IHdpdGhvdXQgX191c2VEZWZhdWx0IGhhbmRsaW5nIGhlcmVcbiAgcmV0dXJuIFJlZ2lzdGVyTG9hZGVyJDEucHJvdG90eXBlLmltcG9ydC5jYWxsKHRoaXMsIGNvbmRpdGlvbk9iai5tb2R1bGUsIHBhcmVudEtleSlcbiAgLnRoZW4oZnVuY3Rpb24gKGNvbmRpdGlvbikge1xuICAgIHZhciBtID0gcmVhZE1lbWJlckV4cHJlc3Npb24oY29uZGl0aW9uT2JqLnByb3AsIGNvbmRpdGlvbik7XG5cbiAgICBpZiAoYm9vbCAmJiB0eXBlb2YgbSAhPT0gJ2Jvb2xlYW4nKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ29uZGl0aW9uIGRpZCBub3QgcmVzb2x2ZSB0byBhIGJvb2xlYW4uJyk7XG5cbiAgICByZXR1cm4gY29uZGl0aW9uT2JqLm5lZ2F0ZSA/ICFtIDogbTtcbiAgfSk7XG59XG5cbnZhciBpbnRlcnBvbGF0aW9uUmVnRXggPSAvI1xce1teXFx9XStcXH0vO1xuZnVuY3Rpb24gaW50ZXJwb2xhdGVDb25kaXRpb25hbCAoa2V5LCBwYXJlbnRLZXksIHBhcmVudE1ldGFkYXRhKSB7XG4gIC8vIGZpcnN0IHdlIG5vcm1hbGl6ZSB0aGUgY29uZGl0aW9uYWxcbiAgdmFyIGNvbmRpdGlvbmFsTWF0Y2ggPSBrZXkubWF0Y2goaW50ZXJwb2xhdGlvblJlZ0V4KTtcblxuICBpZiAoIWNvbmRpdGlvbmFsTWF0Y2gpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShrZXkpO1xuXG4gIHZhciBjb25kaXRpb25PYmogPSBwYXJzZUNvbmRpdGlvbi5jYWxsKHRoaXMsIGNvbmRpdGlvbmFsTWF0Y2hbMF0uc3Vic3RyKDIsIGNvbmRpdGlvbmFsTWF0Y2hbMF0ubGVuZ3RoIC0gMykpO1xuXG4gIC8vIGluIGJ1aWxkcywgcmV0dXJuIG5vcm1hbGl6ZWQgY29uZGl0aW9uYWxcbiAgLyppZiAodGhpcy5idWlsZGVyKVxuICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZShjb25kaXRpb25PYmoubW9kdWxlLCBwYXJlbnRLZXksIGNyZWF0ZU1ldGFkYXRhKCksIHBhcmVudE1ldGFkYXRhKVxuICAgIC50aGVuKGZ1bmN0aW9uIChjb25kaXRpb25Nb2R1bGUpIHtcbiAgICAgIGNvbmRpdGlvbk9iai5tb2R1bGUgPSBjb25kaXRpb25Nb2R1bGU7XG4gICAgICByZXR1cm4ga2V5LnJlcGxhY2UoaW50ZXJwb2xhdGlvblJlZ0V4LCAnI3snICsgc2VyaWFsaXplQ29uZGl0aW9uKGNvbmRpdGlvbk9iaikgKyAnfScpO1xuICAgIH0pOyovXG5cbiAgcmV0dXJuIHJlc29sdmVDb25kaXRpb24uY2FsbCh0aGlzLCBjb25kaXRpb25PYmosIHBhcmVudEtleSwgZmFsc2UpXG4gIC50aGVuKGZ1bmN0aW9uIChjb25kaXRpb25WYWx1ZSkge1xuICAgIGlmICh0eXBlb2YgY29uZGl0aW9uVmFsdWUgIT09ICdzdHJpbmcnKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIGNvbmRpdGlvbiB2YWx1ZSBmb3IgJyArIGtleSArICcgZG9lc25cXCd0IHJlc29sdmUgdG8gYSBzdHJpbmcuJyk7XG5cbiAgICBpZiAoY29uZGl0aW9uVmFsdWUuaW5kZXhPZignLycpICE9PSAtMSlcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuYWJsZWQgdG8gaW50ZXJwb2xhdGUgY29uZGl0aW9uYWwgJyArIGtleSArIChwYXJlbnRLZXkgPyAnIGluICcgKyBwYXJlbnRLZXkgOiAnJykgKyAnXFxuXFx0VGhlIGNvbmRpdGlvbiB2YWx1ZSAnICsgY29uZGl0aW9uVmFsdWUgKyAnIGNhbm5vdCBjb250YWluIGEgXCIvXCIgc2VwYXJhdG9yLicpO1xuXG4gICAgcmV0dXJuIGtleS5yZXBsYWNlKGludGVycG9sYXRpb25SZWdFeCwgY29uZGl0aW9uVmFsdWUpO1xuICB9KTtcbn1cblxuLypcbiBFeHRlbmQgY29uZmlnIG1lcmdpbmcgb25lIGRlZXAgb25seVxuXG4gIGxvYWRlci5jb25maWcoe1xuICAgIHNvbWU6ICdyYW5kb20nLFxuICAgIGNvbmZpZzogJ2hlcmUnLFxuICAgIGRlZXA6IHtcbiAgICAgIGNvbmZpZzogeyB0b286ICd0b28nIH1cbiAgICB9XG4gIH0pO1xuXG4gIDw9PlxuXG4gIGxvYWRlci5zb21lID0gJ3JhbmRvbSc7XG4gIGxvYWRlci5jb25maWcgPSAnaGVyZSdcbiAgbG9hZGVyLmRlZXAgPSBsb2FkZXIuZGVlcCB8fCB7fTtcbiAgbG9hZGVyLmRlZXAuY29uZmlnID0geyB0b286ICd0b28nIH07XG5cblxuICBOb3JtYWxpemVzIG1ldGEgYW5kIHBhY2thZ2UgY29uZmlncyBhbGxvd2luZyBmb3I6XG5cbiAgU3lzdGVtSlMuY29uZmlnKHtcbiAgICBtZXRhOiB7XG4gICAgICAnLi9pbmRleC5qcyc6IHt9XG4gICAgfVxuICB9KTtcblxuICBUbyBiZWNvbWVcblxuICBTeXN0ZW1KUy5tZXRhWydodHRwczovL3RoaXNzaXRlLmNvbS9pbmRleC5qcyddID0ge307XG5cbiAgRm9yIGVhc3kgbm9ybWFsaXphdGlvbiBjYW5vbmljYWxpemF0aW9uIHdpdGggbGF0ZXN0IFVSTCBzdXBwb3J0LlxuXG4qL1xudmFyIGVudkNvbmZpZ05hbWVzID0gWydicm93c2VyQ29uZmlnJywgJ25vZGVDb25maWcnLCAnZGV2Q29uZmlnJywgJ2J1aWxkQ29uZmlnJywgJ3Byb2R1Y3Rpb25Db25maWcnXTtcbmZ1bmN0aW9uIGVudlNldChsb2FkZXIsIGNmZywgZW52Q2FsbGJhY2spIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbnZDb25maWdOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBlbnZDb25maWcgPSBlbnZDb25maWdOYW1lc1tpXTtcbiAgICBpZiAoY2ZnW2VudkNvbmZpZ10gJiYgZW52TW9kdWxlW2VudkNvbmZpZy5zdWJzdHIoMCwgZW52Q29uZmlnLmxlbmd0aCAtIDYpXSlcbiAgICAgIGVudkNhbGxiYWNrKGNmZ1tlbnZDb25maWddKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjbG9uZU9iaiAob2JqLCBtYXhEZXB0aCkge1xuICB2YXIgY2xvbmUgPSB7fTtcbiAgZm9yICh2YXIgcCBpbiBvYmopIHtcbiAgICB2YXIgcHJvcCA9IG9ialtwXTtcbiAgICBpZiAobWF4RGVwdGggPiAxKSB7XG4gICAgICBpZiAocHJvcCBpbnN0YW5jZW9mIEFycmF5KVxuICAgICAgICBjbG9uZVtwXSA9IFtdLmNvbmNhdChwcm9wKTtcbiAgICAgIGVsc2UgaWYgKHR5cGVvZiBwcm9wID09PSAnb2JqZWN0JylcbiAgICAgICAgY2xvbmVbcF0gPSBjbG9uZU9iaihwcm9wLCBtYXhEZXB0aCAtIDEpO1xuICAgICAgZWxzZSBpZiAocCAhPT0gJ3BhY2thZ2VDb25maWcnKVxuICAgICAgICBjbG9uZVtwXSA9IHByb3A7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgY2xvbmVbcF0gPSBwcm9wO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY2xvbmU7XG59XG5cbmZ1bmN0aW9uIGdldENvbmZpZ0l0ZW0gKGNvbmZpZywgcCkge1xuICB2YXIgY2ZnSXRlbSA9IGNvbmZpZ1twXTtcblxuICAvLyBnZXRDb25maWcgbXVzdCByZXR1cm4gYW4gdW5tb2RpZmlhYmxlIGNsb25lIG9mIHRoZSBjb25maWd1cmF0aW9uXG4gIGlmIChjZmdJdGVtIGluc3RhbmNlb2YgQXJyYXkpXG4gICAgcmV0dXJuIGNvbmZpZ1twXS5jb25jYXQoW10pO1xuICBlbHNlIGlmICh0eXBlb2YgY2ZnSXRlbSA9PT0gJ29iamVjdCcpXG4gICAgcmV0dXJuIGNsb25lT2JqKGNmZ0l0ZW0sIDMpXG4gIGVsc2VcbiAgICByZXR1cm4gY29uZmlnW3BdO1xufVxuXG5mdW5jdGlvbiBnZXRDb25maWcgKGNvbmZpZ05hbWUpIHtcbiAgaWYgKGNvbmZpZ05hbWUpIHtcbiAgICBpZiAoY29uZmlnTmFtZXMuaW5kZXhPZihjb25maWdOYW1lKSAhPT0gLTEpXG4gICAgICByZXR1cm4gZ2V0Q29uZmlnSXRlbSh0aGlzW0NPTkZJR10sIGNvbmZpZ05hbWUpO1xuICAgIHRocm93IG5ldyBFcnJvcignXCInICsgY29uZmlnTmFtZSArICdcIiBpcyBub3QgYSB2YWxpZCBjb25maWd1cmF0aW9uIG5hbWUuIE11c3QgYmUgb25lIG9mICcgKyBjb25maWdOYW1lcy5qb2luKCcsICcpICsgJy4nKTtcbiAgfVxuXG4gIHZhciBjZmcgPSB7fTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25maWdOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwID0gY29uZmlnTmFtZXNbaV07XG4gICAgdmFyIGNvbmZpZ0l0ZW0gPSBnZXRDb25maWdJdGVtKHRoaXNbQ09ORklHXSwgcCk7XG4gICAgaWYgKGNvbmZpZ0l0ZW0gIT09IHVuZGVmaW5lZClcbiAgICAgIGNmZ1twXSA9IGNvbmZpZ0l0ZW07XG4gIH1cbiAgcmV0dXJuIGNmZztcbn1cblxuZnVuY3Rpb24gc2V0Q29uZmlnIChjZmcsIGlzRW52Q29uZmlnKSB7XG4gIHZhciBsb2FkZXIgPSB0aGlzO1xuICB2YXIgY29uZmlnID0gdGhpc1tDT05GSUddO1xuXG4gIGlmICgnd2FybmluZ3MnIGluIGNmZylcbiAgICBjb25maWcud2FybmluZ3MgPSBjZmcud2FybmluZ3M7XG5cbiAgaWYgKCd3YXNtJyBpbiBjZmcpXG4gICAgY29uZmlnLndhc20gPSB0eXBlb2YgV2ViQXNzZW1ibHkgIT09ICd1bmRlZmluZWQnICYmIGNmZy53YXNtO1xuXG4gIGlmICgncHJvZHVjdGlvbicgaW4gY2ZnIHx8ICdidWlsZCcgaW4gY2ZnKVxuICAgIHNldFByb2R1Y3Rpb24uY2FsbChsb2FkZXIsICEhY2ZnLnByb2R1Y3Rpb24sICEhKGNmZy5idWlsZCB8fCBlbnZNb2R1bGUgJiYgZW52TW9kdWxlLmJ1aWxkKSk7XG5cbiAgaWYgKCFpc0VudkNvbmZpZykge1xuICAgIC8vIGlmIHVzaW5nIG5vZGVDb25maWcgLyBicm93c2VyQ29uZmlnIC8gcHJvZHVjdGlvbkNvbmZpZywgdGFrZSBiYXNlVVJMIGZyb20gdGhlcmVcbiAgICAvLyB0aGVzZSBleGNlcHRpb25zIHdpbGwgYmUgdW5uZWNlc3Nhcnkgd2hlbiB3ZSBjYW4gcHJvcGVybHkgaW1wbGVtZW50IGNvbmZpZyBxdWV1aW5nc1xuICAgIHZhciBiYXNlVVJMO1xuICAgIGVudlNldChsb2FkZXIsIGNmZywgZnVuY3Rpb24oY2ZnKSB7XG4gICAgICBiYXNlVVJMID0gYmFzZVVSTCB8fCBjZmcuYmFzZVVSTDtcbiAgICB9KTtcbiAgICBiYXNlVVJMID0gYmFzZVVSTCB8fCBjZmcuYmFzZVVSTDtcblxuICAgIC8vIGFsd2F5cyBjb25maWd1cmUgYmFzZVVSTCBmaXJzdFxuICAgIGlmIChiYXNlVVJMKSB7XG4gICAgICBjb25maWcuYmFzZVVSTCA9IHJlc29sdmVJZk5vdFBsYWluKGJhc2VVUkwsIGJhc2VVUkkpIHx8IHJlc29sdmVJZk5vdFBsYWluKCcuLycgKyBiYXNlVVJMLCBiYXNlVVJJKTtcbiAgICAgIGlmIChjb25maWcuYmFzZVVSTFtjb25maWcuYmFzZVVSTC5sZW5ndGggLSAxXSAhPT0gJy8nKVxuICAgICAgICBjb25maWcuYmFzZVVSTCArPSAnLyc7XG4gICAgfVxuXG4gICAgaWYgKGNmZy5wYXRocylcbiAgICAgIGV4dGVuZChjb25maWcucGF0aHMsIGNmZy5wYXRocyk7XG5cbiAgICBlbnZTZXQobG9hZGVyLCBjZmcsIGZ1bmN0aW9uKGNmZykge1xuICAgICAgaWYgKGNmZy5wYXRocylcbiAgICAgICAgZXh0ZW5kKGNvbmZpZy5wYXRocywgY2ZnLnBhdGhzKTtcbiAgICB9KTtcblxuICAgIGZvciAodmFyIHAgaW4gY29uZmlnLnBhdGhzKSB7XG4gICAgICBpZiAoY29uZmlnLnBhdGhzW3BdLmluZGV4T2YoJyonKSA9PT0gLTEpXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgd2Fybi5jYWxsKGNvbmZpZywgJ1BhdGggY29uZmlnICcgKyBwICsgJyAtPiAnICsgY29uZmlnLnBhdGhzW3BdICsgJyBpcyBubyBsb25nZXIgc3VwcG9ydGVkIGFzIHdpbGRjYXJkcyBhcmUgZGVwcmVjYXRlZC4nKTtcbiAgICAgIGRlbGV0ZSBjb25maWcucGF0aHNbcF07XG4gICAgfVxuICB9XG5cbiAgaWYgKGNmZy5kZWZhdWx0SlNFeHRlbnNpb25zKVxuICAgIHdhcm4uY2FsbChjb25maWcsICdUaGUgZGVmYXVsdEpTRXh0ZW5zaW9ucyBjb25maWd1cmF0aW9uIG9wdGlvbiBpcyBkZXByZWNhdGVkLlxcbiAgVXNlIHBhY2thZ2VzIGRlZmF1bHRFeHRlbnNpb24gaW5zdGVhZC4nLCB0cnVlKTtcblxuICBpZiAodHlwZW9mIGNmZy5wbHVnaW5GaXJzdCA9PT0gJ2Jvb2xlYW4nKVxuICAgIGNvbmZpZy5wbHVnaW5GaXJzdCA9IGNmZy5wbHVnaW5GaXJzdDtcblxuICBpZiAoY2ZnLm1hcCkge1xuICAgIGZvciAodmFyIHAgaW4gY2ZnLm1hcCkge1xuICAgICAgdmFyIHYgPSBjZmcubWFwW3BdO1xuXG4gICAgICBpZiAodHlwZW9mIHYgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhciBtYXBwZWQgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCB2LCB1bmRlZmluZWQsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgIGlmIChtYXBwZWRbbWFwcGVkLmxlbmd0aCAtMV0gPT09ICcvJyAmJiBwW3AubGVuZ3RoIC0gMV0gIT09ICc6JyAmJiBwW3AubGVuZ3RoIC0gMV0gIT09ICcvJylcbiAgICAgICAgICBtYXBwZWQgPSBtYXBwZWQuc3Vic3RyKDAsIG1hcHBlZC5sZW5ndGggLSAxKTtcbiAgICAgICAgY29uZmlnLm1hcFtwXSA9IG1hcHBlZDtcbiAgICAgIH1cblxuICAgICAgLy8gb2JqZWN0IG1hcFxuICAgICAgZWxzZSB7XG4gICAgICAgIHZhciBwa2dOYW1lID0gY29yZVJlc29sdmUuY2FsbChsb2FkZXIsIGNvbmZpZywgcFtwLmxlbmd0aCAtIDFdICE9PSAnLycgPyBwICsgJy8nIDogcCwgdW5kZWZpbmVkLCB0cnVlLCB0cnVlKTtcbiAgICAgICAgcGtnTmFtZSA9IHBrZ05hbWUuc3Vic3RyKDAsIHBrZ05hbWUubGVuZ3RoIC0gMSk7XG5cbiAgICAgICAgdmFyIHBrZyA9IGNvbmZpZy5wYWNrYWdlc1twa2dOYW1lXTtcbiAgICAgICAgaWYgKCFwa2cpIHtcbiAgICAgICAgICBwa2cgPSBjb25maWcucGFja2FnZXNbcGtnTmFtZV0gPSBjcmVhdGVQYWNrYWdlKCk7XG4gICAgICAgICAgLy8gdXNlICcnIGluc3RlYWQgb2YgZmFsc2UgdG8ga2VlcCB0eXBlIGNvbnNpc3RlbnRcbiAgICAgICAgICBwa2cuZGVmYXVsdEV4dGVuc2lvbiA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHNldFBrZ0NvbmZpZyhwa2csIHsgbWFwOiB2IH0sIHBrZ05hbWUsIGZhbHNlLCBjb25maWcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChjZmcucGFja2FnZUNvbmZpZ1BhdGhzKSB7XG4gICAgdmFyIHBhY2thZ2VDb25maWdQYXRocyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2ZnLnBhY2thZ2VDb25maWdQYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHBhdGggPSBjZmcucGFja2FnZUNvbmZpZ1BhdGhzW2ldO1xuICAgICAgdmFyIHBhY2thZ2VMZW5ndGggPSBNYXRoLm1heChwYXRoLmxhc3RJbmRleE9mKCcqJykgKyAxLCBwYXRoLmxhc3RJbmRleE9mKCcvJykpO1xuICAgICAgdmFyIG5vcm1hbGl6ZWQgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBwYXRoLnN1YnN0cigwLCBwYWNrYWdlTGVuZ3RoKSwgdW5kZWZpbmVkLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgcGFja2FnZUNvbmZpZ1BhdGhzW2ldID0gbm9ybWFsaXplZCArIHBhdGguc3Vic3RyKHBhY2thZ2VMZW5ndGgpO1xuICAgIH1cbiAgICBjb25maWcucGFja2FnZUNvbmZpZ1BhdGhzID0gcGFja2FnZUNvbmZpZ1BhdGhzO1xuICB9XG5cbiAgaWYgKGNmZy5idW5kbGVzKSB7XG4gICAgZm9yICh2YXIgcCBpbiBjZmcuYnVuZGxlcykge1xuICAgICAgdmFyIGJ1bmRsZSA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjZmcuYnVuZGxlc1twXS5sZW5ndGg7IGkrKylcbiAgICAgICAgYnVuZGxlLnB1c2gobG9hZGVyLm5vcm1hbGl6ZVN5bmMoY2ZnLmJ1bmRsZXNbcF1baV0pKTtcbiAgICAgIGNvbmZpZy5idW5kbGVzW3BdID0gYnVuZGxlO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjZmcucGFja2FnZXMpIHtcbiAgICBmb3IgKHZhciBwIGluIGNmZy5wYWNrYWdlcykge1xuICAgICAgaWYgKHAubWF0Y2goL14oW15cXC9dKzopP1xcL1xcLyQvKSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCInICsgcCArICdcIiBpcyBub3QgYSB2YWxpZCBwYWNrYWdlIG5hbWUuJyk7XG5cbiAgICAgIHZhciBwa2dOYW1lID0gY29yZVJlc29sdmUuY2FsbChsb2FkZXIsIGNvbmZpZywgcFtwLmxlbmd0aCAtIDFdICE9PSAnLycgPyBwICsgJy8nIDogcCwgdW5kZWZpbmVkLCB0cnVlLCB0cnVlKTtcbiAgICAgIHBrZ05hbWUgPSBwa2dOYW1lLnN1YnN0cigwLCBwa2dOYW1lLmxlbmd0aCAtIDEpO1xuXG4gICAgICBzZXRQa2dDb25maWcoY29uZmlnLnBhY2thZ2VzW3BrZ05hbWVdID0gY29uZmlnLnBhY2thZ2VzW3BrZ05hbWVdIHx8IGNyZWF0ZVBhY2thZ2UoKSwgY2ZnLnBhY2thZ2VzW3BdLCBwa2dOYW1lLCBmYWxzZSwgY29uZmlnKTtcbiAgICB9XG4gIH1cblxuICBpZiAoY2ZnLmRlcENhY2hlKSB7XG4gICAgZm9yICh2YXIgcCBpbiBjZmcuZGVwQ2FjaGUpXG4gICAgICBjb25maWcuZGVwQ2FjaGVbbG9hZGVyLm5vcm1hbGl6ZVN5bmMocCldID0gW10uY29uY2F0KGNmZy5kZXBDYWNoZVtwXSk7XG4gIH1cblxuICBpZiAoY2ZnLm1ldGEpIHtcbiAgICBmb3IgKHZhciBwIGluIGNmZy5tZXRhKSB7XG4gICAgICAvLyBiYXNlIHdpbGRjYXJkIHN0YXlzIGJhc2VcbiAgICAgIGlmIChwWzBdID09PSAnKicpIHtcbiAgICAgICAgZXh0ZW5kKGNvbmZpZy5tZXRhW3BdID0gY29uZmlnLm1ldGFbcF0gfHwge30sIGNmZy5tZXRhW3BdKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB2YXIgcmVzb2x2ZWQgPSBjb3JlUmVzb2x2ZS5jYWxsKGxvYWRlciwgY29uZmlnLCBwLCB1bmRlZmluZWQsIHRydWUsIHRydWUpO1xuICAgICAgICBleHRlbmQoY29uZmlnLm1ldGFbcmVzb2x2ZWRdID0gY29uZmlnLm1ldGFbcmVzb2x2ZWRdIHx8IHt9LCBjZmcubWV0YVtwXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKCd0cmFuc3BpbGVyJyBpbiBjZmcpXG4gICAgY29uZmlnLnRyYW5zcGlsZXIgPSBjZmcudHJhbnNwaWxlcjtcblxuXG4gIC8vIGNvcHkgYW55IHJlbWFpbmluZyBub24tc3RhbmRhcmQgY29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzXG4gIGZvciAodmFyIGMgaW4gY2ZnKSB7XG4gICAgaWYgKGNvbmZpZ05hbWVzLmluZGV4T2YoYykgIT09IC0xKVxuICAgICAgY29udGludWU7XG4gICAgaWYgKGVudkNvbmZpZ05hbWVzLmluZGV4T2YoYykgIT09IC0xKVxuICAgICAgY29udGludWU7XG5cbiAgICAvLyB3YXJuLmNhbGwoY29uZmlnLCAnU2V0dGluZyBjdXN0b20gY29uZmlnIG9wdGlvbiBgU3lzdGVtLmNvbmZpZyh7ICcgKyBjICsgJzogLi4uIH0pYCBpcyBkZXByZWNhdGVkLiBBdm9pZCBjdXN0b20gY29uZmlnIG9wdGlvbnMgb3Igc2V0IFN5c3RlbUpTLicgKyBjICsgJyA9IC4uLiBkaXJlY3RseS4nKTtcbiAgICBsb2FkZXJbY10gPSBjZmdbY107XG4gIH1cblxuICBlbnZTZXQobG9hZGVyLCBjZmcsIGZ1bmN0aW9uKGNmZykge1xuICAgIGxvYWRlci5jb25maWcoY2ZnLCB0cnVlKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBhY2thZ2UgKCkge1xuICByZXR1cm4ge1xuICAgIGRlZmF1bHRFeHRlbnNpb246IHVuZGVmaW5lZCxcbiAgICBtYWluOiB1bmRlZmluZWQsXG4gICAgZm9ybWF0OiB1bmRlZmluZWQsXG4gICAgbWV0YTogdW5kZWZpbmVkLFxuICAgIG1hcDogdW5kZWZpbmVkLFxuICAgIHBhY2thZ2VDb25maWc6IHVuZGVmaW5lZCxcbiAgICBjb25maWd1cmVkOiBmYWxzZVxuICB9O1xufVxuXG4vLyBkZWVwbHktbWVyZ2UgKHRvIGZpcnN0IGxldmVsKSBjb25maWcgd2l0aCBhbnkgZXhpc3RpbmcgcGFja2FnZSBjb25maWdcbmZ1bmN0aW9uIHNldFBrZ0NvbmZpZyAocGtnLCBjZmcsIHBrZ05hbWUsIHByZXBlbmRDb25maWcsIGNvbmZpZykge1xuICBmb3IgKHZhciBwcm9wIGluIGNmZykge1xuICAgIGlmIChwcm9wID09PSAnbWFpbicgfHwgcHJvcCA9PT0gJ2Zvcm1hdCcgfHwgcHJvcCA9PT0gJ2RlZmF1bHRFeHRlbnNpb24nIHx8IHByb3AgPT09ICdjb25maWd1cmVkJykge1xuICAgICAgaWYgKCFwcmVwZW5kQ29uZmlnIHx8IHBrZ1twcm9wXSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICBwa2dbcHJvcF0gPSBjZmdbcHJvcF07XG4gICAgfVxuICAgIGVsc2UgaWYgKHByb3AgPT09ICdtYXAnKSB7XG4gICAgICAocHJlcGVuZENvbmZpZyA/IHByZXBlbmQgOiBleHRlbmQpKHBrZy5tYXAgPSBwa2cubWFwIHx8IHt9LCBjZmcubWFwKTtcbiAgICB9XG4gICAgZWxzZSBpZiAocHJvcCA9PT0gJ21ldGEnKSB7XG4gICAgICAocHJlcGVuZENvbmZpZyA/IHByZXBlbmQgOiBleHRlbmQpKHBrZy5tZXRhID0gcGtnLm1ldGEgfHwge30sIGNmZy5tZXRhKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoY2ZnLCBwcm9wKSkge1xuICAgICAgd2Fybi5jYWxsKGNvbmZpZywgJ1wiJyArIHByb3AgKyAnXCIgaXMgbm90IGEgdmFsaWQgcGFja2FnZSBjb25maWd1cmF0aW9uIG9wdGlvbiBpbiBwYWNrYWdlICcgKyBwa2dOYW1lKTtcbiAgICB9XG4gIH1cblxuICAvLyBkZWZhdWx0IGRlZmF1bHRFeHRlbnNpb24gZm9yIHBhY2thZ2VzIG9ubHlcbiAgaWYgKHBrZy5kZWZhdWx0RXh0ZW5zaW9uID09PSB1bmRlZmluZWQpXG4gICAgcGtnLmRlZmF1bHRFeHRlbnNpb24gPSAnanMnO1xuXG4gIGlmIChwa2cubWFpbiA9PT0gdW5kZWZpbmVkICYmIHBrZy5tYXAgJiYgcGtnLm1hcFsnLiddKSB7XG4gICAgcGtnLm1haW4gPSBwa2cubWFwWycuJ107XG4gICAgZGVsZXRlIHBrZy5tYXBbJy4nXTtcbiAgfVxuICAvLyBtYWluIG9iamVjdCBiZWNvbWVzIG1haW4gbWFwXG4gIGVsc2UgaWYgKHR5cGVvZiBwa2cubWFpbiA9PT0gJ29iamVjdCcpIHtcbiAgICBwa2cubWFwID0gcGtnLm1hcCB8fCB7fTtcbiAgICBwa2cubWFwWycuL0BtYWluJ10gPSBwa2cubWFpbjtcbiAgICBwa2cubWFpblsnZGVmYXVsdCddID0gcGtnLm1haW5bJ2RlZmF1bHQnXSB8fCAnLi8nO1xuICAgIHBrZy5tYWluID0gJ0BtYWluJztcbiAgfVxuXG4gIHJldHVybiBwa2c7XG59XG5cbnZhciBoYXNCdWZmZXIgPSB0eXBlb2YgQnVmZmVyICE9PSAndW5kZWZpbmVkJztcbnRyeSB7XG4gIGlmIChoYXNCdWZmZXIgJiYgbmV3IEJ1ZmZlcignYScpLnRvU3RyaW5nKCdiYXNlNjQnKSAhPT0gJ1lRPT0nKVxuICAgIGhhc0J1ZmZlciA9IGZhbHNlO1xufVxuY2F0Y2ggKGUpIHtcbiAgaGFzQnVmZmVyID0gZmFsc2U7XG59XG5cbnZhciBzb3VyY2VNYXBQcmVmaXggPSAnXFxuLy8jIHNvdXJjZU1hcHBpbmcnICsgJ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCc7XG5mdW5jdGlvbiBpbmxpbmVTb3VyY2VNYXAgKHNvdXJjZU1hcFN0cmluZykge1xuICBpZiAoaGFzQnVmZmVyKVxuICAgIHJldHVybiBzb3VyY2VNYXBQcmVmaXggKyBuZXcgQnVmZmVyKHNvdXJjZU1hcFN0cmluZykudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICBlbHNlIGlmICh0eXBlb2YgYnRvYSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgcmV0dXJuIHNvdXJjZU1hcFByZWZpeCArIGJ0b2EodW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHNvdXJjZU1hcFN0cmluZykpKTtcbiAgZWxzZVxuICAgIHJldHVybiAnJztcbn1cblxuZnVuY3Rpb24gZ2V0U291cmNlKHNvdXJjZSwgc291cmNlTWFwLCBhZGRyZXNzLCB3cmFwKSB7XG4gIHZhciBsYXN0TGluZUluZGV4ID0gc291cmNlLmxhc3RJbmRleE9mKCdcXG4nKTtcblxuICBpZiAoc291cmNlTWFwKSB7XG4gICAgaWYgKHR5cGVvZiBzb3VyY2VNYXAgIT0gJ29iamVjdCcpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsb2FkLm1ldGFkYXRhLnNvdXJjZU1hcCBtdXN0IGJlIHNldCB0byBhbiBvYmplY3QuJyk7XG5cbiAgICBzb3VyY2VNYXAgPSBKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApO1xuICB9XG5cbiAgcmV0dXJuICh3cmFwID8gJyhmdW5jdGlvbihTeXN0ZW0sIFN5c3RlbUpTKSB7JyA6ICcnKSArIHNvdXJjZSArICh3cmFwID8gJ1xcbn0pKFN5c3RlbSwgU3lzdGVtKTsnIDogJycpXG4gICAgICAvLyBhZGRzIHRoZSBzb3VyY2VVUkwgY29tbWVudCBpZiBub3QgYWxyZWFkeSBwcmVzZW50XG4gICAgICArIChzb3VyY2Uuc3Vic3RyKGxhc3RMaW5lSW5kZXgsIDE1KSAhPSAnXFxuLy8jIHNvdXJjZVVSTD0nXG4gICAgICAgID8gJ1xcbi8vIyBzb3VyY2VVUkw9JyArIGFkZHJlc3MgKyAoc291cmNlTWFwID8gJyF0cmFuc3BpbGVkJyA6ICcnKSA6ICcnKVxuICAgICAgLy8gYWRkIHNvdXJjZU1hcHBpbmdVUkwgaWYgbG9hZC5tZXRhZGF0YS5zb3VyY2VNYXAgaXMgc2V0XG4gICAgICArIChzb3VyY2VNYXAgJiYgaW5saW5lU291cmNlTWFwKHNvdXJjZU1hcCkgfHwgJycpO1xufVxuXG4vLyBzY3JpcHQgZXhlY3V0aW9uIHZpYSBpbmplY3RpbmcgYSBzY3JpcHQgdGFnIGludG8gdGhlIHBhZ2Vcbi8vIHRoaXMgYWxsb3dzIENTUCBub25jZSB0byBiZSBzZXQgZm9yIENTUCBlbnZpcm9ubWVudHNcbnZhciBoZWFkO1xuZnVuY3Rpb24gc2NyaXB0RXhlYyhsb2FkZXIsIHNvdXJjZSwgc291cmNlTWFwLCBhZGRyZXNzLCBub25jZSkge1xuICBpZiAoIWhlYWQpXG4gICAgaGVhZCA9IGRvY3VtZW50LmhlYWQgfHwgZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cbiAgdmFyIHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICBzY3JpcHQudGV4dCA9IGdldFNvdXJjZShzb3VyY2UsIHNvdXJjZU1hcCwgYWRkcmVzcywgZmFsc2UpO1xuICB2YXIgb25lcnJvciA9IHdpbmRvdy5vbmVycm9yO1xuICB2YXIgZTtcbiAgd2luZG93Lm9uZXJyb3IgPSBmdW5jdGlvbihfZSkge1xuICAgIGUgPSBhZGRUb0Vycm9yKF9lLCAnRXZhbHVhdGluZyAnICsgYWRkcmVzcyk7XG4gICAgaWYgKG9uZXJyb3IpXG4gICAgICBvbmVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH07XG4gIHByZUV4ZWMobG9hZGVyKTtcblxuICBpZiAobm9uY2UpXG4gICAgc2NyaXB0LnNldEF0dHJpYnV0ZSgnbm9uY2UnLCBub25jZSk7XG5cbiAgaGVhZC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICBoZWFkLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG4gIHBvc3RFeGVjKCk7XG4gIHdpbmRvdy5vbmVycm9yID0gb25lcnJvcjtcbiAgaWYgKGUpXG4gICAgcmV0dXJuIGU7XG59XG5cbnZhciB2bTtcbnZhciB1c2VWbTtcblxudmFyIGN1clN5c3RlbTtcblxudmFyIGNhbGxDb3VudGVyID0gMDtcbmZ1bmN0aW9uIHByZUV4ZWMgKGxvYWRlcikge1xuICBpZiAoY2FsbENvdW50ZXIrKyA9PSAwKVxuICAgIGN1clN5c3RlbSA9IGVudkdsb2JhbC5TeXN0ZW07XG4gIGVudkdsb2JhbC5TeXN0ZW0gPSBlbnZHbG9iYWwuU3lzdGVtSlMgPSBsb2FkZXI7XG59XG5mdW5jdGlvbiBwb3N0RXhlYyAoKSB7XG4gIGlmICgtLWNhbGxDb3VudGVyID09IDApXG4gICAgZW52R2xvYmFsLlN5c3RlbSA9IGVudkdsb2JhbC5TeXN0ZW1KUyA9IGN1clN5c3RlbTtcbn1cblxudmFyIHN1cHBvcnRzU2NyaXB0RXhlYyA9IGZhbHNlO1xuaWYgKGlzQnJvd3NlciAmJiB0eXBlb2YgZG9jdW1lbnQgIT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUpIHtcbiAgaWYgKCEod2luZG93LmNocm9tZSAmJiB3aW5kb3cuY2hyb21lLmV4dGVuc2lvbiB8fCBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9eTm9kZVxcLmpzLykpKVxuICAgIHN1cHBvcnRzU2NyaXB0RXhlYyA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGV2YWx1YXRlIChsb2FkZXIsIHNvdXJjZSwgc291cmNlTWFwLCBhZGRyZXNzLCBpbnRlZ3JpdHksIG5vbmNlLCBub1dyYXApIHtcbiAgaWYgKCFzb3VyY2UpXG4gICAgcmV0dXJuO1xuICBpZiAobm9uY2UgJiYgc3VwcG9ydHNTY3JpcHRFeGVjKVxuICAgIHJldHVybiBzY3JpcHRFeGVjKGxvYWRlciwgc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsIG5vbmNlKTtcbiAgdHJ5IHtcbiAgICBwcmVFeGVjKGxvYWRlcik7XG4gICAgLy8gZ2xvYmFsIHNjb3BlZCBldmFsIGZvciBub2RlIChhdm9pZHMgcmVxdWlyZSBzY29wZSBsZWFrKVxuICAgIGlmICghdm0gJiYgbG9hZGVyLl9ub2RlUmVxdWlyZSkge1xuICAgICAgdm0gPSBsb2FkZXIuX25vZGVSZXF1aXJlKCd2bScpO1xuICAgICAgdXNlVm0gPSB2bS5ydW5JblRoaXNDb250ZXh0KFwidHlwZW9mIFN5c3RlbSAhPT0gJ3VuZGVmaW5lZCcgJiYgU3lzdGVtXCIpID09PSBsb2FkZXI7XG4gICAgfVxuICAgIGlmICh1c2VWbSlcbiAgICAgIHZtLnJ1bkluVGhpc0NvbnRleHQoZ2V0U291cmNlKHNvdXJjZSwgc291cmNlTWFwLCBhZGRyZXNzLCAhbm9XcmFwKSwgeyBmaWxlbmFtZTogYWRkcmVzcyArIChzb3VyY2VNYXAgPyAnIXRyYW5zcGlsZWQnIDogJycpIH0pO1xuICAgIGVsc2VcbiAgICAgICgwLCBldmFsKShnZXRTb3VyY2Uoc291cmNlLCBzb3VyY2VNYXAsIGFkZHJlc3MsICFub1dyYXApKTtcbiAgICBwb3N0RXhlYygpO1xuICB9XG4gIGNhdGNoIChlKSB7XG4gICAgcG9zdEV4ZWMoKTtcbiAgICByZXR1cm4gZTtcbiAgfVxufVxuXG52YXIgZm9ybWF0SGVscGVycyA9IGZ1bmN0aW9uIChsb2FkZXIpIHtcbiAgbG9hZGVyLnNldCgnQEBjanMtaGVscGVycycsIGxvYWRlci5uZXdNb2R1bGUoe1xuICAgIHJlcXVpcmVSZXNvbHZlOiByZXF1aXJlUmVzb2x2ZS5iaW5kKGxvYWRlciksXG4gICAgZ2V0UGF0aFZhcnM6IGdldFBhdGhWYXJzXG4gIH0pKTtcblxuICBsb2FkZXIuc2V0KCdAQGdsb2JhbC1oZWxwZXJzJywgbG9hZGVyLm5ld01vZHVsZSh7XG4gICAgcHJlcGFyZUdsb2JhbDogcHJlcGFyZUdsb2JhbFxuICB9KSk7XG5cbiAgLypcbiAgICBBTUQtY29tcGF0aWJsZSByZXF1aXJlXG4gICAgVG8gY29weSBSZXF1aXJlSlMsIHNldCB3aW5kb3cucmVxdWlyZSA9IHdpbmRvdy5yZXF1aXJlanMgPSBsb2FkZXIuYW1kUmVxdWlyZVxuICAqL1xuICBmdW5jdGlvbiByZXF1aXJlIChuYW1lcywgY2FsbGJhY2ssIGVycmJhY2ssIHJlZmVyZXIpIHtcbiAgICAvLyBpbiBhbWQsIGZpcnN0IGFyZyBjYW4gYmUgYSBjb25maWcgb2JqZWN0Li4uIHdlIGp1c3QgaWdub3JlXG4gICAgaWYgKHR5cGVvZiBuYW1lcyA9PT0gJ29iamVjdCcgJiYgIShuYW1lcyBpbnN0YW5jZW9mIEFycmF5KSlcbiAgICAgIHJldHVybiByZXF1aXJlLmFwcGx5KG51bGwsIEFycmF5LnByb3RvdHlwZS5zcGxpY2UuY2FsbChhcmd1bWVudHMsIDEsIGFyZ3VtZW50cy5sZW5ndGggLSAxKSk7XG5cbiAgICAvLyBhbWQgcmVxdWlyZVxuICAgIGlmICh0eXBlb2YgbmFtZXMgPT09ICdzdHJpbmcnICYmIHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJylcbiAgICAgIG5hbWVzID0gW25hbWVzXTtcbiAgICBpZiAobmFtZXMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgdmFyIGR5bmFtaWNSZXF1aXJlcyA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKylcbiAgICAgICAgZHluYW1pY1JlcXVpcmVzLnB1c2gobG9hZGVyLmltcG9ydChuYW1lc1tpXSwgcmVmZXJlcikpO1xuICAgICAgUHJvbWlzZS5hbGwoZHluYW1pY1JlcXVpcmVzKS50aGVuKGZ1bmN0aW9uIChtb2R1bGVzKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaylcbiAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBtb2R1bGVzKTtcbiAgICAgIH0sIGVycmJhY2spO1xuICAgIH1cblxuICAgIC8vIGNvbW1vbmpzIHJlcXVpcmVcbiAgICBlbHNlIGlmICh0eXBlb2YgbmFtZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICB2YXIgbm9ybWFsaXplZCA9IGxvYWRlci5kZWNhbm9uaWNhbGl6ZShuYW1lcywgcmVmZXJlcik7XG4gICAgICB2YXIgbW9kdWxlID0gbG9hZGVyLmdldChub3JtYWxpemVkKTtcbiAgICAgIGlmICghbW9kdWxlKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01vZHVsZSBub3QgYWxyZWFkeSBsb2FkZWQgbG9hZGluZyBcIicgKyBuYW1lcyArICdcIiBhcyAnICsgbm9ybWFsaXplZCArIChyZWZlcmVyID8gJyBmcm9tIFwiJyArIHJlZmVyZXIgKyAnXCIuJyA6ICcuJykpO1xuICAgICAgcmV0dXJuICdfX3VzZURlZmF1bHQnIGluIG1vZHVsZSA/IG1vZHVsZS5fX3VzZURlZmF1bHQgOiBtb2R1bGU7XG4gICAgfVxuXG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCByZXF1aXJlJyk7XG4gIH1cblxuICBmdW5jdGlvbiBkZWZpbmUgKG5hbWUsIGRlcHMsIGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBmYWN0b3J5ID0gZGVwcztcbiAgICAgIGRlcHMgPSBuYW1lO1xuICAgICAgbmFtZSA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCEoZGVwcyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgZmFjdG9yeSA9IGRlcHM7XG4gICAgICBkZXBzID0gWydyZXF1aXJlJywgJ2V4cG9ydHMnLCAnbW9kdWxlJ10uc3BsaWNlKDAsIGZhY3RvcnkubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGZhY3RvcnkgIT09ICdmdW5jdGlvbicpXG4gICAgICBmYWN0b3J5ID0gKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsgcmV0dXJuIGZhY3Rvcnk7IH1cbiAgICAgIH0pKGZhY3RvcnkpO1xuXG4gICAgaWYgKCFuYW1lKSB7XG4gICAgICBpZiAoY3VyTWV0YURlcHMpIHtcbiAgICAgICAgZGVwcyA9IGRlcHMuY29uY2F0KGN1ck1ldGFEZXBzKTtcbiAgICAgICAgY3VyTWV0YURlcHMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIHN5c3RlbSBkZXBlbmRlbmNpZXNcbiAgICB2YXIgcmVxdWlyZUluZGV4LCBleHBvcnRzSW5kZXgsIG1vZHVsZUluZGV4O1xuXG4gICAgaWYgKChyZXF1aXJlSW5kZXggPSBkZXBzLmluZGV4T2YoJ3JlcXVpcmUnKSkgIT09IC0xKSB7XG5cbiAgICAgIGRlcHMuc3BsaWNlKHJlcXVpcmVJbmRleCwgMSk7XG5cbiAgICAgIC8vIG9ubHkgdHJhY2UgY2pzIHJlcXVpcmVzIGZvciBub24tbmFtZWRcbiAgICAgIC8vIG5hbWVkIGRlZmluZXMgYXNzdW1lIHRoZSB0cmFjZSBoYXMgYWxyZWFkeSBiZWVuIGRvbmVcbiAgICAgIGlmICghbmFtZSlcbiAgICAgICAgZGVwcyA9IGRlcHMuY29uY2F0KGFtZEdldENKU0RlcHMoZmFjdG9yeS50b1N0cmluZygpLCByZXF1aXJlSW5kZXgpKTtcbiAgICB9XG5cbiAgICBpZiAoKGV4cG9ydHNJbmRleCA9IGRlcHMuaW5kZXhPZignZXhwb3J0cycpKSAhPT0gLTEpXG4gICAgICBkZXBzLnNwbGljZShleHBvcnRzSW5kZXgsIDEpO1xuXG4gICAgaWYgKChtb2R1bGVJbmRleCA9IGRlcHMuaW5kZXhPZignbW9kdWxlJykpICE9PSAtMSlcbiAgICAgIGRlcHMuc3BsaWNlKG1vZHVsZUluZGV4LCAxKTtcblxuICAgIGZ1bmN0aW9uIGV4ZWN1dGUgKHJlcSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICB2YXIgZGVwVmFsdWVzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRlcHMubGVuZ3RoOyBpKyspXG4gICAgICAgIGRlcFZhbHVlcy5wdXNoKHJlcShkZXBzW2ldKSk7XG5cbiAgICAgIG1vZHVsZS51cmkgPSBtb2R1bGUuaWQ7XG5cbiAgICAgIG1vZHVsZS5jb25maWcgPSBub29wO1xuXG4gICAgICAvLyBhZGQgYmFjayBpbiBzeXN0ZW0gZGVwZW5kZW5jaWVzXG4gICAgICBpZiAobW9kdWxlSW5kZXggIT09IC0xKVxuICAgICAgICBkZXBWYWx1ZXMuc3BsaWNlKG1vZHVsZUluZGV4LCAwLCBtb2R1bGUpO1xuXG4gICAgICBpZiAoZXhwb3J0c0luZGV4ICE9PSAtMSlcbiAgICAgICAgZGVwVmFsdWVzLnNwbGljZShleHBvcnRzSW5kZXgsIDAsIGV4cG9ydHMpO1xuXG4gICAgICBpZiAocmVxdWlyZUluZGV4ICE9PSAtMSkge1xuICAgICAgICB2YXIgY29udGV4dHVhbFJlcXVpcmUgPSBmdW5jdGlvbiAobmFtZXMsIGNhbGxiYWNrLCBlcnJiYWNrKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBuYW1lcyA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICAgICAgcmV0dXJuIHJlcShuYW1lcyk7XG4gICAgICAgICAgcmV0dXJuIHJlcXVpcmUuY2FsbChsb2FkZXIsIG5hbWVzLCBjYWxsYmFjaywgZXJyYmFjaywgbW9kdWxlLmlkKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29udGV4dHVhbFJlcXVpcmUudG9VcmwgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgIHJldHVybiBsb2FkZXIubm9ybWFsaXplU3luYyhuYW1lLCBtb2R1bGUuaWQpO1xuICAgICAgICB9O1xuICAgICAgICBkZXBWYWx1ZXMuc3BsaWNlKHJlcXVpcmVJbmRleCwgMCwgY29udGV4dHVhbFJlcXVpcmUpO1xuICAgICAgfVxuXG4gICAgICAvLyBzZXQgZ2xvYmFsIHJlcXVpcmUgdG8gQU1EIHJlcXVpcmVcbiAgICAgIHZhciBjdXJSZXF1aXJlID0gZW52R2xvYmFsLnJlcXVpcmU7XG4gICAgICBlbnZHbG9iYWwucmVxdWlyZSA9IHJlcXVpcmU7XG5cbiAgICAgIHZhciBvdXRwdXQgPSBmYWN0b3J5LmFwcGx5KGV4cG9ydHNJbmRleCA9PT0gLTEgPyBlbnZHbG9iYWwgOiBleHBvcnRzLCBkZXBWYWx1ZXMpO1xuXG4gICAgICBlbnZHbG9iYWwucmVxdWlyZSA9IGN1clJlcXVpcmU7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3V0cHV0ICE9PSAndW5kZWZpbmVkJylcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBvdXRwdXQ7XG4gICAgfVxuXG4gICAgLy8gYW5vbnltb3VzIGRlZmluZVxuICAgIGlmICghbmFtZSkge1xuICAgICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhkZXBzLCBmYWxzZSwgY3VyRXNNb2R1bGUgPyB3cmFwRXNNb2R1bGVFeGVjdXRlKGV4ZWN1dGUpIDogZXhlY3V0ZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhuYW1lLCBkZXBzLCBmYWxzZSwgZXhlY3V0ZSk7XG5cbiAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgYW55IG90aGVyIGRlZmluZXMsXG4gICAgICAvLyB0aGVuIGxldCB0aGlzIGJlIGFuIGFub255bW91cyBkZWZpbmVcbiAgICAgIC8vIHRoaXMgaXMganVzdCB0byBzdXBwb3J0IHNpbmdsZSBtb2R1bGVzIG9mIHRoZSBmb3JtOlxuICAgICAgLy8gZGVmaW5lKCdqcXVlcnknKVxuICAgICAgLy8gc3RpbGwgbG9hZGluZyBhbm9ueW1vdXNseVxuICAgICAgLy8gYmVjYXVzZSBpdCBpcyBkb25lIHdpZGVseSBlbm91Z2ggdG8gYmUgdXNlZnVsXG4gICAgICAvLyBhcyBzb29uIGFzIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgZGVmaW5lLCB0aGlzIGdldHMgcmVtb3ZlZCB0aG91Z2hcbiAgICAgIGlmIChsYXN0TmFtZWREZWZpbmUpIHtcbiAgICAgICAgbGFzdE5hbWVkRGVmaW5lID0gdW5kZWZpbmVkO1xuICAgICAgICBtdWx0aXBsZU5hbWVkRGVmaW5lcyA9IHRydWU7XG4gICAgICB9XG4gICAgICBlbHNlIGlmICghbXVsdGlwbGVOYW1lZERlZmluZXMpIHtcbiAgICAgICAgbGFzdE5hbWVkRGVmaW5lID0gW2RlcHMsIGV4ZWN1dGVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBkZWZpbmUuYW1kID0ge307XG5cbiAgbG9hZGVyLmFtZERlZmluZSA9IGRlZmluZTtcbiAgbG9hZGVyLmFtZFJlcXVpcmUgPSByZXF1aXJlO1xufTtcblxuLy8gQ0pTXG52YXIgd2luZG93T3JpZ2luO1xuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93LmxvY2F0aW9uKVxuICB3aW5kb3dPcmlnaW4gPSBsb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyBsb2NhdGlvbi5ob3N0bmFtZSArIChsb2NhdGlvbi5wb3J0ID8gJzonICsgbG9jYXRpb24ucG9ydCA6ICcnKTtcblxuZnVuY3Rpb24gc3RyaXBPcmlnaW4ocGF0aCkge1xuICBpZiAocGF0aC5zdWJzdHIoMCwgOCkgPT09ICdmaWxlOi8vLycpXG4gICAgcmV0dXJuIHBhdGguc3Vic3RyKDcgKyAhIWlzV2luZG93cyk7XG5cbiAgaWYgKHdpbmRvd09yaWdpbiAmJiBwYXRoLnN1YnN0cigwLCB3aW5kb3dPcmlnaW4ubGVuZ3RoKSA9PT0gd2luZG93T3JpZ2luKVxuICAgIHJldHVybiBwYXRoLnN1YnN0cih3aW5kb3dPcmlnaW4ubGVuZ3RoKTtcblxuICByZXR1cm4gcGF0aDtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZVJlc29sdmUgKHJlcXVlc3QsIHBhcmVudElkKSB7XG4gIHJldHVybiBzdHJpcE9yaWdpbih0aGlzLm5vcm1hbGl6ZVN5bmMocmVxdWVzdCwgcGFyZW50SWQpKTtcbn1cblxuZnVuY3Rpb24gZ2V0UGF0aFZhcnMgKG1vZHVsZUlkKSB7XG4gIC8vIHJlbW92ZSBhbnkgcGx1Z2luIHN5bnRheFxuICB2YXIgcGx1Z2luSW5kZXggPSBtb2R1bGVJZC5sYXN0SW5kZXhPZignIScpO1xuICB2YXIgZmlsZW5hbWU7XG4gIGlmIChwbHVnaW5JbmRleCAhPT0gLTEpXG4gICAgZmlsZW5hbWUgPSBtb2R1bGVJZC5zdWJzdHIoMCwgcGx1Z2luSW5kZXgpO1xuICBlbHNlXG4gICAgZmlsZW5hbWUgPSBtb2R1bGVJZDtcblxuICB2YXIgZGlybmFtZSA9IGZpbGVuYW1lLnNwbGl0KCcvJyk7XG4gIGRpcm5hbWUucG9wKCk7XG4gIGRpcm5hbWUgPSBkaXJuYW1lLmpvaW4oJy8nKTtcblxuICByZXR1cm4ge1xuICAgIGZpbGVuYW1lOiBzdHJpcE9yaWdpbihmaWxlbmFtZSksXG4gICAgZGlybmFtZTogc3RyaXBPcmlnaW4oZGlybmFtZSlcbiAgfTtcbn1cblxudmFyIGNvbW1lbnRSZWdFeCQxID0gLyhefFteXFxcXF0pKFxcL1xcKihbXFxzXFxTXSo/KVxcKlxcL3woW146XXxeKVxcL1xcLyguKikkKS9tZztcbnZhciBzdHJpbmdSZWdFeCQxID0gLyhcIlteXCJcXFxcXFxuXFxyXSooXFxcXC5bXlwiXFxcXFxcblxccl0qKSpcInwnW14nXFxcXFxcblxccl0qKFxcXFwuW14nXFxcXFxcblxccl0qKSonKS9nO1xuXG4vLyBleHRyYWN0IENKUyBkZXBlbmRlbmNpZXMgZnJvbSBzb3VyY2UgdGV4dCB2aWEgcmVnZXggc3RhdGljIGFuYWx5c2lzXG4vLyByZWFkIHJlcXVpcmUoJ3gnKSBzdGF0ZW1lbnRzIG5vdCBpbiBjb21tZW50cyBvciBzdHJpbmdzXG5mdW5jdGlvbiBnZXRDSlNEZXBzIChzb3VyY2UpIHtcbiAgY2pzUmVxdWlyZVJlZ0V4Lmxhc3RJbmRleCA9IGNvbW1lbnRSZWdFeCQxLmxhc3RJbmRleCA9IHN0cmluZ1JlZ0V4JDEubGFzdEluZGV4ID0gMDtcblxuICB2YXIgZGVwcyA9IFtdO1xuXG4gIHZhciBtYXRjaDtcblxuICAvLyB0cmFjayBzdHJpbmcgYW5kIGNvbW1lbnQgbG9jYXRpb25zIGZvciB1bm1pbmlmaWVkIHNvdXJjZVxuICB2YXIgc3RyaW5nTG9jYXRpb25zID0gW10sIGNvbW1lbnRMb2NhdGlvbnMgPSBbXTtcblxuICBmdW5jdGlvbiBpbkxvY2F0aW9uIChsb2NhdGlvbnMsIG1hdGNoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb2NhdGlvbnMubGVuZ3RoOyBpKyspXG4gICAgICBpZiAobG9jYXRpb25zW2ldWzBdIDwgbWF0Y2guaW5kZXggJiYgbG9jYXRpb25zW2ldWzFdID4gbWF0Y2guaW5kZXgpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChzb3VyY2UubGVuZ3RoIC8gc291cmNlLnNwbGl0KCdcXG4nKS5sZW5ndGggPCAyMDApIHtcbiAgICB3aGlsZSAobWF0Y2ggPSBzdHJpbmdSZWdFeCQxLmV4ZWMoc291cmNlKSlcbiAgICAgIHN0cmluZ0xvY2F0aW9ucy5wdXNoKFttYXRjaC5pbmRleCwgbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGhdKTtcblxuICAgIC8vIFRPRE86IHRyYWNrIHRlbXBsYXRlIGxpdGVyYWxzIGhlcmUgYmVmb3JlIGNvbW1lbnRzXG5cbiAgICB3aGlsZSAobWF0Y2ggPSBjb21tZW50UmVnRXgkMS5leGVjKHNvdXJjZSkpIHtcbiAgICAgIC8vIG9ubHkgdHJhY2sgY29tbWVudHMgbm90IHN0YXJ0aW5nIGluIHN0cmluZ3NcbiAgICAgIGlmICghaW5Mb2NhdGlvbihzdHJpbmdMb2NhdGlvbnMsIG1hdGNoKSlcbiAgICAgICAgY29tbWVudExvY2F0aW9ucy5wdXNoKFttYXRjaC5pbmRleCArIG1hdGNoWzFdLmxlbmd0aCwgbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGggLSAxXSk7XG4gICAgfVxuICB9XG5cbiAgd2hpbGUgKG1hdGNoID0gY2pzUmVxdWlyZVJlZ0V4LmV4ZWMoc291cmNlKSkge1xuICAgIC8vIGVuc3VyZSB3ZSdyZSBub3Qgd2l0aGluIGEgc3RyaW5nIG9yIGNvbW1lbnQgbG9jYXRpb25cbiAgICBpZiAoIWluTG9jYXRpb24oc3RyaW5nTG9jYXRpb25zLCBtYXRjaCkgJiYgIWluTG9jYXRpb24oY29tbWVudExvY2F0aW9ucywgbWF0Y2gpKSB7XG4gICAgICB2YXIgZGVwID0gbWF0Y2hbMV0uc3Vic3RyKDEsIG1hdGNoWzFdLmxlbmd0aCAtIDIpO1xuICAgICAgLy8gc2tpcCBjYXNlcyBsaWtlIHJlcXVpcmUoJ1wiICsgZmlsZSArIFwiJylcbiAgICAgIGlmIChkZXAubWF0Y2goL1wifCcvKSlcbiAgICAgICAgY29udGludWU7XG4gICAgICBkZXBzLnB1c2goZGVwKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGVwcztcbn1cblxuLy8gR2xvYmFsXG4vLyBiYXJlIG1pbmltdW0gaWdub3Jlc1xudmFyIGlnbm9yZWRHbG9iYWxQcm9wcyA9IFsnX2cnLCAnc2Vzc2lvblN0b3JhZ2UnLCAnbG9jYWxTdG9yYWdlJywgJ2NsaXBib2FyZERhdGEnLCAnZnJhbWVzJywgJ2ZyYW1lRWxlbWVudCcsICdleHRlcm5hbCcsXG4gICdtb3pBbmltYXRpb25TdGFydFRpbWUnLCAnd2Via2l0U3RvcmFnZUluZm8nLCAnd2Via2l0SW5kZXhlZERCJywgJ21veklubmVyU2NyZWVuWScsICdtb3pJbm5lclNjcmVlblgnXTtcblxudmFyIGdsb2JhbFNuYXBzaG90O1xuZnVuY3Rpb24gZ2xvYmFsSXRlcmF0b3IgKGdsb2JhbE5hbWUpIHtcbiAgaWYgKGlnbm9yZWRHbG9iYWxQcm9wcy5pbmRleE9mKGdsb2JhbE5hbWUpICE9PSAtMSlcbiAgICByZXR1cm47XG4gIHRyeSB7XG4gICAgdmFyIHZhbHVlID0gZW52R2xvYmFsW2dsb2JhbE5hbWVdO1xuICB9XG4gIGNhdGNoIChlKSB7XG4gICAgaWdub3JlZEdsb2JhbFByb3BzLnB1c2goZ2xvYmFsTmFtZSk7XG4gIH1cbiAgdGhpcyhnbG9iYWxOYW1lLCB2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGdldEdsb2JhbFZhbHVlIChleHBvcnRzKSB7XG4gIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ3N0cmluZycpXG4gICAgcmV0dXJuIHJlYWRNZW1iZXJFeHByZXNzaW9uKGV4cG9ydHMsIGVudkdsb2JhbCk7XG5cbiAgaWYgKCEoZXhwb3J0cyBpbnN0YW5jZW9mIEFycmF5KSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dsb2JhbCBleHBvcnRzIG11c3QgYmUgYSBzdHJpbmcgb3IgYXJyYXkuJyk7XG5cbiAgdmFyIGdsb2JhbFZhbHVlID0ge307XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZXhwb3J0cy5sZW5ndGg7IGkrKylcbiAgICBnbG9iYWxWYWx1ZVtleHBvcnRzW2ldLnNwbGl0KCcuJykucG9wKCldID0gcmVhZE1lbWJlckV4cHJlc3Npb24oZXhwb3J0c1tpXSwgZW52R2xvYmFsKTtcbiAgcmV0dXJuIGdsb2JhbFZhbHVlO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlR2xvYmFsIChtb2R1bGVOYW1lLCBleHBvcnRzLCBnbG9iYWxzLCBlbmNhcHN1bGF0ZSkge1xuICAvLyBkaXNhYmxlIG1vZHVsZSBkZXRlY3Rpb25cbiAgdmFyIGN1ckRlZmluZSA9IGVudkdsb2JhbC5kZWZpbmU7XG5cbiAgZW52R2xvYmFsLmRlZmluZSA9IHVuZGVmaW5lZDtcblxuICAvLyBzZXQgZ2xvYmFsc1xuICB2YXIgb2xkR2xvYmFscztcbiAgaWYgKGdsb2JhbHMpIHtcbiAgICBvbGRHbG9iYWxzID0ge307XG4gICAgZm9yICh2YXIgZyBpbiBnbG9iYWxzKSB7XG4gICAgICBvbGRHbG9iYWxzW2ddID0gZW52R2xvYmFsW2ddO1xuICAgICAgZW52R2xvYmFsW2ddID0gZ2xvYmFsc1tnXTtcbiAgICB9XG4gIH1cblxuICAvLyBzdG9yZSBhIGNvbXBsZXRlIGNvcHkgb2YgdGhlIGdsb2JhbCBvYmplY3QgaW4gb3JkZXIgdG8gZGV0ZWN0IGNoYW5nZXNcbiAgaWYgKCFleHBvcnRzKSB7XG4gICAgZ2xvYmFsU25hcHNob3QgPSB7fTtcblxuICAgIE9iamVjdC5rZXlzKGVudkdsb2JhbCkuZm9yRWFjaChnbG9iYWxJdGVyYXRvciwgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgICBnbG9iYWxTbmFwc2hvdFtuYW1lXSA9IHZhbHVlO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gcmV0dXJuIGZ1bmN0aW9uIHRvIHJldHJpZXZlIGdsb2JhbFxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBnbG9iYWxWYWx1ZSA9IGV4cG9ydHMgPyBnZXRHbG9iYWxWYWx1ZShleHBvcnRzKSA6IHt9O1xuXG4gICAgdmFyIHNpbmdsZUdsb2JhbDtcbiAgICB2YXIgbXVsdGlwbGVFeHBvcnRzID0gISFleHBvcnRzO1xuXG4gICAgaWYgKCFleHBvcnRzIHx8IGVuY2Fwc3VsYXRlKVxuICAgICAgT2JqZWN0LmtleXMoZW52R2xvYmFsKS5mb3JFYWNoKGdsb2JhbEl0ZXJhdG9yLCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKGdsb2JhbFNuYXBzaG90W25hbWVdID09PSB2YWx1ZSlcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAvLyBhbGxvdyBnbG9iYWwgZW5jYXBzdWxhdGlvbiB3aGVyZSBnbG9iYWxzIGFyZSByZW1vdmVkXG4gICAgICAgIGlmIChlbmNhcHN1bGF0ZSlcbiAgICAgICAgICBlbnZHbG9iYWxbbmFtZV0gPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKCFleHBvcnRzKSB7XG4gICAgICAgICAgZ2xvYmFsVmFsdWVbbmFtZV0gPSB2YWx1ZTtcblxuICAgICAgICAgIGlmIChzaW5nbGVHbG9iYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKCFtdWx0aXBsZUV4cG9ydHMgJiYgc2luZ2xlR2xvYmFsICE9PSB2YWx1ZSlcbiAgICAgICAgICAgICAgbXVsdGlwbGVFeHBvcnRzID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzaW5nbGVHbG9iYWwgPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgZ2xvYmFsVmFsdWUgPSBtdWx0aXBsZUV4cG9ydHMgPyBnbG9iYWxWYWx1ZSA6IHNpbmdsZUdsb2JhbDtcblxuICAgIC8vIHJldmVydCBnbG9iYWxzXG4gICAgaWYgKG9sZEdsb2JhbHMpIHtcbiAgICAgIGZvciAodmFyIGcgaW4gb2xkR2xvYmFscylcbiAgICAgICAgZW52R2xvYmFsW2ddID0gb2xkR2xvYmFsc1tnXTtcbiAgICB9XG4gICAgZW52R2xvYmFsLmRlZmluZSA9IGN1ckRlZmluZTtcblxuICAgIHJldHVybiBnbG9iYWxWYWx1ZTtcbiAgfTtcbn1cblxuLy8gQU1EXG52YXIgY2pzUmVxdWlyZVByZSA9IFwiKD86XnxbXiRfYS16QS1aXFxcXHhBMC1cXFxcdUZGRkYuXSlcIjtcbnZhciBjanNSZXF1aXJlUG9zdCA9IFwiXFxcXHMqXFxcXChcXFxccyooXFxcIihbXlxcXCJdKylcXFwifCcoW14nXSspJylcXFxccypcXFxcKVwiO1xudmFyIGZuQnJhY2tldFJlZ0V4ID0gL1xcKChbXlxcKV0qKVxcKS87XG52YXIgd3NSZWdFeCA9IC9eXFxzK3xcXHMrJC9nO1xuXG52YXIgcmVxdWlyZVJlZ0V4cyA9IHt9O1xuXG5mdW5jdGlvbiBhbWRHZXRDSlNEZXBzKHNvdXJjZSwgcmVxdWlyZUluZGV4KSB7XG5cbiAgLy8gcmVtb3ZlIGNvbW1lbnRzXG4gIHNvdXJjZSA9IHNvdXJjZS5yZXBsYWNlKGNvbW1lbnRSZWdFeCQxLCAnJyk7XG5cbiAgLy8gZGV0ZXJtaW5lIHRoZSByZXF1aXJlIGFsaWFzXG4gIHZhciBwYXJhbXMgPSBzb3VyY2UubWF0Y2goZm5CcmFja2V0UmVnRXgpO1xuICB2YXIgcmVxdWlyZUFsaWFzID0gKHBhcmFtc1sxXS5zcGxpdCgnLCcpW3JlcXVpcmVJbmRleF0gfHwgJ3JlcXVpcmUnKS5yZXBsYWNlKHdzUmVnRXgsICcnKTtcblxuICAvLyBmaW5kIG9yIGdlbmVyYXRlIHRoZSByZWdleCBmb3IgdGhpcyByZXF1aXJlQWxpYXNcbiAgdmFyIHJlcXVpcmVSZWdFeCA9IHJlcXVpcmVSZWdFeHNbcmVxdWlyZUFsaWFzXSB8fCAocmVxdWlyZVJlZ0V4c1tyZXF1aXJlQWxpYXNdID0gbmV3IFJlZ0V4cChjanNSZXF1aXJlUHJlICsgcmVxdWlyZUFsaWFzICsgY2pzUmVxdWlyZVBvc3QsICdnJykpO1xuXG4gIHJlcXVpcmVSZWdFeC5sYXN0SW5kZXggPSAwO1xuXG4gIHZhciBkZXBzID0gW107XG5cbiAgdmFyIG1hdGNoO1xuICB3aGlsZSAobWF0Y2ggPSByZXF1aXJlUmVnRXguZXhlYyhzb3VyY2UpKVxuICAgIGRlcHMucHVzaChtYXRjaFsyXSB8fCBtYXRjaFszXSk7XG5cbiAgcmV0dXJuIGRlcHM7XG59XG5cbmZ1bmN0aW9uIHdyYXBFc01vZHVsZUV4ZWN1dGUgKGV4ZWN1dGUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICBleGVjdXRlKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSk7XG4gICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzO1xuICAgIGlmICgodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnIHx8IHR5cGVvZiBleHBvcnRzID09PSAnZnVuY3Rpb24nKSAmJiAhKCdfX2VzTW9kdWxlJyBpbiBleHBvcnRzKSlcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUuZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICB9KTtcbiAgfTtcbn1cblxuLy8gZ2VuZXJhdGUgYW5vbnltb3VzIGRlZmluZSBmcm9tIHNpbmd1bGFyIG5hbWVkIGRlZmluZVxudmFyIG11bHRpcGxlTmFtZWREZWZpbmVzID0gZmFsc2U7XG52YXIgbGFzdE5hbWVkRGVmaW5lO1xudmFyIGN1ck1ldGFEZXBzO1xudmFyIGN1ckVzTW9kdWxlID0gZmFsc2U7XG5mdW5jdGlvbiBjbGVhckxhc3REZWZpbmUgKG1ldGFEZXBzLCBlc01vZHVsZSkge1xuICBjdXJNZXRhRGVwcyA9IG1ldGFEZXBzO1xuICBjdXJFc01vZHVsZSA9IGVzTW9kdWxlO1xuICBsYXN0TmFtZWREZWZpbmUgPSB1bmRlZmluZWQ7XG4gIG11bHRpcGxlTmFtZWREZWZpbmVzID0gZmFsc2U7XG59XG5mdW5jdGlvbiByZWdpc3Rlckxhc3REZWZpbmUgKGxvYWRlcikge1xuICBpZiAobGFzdE5hbWVkRGVmaW5lKVxuICAgIGxvYWRlci5yZWdpc3RlckR5bmFtaWMoY3VyTWV0YURlcHMgPyBsYXN0TmFtZWREZWZpbmVbMF0uY29uY2F0KGN1ck1ldGFEZXBzKSA6IGxhc3ROYW1lZERlZmluZVswXSxcbiAgICAgICAgZmFsc2UsIGN1ckVzTW9kdWxlID8gd3JhcEVzTW9kdWxlRXhlY3V0ZShsYXN0TmFtZWREZWZpbmVbMV0pIDogbGFzdE5hbWVkRGVmaW5lWzFdKTtcblxuICAvLyBidW5kbGVzIGFyZSBhbiBlbXB0eSBtb2R1bGVcbiAgZWxzZSBpZiAobXVsdGlwbGVOYW1lZERlZmluZXMpXG4gICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhbXSwgZmFsc2UsIG5vb3ApO1xufVxuXG52YXIgc3VwcG9ydHNTY3JpcHRMb2FkID0gKGlzQnJvd3NlciB8fCBpc1dvcmtlcikgJiYgdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudCAmJiAhbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvTVNJRSAoOXwxMCkuMC8pO1xuXG4vLyBpbmNsdWRlIHRoZSBub2RlIHJlcXVpcmUgc2luY2Ugd2UncmUgb3ZlcnJpZGluZyBpdFxudmFyIG5vZGVSZXF1aXJlO1xuaWYgKHR5cGVvZiByZXF1aXJlICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgIXByb2Nlc3MuYnJvd3NlcilcbiAgbm9kZVJlcXVpcmUgPSByZXF1aXJlO1xuXG5mdW5jdGlvbiBzZXRNZXRhRXNNb2R1bGUgKG1ldGFkYXRhLCBtb2R1bGVWYWx1ZSkge1xuICBpZiAobWV0YWRhdGEubG9hZC5lc01vZHVsZSAmJiAodHlwZW9mIG1vZHVsZVZhbHVlID09PSAnb2JqZWN0JyB8fCB0eXBlb2YgbW9kdWxlVmFsdWUgPT09ICdmdW5jdGlvbicpICYmXG4gICAgICAhKCdfX2VzTW9kdWxlJyBpbiBtb2R1bGVWYWx1ZSkpXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZVZhbHVlLCAnX19lc01vZHVsZScsIHtcbiAgICAgIHZhbHVlOiB0cnVlXG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGluc3RhbnRpYXRlJDEgKGtleSwgcHJvY2Vzc0Fub25SZWdpc3Rlcikge1xuICB2YXIgbG9hZGVyID0gdGhpcztcbiAgdmFyIGNvbmZpZyA9IHRoaXNbQ09ORklHXTtcbiAgLy8gZmlyc3QgZG8gYnVuZGxlcyBhbmQgZGVwQ2FjaGVcbiAgcmV0dXJuIChsb2FkQnVuZGxlc0FuZERlcENhY2hlKGNvbmZpZywgdGhpcywga2V5KSB8fCByZXNvbHZlZFByb21pc2UpXG4gIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICBpZiAocHJvY2Vzc0Fub25SZWdpc3RlcigpKVxuICAgICAgcmV0dXJuO1xuXG4gICAgdmFyIG1ldGFkYXRhID0gbG9hZGVyW01FVEFEQVRBXVtrZXldO1xuXG4gICAgLy8gbm9kZSBtb2R1bGUgbG9hZGluZ1xuICAgIGlmIChrZXkuc3Vic3RyKDAsIDYpID09PSAnQG5vZGUvJykge1xuICAgICAgaWYgKCFsb2FkZXIuX25vZGVSZXF1aXJlKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFcnJvciBsb2FkaW5nICcgKyBrZXkgKyAnLiBDYW4gb25seSBsb2FkIG5vZGUgY29yZSBtb2R1bGVzIGluIE5vZGUuJyk7XG4gICAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKFtdLCBmYWxzZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbG9hZE5vZGVNb2R1bGUuY2FsbChsb2FkZXIsIGtleS5zdWJzdHIoNiksIGxvYWRlci5iYXNlVVJMKTtcbiAgICAgIH0pO1xuICAgICAgcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChtZXRhZGF0YS5sb2FkLnNjcmlwdExvYWQgKSB7XG4gICAgICBpZiAobWV0YWRhdGEubG9hZC5wbHVnaW5LZXkgfHwgIXN1cHBvcnRzU2NyaXB0TG9hZCkge1xuICAgICAgICBtZXRhZGF0YS5sb2FkLnNjcmlwdExvYWQgPSBmYWxzZTtcbiAgICAgICAgd2Fybi5jYWxsKGNvbmZpZywgJ3NjcmlwdExvYWQgbm90IHN1cHBvcnRlZCBmb3IgXCInICsga2V5ICsgJ1wiJyk7XG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKG1ldGFkYXRhLmxvYWQuc2NyaXB0TG9hZCAhPT0gZmFsc2UgJiYgIW1ldGFkYXRhLmxvYWQucGx1Z2luS2V5ICYmIHN1cHBvcnRzU2NyaXB0TG9hZCkge1xuICAgICAgLy8gYXV0byBzY3JpcHQgbG9hZCBBTUQsIGdsb2JhbCB3aXRob3V0IGRlcHNcbiAgICAgIGlmICghbWV0YWRhdGEubG9hZC5kZXBzICYmICFtZXRhZGF0YS5sb2FkLmdsb2JhbHMgJiZcbiAgICAgICAgICAobWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdzeXN0ZW0nIHx8IG1ldGFkYXRhLmxvYWQuZm9ybWF0ID09PSAncmVnaXN0ZXInIHx8IG1ldGFkYXRhLmxvYWQuZm9ybWF0ID09PSAnZ2xvYmFsJyAmJiBtZXRhZGF0YS5sb2FkLmV4cG9ydHMpKVxuICAgICAgICBtZXRhZGF0YS5sb2FkLnNjcmlwdExvYWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIGZldGNoIC8gdHJhbnNsYXRlIC8gaW5zdGFudGlhdGUgcGlwZWxpbmVcbiAgICBpZiAoIW1ldGFkYXRhLmxvYWQuc2NyaXB0TG9hZClcbiAgICAgIHJldHVybiBpbml0aWFsaXplUGx1Z2luKGxvYWRlciwga2V5LCBtZXRhZGF0YSlcbiAgICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJ1bkZldGNoUGlwZWxpbmUobG9hZGVyLCBrZXksIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyLCBjb25maWcud2FzbSk7XG4gICAgICB9KVxuXG4gICAgLy8ganVzdCBzY3JpcHQgbG9hZGluZ1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBpZiAobWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdhbWQnICYmIGVudkdsb2JhbC5kZWZpbmUgIT09IGxvYWRlci5hbWREZWZpbmUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTG9hZGluZyBBTUQgd2l0aCBzY3JpcHRMb2FkIHJlcXVpcmVzIHNldHRpbmcgdGhlIGdsb2JhbCBgJyArIGdsb2JhbE5hbWUgKyAnLmRlZmluZSA9IFN5c3RlbUpTLmFtZERlZmluZWAnKTtcblxuICAgICAgc2NyaXB0TG9hZChrZXksIG1ldGFkYXRhLmxvYWQuY3Jvc3NPcmlnaW4sIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghcHJvY2Vzc0Fub25SZWdpc3RlcigpKSB7XG4gICAgICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSAnZ2xvYmFsJztcbiAgICAgICAgICB2YXIgZ2xvYmFsVmFsdWUgPSBtZXRhZGF0YS5sb2FkLmV4cG9ydHMgJiYgZ2V0R2xvYmFsVmFsdWUobWV0YWRhdGEubG9hZC5leHBvcnRzKTtcbiAgICAgICAgICBsb2FkZXIucmVnaXN0ZXJEeW5hbWljKFtdLCBmYWxzZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2V0TWV0YUVzTW9kdWxlKG1ldGFkYXRhLCBnbG9iYWxWYWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gZ2xvYmFsVmFsdWU7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSwgcmVqZWN0KTtcbiAgICB9KTtcbiAgfSlcbiAgLnRoZW4oZnVuY3Rpb24gKGluc3RhbnRpYXRlZCkge1xuICAgIGRlbGV0ZSBsb2FkZXJbTUVUQURBVEFdW2tleV07XG4gICAgcmV0dXJuIGluc3RhbnRpYXRlZDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQbHVnaW4gKGxvYWRlciwga2V5LCBtZXRhZGF0YSkge1xuICBpZiAoIW1ldGFkYXRhLnBsdWdpbktleSlcbiAgICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlO1xuXG4gIHJldHVybiBsb2FkZXIuaW1wb3J0KG1ldGFkYXRhLnBsdWdpbktleSkudGhlbihmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgbWV0YWRhdGEucGx1Z2luTW9kdWxlID0gcGx1Z2luO1xuICAgIG1ldGFkYXRhLnBsdWdpbkxvYWQgPSB7XG4gICAgICBuYW1lOiBrZXksXG4gICAgICBhZGRyZXNzOiBtZXRhZGF0YS5wbHVnaW5Bcmd1bWVudCxcbiAgICAgIHNvdXJjZTogdW5kZWZpbmVkLFxuICAgICAgbWV0YWRhdGE6IG1ldGFkYXRhLmxvYWRcbiAgICB9O1xuICAgIG1ldGFkYXRhLmxvYWQuZGVwcyA9IG1ldGFkYXRhLmxvYWQuZGVwcyB8fCBbXTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGxvYWRCdW5kbGVzQW5kRGVwQ2FjaGUgKGNvbmZpZywgbG9hZGVyLCBrZXkpIHtcbiAgLy8gbG9hZCBkaXJlY3QgZGVwcywgaW4gdHVybiB3aWxsIHBpY2sgdXAgdGhlaXIgdHJhY2UgdHJlZXNcbiAgdmFyIGRlcHMgPSBjb25maWcuZGVwQ2FjaGVba2V5XTtcbiAgaWYgKGRlcHMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRlcHMubGVuZ3RoOyBpKyspXG4gICAgICBsb2FkZXIubm9ybWFsaXplKGRlcHNbaV0sIGtleSkudGhlbihwcmVsb2FkU2NyaXB0KTtcbiAgfVxuICBlbHNlIHtcbiAgICB2YXIgbWF0Y2hlZCA9IGZhbHNlO1xuICAgIGZvciAodmFyIGIgaW4gY29uZmlnLmJ1bmRsZXMpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29uZmlnLmJ1bmRsZXNbYl0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGN1ck1vZHVsZSA9IGNvbmZpZy5idW5kbGVzW2JdW2ldO1xuXG4gICAgICAgIGlmIChjdXJNb2R1bGUgPT09IGtleSkge1xuICAgICAgICAgIG1hdGNoZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2lsZGNhcmQgaW4gYnVuZGxlcyBpbmNsdWRlcyAvIGJvdW5kYXJpZXNcbiAgICAgICAgaWYgKGN1ck1vZHVsZS5pbmRleE9mKCcqJykgIT09IC0xKSB7XG4gICAgICAgICAgdmFyIHBhcnRzID0gY3VyTW9kdWxlLnNwbGl0KCcqJyk7XG4gICAgICAgICAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgY29uZmlnLmJ1bmRsZXNbYl0uc3BsaWNlKGktLSwgMSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoa2V5LnN1YnN0cigwLCBwYXJ0c1swXS5sZW5ndGgpID09PSBwYXJ0c1swXSAmJlxuICAgICAgICAgICAgICBrZXkuc3Vic3RyKGtleS5sZW5ndGggLSBwYXJ0c1sxXS5sZW5ndGgsIHBhcnRzWzFdLmxlbmd0aCkgPT09IHBhcnRzWzFdKSB7XG4gICAgICAgICAgICBtYXRjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobWF0Y2hlZClcbiAgICAgICAgcmV0dXJuIGxvYWRlci5pbXBvcnQoYik7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHJ1bkZldGNoUGlwZWxpbmUgKGxvYWRlciwga2V5LCBtZXRhZGF0YSwgcHJvY2Vzc0Fub25SZWdpc3Rlciwgd2FzbSkge1xuICBpZiAobWV0YWRhdGEubG9hZC5leHBvcnRzICYmICFtZXRhZGF0YS5sb2FkLmZvcm1hdClcbiAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdnbG9iYWwnO1xuXG4gIHJldHVybiByZXNvbHZlZFByb21pc2VcblxuICAvLyBsb2NhdGVcbiAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIGlmICghbWV0YWRhdGEucGx1Z2luTW9kdWxlIHx8ICFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUubG9jYXRlKVxuICAgICAgcmV0dXJuO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtZXRhZGF0YS5wbHVnaW5Nb2R1bGUubG9jYXRlLmNhbGwobG9hZGVyLCBtZXRhZGF0YS5wbHVnaW5Mb2FkKSlcbiAgICAudGhlbihmdW5jdGlvbiAoYWRkcmVzcykge1xuICAgICAgaWYgKGFkZHJlc3MpXG4gICAgICAgIG1ldGFkYXRhLnBsdWdpbkxvYWQuYWRkcmVzcyA9IGFkZHJlc3M7XG4gICAgfSk7XG4gIH0pXG5cbiAgLy8gZmV0Y2hcbiAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIGlmICghbWV0YWRhdGEucGx1Z2luTW9kdWxlKVxuICAgICAgcmV0dXJuIGZldGNoJDEoa2V5LCBtZXRhZGF0YS5sb2FkLmF1dGhvcml6YXRpb24sIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCB3YXNtKTtcblxuICAgIHdhc20gPSBmYWxzZTtcblxuICAgIGlmICghbWV0YWRhdGEucGx1Z2luTW9kdWxlLmZldGNoKVxuICAgICAgcmV0dXJuIGZldGNoJDEobWV0YWRhdGEucGx1Z2luTG9hZC5hZGRyZXNzLCBtZXRhZGF0YS5sb2FkLmF1dGhvcml6YXRpb24sIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBmYWxzZSk7XG5cbiAgICByZXR1cm4gbWV0YWRhdGEucGx1Z2luTW9kdWxlLmZldGNoLmNhbGwobG9hZGVyLCBtZXRhZGF0YS5wbHVnaW5Mb2FkLCBmdW5jdGlvbiAobG9hZCkge1xuICAgICAgcmV0dXJuIGZldGNoJDEobG9hZC5hZGRyZXNzLCBtZXRhZGF0YS5sb2FkLmF1dGhvcml6YXRpb24sIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pXG5cbiAgLnRoZW4oZnVuY3Rpb24gKGZldGNoZWQpIHtcbiAgICAvLyBmZXRjaCBpcyBhbHJlYWR5IGEgdXRmLTggc3RyaW5nIGlmIG5vdCBkb2luZyB3YXNtIGRldGVjdGlvblxuICAgIGlmICghd2FzbSB8fCB0eXBlb2YgZmV0Y2hlZCA9PT0gJ3N0cmluZycpXG4gICAgICByZXR1cm4gdHJhbnNsYXRlQW5kSW5zdGFudGlhdGUobG9hZGVyLCBrZXksIGZldGNoZWQsIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyKTtcblxuICAgIHJldHVybiBjaGVja0luc3RhbnRpYXRlV2FzbShsb2FkZXIsIGZldGNoZWQsIHByb2Nlc3NBbm9uUmVnaXN0ZXIpXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhc21JbnN0YW50aWF0ZWQpIHtcbiAgICAgIGlmICh3YXNtSW5zdGFudGlhdGVkKVxuICAgICAgICByZXR1cm47XG5cbiAgICAgIC8vIG5vdCB3YXNtIC0+IGNvbnZlcnQgYnVmZmVyIGludG8gdXRmLTggc3RyaW5nIHRvIGV4ZWN1dGUgYXMgYSBtb2R1bGVcbiAgICAgIC8vIFRleHREZWNvZGVyIGNvbXBhdGliaWxpdHkgbWF0Y2hlcyBXQVNNIGN1cnJlbnRseS4gTmVlZCB0byBrZWVwIGNoZWNraW5nIHRoaXMuXG4gICAgICAvLyBUaGUgVGV4dERlY29kZXIgaW50ZXJmYWNlIGlzIGRvY3VtZW50ZWQgYXQgaHR0cDovL2VuY29kaW5nLnNwZWMud2hhdHdnLm9yZy8jaW50ZXJmYWNlLXRleHRkZWNvZGVyXG4gICAgICB2YXIgc3RyaW5nU291cmNlID0gaXNCcm93c2VyID8gbmV3IFRleHREZWNvZGVyKCd1dGYtOCcpLmRlY29kZShuZXcgVWludDhBcnJheShmZXRjaGVkKSkgOiBmZXRjaGVkLnRvU3RyaW5nKCk7XG4gICAgICByZXR1cm4gdHJhbnNsYXRlQW5kSW5zdGFudGlhdGUobG9hZGVyLCBrZXksIHN0cmluZ1NvdXJjZSwgbWV0YWRhdGEsIHByb2Nlc3NBbm9uUmVnaXN0ZXIpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlQW5kSW5zdGFudGlhdGUgKGxvYWRlciwga2V5LCBzb3VyY2UsIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoc291cmNlKVxuICAvLyB0cmFuc2xhdGVcbiAgLnRoZW4oZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgIGlmIChtZXRhZGF0YS5sb2FkLmZvcm1hdCA9PT0gJ2RldGVjdCcpXG4gICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9IHVuZGVmaW5lZDtcblxuICAgIHJlYWRNZXRhU3ludGF4KHNvdXJjZSwgbWV0YWRhdGEpO1xuXG4gICAgaWYgKCFtZXRhZGF0YS5wbHVnaW5Nb2R1bGUpXG4gICAgICByZXR1cm4gc291cmNlO1xuXG4gICAgbWV0YWRhdGEucGx1Z2luTG9hZC5zb3VyY2UgPSBzb3VyY2U7XG5cbiAgICBpZiAoIW1ldGFkYXRhLnBsdWdpbk1vZHVsZS50cmFuc2xhdGUpXG4gICAgICByZXR1cm4gc291cmNlO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtZXRhZGF0YS5wbHVnaW5Nb2R1bGUudHJhbnNsYXRlLmNhbGwobG9hZGVyLCBtZXRhZGF0YS5wbHVnaW5Mb2FkLCBtZXRhZGF0YS50cmFjZU9wdHMpKVxuICAgIC50aGVuKGZ1bmN0aW9uICh0cmFuc2xhdGVkKSB7XG4gICAgICBpZiAobWV0YWRhdGEubG9hZC5zb3VyY2VNYXApIHtcbiAgICAgICAgaWYgKHR5cGVvZiBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCAhPT0gJ29iamVjdCcpXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCBtdXN0IGJlIHNldCB0byBhbiBvYmplY3QuJyk7XG4gICAgICAgIHNhbml0aXplU291cmNlTWFwKG1ldGFkYXRhLnBsdWdpbkxvYWQuYWRkcmVzcywgbWV0YWRhdGEubG9hZC5zb3VyY2VNYXApO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHRyYW5zbGF0ZWQgPT09ICdzdHJpbmcnKVxuICAgICAgICByZXR1cm4gdHJhbnNsYXRlZDtcbiAgICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG1ldGFkYXRhLnBsdWdpbkxvYWQuc291cmNlO1xuICAgIH0pO1xuICB9KVxuICAudGhlbihmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgaWYgKCFtZXRhZGF0YS5sb2FkLmZvcm1hdCAmJiBzb3VyY2Uuc3Vic3RyaW5nKDAsIDgpID09PSAnXCJidW5kbGVcIicpIHtcbiAgICAgIG1ldGFkYXRhLmxvYWQuZm9ybWF0ID0gJ3N5c3RlbSc7XG4gICAgICByZXR1cm4gc291cmNlO1xuICAgIH1cblxuICAgIGlmIChtZXRhZGF0YS5sb2FkLmZvcm1hdCA9PT0gJ3JlZ2lzdGVyJyB8fCAhbWV0YWRhdGEubG9hZC5mb3JtYXQgJiYgZGV0ZWN0UmVnaXN0ZXJGb3JtYXQoc291cmNlKSkge1xuICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSAncmVnaXN0ZXInO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG5cbiAgICBpZiAobWV0YWRhdGEubG9hZC5mb3JtYXQgIT09ICdlc20nICYmIChtZXRhZGF0YS5sb2FkLmZvcm1hdCB8fCAhc291cmNlLm1hdGNoKGVzbVJlZ0V4KSkpIHtcbiAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfVxuXG4gICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSAnZXNtJztcbiAgICByZXR1cm4gdHJhbnNwaWxlKGxvYWRlciwgc291cmNlLCBrZXksIG1ldGFkYXRhLCBwcm9jZXNzQW5vblJlZ2lzdGVyKTtcbiAgfSlcblxuICAvLyBpbnN0YW50aWF0ZVxuICAudGhlbihmdW5jdGlvbiAodHJhbnNsYXRlZCkge1xuICAgIGlmICh0eXBlb2YgdHJhbnNsYXRlZCAhPT0gJ3N0cmluZycgfHwgIW1ldGFkYXRhLnBsdWdpbk1vZHVsZSB8fCAhbWV0YWRhdGEucGx1Z2luTW9kdWxlLmluc3RhbnRpYXRlKVxuICAgICAgcmV0dXJuIHRyYW5zbGF0ZWQ7XG5cbiAgICB2YXIgY2FsbGVkSW5zdGFudGlhdGUgPSBmYWxzZTtcbiAgICBtZXRhZGF0YS5wbHVnaW5Mb2FkLnNvdXJjZSA9IHRyYW5zbGF0ZWQ7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShtZXRhZGF0YS5wbHVnaW5Nb2R1bGUuaW5zdGFudGlhdGUuY2FsbChsb2FkZXIsIG1ldGFkYXRhLnBsdWdpbkxvYWQsIGZ1bmN0aW9uIChsb2FkKSB7XG4gICAgICB0cmFuc2xhdGVkID0gbG9hZC5zb3VyY2U7XG4gICAgICBtZXRhZGF0YS5sb2FkID0gbG9hZC5tZXRhZGF0YTtcbiAgICAgIGlmIChjYWxsZWRJbnN0YW50aWF0ZSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnN0YW50aWF0ZSBtdXN0IG9ubHkgYmUgY2FsbGVkIG9uY2UuJyk7XG4gICAgICBjYWxsZWRJbnN0YW50aWF0ZSA9IHRydWU7XG4gICAgfSkpXG4gICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgaWYgKGNhbGxlZEluc3RhbnRpYXRlKVxuICAgICAgICByZXR1cm4gdHJhbnNsYXRlZDtcbiAgICAgIHJldHVybiBwcm90ZWN0ZWRDcmVhdGVOYW1lc3BhY2UocmVzdWx0KTtcbiAgICB9KTtcbiAgfSlcbiAgLnRoZW4oZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgIC8vIHBsdWdpbiBpbnN0YW50aWF0ZSByZXN1bHQgY2FzZVxuICAgIGlmICh0eXBlb2Ygc291cmNlICE9PSAnc3RyaW5nJylcbiAgICAgIHJldHVybiBzb3VyY2U7XG5cbiAgICBpZiAoIW1ldGFkYXRhLmxvYWQuZm9ybWF0KVxuICAgICAgbWV0YWRhdGEubG9hZC5mb3JtYXQgPSBkZXRlY3RMZWdhY3lGb3JtYXQoc291cmNlKTtcblxuICAgIHZhciByZWdpc3RlcmVkID0gZmFsc2U7XG5cbiAgICBzd2l0Y2ggKG1ldGFkYXRhLmxvYWQuZm9ybWF0KSB7XG4gICAgICBjYXNlICdlc20nOlxuICAgICAgY2FzZSAncmVnaXN0ZXInOlxuICAgICAgY2FzZSAnc3lzdGVtJzpcbiAgICAgICAgdmFyIGVyciA9IGV2YWx1YXRlKGxvYWRlciwgc291cmNlLCBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCwga2V5LCBtZXRhZGF0YS5sb2FkLmludGVncml0eSwgbWV0YWRhdGEubG9hZC5ub25jZSwgZmFsc2UpO1xuICAgICAgICBpZiAoZXJyKVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgaWYgKCFwcm9jZXNzQW5vblJlZ2lzdGVyKCkpXG4gICAgICAgICAgcmV0dXJuIGVtcHR5TW9kdWxlO1xuICAgICAgICByZXR1cm47XG4gICAgICBicmVhaztcblxuICAgICAgY2FzZSAnanNvbic6XG4gICAgICAgIC8vIHdhcm4uY2FsbChjb25maWcsICdcImpzb25cIiBtb2R1bGUgZm9ybWF0IGlzIGRlcHJlY2F0ZWQuJyk7XG4gICAgICAgIHZhciBwYXJzZWQgPSBKU09OLnBhcnNlKHNvdXJjZSk7XG4gICAgICAgIHJldHVybiBsb2FkZXIubmV3TW9kdWxlKHsgZGVmYXVsdDogcGFyc2VkLCBfX3VzZURlZmF1bHQ6IHBhcnNlZCB9KTtcblxuICAgICAgY2FzZSAnYW1kJzpcbiAgICAgICAgdmFyIGN1ckRlZmluZSA9IGVudkdsb2JhbC5kZWZpbmU7XG4gICAgICAgIGVudkdsb2JhbC5kZWZpbmUgPSBsb2FkZXIuYW1kRGVmaW5lO1xuXG4gICAgICAgIGNsZWFyTGFzdERlZmluZShtZXRhZGF0YS5sb2FkLmRlcHMsIG1ldGFkYXRhLmxvYWQuZXNNb2R1bGUpO1xuXG4gICAgICAgIHZhciBlcnIgPSBldmFsdWF0ZShsb2FkZXIsIHNvdXJjZSwgbWV0YWRhdGEubG9hZC5zb3VyY2VNYXAsIGtleSwgbWV0YWRhdGEubG9hZC5pbnRlZ3JpdHksIG1ldGFkYXRhLmxvYWQubm9uY2UsIGZhbHNlKTtcblxuICAgICAgICAvLyBpZiBkaWRuJ3QgcmVnaXN0ZXIgYW5vbnltb3VzbHksIHVzZSB0aGUgbGFzdCBuYW1lZCBkZWZpbmUgaWYgb25seSBvbmVcbiAgICAgICAgcmVnaXN0ZXJlZCA9IHByb2Nlc3NBbm9uUmVnaXN0ZXIoKTtcbiAgICAgICAgaWYgKCFyZWdpc3RlcmVkKSB7XG4gICAgICAgICAgcmVnaXN0ZXJMYXN0RGVmaW5lKGxvYWRlcik7XG4gICAgICAgICAgcmVnaXN0ZXJlZCA9IHByb2Nlc3NBbm9uUmVnaXN0ZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVudkdsb2JhbC5kZWZpbmUgPSBjdXJEZWZpbmU7XG5cbiAgICAgICAgaWYgKGVycilcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICBicmVhaztcblxuICAgICAgY2FzZSAnY2pzJzpcbiAgICAgICAgdmFyIG1ldGFEZXBzID0gbWV0YWRhdGEubG9hZC5kZXBzO1xuICAgICAgICB2YXIgZGVwcyA9IChtZXRhZGF0YS5sb2FkLmRlcHMgfHwgW10pLmNvbmNhdChtZXRhZGF0YS5sb2FkLmNqc1JlcXVpcmVEZXRlY3Rpb24gPyBnZXRDSlNEZXBzKHNvdXJjZSkgOiBbXSk7XG5cbiAgICAgICAgZm9yICh2YXIgZyBpbiBtZXRhZGF0YS5sb2FkLmdsb2JhbHMpXG4gICAgICAgICAgaWYgKG1ldGFkYXRhLmxvYWQuZ2xvYmFsc1tnXSlcbiAgICAgICAgICAgIGRlcHMucHVzaChtZXRhZGF0YS5sb2FkLmdsb2JhbHNbZ10pO1xuXG4gICAgICAgIGxvYWRlci5yZWdpc3RlckR5bmFtaWMoZGVwcywgdHJ1ZSwgZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICAgIHJlcXVpcmUucmVzb2x2ZSA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiByZXF1aXJlUmVzb2x2ZS5jYWxsKGxvYWRlciwga2V5LCBtb2R1bGUuaWQpO1xuICAgICAgICAgIH07XG4gICAgICAgICAgLy8gc3VwcG9ydCBtb2R1bGUucGF0aHMgaXNoXG4gICAgICAgICAgbW9kdWxlLnBhdGhzID0gW107XG4gICAgICAgICAgbW9kdWxlLnJlcXVpcmUgPSByZXF1aXJlO1xuXG4gICAgICAgICAgLy8gZW5zdXJlIG1ldGEgZGVwcyBleGVjdXRlIGZpcnN0XG4gICAgICAgICAgaWYgKCFtZXRhZGF0YS5sb2FkLmNqc0RlZmVyRGVwc0V4ZWN1dGUgJiYgbWV0YURlcHMpXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1ldGFEZXBzLmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAgICByZXF1aXJlKG1ldGFEZXBzW2ldKTtcblxuICAgICAgICAgIHZhciBwYXRoVmFycyA9IGdldFBhdGhWYXJzKG1vZHVsZS5pZCk7XG4gICAgICAgICAgdmFyIF9fY2pzV3JhcHBlciA9IHtcbiAgICAgICAgICAgIGV4cG9ydHM6IGV4cG9ydHMsXG4gICAgICAgICAgICBhcmdzOiBbcmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlLCBwYXRoVmFycy5maWxlbmFtZSwgcGF0aFZhcnMuZGlybmFtZSwgZW52R2xvYmFsLCBlbnZHbG9iYWxdXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIHZhciBjanNXcmFwcGVyID0gXCIoZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSwgX19maWxlbmFtZSwgX19kaXJuYW1lLCBnbG9iYWwsIEdMT0JBTFwiO1xuXG4gICAgICAgICAgLy8gYWRkIG1ldGFkYXRhLmdsb2JhbHMgdG8gdGhlIHdyYXBwZXIgYXJndW1lbnRzXG4gICAgICAgICAgaWYgKG1ldGFkYXRhLmxvYWQuZ2xvYmFscylcbiAgICAgICAgICAgIGZvciAodmFyIGcgaW4gbWV0YWRhdGEubG9hZC5nbG9iYWxzKSB7XG4gICAgICAgICAgICAgIF9fY2pzV3JhcHBlci5hcmdzLnB1c2gocmVxdWlyZShtZXRhZGF0YS5sb2FkLmdsb2JhbHNbZ10pKTtcbiAgICAgICAgICAgICAgY2pzV3JhcHBlciArPSBcIiwgXCIgKyBnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gZGlzYWJsZSBBTUQgZGV0ZWN0aW9uXG4gICAgICAgICAgdmFyIGRlZmluZSA9IGVudkdsb2JhbC5kZWZpbmU7XG4gICAgICAgICAgZW52R2xvYmFsLmRlZmluZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBlbnZHbG9iYWwuX19janNXcmFwcGVyID0gX19janNXcmFwcGVyO1xuXG4gICAgICAgICAgc291cmNlID0gY2pzV3JhcHBlciArIFwiKSB7XCIgKyBzb3VyY2UucmVwbGFjZShoYXNoQmFuZ1JlZ0V4LCAnJykgKyBcIlxcbn0pLmFwcGx5KF9fY2pzV3JhcHBlci5leHBvcnRzLCBfX2Nqc1dyYXBwZXIuYXJncyk7XCI7XG5cbiAgICAgICAgICB2YXIgZXJyID0gZXZhbHVhdGUobG9hZGVyLCBzb3VyY2UsIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwLCBrZXksIG1ldGFkYXRhLmxvYWQuaW50ZWdyaXR5LCBtZXRhZGF0YS5sb2FkLm5vbmNlLCBmYWxzZSk7XG4gICAgICAgICAgaWYgKGVycilcbiAgICAgICAgICAgIHRocm93IGVycjtcblxuICAgICAgICAgIHNldE1ldGFFc01vZHVsZShtZXRhZGF0YSwgZXhwb3J0cyk7XG5cbiAgICAgICAgICBlbnZHbG9iYWwuX19janNXcmFwcGVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGVudkdsb2JhbC5kZWZpbmUgPSBkZWZpbmU7XG4gICAgICAgIH0pO1xuICAgICAgICByZWdpc3RlcmVkID0gcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2dsb2JhbCc6XG4gICAgICAgIHZhciBkZXBzID0gbWV0YWRhdGEubG9hZC5kZXBzIHx8IFtdO1xuICAgICAgICBmb3IgKHZhciBnIGluIG1ldGFkYXRhLmxvYWQuZ2xvYmFscykge1xuICAgICAgICAgIHZhciBnbCA9IG1ldGFkYXRhLmxvYWQuZ2xvYmFsc1tnXTtcbiAgICAgICAgICBpZiAoZ2wpXG4gICAgICAgICAgICBkZXBzLnB1c2goZ2wpO1xuICAgICAgICB9XG5cbiAgICAgICAgbG9hZGVyLnJlZ2lzdGVyRHluYW1pYyhkZXBzLCBmYWxzZSwgZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICAgIHZhciBnbG9iYWxzO1xuICAgICAgICAgIGlmIChtZXRhZGF0YS5sb2FkLmdsb2JhbHMpIHtcbiAgICAgICAgICAgIGdsb2JhbHMgPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIGcgaW4gbWV0YWRhdGEubG9hZC5nbG9iYWxzKVxuICAgICAgICAgICAgICBpZiAobWV0YWRhdGEubG9hZC5nbG9iYWxzW2ddKVxuICAgICAgICAgICAgICAgIGdsb2JhbHNbZ10gPSByZXF1aXJlKG1ldGFkYXRhLmxvYWQuZ2xvYmFsc1tnXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGV4cG9ydE5hbWUgPSBtZXRhZGF0YS5sb2FkLmV4cG9ydHM7XG5cbiAgICAgICAgICBpZiAoZXhwb3J0TmFtZSlcbiAgICAgICAgICAgIHNvdXJjZSArPSAnXFxuJyArIGdsb2JhbE5hbWUgKyAnW1wiJyArIGV4cG9ydE5hbWUgKyAnXCJdID0gJyArIGV4cG9ydE5hbWUgKyAnOyc7XG5cbiAgICAgICAgICB2YXIgcmV0cmlldmVHbG9iYWwgPSBwcmVwYXJlR2xvYmFsKG1vZHVsZS5pZCwgZXhwb3J0TmFtZSwgZ2xvYmFscywgbWV0YWRhdGEubG9hZC5lbmNhcHN1bGF0ZUdsb2JhbCk7XG4gICAgICAgICAgdmFyIGVyciA9IGV2YWx1YXRlKGxvYWRlciwgc291cmNlLCBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCwga2V5LCBtZXRhZGF0YS5sb2FkLmludGVncml0eSwgbWV0YWRhdGEubG9hZC5ub25jZSwgdHJ1ZSk7XG5cbiAgICAgICAgICBpZiAoZXJyKVxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuXG4gICAgICAgICAgdmFyIG91dHB1dCA9IHJldHJpZXZlR2xvYmFsKCk7XG4gICAgICAgICAgc2V0TWV0YUVzTW9kdWxlKG1ldGFkYXRhLCBvdXRwdXQpO1xuICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIH0pO1xuICAgICAgICByZWdpc3RlcmVkID0gcHJvY2Vzc0Fub25SZWdpc3RlcigpO1xuICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gbW9kdWxlIGZvcm1hdCBcIicgKyBtZXRhZGF0YS5sb2FkLmZvcm1hdCArICdcIiBmb3IgXCInICsga2V5ICsgJ1wiLicgKyAobWV0YWRhdGEubG9hZC5mb3JtYXQgPT09ICdlczYnID8gJyBVc2UgXCJlc21cIiBpbnN0ZWFkIGhlcmUuJyA6ICcnKSk7XG4gICAgfVxuXG4gICAgaWYgKCFyZWdpc3RlcmVkKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2R1bGUgJyArIGtleSArICcgZGV0ZWN0ZWQgYXMgJyArIG1ldGFkYXRhLmxvYWQuZm9ybWF0ICsgJyBidXQgZGlkblxcJ3QgZXhlY3V0ZSBjb3JyZWN0bHkuJyk7XG4gIH0pO1xufVxuXG52YXIgZ2xvYmFsTmFtZSA9IHR5cGVvZiBzZWxmICE9ICd1bmRlZmluZWQnID8gJ3NlbGYnIDogJ2dsb2JhbCc7XG5cbi8vIGdvb2QgZW5vdWdoIEVTNiBtb2R1bGUgZGV0ZWN0aW9uIHJlZ2V4IC0gZm9ybWF0IGRldGVjdGlvbnMgbm90IGRlc2lnbmVkIHRvIGJlIGFjY3VyYXRlLCBidXQgdG8gaGFuZGxlIHRoZSA5OSUgdXNlIGNhc2VcbnZhciBlc21SZWdFeCA9IC8oXlxccyp8W31cXCk7XFxuXVxccyopKGltcG9ydFxccyooWydcIl18KFxcKlxccythc1xccyspPyg/IXR5cGUpKFteXCInXFwoXFwpXFxuOyBdKylcXHMqZnJvbVxccypbJ1wiXXxcXHspfGV4cG9ydFxccytcXCpcXHMrZnJvbVxccytbXCInXXxleHBvcnRcXHMqKFxce3xkZWZhdWx0fGZ1bmN0aW9ufGNsYXNzfHZhcnxjb25zdHxsZXR8YXN5bmNcXHMrZnVuY3Rpb24pKS87XG5cbnZhciBsZWFkaW5nQ29tbWVudEFuZE1ldGFSZWdFeCA9IC9eKFxccypcXC9cXCpbXlxcKl0qKFxcKig/IVxcLylbXlxcKl0qKSpcXCpcXC98XFxzKlxcL1xcL1teXFxuXSp8XFxzKlwiW15cIl0rXCJcXHMqOz98XFxzKidbXiddKydcXHMqOz8pKlxccyovO1xuZnVuY3Rpb24gZGV0ZWN0UmVnaXN0ZXJGb3JtYXQoc291cmNlKSB7XG4gIHZhciBsZWFkaW5nQ29tbWVudEFuZE1ldGEgPSBzb3VyY2UubWF0Y2gobGVhZGluZ0NvbW1lbnRBbmRNZXRhUmVnRXgpO1xuICByZXR1cm4gbGVhZGluZ0NvbW1lbnRBbmRNZXRhICYmIHNvdXJjZS5zdWJzdHIobGVhZGluZ0NvbW1lbnRBbmRNZXRhWzBdLmxlbmd0aCwgMTUpID09PSAnU3lzdGVtLnJlZ2lzdGVyJztcbn1cblxuLy8gQU1EIE1vZHVsZSBGb3JtYXQgRGV0ZWN0aW9uIFJlZ0V4XG4vLyBkZWZpbmUoWy4uLCAuLiwgLi5dLCAuLi4pXG4vLyBkZWZpbmUodmFyTmFtZSk7IHx8IGRlZmluZShmdW5jdGlvbihyZXF1aXJlLCBleHBvcnRzKSB7fSk7IHx8IGRlZmluZSh7fSlcbnZhciBhbWRSZWdFeCA9IC8oPzpeXFx1RkVGRj98W14kX2EtekEtWlxceEEwLVxcdUZGRkYuXSlkZWZpbmVcXHMqXFwoXFxzKihcIlteXCJdK1wiXFxzKixcXHMqfCdbXiddKydcXHMqLFxccyopP1xccyooXFxbKFxccyooKFwiW15cIl0rXCJ8J1teJ10rJylcXHMqLHxcXC9cXC8uKlxccj9cXG58XFwvXFwqKC58XFxzKSo/XFwqXFwvKSkqKFxccyooXCJbXlwiXStcInwnW14nXSsnKVxccyosPyk/KFxccyooXFwvXFwvLipcXHI/XFxufFxcL1xcKigufFxccykqP1xcKlxcLykpKlxccypcXF18ZnVuY3Rpb25cXHMqfHt8W18kYS16QS1aXFx4QTAtXFx1RkZGRl1bXyRhLXpBLVowLTlcXHhBMC1cXHVGRkZGXSpcXCkpLztcblxuLy8vIHJlcXVpcmUoJy4uLicpIHx8IGV4cG9ydHNbJyddID0gLi4uIHx8IGV4cG9ydHMuYXNkID0gLi4uIHx8IG1vZHVsZS5leHBvcnRzID0gLi4uXG52YXIgY2pzRXhwb3J0c1JlZ0V4ID0gLyg/Ol5cXHVGRUZGP3xbXiRfYS16QS1aXFx4QTAtXFx1RkZGRi5dKShleHBvcnRzXFxzKihcXFtbJ1wiXXxcXC4pfG1vZHVsZShcXC5leHBvcnRzfFxcWydleHBvcnRzJ1xcXXxcXFtcImV4cG9ydHNcIlxcXSlcXHMqKFxcW1snXCJdfFs9LFxcLl0pKS87XG4vLyB1c2VkIHRvIHN1cHBvcnQgbGVhZGluZyAjIS91c3IvYmluL2VudiBpbiBzY3JpcHRzIGFzIHN1cHBvcnRlZCBpbiBOb2RlXG52YXIgaGFzaEJhbmdSZWdFeCA9IC9eXFwjXFwhLiovO1xuXG5mdW5jdGlvbiBkZXRlY3RMZWdhY3lGb3JtYXQgKHNvdXJjZSkge1xuICBpZiAoc291cmNlLm1hdGNoKGFtZFJlZ0V4KSlcbiAgICByZXR1cm4gJ2FtZCc7XG5cbiAgY2pzRXhwb3J0c1JlZ0V4Lmxhc3RJbmRleCA9IDA7XG4gIGNqc1JlcXVpcmVSZWdFeC5sYXN0SW5kZXggPSAwO1xuICBpZiAoY2pzUmVxdWlyZVJlZ0V4LmV4ZWMoc291cmNlKSB8fCBjanNFeHBvcnRzUmVnRXguZXhlYyhzb3VyY2UpKVxuICAgIHJldHVybiAnY2pzJztcblxuICAvLyBnbG9iYWwgaXMgdGhlIGZhbGxiYWNrIGZvcm1hdFxuICByZXR1cm4gJ2dsb2JhbCc7XG59XG5cbmZ1bmN0aW9uIHNhbml0aXplU291cmNlTWFwIChhZGRyZXNzLCBzb3VyY2VNYXApIHtcbiAgdmFyIG9yaWdpbmFsTmFtZSA9IGFkZHJlc3Muc3BsaXQoJyEnKVswXTtcblxuICAvLyBmb3JjZSBzZXQgdGhlIGZpbGVuYW1lIG9mIHRoZSBvcmlnaW5hbCBmaWxlXG4gIGlmICghc291cmNlTWFwLmZpbGUgfHwgc291cmNlTWFwLmZpbGUgPT0gYWRkcmVzcylcbiAgICBzb3VyY2VNYXAuZmlsZSA9IG9yaWdpbmFsTmFtZSArICchdHJhbnNwaWxlZCc7XG5cbiAgLy8gZm9yY2Ugc2V0IHRoZSBzb3VyY2VzIGxpc3QgaWYgb25seSBvbmUgc291cmNlXG4gIGlmICghc291cmNlTWFwLnNvdXJjZXMgfHwgc291cmNlTWFwLnNvdXJjZXMubGVuZ3RoIDw9IDEgJiYgKCFzb3VyY2VNYXAuc291cmNlc1swXSB8fCBzb3VyY2VNYXAuc291cmNlc1swXSA9PT0gYWRkcmVzcykpXG4gICAgc291cmNlTWFwLnNvdXJjZXMgPSBbb3JpZ2luYWxOYW1lXTtcbn1cblxuZnVuY3Rpb24gdHJhbnNwaWxlIChsb2FkZXIsIHNvdXJjZSwga2V5LCBtZXRhZGF0YSwgcHJvY2Vzc0Fub25SZWdpc3Rlcikge1xuICBpZiAoIWxvYWRlci50cmFuc3BpbGVyKVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuYWJsZSB0byBkeW5hbWljYWxseSB0cmFuc3BpbGUgRVMgbW9kdWxlXFxuICAgQSBsb2FkZXIgcGx1Z2luIG5lZWRzIHRvIGJlIGNvbmZpZ3VyZWQgdmlhIGBTeXN0ZW1KUy5jb25maWcoeyB0cmFuc3BpbGVyOiBcXCd0cmFuc3BpbGVyLW1vZHVsZVxcJyB9KWAuJyk7XG5cbiAgLy8gZGVwcyBzdXBwb3J0IGZvciBlcyB0cmFuc3BpbGVcbiAgaWYgKG1ldGFkYXRhLmxvYWQuZGVwcykge1xuICAgIHZhciBkZXBzUHJlZml4ID0gJyc7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXRhZGF0YS5sb2FkLmRlcHMubGVuZ3RoOyBpKyspXG4gICAgICBkZXBzUHJlZml4ICs9ICdpbXBvcnQgXCInICsgbWV0YWRhdGEubG9hZC5kZXBzW2ldICsgJ1wiOyAnO1xuICAgIHNvdXJjZSA9IGRlcHNQcmVmaXggKyBzb3VyY2U7XG4gIH1cblxuICAvLyBkbyB0cmFuc3BpbGF0aW9uXG4gIHJldHVybiBsb2FkZXIuaW1wb3J0LmNhbGwobG9hZGVyLCBsb2FkZXIudHJhbnNwaWxlcilcbiAgLnRoZW4oZnVuY3Rpb24gKHRyYW5zcGlsZXIpIHtcbiAgICB0cmFuc3BpbGVyID0gdHJhbnNwaWxlci5fX3VzZURlZmF1bHQgfHwgdHJhbnNwaWxlcjtcblxuICAgIC8vIHRyYW5zbGF0ZSBob29rcyBtZWFucyB0aGlzIGlzIGEgdHJhbnNwaWxlciBwbHVnaW4gaW5zdGVhZCBvZiBhIHJhdyBpbXBsZW1lbnRhdGlvblxuICAgIGlmICghdHJhbnNwaWxlci50cmFuc2xhdGUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IobG9hZGVyLnRyYW5zcGlsZXIgKyAnIGlzIG5vdCBhIHZhbGlkIHRyYW5zcGlsZXIgcGx1Z2luLicpO1xuXG4gICAgLy8gaWYgdHJhbnNwaWxlciBpcyB0aGUgc2FtZSBhcyB0aGUgcGx1Z2luIGxvYWRlciwgdGhlbiBkb24ndCBydW4gdHdpY2VcbiAgICBpZiAodHJhbnNwaWxlciA9PT0gbWV0YWRhdGEucGx1Z2luTW9kdWxlKVxuICAgICAgcmV0dXJuIHNvdXJjZTtcblxuICAgIC8vIGNvbnZlcnQgdGhlIHNvdXJjZSBtYXAgaW50byBhbiBvYmplY3QgZm9yIHRyYW5zcGlsYXRpb24gY2hhaW5pbmdcbiAgICBpZiAodHlwZW9mIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwID09PSAnc3RyaW5nJylcbiAgICAgIG1ldGFkYXRhLmxvYWQuc291cmNlTWFwID0gSlNPTi5wYXJzZShtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcCk7XG5cbiAgICBtZXRhZGF0YS5wbHVnaW5Mb2FkID0gbWV0YWRhdGEucGx1Z2luTG9hZCB8fCB7XG4gICAgICBuYW1lOiBrZXksXG4gICAgICBhZGRyZXNzOiBrZXksXG4gICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgIG1ldGFkYXRhOiBtZXRhZGF0YS5sb2FkXG4gICAgfTtcbiAgICBtZXRhZGF0YS5sb2FkLmRlcHMgPSBtZXRhZGF0YS5sb2FkLmRlcHMgfHwgW107XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRyYW5zcGlsZXIudHJhbnNsYXRlLmNhbGwobG9hZGVyLCBtZXRhZGF0YS5wbHVnaW5Mb2FkLCBtZXRhZGF0YS50cmFjZU9wdHMpKVxuICAgIC50aGVuKGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgIC8vIHNhbml0aXplIHNvdXJjZU1hcCBpZiBhbiBvYmplY3Qgbm90IGEgSlNPTiBzdHJpbmdcbiAgICAgIHZhciBzb3VyY2VNYXAgPSBtZXRhZGF0YS5sb2FkLnNvdXJjZU1hcDtcbiAgICAgIGlmIChzb3VyY2VNYXAgJiYgdHlwZW9mIHNvdXJjZU1hcCA9PT0gJ29iamVjdCcpXG4gICAgICAgIHNhbml0aXplU291cmNlTWFwKGtleSwgc291cmNlTWFwKTtcblxuICAgICAgaWYgKG1ldGFkYXRhLmxvYWQuZm9ybWF0ID09PSAnZXNtJyAmJiBkZXRlY3RSZWdpc3RlckZvcm1hdChzb3VyY2UpKVxuICAgICAgICBtZXRhZGF0YS5sb2FkLmZvcm1hdCA9ICdyZWdpc3Rlcic7XG5cbiAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfSk7XG4gIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICB0aHJvdyBMb2FkZXJFcnJvcl9fQ2hlY2tfZXJyb3JfbWVzc2FnZV9mb3JfbG9hZGVyX3N0YWNrKGVyciwgJ1VuYWJsZSB0byBsb2FkIHRyYW5zcGlsZXIgdG8gdHJhbnNwaWxlICcgKyBrZXkpO1xuICB9KTtcbn1cblxuLy8gZGV0ZWN0IGFueSBtZXRhIGhlYWRlciBzeW50YXhcbi8vIG9ubHkgc2V0IGlmIG5vdCBhbHJlYWR5IHNldFxudmFyIG1ldGFSZWdFeCA9IC9eKFxccypcXC9cXCpbXlxcKl0qKFxcKig/IVxcLylbXlxcKl0qKSpcXCpcXC98XFxzKlxcL1xcL1teXFxuXSp8XFxzKlwiW15cIl0rXCJcXHMqOz98XFxzKidbXiddKydcXHMqOz8pKy87XG52YXIgbWV0YVBhcnRSZWdFeCA9IC9cXC9cXCpbXlxcKl0qKFxcKig/IVxcLylbXlxcKl0qKSpcXCpcXC98XFwvXFwvW15cXG5dKnxcIlteXCJdK1wiXFxzKjs/fCdbXiddKydcXHMqOz8vZztcblxuZnVuY3Rpb24gc2V0TWV0YVByb3BlcnR5KHRhcmdldCwgcCwgdmFsdWUpIHtcbiAgdmFyIHBQYXJ0cyA9IHAuc3BsaXQoJy4nKTtcbiAgdmFyIGN1clBhcnQ7XG4gIHdoaWxlIChwUGFydHMubGVuZ3RoID4gMSkge1xuICAgIGN1clBhcnQgPSBwUGFydHMuc2hpZnQoKTtcbiAgICB0YXJnZXQgPSB0YXJnZXRbY3VyUGFydF0gPSB0YXJnZXRbY3VyUGFydF0gfHwge307XG4gIH1cbiAgY3VyUGFydCA9IHBQYXJ0cy5zaGlmdCgpO1xuICBpZiAodGFyZ2V0W2N1clBhcnRdID09PSB1bmRlZmluZWQpXG4gICAgdGFyZ2V0W2N1clBhcnRdID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIHJlYWRNZXRhU3ludGF4IChzb3VyY2UsIG1ldGFkYXRhKSB7XG4gIHZhciBtZXRhID0gc291cmNlLm1hdGNoKG1ldGFSZWdFeCk7XG4gIGlmICghbWV0YSlcbiAgICByZXR1cm47XG5cbiAgdmFyIG1ldGFQYXJ0cyA9IG1ldGFbMF0ubWF0Y2gobWV0YVBhcnRSZWdFeCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXRhUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY3VyUGFydCA9IG1ldGFQYXJ0c1tpXTtcbiAgICB2YXIgbGVuID0gY3VyUGFydC5sZW5ndGg7XG5cbiAgICB2YXIgZmlyc3RDaGFyID0gY3VyUGFydC5zdWJzdHIoMCwgMSk7XG4gICAgaWYgKGN1clBhcnQuc3Vic3RyKGxlbiAtIDEsIDEpID09ICc7JylcbiAgICAgIGxlbi0tO1xuXG4gICAgaWYgKGZpcnN0Q2hhciAhPSAnXCInICYmIGZpcnN0Q2hhciAhPSBcIidcIilcbiAgICAgIGNvbnRpbnVlO1xuXG4gICAgdmFyIG1ldGFTdHJpbmcgPSBjdXJQYXJ0LnN1YnN0cigxLCBjdXJQYXJ0Lmxlbmd0aCAtIDMpO1xuICAgIHZhciBtZXRhTmFtZSA9IG1ldGFTdHJpbmcuc3Vic3RyKDAsIG1ldGFTdHJpbmcuaW5kZXhPZignICcpKTtcblxuICAgIGlmIChtZXRhTmFtZSkge1xuICAgICAgdmFyIG1ldGFWYWx1ZSA9IG1ldGFTdHJpbmcuc3Vic3RyKG1ldGFOYW1lLmxlbmd0aCArIDEsIG1ldGFTdHJpbmcubGVuZ3RoIC0gbWV0YU5hbWUubGVuZ3RoIC0gMSk7XG5cbiAgICAgIGlmIChtZXRhTmFtZSA9PT0gJ2RlcHMnKVxuICAgICAgICBtZXRhTmFtZSA9ICdkZXBzW10nO1xuXG4gICAgICBpZiAobWV0YU5hbWUuc3Vic3RyKG1ldGFOYW1lLmxlbmd0aCAtIDIsIDIpID09PSAnW10nKSB7XG4gICAgICAgIG1ldGFOYW1lID0gbWV0YU5hbWUuc3Vic3RyKDAsIG1ldGFOYW1lLmxlbmd0aCAtIDIpO1xuICAgICAgICBtZXRhZGF0YS5sb2FkW21ldGFOYW1lXSA9IG1ldGFkYXRhLmxvYWRbbWV0YU5hbWVdIHx8IFtdO1xuICAgICAgICBtZXRhZGF0YS5sb2FkW21ldGFOYW1lXS5wdXNoKG1ldGFWYWx1ZSk7XG4gICAgICB9XG4gICAgICAvLyBcInVzZSBzdHJpY3RcIiBpcyBub3QgbWV0YVxuICAgICAgZWxzZSBpZiAobWV0YU5hbWUgIT09ICd1c2UnKSB7XG4gICAgICAgIHNldE1ldGFQcm9wZXJ0eShtZXRhZGF0YS5sb2FkLCBtZXRhTmFtZSwgbWV0YVZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBtZXRhZGF0YS5sb2FkW21ldGFTdHJpbmddID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cblxudmFyIHNjcmlwdFNyYztcblxuLy8gUHJvbWlzZSBkZXRlY3Rpb24gYW5kIGVycm9yIG1lc3NhZ2VcbmlmICh0eXBlb2YgUHJvbWlzZSA9PT0gJ3VuZGVmaW5lZCcpXG4gIHRocm93IG5ldyBFcnJvcignU3lzdGVtSlMgbmVlZHMgYSBQcm9taXNlIHBvbHlmaWxsLicpO1xuXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICB2YXIgc2NyaXB0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdzY3JpcHQnKTtcbiAgdmFyIGN1clNjcmlwdCA9IHNjcmlwdHNbc2NyaXB0cy5sZW5ndGggLSAxXTtcbiAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgJiYgKGN1clNjcmlwdC5kZWZlciB8fCBjdXJTY3JpcHQuYXN5bmMpKVxuICAgIGN1clNjcmlwdCA9IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQ7XG5cbiAgc2NyaXB0U3JjID0gY3VyU2NyaXB0ICYmIGN1clNjcmlwdC5zcmM7XG59XG4vLyB3b3JrZXJcbmVsc2UgaWYgKHR5cGVvZiBpbXBvcnRTY3JpcHRzICE9PSAndW5kZWZpbmVkJykge1xuICB0cnkge1xuICAgIHRocm93IG5ldyBFcnJvcignXycpO1xuICB9XG4gIGNhdGNoIChlKSB7XG4gICAgZS5zdGFjay5yZXBsYWNlKC8oPzphdHxAKS4qKGh0dHAuKyk6W1xcZF0rOltcXGRdKy8sIGZ1bmN0aW9uKG0sIHVybCkge1xuICAgICAgc2NyaXB0U3JjID0gdXJsO1xuICAgIH0pO1xuICB9XG59XG4vLyBub2RlXG5lbHNlIGlmICh0eXBlb2YgX19maWxlbmFtZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgc2NyaXB0U3JjID0gX19maWxlbmFtZTtcbn1cblxuZnVuY3Rpb24gU3lzdGVtSlNMb2FkZXIkMSAoKSB7XG4gIFJlZ2lzdGVyTG9hZGVyJDEuY2FsbCh0aGlzKTtcblxuICAvLyBOQiBkZXByZWNhdGVcbiAgdGhpcy5fbG9hZGVyID0ge307XG5cbiAgLy8gaW50ZXJuYWwgbWV0YWRhdGEgc3RvcmVcbiAgdGhpc1tNRVRBREFUQV0gPSB7fTtcblxuICAvLyBpbnRlcm5hbCBjb25maWd1cmF0aW9uXG4gIHRoaXNbQ09ORklHXSA9IHtcbiAgICBiYXNlVVJMOiBiYXNlVVJJLFxuICAgIHBhdGhzOiB7fSxcblxuICAgIHBhY2thZ2VDb25maWdQYXRoczogW10sXG4gICAgcGFja2FnZUNvbmZpZ0tleXM6IFtdLFxuICAgIG1hcDoge30sXG4gICAgcGFja2FnZXM6IHt9LFxuICAgIGRlcENhY2hlOiB7fSxcbiAgICBtZXRhOiB7fSxcbiAgICBidW5kbGVzOiB7fSxcblxuICAgIHByb2R1Y3Rpb246IGZhbHNlLFxuXG4gICAgdHJhbnNwaWxlcjogdW5kZWZpbmVkLFxuICAgIGxvYWRlZEJ1bmRsZXM6IHt9LFxuXG4gICAgLy8gZ2xvYmFsIGJlaGF2aW91ciBmbGFnc1xuICAgIHdhcm5pbmdzOiBmYWxzZSxcbiAgICBwbHVnaW5GaXJzdDogZmFsc2UsXG5cbiAgICAvLyBlbmFibGUgd2FzbSBsb2FkaW5nIGFuZCBkZXRlY3Rpb24gd2hlbiBzdXBwb3J0ZWRcbiAgICB3YXNtOiBmYWxzZVxuICB9O1xuXG4gIC8vIG1ha2UgdGhlIGxvY2F0aW9uIG9mIHRoZSBzeXN0ZW0uanMgc2NyaXB0IGFjY2Vzc2libGUgKGlmIGFueSlcbiAgdGhpcy5zY3JpcHRTcmMgPSBzY3JpcHRTcmM7XG5cbiAgdGhpcy5fbm9kZVJlcXVpcmUgPSBub2RlUmVxdWlyZTtcblxuICAvLyBzdXBwb3J0IHRoZSBlbXB0eSBtb2R1bGUsIGFzIGEgY29uY2VwdFxuICB0aGlzLnJlZ2lzdHJ5LnNldCgnQGVtcHR5JywgZW1wdHlNb2R1bGUpO1xuXG4gIHNldFByb2R1Y3Rpb24uY2FsbCh0aGlzLCBmYWxzZSwgZmFsc2UpO1xuXG4gIC8vIGFkZCBtb2R1bGUgZm9ybWF0IGhlbHBlcnNcbiAgZm9ybWF0SGVscGVycyh0aGlzKTtcbn1cblxudmFyIGVudk1vZHVsZTtcbmZ1bmN0aW9uIHNldFByb2R1Y3Rpb24gKGlzUHJvZHVjdGlvbiwgaXNCdWlsZGVyKSB7XG4gIHRoaXNbQ09ORklHXS5wcm9kdWN0aW9uID0gaXNQcm9kdWN0aW9uO1xuICB0aGlzLnJlZ2lzdHJ5LnNldCgnQHN5c3RlbS1lbnYnLCBlbnZNb2R1bGUgPSB0aGlzLm5ld01vZHVsZSh7XG4gICAgYnJvd3NlcjogaXNCcm93c2VyLFxuICAgIG5vZGU6ICEhdGhpcy5fbm9kZVJlcXVpcmUsXG4gICAgcHJvZHVjdGlvbjogIWlzQnVpbGRlciAmJiBpc1Byb2R1Y3Rpb24sXG4gICAgZGV2OiBpc0J1aWxkZXIgfHwgIWlzUHJvZHVjdGlvbixcbiAgICBidWlsZDogaXNCdWlsZGVyLFxuICAgICdkZWZhdWx0JzogdHJ1ZVxuICB9KSk7XG59XG5cblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShSZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZSk7XG5cblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU3lzdGVtSlNMb2FkZXIkMTtcblxuLy8gTkIgZGVwcmVjYXRlIG5vcm1hbGl6ZVxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGVbU3lzdGVtSlNMb2FkZXIkMS5yZXNvbHZlID0gUmVnaXN0ZXJMb2FkZXIkMS5yZXNvbHZlXSA9IFN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLm5vcm1hbGl6ZSA9IG5vcm1hbGl6ZTtcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uIChrZXksIHBhcmVudEtleSkge1xuICB3YXJuLmNhbGwodGhpc1tDT05GSUddLCAnU3lzdGVtLmxvYWQgaXMgZGVwcmVjYXRlZC4nKTtcbiAgcmV0dXJuIHRoaXMuaW1wb3J0KGtleSwgcGFyZW50S2V5KTtcbn07XG5cbi8vIE5CIGRlcHJlY2F0ZSBkZWNhbm9uaWNhbGl6ZSwgbm9ybWFsaXplU3luY1xuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuZGVjYW5vbmljYWxpemUgPSBTeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5ub3JtYWxpemVTeW5jID0gU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUucmVzb2x2ZVN5bmMgPSBub3JtYWxpemVTeW5jO1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZVtTeXN0ZW1KU0xvYWRlciQxLmluc3RhbnRpYXRlID0gUmVnaXN0ZXJMb2FkZXIkMS5pbnN0YW50aWF0ZV0gPSBpbnN0YW50aWF0ZSQxO1xuXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5jb25maWcgPSBzZXRDb25maWc7XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5nZXRDb25maWcgPSBnZXRDb25maWc7XG5cblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmdsb2JhbCA9IGVudkdsb2JhbDtcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuaW1wb3J0ID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUuaW1wb3J0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgLnRoZW4oZnVuY3Rpb24gKG0pIHtcbiAgICByZXR1cm4gJ19fdXNlRGVmYXVsdCcgaW4gbSA/IG0uX191c2VEZWZhdWx0IDogbTtcbiAgfSk7XG59O1xuXG52YXIgY29uZmlnTmFtZXMgPSBbJ2Jhc2VVUkwnLCAnbWFwJywgJ3BhdGhzJywgJ3BhY2thZ2VzJywgJ3BhY2thZ2VDb25maWdQYXRocycsICdkZXBDYWNoZScsICdtZXRhJywgJ2J1bmRsZXMnLCAndHJhbnNwaWxlcicsICd3YXJuaW5ncycsICdwbHVnaW5GaXJzdCcsICdwcm9kdWN0aW9uJywgJ3dhc20nXTtcblxudmFyIGhhc1Byb3h5ID0gdHlwZW9mIFByb3h5ICE9PSAndW5kZWZpbmVkJztcbmZvciAodmFyIGkgPSAwOyBpIDwgY29uZmlnTmFtZXMubGVuZ3RoOyBpKyspIChmdW5jdGlvbiAoY29uZmlnTmFtZSkge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUsIGNvbmZpZ05hbWUsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBjZmcgPSBnZXRDb25maWdJdGVtKHRoaXNbQ09ORklHXSwgY29uZmlnTmFtZSk7XG5cbiAgICAgIGlmIChoYXNQcm94eSAmJiB0eXBlb2YgY2ZnID09PSAnb2JqZWN0JylcbiAgICAgICAgY2ZnID0gbmV3IFByb3h5KGNmZywge1xuICAgICAgICAgIHNldDogZnVuY3Rpb24gKHRhcmdldCwgb3B0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzZXQgU3lzdGVtSlMuJyArIGNvbmZpZ05hbWUgKyAnW1wiJyArIG9wdGlvbiArICdcIl0gZGlyZWN0bHkuIFVzZSBTeXN0ZW1KUy5jb25maWcoeyAnICsgY29uZmlnTmFtZSArICc6IHsgXCInICsgb3B0aW9uICsgJ1wiOiAuLi4gfSB9KSByYXRoZXIuJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgLy9pZiAodHlwZW9mIGNmZyA9PT0gJ29iamVjdCcpXG4gICAgICAvLyAgd2Fybi5jYWxsKHRoaXNbQ09ORklHXSwgJ1JlZmVyZW5jaW5nIGBTeXN0ZW1KUy4nICsgY29uZmlnTmFtZSArICdgIGlzIGRlcHJlY2F0ZWQuIFVzZSB0aGUgY29uZmlnIGdldHRlciBgU3lzdGVtSlMuZ2V0Q29uZmlnKFxcJycgKyBjb25maWdOYW1lICsgJ1xcJylgJyk7XG4gICAgICByZXR1cm4gY2ZnO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZXR0aW5nIGBTeXN0ZW1KUy4nICsgY29uZmlnTmFtZSArICdgIGRpcmVjdGx5IGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQuIFVzZSBgU3lzdGVtSlMuY29uZmlnKHsgJyArIGNvbmZpZ05hbWUgKyAnOiAuLi4gfSlgLicpO1xuICAgIH1cbiAgfSk7XG59KShjb25maWdOYW1lc1tpXSk7XG5cbi8qXG4gKiBCYWNrd2FyZHMtY29tcGF0aWJsZSByZWdpc3RyeSBBUEksIHRvIGJlIGRlcHJlY2F0ZWRcbiAqL1xuZnVuY3Rpb24gcmVnaXN0cnlXYXJuKGxvYWRlciwgbWV0aG9kKSB7XG4gIHdhcm4uY2FsbChsb2FkZXJbQ09ORklHXSwgJ1N5c3RlbUpTLicgKyBtZXRob2QgKyAnIGlzIGRlcHJlY2F0ZWQgZm9yIFN5c3RlbUpTLnJlZ2lzdHJ5LicgKyBtZXRob2QpO1xufVxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICByZWdpc3RyeVdhcm4odGhpcywgJ2RlbGV0ZScpO1xuICByZXR1cm4gdGhpcy5yZWdpc3RyeS5kZWxldGUoa2V5KTtcbn07XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJlZ2lzdHJ5V2Fybih0aGlzLCAnZ2V0Jyk7XG4gIHJldHVybiB0aGlzLnJlZ2lzdHJ5LmdldChrZXkpO1xufTtcblN5c3RlbUpTTG9hZGVyJDEucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmVnaXN0cnlXYXJuKHRoaXMsICdoYXMnKTtcbiAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKGtleSk7XG59O1xuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKGtleSwgbW9kdWxlKSB7XG4gIHJlZ2lzdHJ5V2Fybih0aGlzLCAnc2V0Jyk7XG4gIHJldHVybiB0aGlzLnJlZ2lzdHJ5LnNldChrZXksIG1vZHVsZSk7XG59O1xuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUubmV3TW9kdWxlID0gZnVuY3Rpb24gKGJpbmRpbmdzKSB7XG4gIHJldHVybiBuZXcgTW9kdWxlTmFtZXNwYWNlKGJpbmRpbmdzKTtcbn07XG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5pc01vZHVsZSA9IGlzTW9kdWxlO1xuXG4vLyBlbnN1cmUgU3lzdGVtLnJlZ2lzdGVyIGFuZCBTeXN0ZW0ucmVnaXN0ZXJEeW5hbWljIGRlY2Fub25pY2FsaXplXG5TeXN0ZW1KU0xvYWRlciQxLnByb3RvdHlwZS5yZWdpc3RlciA9IGZ1bmN0aW9uIChrZXksIGRlcHMsIGRlY2xhcmUpIHtcbiAgaWYgKHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnKVxuICAgIGtleSA9IGRlY2Fub25pY2FsaXplLmNhbGwodGhpcywgdGhpc1tDT05GSUddLCBrZXkpO1xuICByZXR1cm4gUmVnaXN0ZXJMb2FkZXIkMS5wcm90b3R5cGUucmVnaXN0ZXIuY2FsbCh0aGlzLCBrZXksIGRlcHMsIGRlY2xhcmUpO1xufTtcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUucmVnaXN0ZXJEeW5hbWljID0gZnVuY3Rpb24gKGtleSwgZGVwcywgZXhlY3V0aW5nUmVxdWlyZSwgZXhlY3V0ZSkge1xuICBpZiAodHlwZW9mIGtleSA9PT0gJ3N0cmluZycpXG4gICAga2V5ID0gZGVjYW5vbmljYWxpemUuY2FsbCh0aGlzLCB0aGlzW0NPTkZJR10sIGtleSk7XG4gIHJldHVybiBSZWdpc3RlckxvYWRlciQxLnByb3RvdHlwZS5yZWdpc3RlckR5bmFtaWMuY2FsbCh0aGlzLCBrZXksIGRlcHMsIGV4ZWN1dGluZ1JlcXVpcmUsIGV4ZWN1dGUpO1xufTtcblxuU3lzdGVtSlNMb2FkZXIkMS5wcm90b3R5cGUudmVyc2lvbiA9IFwiMC4yMC4xOSBEZXZcIjtcblxudmFyIFN5c3RlbSA9IG5ldyBTeXN0ZW1KU0xvYWRlciQxKCk7XG5cbi8vIG9ubHkgc2V0IHRoZSBnbG9iYWwgU3lzdGVtIG9uIHRoZSBnbG9iYWwgaW4gYnJvd3NlcnNcbmlmIChpc0Jyb3dzZXIgfHwgaXNXb3JrZXIpXG4gIGVudkdsb2JhbC5TeXN0ZW1KUyA9IGVudkdsb2JhbC5TeXN0ZW0gPSBTeXN0ZW07XG5cbmlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cylcbiAgbW9kdWxlLmV4cG9ydHMgPSBTeXN0ZW07XG5cbn0oKSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zeXN0ZW0uc3JjLmpzLm1hcFxuIiwiKGZ1bmN0aW9uKHNlbGYpIHtcbiAgJ3VzZSBzdHJpY3QnO1xuXG4gIGlmIChzZWxmLmZldGNoKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB2YXIgc3VwcG9ydCA9IHtcbiAgICBzZWFyY2hQYXJhbXM6ICdVUkxTZWFyY2hQYXJhbXMnIGluIHNlbGYsXG4gICAgaXRlcmFibGU6ICdTeW1ib2wnIGluIHNlbGYgJiYgJ2l0ZXJhdG9yJyBpbiBTeW1ib2wsXG4gICAgYmxvYjogJ0ZpbGVSZWFkZXInIGluIHNlbGYgJiYgJ0Jsb2InIGluIHNlbGYgJiYgKGZ1bmN0aW9uKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbmV3IEJsb2IoKVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH0pKCksXG4gICAgZm9ybURhdGE6ICdGb3JtRGF0YScgaW4gc2VsZixcbiAgICBhcnJheUJ1ZmZlcjogJ0FycmF5QnVmZmVyJyBpbiBzZWxmXG4gIH1cblxuICBpZiAoc3VwcG9ydC5hcnJheUJ1ZmZlcikge1xuICAgIHZhciB2aWV3Q2xhc3NlcyA9IFtcbiAgICAgICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICAgICdbb2JqZWN0IEludDE2QXJyYXldJyxcbiAgICAgICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgICAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgICAnW29iamVjdCBVaW50MzJBcnJheV0nLFxuICAgICAgJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgICAnW29iamVjdCBGbG9hdDY0QXJyYXldJ1xuICAgIF1cblxuICAgIHZhciBpc0RhdGFWaWV3ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIERhdGFWaWV3LnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKG9iailcbiAgICB9XG5cbiAgICB2YXIgaXNBcnJheUJ1ZmZlclZpZXcgPSBBcnJheUJ1ZmZlci5pc1ZpZXcgfHwgZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIHZpZXdDbGFzc2VzLmluZGV4T2YoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikpID4gLTFcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBub3JtYWxpemVOYW1lKG5hbWUpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBuYW1lID0gU3RyaW5nKG5hbWUpXG4gICAgfVxuICAgIGlmICgvW15hLXowLTlcXC0jJCUmJyorLlxcXl9gfH5dL2kudGVzdChuYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCBjaGFyYWN0ZXIgaW4gaGVhZGVyIGZpZWxkIG5hbWUnKVxuICAgIH1cbiAgICByZXR1cm4gbmFtZS50b0xvd2VyQ2FzZSgpXG4gIH1cblxuICBmdW5jdGlvbiBub3JtYWxpemVWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICB2YWx1ZSA9IFN0cmluZyh2YWx1ZSlcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvLyBCdWlsZCBhIGRlc3RydWN0aXZlIGl0ZXJhdG9yIGZvciB0aGUgdmFsdWUgbGlzdFxuICBmdW5jdGlvbiBpdGVyYXRvckZvcihpdGVtcykge1xuICAgIHZhciBpdGVyYXRvciA9IHtcbiAgICAgIG5leHQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBpdGVtcy5zaGlmdCgpXG4gICAgICAgIHJldHVybiB7ZG9uZTogdmFsdWUgPT09IHVuZGVmaW5lZCwgdmFsdWU6IHZhbHVlfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdXBwb3J0Lml0ZXJhYmxlKSB7XG4gICAgICBpdGVyYXRvcltTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBpdGVyYXRvclxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpdGVyYXRvclxuICB9XG5cbiAgZnVuY3Rpb24gSGVhZGVycyhoZWFkZXJzKSB7XG4gICAgdGhpcy5tYXAgPSB7fVxuXG4gICAgaWYgKGhlYWRlcnMgaW5zdGFuY2VvZiBIZWFkZXJzKSB7XG4gICAgICBoZWFkZXJzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICAgICAgdGhpcy5hcHBlbmQobmFtZSwgdmFsdWUpXG4gICAgICB9LCB0aGlzKVxuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShoZWFkZXJzKSkge1xuICAgICAgaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uKGhlYWRlcikge1xuICAgICAgICB0aGlzLmFwcGVuZChoZWFkZXJbMF0sIGhlYWRlclsxXSlcbiAgICAgIH0sIHRoaXMpXG4gICAgfSBlbHNlIGlmIChoZWFkZXJzKSB7XG4gICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhoZWFkZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgdGhpcy5hcHBlbmQobmFtZSwgaGVhZGVyc1tuYW1lXSlcbiAgICAgIH0sIHRoaXMpXG4gICAgfVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICBuYW1lID0gbm9ybWFsaXplTmFtZShuYW1lKVxuICAgIHZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUpXG4gICAgdmFyIG9sZFZhbHVlID0gdGhpcy5tYXBbbmFtZV1cbiAgICB0aGlzLm1hcFtuYW1lXSA9IG9sZFZhbHVlID8gb2xkVmFsdWUrJywnK3ZhbHVlIDogdmFsdWVcbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlWydkZWxldGUnXSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBkZWxldGUgdGhpcy5tYXBbbm9ybWFsaXplTmFtZShuYW1lKV1cbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBuYW1lID0gbm9ybWFsaXplTmFtZShuYW1lKVxuICAgIHJldHVybiB0aGlzLmhhcyhuYW1lKSA/IHRoaXMubWFwW25hbWVdIDogbnVsbFxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHJldHVybiB0aGlzLm1hcC5oYXNPd25Qcm9wZXJ0eShub3JtYWxpemVOYW1lKG5hbWUpKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgZm9yICh2YXIgbmFtZSBpbiB0aGlzLm1hcCkge1xuICAgICAgaWYgKHRoaXMubWFwLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdGhpcy5tYXBbbmFtZV0sIG5hbWUsIHRoaXMpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7IGl0ZW1zLnB1c2gobmFtZSkgfSlcbiAgICByZXR1cm4gaXRlcmF0b3JGb3IoaXRlbXMpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS52YWx1ZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaXRlbXMgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkgeyBpdGVtcy5wdXNoKHZhbHVlKSB9KVxuICAgIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlLmVudHJpZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaXRlbXMgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkgeyBpdGVtcy5wdXNoKFtuYW1lLCB2YWx1ZV0pIH0pXG4gICAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxuICB9XG5cbiAgaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgICBIZWFkZXJzLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gSGVhZGVycy5wcm90b3R5cGUuZW50cmllc1xuICB9XG5cbiAgZnVuY3Rpb24gY29uc3VtZWQoYm9keSkge1xuICAgIGlmIChib2R5LmJvZHlVc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcignQWxyZWFkeSByZWFkJykpXG4gICAgfVxuICAgIGJvZHkuYm9keVVzZWQgPSB0cnVlXG4gIH1cblxuICBmdW5jdGlvbiBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXNvbHZlKHJlYWRlci5yZXN1bHQpXG4gICAgICB9XG4gICAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QocmVhZGVyLmVycm9yKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQmxvYkFzQXJyYXlCdWZmZXIoYmxvYikge1xuICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpXG4gICAgdmFyIHByb21pc2UgPSBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKVxuICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihibG9iKVxuICAgIHJldHVybiBwcm9taXNlXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQmxvYkFzVGV4dChibG9iKSB7XG4gICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgICB2YXIgcHJvbWlzZSA9IGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpXG4gICAgcmVhZGVyLnJlYWRBc1RleHQoYmxvYilcbiAgICByZXR1cm4gcHJvbWlzZVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZEFycmF5QnVmZmVyQXNUZXh0KGJ1Zikge1xuICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmKVxuICAgIHZhciBjaGFycyA9IG5ldyBBcnJheSh2aWV3Lmxlbmd0aClcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgY2hhcnNbaV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHZpZXdbaV0pXG4gICAgfVxuICAgIHJldHVybiBjaGFycy5qb2luKCcnKVxuICB9XG5cbiAgZnVuY3Rpb24gYnVmZmVyQ2xvbmUoYnVmKSB7XG4gICAgaWYgKGJ1Zi5zbGljZSkge1xuICAgICAgcmV0dXJuIGJ1Zi5zbGljZSgwKVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdmlldyA9IG5ldyBVaW50OEFycmF5KGJ1Zi5ieXRlTGVuZ3RoKVxuICAgICAgdmlldy5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmKSlcbiAgICAgIHJldHVybiB2aWV3LmJ1ZmZlclxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIEJvZHkoKSB7XG4gICAgdGhpcy5ib2R5VXNlZCA9IGZhbHNlXG5cbiAgICB0aGlzLl9pbml0Qm9keSA9IGZ1bmN0aW9uKGJvZHkpIHtcbiAgICAgIHRoaXMuX2JvZHlJbml0ID0gYm9keVxuICAgICAgaWYgKCFib2R5KSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gJydcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmJsb2IgJiYgQmxvYi5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5QmxvYiA9IGJvZHlcbiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5mb3JtRGF0YSAmJiBGb3JtRGF0YS5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5Rm9ybURhdGEgPSBib2R5XG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5VGV4dCA9IGJvZHkudG9TdHJpbmcoKVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIHN1cHBvcnQuYmxvYiAmJiBpc0RhdGFWaWV3KGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlciA9IGJ1ZmZlckNsb25lKGJvZHkuYnVmZmVyKVxuICAgICAgICAvLyBJRSAxMC0xMSBjYW4ndCBoYW5kbGUgYSBEYXRhVmlldyBib2R5LlxuICAgICAgICB0aGlzLl9ib2R5SW5pdCA9IG5ldyBCbG9iKFt0aGlzLl9ib2R5QXJyYXlCdWZmZXJdKVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIChBcnJheUJ1ZmZlci5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSB8fCBpc0FycmF5QnVmZmVyVmlldyhib2R5KSkpIHtcbiAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyID0gYnVmZmVyQ2xvbmUoYm9keSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgQm9keUluaXQgdHlwZScpXG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJykpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICd0ZXh0L3BsYWluO2NoYXJzZXQ9VVRGLTgnKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlCbG9iICYmIHRoaXMuX2JvZHlCbG9iLnR5cGUpIHtcbiAgICAgICAgICB0aGlzLmhlYWRlcnMuc2V0KCdjb250ZW50LXR5cGUnLCB0aGlzLl9ib2R5QmxvYi50eXBlKVxuICAgICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7Y2hhcnNldD1VVEYtOCcpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3VwcG9ydC5ibG9iKSB7XG4gICAgICB0aGlzLmJsb2IgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICAgICAgaWYgKHJlamVjdGVkKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdGVkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fYm9keUJsb2IpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlCbG9iKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEJsb2IoW3RoaXMuX2JvZHlBcnJheUJ1ZmZlcl0pKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgRm9ybURhdGEgYm9keSBhcyBibG9iJylcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBCbG9iKFt0aGlzLl9ib2R5VGV4dF0pKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXJyYXlCdWZmZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBjb25zdW1lZCh0aGlzKSB8fCBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUFycmF5QnVmZmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLmJsb2IoKS50aGVuKHJlYWRCbG9iQXNBcnJheUJ1ZmZlcilcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudGV4dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICAgIGlmIChyZWplY3RlZCkge1xuICAgICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2JvZHlCbG9iKSB7XG4gICAgICAgIHJldHVybiByZWFkQmxvYkFzVGV4dCh0aGlzLl9ib2R5QmxvYilcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVhZEFycmF5QnVmZmVyQXNUZXh0KHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCByZWFkIEZvcm1EYXRhIGJvZHkgYXMgdGV4dCcpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlUZXh0KVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdXBwb3J0LmZvcm1EYXRhKSB7XG4gICAgICB0aGlzLmZvcm1EYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRleHQoKS50aGVuKGRlY29kZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnRleHQoKS50aGVuKEpTT04ucGFyc2UpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8vIEhUVFAgbWV0aG9kcyB3aG9zZSBjYXBpdGFsaXphdGlvbiBzaG91bGQgYmUgbm9ybWFsaXplZFxuICB2YXIgbWV0aG9kcyA9IFsnREVMRVRFJywgJ0dFVCcsICdIRUFEJywgJ09QVElPTlMnLCAnUE9TVCcsICdQVVQnXVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZU1ldGhvZChtZXRob2QpIHtcbiAgICB2YXIgdXBjYXNlZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gICAgcmV0dXJuIChtZXRob2RzLmluZGV4T2YodXBjYXNlZCkgPiAtMSkgPyB1cGNhc2VkIDogbWV0aG9kXG4gIH1cblxuICBmdW5jdGlvbiBSZXF1ZXN0KGlucHV0LCBvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICB2YXIgYm9keSA9IG9wdGlvbnMuYm9keVxuXG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgUmVxdWVzdCkge1xuICAgICAgaWYgKGlucHV0LmJvZHlVc2VkKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FscmVhZHkgcmVhZCcpXG4gICAgICB9XG4gICAgICB0aGlzLnVybCA9IGlucHV0LnVybFxuICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGlucHV0LmNyZWRlbnRpYWxzXG4gICAgICBpZiAoIW9wdGlvbnMuaGVhZGVycykge1xuICAgICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhpbnB1dC5oZWFkZXJzKVxuICAgICAgfVxuICAgICAgdGhpcy5tZXRob2QgPSBpbnB1dC5tZXRob2RcbiAgICAgIHRoaXMubW9kZSA9IGlucHV0Lm1vZGVcbiAgICAgIGlmICghYm9keSAmJiBpbnB1dC5fYm9keUluaXQgIT0gbnVsbCkge1xuICAgICAgICBib2R5ID0gaW5wdXQuX2JvZHlJbml0XG4gICAgICAgIGlucHV0LmJvZHlVc2VkID0gdHJ1ZVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVybCA9IFN0cmluZyhpbnB1dClcbiAgICB9XG5cbiAgICB0aGlzLmNyZWRlbnRpYWxzID0gb3B0aW9ucy5jcmVkZW50aWFscyB8fCB0aGlzLmNyZWRlbnRpYWxzIHx8ICdvbWl0J1xuICAgIGlmIChvcHRpb25zLmhlYWRlcnMgfHwgIXRoaXMuaGVhZGVycykge1xuICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICAgIH1cbiAgICB0aGlzLm1ldGhvZCA9IG5vcm1hbGl6ZU1ldGhvZChvcHRpb25zLm1ldGhvZCB8fCB0aGlzLm1ldGhvZCB8fCAnR0VUJylcbiAgICB0aGlzLm1vZGUgPSBvcHRpb25zLm1vZGUgfHwgdGhpcy5tb2RlIHx8IG51bGxcbiAgICB0aGlzLnJlZmVycmVyID0gbnVsbFxuXG4gICAgaWYgKCh0aGlzLm1ldGhvZCA9PT0gJ0dFVCcgfHwgdGhpcy5tZXRob2QgPT09ICdIRUFEJykgJiYgYm9keSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQm9keSBub3QgYWxsb3dlZCBmb3IgR0VUIG9yIEhFQUQgcmVxdWVzdHMnKVxuICAgIH1cbiAgICB0aGlzLl9pbml0Qm9keShib2R5KVxuICB9XG5cbiAgUmVxdWVzdC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IFJlcXVlc3QodGhpcywgeyBib2R5OiB0aGlzLl9ib2R5SW5pdCB9KVxuICB9XG5cbiAgZnVuY3Rpb24gZGVjb2RlKGJvZHkpIHtcbiAgICB2YXIgZm9ybSA9IG5ldyBGb3JtRGF0YSgpXG4gICAgYm9keS50cmltKCkuc3BsaXQoJyYnKS5mb3JFYWNoKGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBpZiAoYnl0ZXMpIHtcbiAgICAgICAgdmFyIHNwbGl0ID0gYnl0ZXMuc3BsaXQoJz0nKVxuICAgICAgICB2YXIgbmFtZSA9IHNwbGl0LnNoaWZ0KCkucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgdmFyIHZhbHVlID0gc3BsaXQuam9pbignPScpLnJlcGxhY2UoL1xcKy9nLCAnICcpXG4gICAgICAgIGZvcm0uYXBwZW5kKGRlY29kZVVSSUNvbXBvbmVudChuYW1lKSwgZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSlcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiBmb3JtXG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUhlYWRlcnMocmF3SGVhZGVycykge1xuICAgIHZhciBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKVxuICAgIC8vIFJlcGxhY2UgaW5zdGFuY2VzIG9mIFxcclxcbiBhbmQgXFxuIGZvbGxvd2VkIGJ5IGF0IGxlYXN0IG9uZSBzcGFjZSBvciBob3Jpem9udGFsIHRhYiB3aXRoIGEgc3BhY2VcbiAgICAvLyBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzIzMCNzZWN0aW9uLTMuMlxuICAgIHZhciBwcmVQcm9jZXNzZWRIZWFkZXJzID0gcmF3SGVhZGVycy5yZXBsYWNlKC9cXHI/XFxuW1xcdCBdKy9nLCAnICcpXG4gICAgcHJlUHJvY2Vzc2VkSGVhZGVycy5zcGxpdCgvXFxyP1xcbi8pLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIHBhcnRzID0gbGluZS5zcGxpdCgnOicpXG4gICAgICB2YXIga2V5ID0gcGFydHMuc2hpZnQoKS50cmltKClcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gcGFydHMuam9pbignOicpLnRyaW0oKVxuICAgICAgICBoZWFkZXJzLmFwcGVuZChrZXksIHZhbHVlKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIGhlYWRlcnNcbiAgfVxuXG4gIEJvZHkuY2FsbChSZXF1ZXN0LnByb3RvdHlwZSlcblxuICBmdW5jdGlvbiBSZXNwb25zZShib2R5SW5pdCwgb3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgb3B0aW9ucyA9IHt9XG4gICAgfVxuXG4gICAgdGhpcy50eXBlID0gJ2RlZmF1bHQnXG4gICAgdGhpcy5zdGF0dXMgPSBvcHRpb25zLnN0YXR1cyA9PT0gdW5kZWZpbmVkID8gMjAwIDogb3B0aW9ucy5zdGF0dXNcbiAgICB0aGlzLm9rID0gdGhpcy5zdGF0dXMgPj0gMjAwICYmIHRoaXMuc3RhdHVzIDwgMzAwXG4gICAgdGhpcy5zdGF0dXNUZXh0ID0gJ3N0YXR1c1RleHQnIGluIG9wdGlvbnMgPyBvcHRpb25zLnN0YXR1c1RleHQgOiAnT0snXG4gICAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmwgfHwgJydcbiAgICB0aGlzLl9pbml0Qm9keShib2R5SW5pdClcbiAgfVxuXG4gIEJvZHkuY2FsbChSZXNwb25zZS5wcm90b3R5cGUpXG5cbiAgUmVzcG9uc2UucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZSh0aGlzLl9ib2R5SW5pdCwge1xuICAgICAgc3RhdHVzOiB0aGlzLnN0YXR1cyxcbiAgICAgIHN0YXR1c1RleHQ6IHRoaXMuc3RhdHVzVGV4dCxcbiAgICAgIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHRoaXMuaGVhZGVycyksXG4gICAgICB1cmw6IHRoaXMudXJsXG4gICAgfSlcbiAgfVxuXG4gIFJlc3BvbnNlLmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKG51bGwsIHtzdGF0dXM6IDAsIHN0YXR1c1RleHQ6ICcnfSlcbiAgICByZXNwb25zZS50eXBlID0gJ2Vycm9yJ1xuICAgIHJldHVybiByZXNwb25zZVxuICB9XG5cbiAgdmFyIHJlZGlyZWN0U3RhdHVzZXMgPSBbMzAxLCAzMDIsIDMwMywgMzA3LCAzMDhdXG5cbiAgUmVzcG9uc2UucmVkaXJlY3QgPSBmdW5jdGlvbih1cmwsIHN0YXR1cykge1xuICAgIGlmIChyZWRpcmVjdFN0YXR1c2VzLmluZGV4T2Yoc3RhdHVzKSA9PT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbnZhbGlkIHN0YXR1cyBjb2RlJylcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKG51bGwsIHtzdGF0dXM6IHN0YXR1cywgaGVhZGVyczoge2xvY2F0aW9uOiB1cmx9fSlcbiAgfVxuXG4gIHNlbGYuSGVhZGVycyA9IEhlYWRlcnNcbiAgc2VsZi5SZXF1ZXN0ID0gUmVxdWVzdFxuICBzZWxmLlJlc3BvbnNlID0gUmVzcG9uc2VcblxuICBzZWxmLmZldGNoID0gZnVuY3Rpb24oaW5wdXQsIGluaXQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGlucHV0LCBpbml0KVxuICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpXG5cbiAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgc3RhdHVzOiB4aHIuc3RhdHVzLFxuICAgICAgICAgIHN0YXR1c1RleHQ6IHhoci5zdGF0dXNUZXh0LFxuICAgICAgICAgIGhlYWRlcnM6IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkgfHwgJycpXG4gICAgICAgIH1cbiAgICAgICAgb3B0aW9ucy51cmwgPSAncmVzcG9uc2VVUkwnIGluIHhociA/IHhoci5yZXNwb25zZVVSTCA6IG9wdGlvbnMuaGVhZGVycy5nZXQoJ1gtUmVxdWVzdC1VUkwnKVxuICAgICAgICB2YXIgYm9keSA9ICdyZXNwb25zZScgaW4geGhyID8geGhyLnJlc3BvbnNlIDogeGhyLnJlc3BvbnNlVGV4dFxuICAgICAgICByZXNvbHZlKG5ldyBSZXNwb25zZShib2R5LCBvcHRpb25zKSlcbiAgICAgIH1cblxuICAgICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSlcbiAgICAgIH1cblxuICAgICAgeGhyLm9udGltZW91dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QobmV3IFR5cGVFcnJvcignTmV0d29yayByZXF1ZXN0IGZhaWxlZCcpKVxuICAgICAgfVxuXG4gICAgICB4aHIub3BlbihyZXF1ZXN0Lm1ldGhvZCwgcmVxdWVzdC51cmwsIHRydWUpXG5cbiAgICAgIGlmIChyZXF1ZXN0LmNyZWRlbnRpYWxzID09PSAnaW5jbHVkZScpIHtcbiAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWVcbiAgICAgIH0gZWxzZSBpZiAocmVxdWVzdC5jcmVkZW50aWFscyA9PT0gJ29taXQnKSB7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSBmYWxzZVxuICAgICAgfVxuXG4gICAgICBpZiAoJ3Jlc3BvbnNlVHlwZScgaW4geGhyICYmIHN1cHBvcnQuYmxvYikge1xuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2Jsb2InXG4gICAgICB9XG5cbiAgICAgIHJlcXVlc3QuaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIHZhbHVlKVxuICAgICAgfSlcblxuICAgICAgeGhyLnNlbmQodHlwZW9mIHJlcXVlc3QuX2JvZHlJbml0ID09PSAndW5kZWZpbmVkJyA/IG51bGwgOiByZXF1ZXN0Ll9ib2R5SW5pdClcbiAgICB9KVxuICB9XG4gIHNlbGYuZmV0Y2gucG9seWZpbGwgPSB0cnVlXG59KSh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgPyBzZWxmIDogdGhpcyk7XG4iLCIoZnVuY3Rpb24oKXsndXNlIHN0cmljdCc7dmFyIGs9dGhpcztcbmZ1bmN0aW9uIGFhKGEpe3ZhciBiPXR5cGVvZiBhO2lmKFwib2JqZWN0XCI9PWIpaWYoYSl7aWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVyblwiYXJyYXlcIjtpZihhIGluc3RhbmNlb2YgT2JqZWN0KXJldHVybiBiO3ZhciBjPU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKTtpZihcIltvYmplY3QgV2luZG93XVwiPT1jKXJldHVyblwib2JqZWN0XCI7aWYoXCJbb2JqZWN0IEFycmF5XVwiPT1jfHxcIm51bWJlclwiPT10eXBlb2YgYS5sZW5ndGgmJlwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLnNwbGljZSYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEucHJvcGVydHlJc0VudW1lcmFibGUmJiFhLnByb3BlcnR5SXNFbnVtZXJhYmxlKFwic3BsaWNlXCIpKXJldHVyblwiYXJyYXlcIjtpZihcIltvYmplY3QgRnVuY3Rpb25dXCI9PWN8fFwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLmNhbGwmJlwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLnByb3BlcnR5SXNFbnVtZXJhYmxlJiYhYS5wcm9wZXJ0eUlzRW51bWVyYWJsZShcImNhbGxcIikpcmV0dXJuXCJmdW5jdGlvblwifWVsc2UgcmV0dXJuXCJudWxsXCI7ZWxzZSBpZihcImZ1bmN0aW9uXCI9PVxuYiYmXCJ1bmRlZmluZWRcIj09dHlwZW9mIGEuY2FsbClyZXR1cm5cIm9iamVjdFwiO3JldHVybiBifWZ1bmN0aW9uIGwoYSl7cmV0dXJuXCJzdHJpbmdcIj09dHlwZW9mIGF9ZnVuY3Rpb24gYmEoYSxiLGMpe3JldHVybiBhLmNhbGwuYXBwbHkoYS5iaW5kLGFyZ3VtZW50cyl9ZnVuY3Rpb24gY2EoYSxiLGMpe2lmKCFhKXRocm93IEVycm9yKCk7aWYoMjxhcmd1bWVudHMubGVuZ3RoKXt2YXIgZD1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsMik7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIGM9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtBcnJheS5wcm90b3R5cGUudW5zaGlmdC5hcHBseShjLGQpO3JldHVybiBhLmFwcGx5KGIsYyl9fXJldHVybiBmdW5jdGlvbigpe3JldHVybiBhLmFwcGx5KGIsYXJndW1lbnRzKX19XG5mdW5jdGlvbiBkYShhLGIsYyl7ZGE9RnVuY3Rpb24ucHJvdG90eXBlLmJpbmQmJi0xIT1GdW5jdGlvbi5wcm90b3R5cGUuYmluZC50b1N0cmluZygpLmluZGV4T2YoXCJuYXRpdmUgY29kZVwiKT9iYTpjYTtyZXR1cm4gZGEuYXBwbHkobnVsbCxhcmd1bWVudHMpfWZ1bmN0aW9uIGVhKGEsYil7dmFyIGM9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDEpO3JldHVybiBmdW5jdGlvbigpe3ZhciBiPWMuc2xpY2UoKTtiLnB1c2guYXBwbHkoYixhcmd1bWVudHMpO3JldHVybiBhLmFwcGx5KHRoaXMsYil9fVxuZnVuY3Rpb24gbShhKXt2YXIgYj1uO2Z1bmN0aW9uIGMoKXt9Yy5wcm90b3R5cGU9Yi5wcm90b3R5cGU7YS5HPWIucHJvdG90eXBlO2EucHJvdG90eXBlPW5ldyBjO2EucHJvdG90eXBlLmNvbnN0cnVjdG9yPWE7YS5GPWZ1bmN0aW9uKGEsYyxmKXtmb3IodmFyIGc9QXJyYXkoYXJndW1lbnRzLmxlbmd0aC0yKSxoPTI7aDxhcmd1bWVudHMubGVuZ3RoO2grKylnW2gtMl09YXJndW1lbnRzW2hdO3JldHVybiBiLnByb3RvdHlwZVtjXS5hcHBseShhLGcpfX07LypcblxuIFRoZSBNSVQgTGljZW5zZVxuXG4gQ29weXJpZ2h0IChjKSAyMDA3IEN5Ym96dSBMYWJzLCBJbmMuXG4gQ29weXJpZ2h0IChjKSAyMDEyIEdvb2dsZSBJbmMuXG5cbiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbiBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HU1xuIElOIFRIRSBTT0ZUV0FSRS5cbiovXG52YXIgZmE9U3RyaW5nLnByb3RvdHlwZS50cmltP2Z1bmN0aW9uKGEpe3JldHVybiBhLnRyaW0oKX06ZnVuY3Rpb24oYSl7cmV0dXJuIGEucmVwbGFjZSgvXltcXHNcXHhhMF0rfFtcXHNcXHhhMF0rJC9nLFwiXCIpfTtmdW5jdGlvbiBxKGEsYil7cmV0dXJuLTEhPWEuaW5kZXhPZihiKX1mdW5jdGlvbiBnYShhLGIpe3JldHVybiBhPGI/LTE6YT5iPzE6MH07dmFyIGhhPUFycmF5LnByb3RvdHlwZS5pbmRleE9mP2Z1bmN0aW9uKGEsYixjKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChhLGIsYyl9OmZ1bmN0aW9uKGEsYixjKXtjPW51bGw9PWM/MDowPmM/TWF0aC5tYXgoMCxhLmxlbmd0aCtjKTpjO2lmKGwoYSkpcmV0dXJuIGwoYikmJjE9PWIubGVuZ3RoP2EuaW5kZXhPZihiLGMpOi0xO2Zvcig7YzxhLmxlbmd0aDtjKyspaWYoYyBpbiBhJiZhW2NdPT09YilyZXR1cm4gYztyZXR1cm4tMX0scj1BcnJheS5wcm90b3R5cGUuZm9yRWFjaD9mdW5jdGlvbihhLGIsYyl7QXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChhLGIsYyl9OmZ1bmN0aW9uKGEsYixjKXtmb3IodmFyIGQ9YS5sZW5ndGgsZT1sKGEpP2Euc3BsaXQoXCJcIik6YSxmPTA7ZjxkO2YrKylmIGluIGUmJmIuY2FsbChjLGVbZl0sZixhKX0saWE9QXJyYXkucHJvdG90eXBlLmZpbHRlcj9mdW5jdGlvbihhLGIsYyl7cmV0dXJuIEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChhLFxuYixjKX06ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD1hLmxlbmd0aCxlPVtdLGY9MCxnPWwoYSk/YS5zcGxpdChcIlwiKTphLGg9MDtoPGQ7aCsrKWlmKGggaW4gZyl7dmFyIHA9Z1toXTtiLmNhbGwoYyxwLGgsYSkmJihlW2YrK109cCl9cmV0dXJuIGV9LHQ9QXJyYXkucHJvdG90eXBlLnJlZHVjZT9mdW5jdGlvbihhLGIsYyxkKXtkJiYoYj1kYShiLGQpKTtyZXR1cm4gQXJyYXkucHJvdG90eXBlLnJlZHVjZS5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9YztyKGEsZnVuY3Rpb24oYyxnKXtlPWIuY2FsbChkLGUsYyxnLGEpfSk7cmV0dXJuIGV9LGphPUFycmF5LnByb3RvdHlwZS5zb21lP2Z1bmN0aW9uKGEsYixjKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNvbWUuY2FsbChhLGIsYyl9OmZ1bmN0aW9uKGEsYixjKXtmb3IodmFyIGQ9YS5sZW5ndGgsZT1sKGEpP2Euc3BsaXQoXCJcIik6YSxmPTA7ZjxkO2YrKylpZihmIGluIGUmJmIuY2FsbChjLGVbZl0sZixhKSlyZXR1cm4hMDtcbnJldHVybiExfTtmdW5jdGlvbiBrYShhLGIpe3ZhciBjO2E6e2M9YS5sZW5ndGg7Zm9yKHZhciBkPWwoYSk/YS5zcGxpdChcIlwiKTphLGU9MDtlPGM7ZSsrKWlmKGUgaW4gZCYmYi5jYWxsKHZvaWQgMCxkW2VdLGUsYSkpe2M9ZTticmVhayBhfWM9LTF9cmV0dXJuIDA+Yz9udWxsOmwoYSk/YS5jaGFyQXQoYyk6YVtjXX1mdW5jdGlvbiBsYShhKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShBcnJheS5wcm90b3R5cGUsYXJndW1lbnRzKX1mdW5jdGlvbiBtYShhLGIsYyl7cmV0dXJuIDI+PWFyZ3VtZW50cy5sZW5ndGg/QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYSxiKTpBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhLGIsYyl9O3ZhciB1O2E6e3ZhciBuYT1rLm5hdmlnYXRvcjtpZihuYSl7dmFyIG9hPW5hLnVzZXJBZ2VudDtpZihvYSl7dT1vYTticmVhayBhfX11PVwiXCJ9O3ZhciBwYT1xKHUsXCJPcGVyYVwiKXx8cSh1LFwiT1BSXCIpLHY9cSh1LFwiVHJpZGVudFwiKXx8cSh1LFwiTVNJRVwiKSxxYT1xKHUsXCJFZGdlXCIpLHJhPXEodSxcIkdlY2tvXCIpJiYhKHEodS50b0xvd2VyQ2FzZSgpLFwid2Via2l0XCIpJiYhcSh1LFwiRWRnZVwiKSkmJiEocSh1LFwiVHJpZGVudFwiKXx8cSh1LFwiTVNJRVwiKSkmJiFxKHUsXCJFZGdlXCIpLHNhPXEodS50b0xvd2VyQ2FzZSgpLFwid2Via2l0XCIpJiYhcSh1LFwiRWRnZVwiKTtmdW5jdGlvbiB0YSgpe3ZhciBhPWsuZG9jdW1lbnQ7cmV0dXJuIGE/YS5kb2N1bWVudE1vZGU6dm9pZCAwfXZhciB1YTtcbmE6e3ZhciB2YT1cIlwiLHdhPWZ1bmN0aW9uKCl7dmFyIGE9dTtpZihyYSlyZXR1cm4vcnZcXDooW15cXCk7XSspKFxcKXw7KS8uZXhlYyhhKTtpZihxYSlyZXR1cm4vRWRnZVxcLyhbXFxkXFwuXSspLy5leGVjKGEpO2lmKHYpcmV0dXJuL1xcYig/Ok1TSUV8cnYpWzogXShbXlxcKTtdKykoXFwpfDspLy5leGVjKGEpO2lmKHNhKXJldHVybi9XZWJLaXRcXC8oXFxTKykvLmV4ZWMoYSk7aWYocGEpcmV0dXJuLyg/OlZlcnNpb24pWyBcXC9dPyhcXFMrKS8uZXhlYyhhKX0oKTt3YSYmKHZhPXdhP3dhWzFdOlwiXCIpO2lmKHYpe3ZhciB4YT10YSgpO2lmKG51bGwhPXhhJiZ4YT5wYXJzZUZsb2F0KHZhKSl7dWE9U3RyaW5nKHhhKTticmVhayBhfX11YT12YX12YXIgeWE9e307XG5mdW5jdGlvbiB6YShhKXtpZigheWFbYV0pe2Zvcih2YXIgYj0wLGM9ZmEoU3RyaW5nKHVhKSkuc3BsaXQoXCIuXCIpLGQ9ZmEoU3RyaW5nKGEpKS5zcGxpdChcIi5cIiksZT1NYXRoLm1heChjLmxlbmd0aCxkLmxlbmd0aCksZj0wOzA9PWImJmY8ZTtmKyspe3ZhciBnPWNbZl18fFwiXCIsaD1kW2ZdfHxcIlwiLHA9LyhcXGQqKShcXEQqKS9nLHk9LyhcXGQqKShcXEQqKS9nO2Rve3ZhciBEPXAuZXhlYyhnKXx8W1wiXCIsXCJcIixcIlwiXSxYPXkuZXhlYyhoKXx8W1wiXCIsXCJcIixcIlwiXTtpZigwPT1EWzBdLmxlbmd0aCYmMD09WFswXS5sZW5ndGgpYnJlYWs7Yj1nYSgwPT1EWzFdLmxlbmd0aD8wOnBhcnNlSW50KERbMV0sMTApLDA9PVhbMV0ubGVuZ3RoPzA6cGFyc2VJbnQoWFsxXSwxMCkpfHxnYSgwPT1EWzJdLmxlbmd0aCwwPT1YWzJdLmxlbmd0aCl8fGdhKERbMl0sWFsyXSl9d2hpbGUoMD09Yil9eWFbYV09MDw9Yn19XG52YXIgQWE9ay5kb2N1bWVudCxCYT1BYSYmdj90YSgpfHwoXCJDU1MxQ29tcGF0XCI9PUFhLmNvbXBhdE1vZGU/cGFyc2VJbnQodWEsMTApOjUpOnZvaWQgMDt2YXIgdz12JiYhKDk8PU51bWJlcihCYSkpLENhPXYmJiEoODw9TnVtYmVyKEJhKSk7ZnVuY3Rpb24geChhLGIsYyxkKXt0aGlzLmE9YTt0aGlzLm5vZGVOYW1lPWM7dGhpcy5ub2RlVmFsdWU9ZDt0aGlzLm5vZGVUeXBlPTI7dGhpcy5wYXJlbnROb2RlPXRoaXMub3duZXJFbGVtZW50PWJ9ZnVuY3Rpb24gRGEoYSxiKXt2YXIgYz1DYSYmXCJocmVmXCI9PWIubm9kZU5hbWU/YS5nZXRBdHRyaWJ1dGUoYi5ub2RlTmFtZSwyKTpiLm5vZGVWYWx1ZTtyZXR1cm4gbmV3IHgoYixhLGIubm9kZU5hbWUsYyl9O2Z1bmN0aW9uIHooYSl7dmFyIGI9bnVsbCxjPWEubm9kZVR5cGU7MT09YyYmKGI9YS50ZXh0Q29udGVudCxiPXZvaWQgMD09Ynx8bnVsbD09Yj9hLmlubmVyVGV4dDpiLGI9dm9pZCAwPT1ifHxudWxsPT1iP1wiXCI6Yik7aWYoXCJzdHJpbmdcIiE9dHlwZW9mIGIpaWYodyYmXCJ0aXRsZVwiPT1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkmJjE9PWMpYj1hLnRleHQ7ZWxzZSBpZig5PT1jfHwxPT1jKXthPTk9PWM/YS5kb2N1bWVudEVsZW1lbnQ6YS5maXJzdENoaWxkO2Zvcih2YXIgYz0wLGQ9W10sYj1cIlwiO2E7KXtkbyAxIT1hLm5vZGVUeXBlJiYoYis9YS5ub2RlVmFsdWUpLHcmJlwidGl0bGVcIj09YS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpJiYoYis9YS50ZXh0KSxkW2MrK109YTt3aGlsZShhPWEuZmlyc3RDaGlsZCk7Zm9yKDtjJiYhKGE9ZFstLWNdLm5leHRTaWJsaW5nKTspO319ZWxzZSBiPWEubm9kZVZhbHVlO3JldHVyblwiXCIrYn1cbmZ1bmN0aW9uIEEoYSxiLGMpe2lmKG51bGw9PT1iKXJldHVybiEwO3RyeXtpZighYS5nZXRBdHRyaWJ1dGUpcmV0dXJuITF9Y2F0Y2goZCl7cmV0dXJuITF9Q2EmJlwiY2xhc3NcIj09YiYmKGI9XCJjbGFzc05hbWVcIik7cmV0dXJuIG51bGw9PWM/ISFhLmdldEF0dHJpYnV0ZShiKTphLmdldEF0dHJpYnV0ZShiLDIpPT1jfWZ1bmN0aW9uIEIoYSxiLGMsZCxlKXtyZXR1cm4odz9FYTpGYSkuY2FsbChudWxsLGEsYixsKGMpP2M6bnVsbCxsKGQpP2Q6bnVsbCxlfHxuZXcgQyl9XG5mdW5jdGlvbiBFYShhLGIsYyxkLGUpe2lmKGEgaW5zdGFuY2VvZiBFfHw4PT1hLmJ8fGMmJm51bGw9PT1hLmIpe3ZhciBmPWIuYWxsO2lmKCFmKXJldHVybiBlO2E9R2EoYSk7aWYoXCIqXCIhPWEmJihmPWIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoYSksIWYpKXJldHVybiBlO2lmKGMpe2Zvcih2YXIgZz1bXSxoPTA7Yj1mW2grK107KUEoYixjLGQpJiZnLnB1c2goYik7Zj1nfWZvcihoPTA7Yj1mW2grK107KVwiKlwiPT1hJiZcIiFcIj09Yi50YWdOYW1lfHxGKGUsYik7cmV0dXJuIGV9SGEoYSxiLGMsZCxlKTtyZXR1cm4gZX1cbmZ1bmN0aW9uIEZhKGEsYixjLGQsZSl7Yi5nZXRFbGVtZW50c0J5TmFtZSYmZCYmXCJuYW1lXCI9PWMmJiF2PyhiPWIuZ2V0RWxlbWVudHNCeU5hbWUoZCkscihiLGZ1bmN0aW9uKGIpe2EuYShiKSYmRihlLGIpfSkpOmIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSYmZCYmXCJjbGFzc1wiPT1jPyhiPWIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShkKSxyKGIsZnVuY3Rpb24oYil7Yi5jbGFzc05hbWU9PWQmJmEuYShiKSYmRihlLGIpfSkpOmEgaW5zdGFuY2VvZiBHP0hhKGEsYixjLGQsZSk6Yi5nZXRFbGVtZW50c0J5VGFnTmFtZSYmKGI9Yi5nZXRFbGVtZW50c0J5VGFnTmFtZShhLmYoKSkscihiLGZ1bmN0aW9uKGEpe0EoYSxjLGQpJiZGKGUsYSl9KSk7cmV0dXJuIGV9XG5mdW5jdGlvbiBJYShhLGIsYyxkLGUpe3ZhciBmO2lmKChhIGluc3RhbmNlb2YgRXx8OD09YS5ifHxjJiZudWxsPT09YS5iKSYmKGY9Yi5jaGlsZE5vZGVzKSl7dmFyIGc9R2EoYSk7aWYoXCIqXCIhPWcmJihmPWlhKGYsZnVuY3Rpb24oYSl7cmV0dXJuIGEudGFnTmFtZSYmYS50YWdOYW1lLnRvTG93ZXJDYXNlKCk9PWd9KSwhZikpcmV0dXJuIGU7YyYmKGY9aWEoZixmdW5jdGlvbihhKXtyZXR1cm4gQShhLGMsZCl9KSk7cihmLGZ1bmN0aW9uKGEpe1wiKlwiPT1nJiYoXCIhXCI9PWEudGFnTmFtZXx8XCIqXCI9PWcmJjEhPWEubm9kZVR5cGUpfHxGKGUsYSl9KTtyZXR1cm4gZX1yZXR1cm4gSmEoYSxiLGMsZCxlKX1mdW5jdGlvbiBKYShhLGIsYyxkLGUpe2ZvcihiPWIuZmlyc3RDaGlsZDtiO2I9Yi5uZXh0U2libGluZylBKGIsYyxkKSYmYS5hKGIpJiZGKGUsYik7cmV0dXJuIGV9XG5mdW5jdGlvbiBIYShhLGIsYyxkLGUpe2ZvcihiPWIuZmlyc3RDaGlsZDtiO2I9Yi5uZXh0U2libGluZylBKGIsYyxkKSYmYS5hKGIpJiZGKGUsYiksSGEoYSxiLGMsZCxlKX1mdW5jdGlvbiBHYShhKXtpZihhIGluc3RhbmNlb2YgRyl7aWYoOD09YS5iKXJldHVyblwiIVwiO2lmKG51bGw9PT1hLmIpcmV0dXJuXCIqXCJ9cmV0dXJuIGEuZigpfTshcmEmJiF2fHx2JiY5PD1OdW1iZXIoQmEpfHxyYSYmemEoXCIxLjkuMVwiKTt2JiZ6YShcIjlcIik7ZnVuY3Rpb24gS2EoYSxiKXtpZighYXx8IWIpcmV0dXJuITE7aWYoYS5jb250YWlucyYmMT09Yi5ub2RlVHlwZSlyZXR1cm4gYT09Ynx8YS5jb250YWlucyhiKTtpZihcInVuZGVmaW5lZFwiIT10eXBlb2YgYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbilyZXR1cm4gYT09Ynx8ISEoYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihiKSYxNik7Zm9yKDtiJiZhIT1iOyliPWIucGFyZW50Tm9kZTtyZXR1cm4gYj09YX1cbmZ1bmN0aW9uIExhKGEsYil7aWYoYT09YilyZXR1cm4gMDtpZihhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKXJldHVybiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGIpJjI/MTotMTtpZih2JiYhKDk8PU51bWJlcihCYSkpKXtpZig5PT1hLm5vZGVUeXBlKXJldHVybi0xO2lmKDk9PWIubm9kZVR5cGUpcmV0dXJuIDF9aWYoXCJzb3VyY2VJbmRleFwiaW4gYXx8YS5wYXJlbnROb2RlJiZcInNvdXJjZUluZGV4XCJpbiBhLnBhcmVudE5vZGUpe3ZhciBjPTE9PWEubm9kZVR5cGUsZD0xPT1iLm5vZGVUeXBlO2lmKGMmJmQpcmV0dXJuIGEuc291cmNlSW5kZXgtYi5zb3VyY2VJbmRleDt2YXIgZT1hLnBhcmVudE5vZGUsZj1iLnBhcmVudE5vZGU7cmV0dXJuIGU9PWY/TWEoYSxiKTohYyYmS2EoZSxiKT8tMSpOYShhLGIpOiFkJiZLYShmLGEpP05hKGIsYSk6KGM/YS5zb3VyY2VJbmRleDplLnNvdXJjZUluZGV4KS0oZD9iLnNvdXJjZUluZGV4OmYuc291cmNlSW5kZXgpfWQ9OT09YS5ub2RlVHlwZT9cbmE6YS5vd25lckRvY3VtZW50fHxhLmRvY3VtZW50O2M9ZC5jcmVhdGVSYW5nZSgpO2Muc2VsZWN0Tm9kZShhKTtjLmNvbGxhcHNlKCEwKTtkPWQuY3JlYXRlUmFuZ2UoKTtkLnNlbGVjdE5vZGUoYik7ZC5jb2xsYXBzZSghMCk7cmV0dXJuIGMuY29tcGFyZUJvdW5kYXJ5UG9pbnRzKGsuUmFuZ2UuU1RBUlRfVE9fRU5ELGQpfWZ1bmN0aW9uIE5hKGEsYil7dmFyIGM9YS5wYXJlbnROb2RlO2lmKGM9PWIpcmV0dXJuLTE7Zm9yKHZhciBkPWI7ZC5wYXJlbnROb2RlIT1jOylkPWQucGFyZW50Tm9kZTtyZXR1cm4gTWEoZCxhKX1mdW5jdGlvbiBNYShhLGIpe2Zvcih2YXIgYz1iO2M9Yy5wcmV2aW91c1NpYmxpbmc7KWlmKGM9PWEpcmV0dXJuLTE7cmV0dXJuIDF9O2Z1bmN0aW9uIEMoKXt0aGlzLmI9dGhpcy5hPW51bGw7dGhpcy5sPTB9ZnVuY3Rpb24gT2EoYSl7dGhpcy5ub2RlPWE7dGhpcy5hPXRoaXMuYj1udWxsfWZ1bmN0aW9uIFBhKGEsYil7aWYoIWEuYSlyZXR1cm4gYjtpZighYi5hKXJldHVybiBhO2Zvcih2YXIgYz1hLmEsZD1iLmEsZT1udWxsLGY9bnVsbCxnPTA7YyYmZDspe3ZhciBmPWMubm9kZSxoPWQubm9kZTtmPT1ofHxmIGluc3RhbmNlb2YgeCYmaCBpbnN0YW5jZW9mIHgmJmYuYT09aC5hPyhmPWMsYz1jLmEsZD1kLmEpOjA8TGEoYy5ub2RlLGQubm9kZSk/KGY9ZCxkPWQuYSk6KGY9YyxjPWMuYSk7KGYuYj1lKT9lLmE9ZjphLmE9ZjtlPWY7ZysrfWZvcihmPWN8fGQ7ZjspZi5iPWUsZT1lLmE9ZixnKyssZj1mLmE7YS5iPWU7YS5sPWc7cmV0dXJuIGF9ZnVuY3Rpb24gUWEoYSxiKXt2YXIgYz1uZXcgT2EoYik7Yy5hPWEuYTthLmI/YS5hLmI9YzphLmE9YS5iPWM7YS5hPWM7YS5sKyt9XG5mdW5jdGlvbiBGKGEsYil7dmFyIGM9bmV3IE9hKGIpO2MuYj1hLmI7YS5hP2EuYi5hPWM6YS5hPWEuYj1jO2EuYj1jO2EubCsrfWZ1bmN0aW9uIFJhKGEpe3JldHVybihhPWEuYSk/YS5ub2RlOm51bGx9ZnVuY3Rpb24gU2EoYSl7cmV0dXJuKGE9UmEoYSkpP3ooYSk6XCJcIn1mdW5jdGlvbiBIKGEsYil7cmV0dXJuIG5ldyBUYShhLCEhYil9ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmY9YTt0aGlzLmI9KHRoaXMuYz1iKT9hLmI6YS5hO3RoaXMuYT1udWxsfWZ1bmN0aW9uIEkoYSl7dmFyIGI9YS5iO2lmKG51bGw9PWIpcmV0dXJuIG51bGw7dmFyIGM9YS5hPWI7YS5iPWEuYz9iLmI6Yi5hO3JldHVybiBjLm5vZGV9O2Z1bmN0aW9uIG4oYSl7dGhpcy5pPWE7dGhpcy5iPXRoaXMuZz0hMTt0aGlzLmY9bnVsbH1mdW5jdGlvbiBKKGEpe3JldHVyblwiXFxuICBcIithLnRvU3RyaW5nKCkuc3BsaXQoXCJcXG5cIikuam9pbihcIlxcbiAgXCIpfWZ1bmN0aW9uIFVhKGEsYil7YS5nPWJ9ZnVuY3Rpb24gVmEoYSxiKXthLmI9Yn1mdW5jdGlvbiBLKGEsYil7dmFyIGM9YS5hKGIpO3JldHVybiBjIGluc3RhbmNlb2YgQz8rU2EoYyk6K2N9ZnVuY3Rpb24gTChhLGIpe3ZhciBjPWEuYShiKTtyZXR1cm4gYyBpbnN0YW5jZW9mIEM/U2EoYyk6XCJcIitjfWZ1bmN0aW9uIE0oYSxiKXt2YXIgYz1hLmEoYik7cmV0dXJuIGMgaW5zdGFuY2VvZiBDPyEhYy5sOiEhY307ZnVuY3Rpb24gTihhLGIsYyl7bi5jYWxsKHRoaXMsYS5pKTt0aGlzLmM9YTt0aGlzLmg9Yjt0aGlzLm89Yzt0aGlzLmc9Yi5nfHxjLmc7dGhpcy5iPWIuYnx8Yy5iO3RoaXMuYz09V2EmJihjLmJ8fGMuZ3x8ND09Yy5pfHwwPT1jLml8fCFiLmY/Yi5ifHxiLmd8fDQ9PWIuaXx8MD09Yi5pfHwhYy5mfHwodGhpcy5mPXtuYW1lOmMuZi5uYW1lLHM6Yn0pOnRoaXMuZj17bmFtZTpiLmYubmFtZSxzOmN9KX1tKE4pO1xuZnVuY3Rpb24gTyhhLGIsYyxkLGUpe2I9Yi5hKGQpO2M9Yy5hKGQpO3ZhciBmO2lmKGIgaW5zdGFuY2VvZiBDJiZjIGluc3RhbmNlb2YgQyl7Yj1IKGIpO2ZvcihkPUkoYik7ZDtkPUkoYikpZm9yKGU9SChjKSxmPUkoZSk7ZjtmPUkoZSkpaWYoYSh6KGQpLHooZikpKXJldHVybiEwO3JldHVybiExfWlmKGIgaW5zdGFuY2VvZiBDfHxjIGluc3RhbmNlb2YgQyl7YiBpbnN0YW5jZW9mIEM/KGU9YixkPWMpOihlPWMsZD1iKTtmPUgoZSk7Zm9yKHZhciBnPXR5cGVvZiBkLGg9SShmKTtoO2g9SShmKSl7c3dpdGNoKGcpe2Nhc2UgXCJudW1iZXJcIjpoPSt6KGgpO2JyZWFrO2Nhc2UgXCJib29sZWFuXCI6aD0hIXooaCk7YnJlYWs7Y2FzZSBcInN0cmluZ1wiOmg9eihoKTticmVhaztkZWZhdWx0OnRocm93IEVycm9yKFwiSWxsZWdhbCBwcmltaXRpdmUgdHlwZSBmb3IgY29tcGFyaXNvbi5cIik7fWlmKGU9PWImJmEoaCxkKXx8ZT09YyYmYShkLGgpKXJldHVybiEwfXJldHVybiExfXJldHVybiBlP1wiYm9vbGVhblwiPT1cbnR5cGVvZiBifHxcImJvb2xlYW5cIj09dHlwZW9mIGM/YSghIWIsISFjKTpcIm51bWJlclwiPT10eXBlb2YgYnx8XCJudW1iZXJcIj09dHlwZW9mIGM/YSgrYiwrYyk6YShiLGMpOmEoK2IsK2MpfU4ucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYy5tKHRoaXMuaCx0aGlzLm8sYSl9O04ucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7dmFyIGE9XCJCaW5hcnkgRXhwcmVzc2lvbjogXCIrdGhpcy5jLGE9YStKKHRoaXMuaCk7cmV0dXJuIGErPUoodGhpcy5vKX07ZnVuY3Rpb24gWGEoYSxiLGMsZCl7dGhpcy5hPWE7dGhpcy53PWI7dGhpcy5pPWM7dGhpcy5tPWR9WGEucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYX07dmFyIFlhPXt9O1xuZnVuY3Rpb24gUChhLGIsYyxkKXtpZihZYS5oYXNPd25Qcm9wZXJ0eShhKSl0aHJvdyBFcnJvcihcIkJpbmFyeSBvcGVyYXRvciBhbHJlYWR5IGNyZWF0ZWQ6IFwiK2EpO2E9bmV3IFhhKGEsYixjLGQpO3JldHVybiBZYVthLnRvU3RyaW5nKCldPWF9UChcImRpdlwiLDYsMSxmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEsoYSxjKS9LKGIsYyl9KTtQKFwibW9kXCIsNiwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpJUsoYixjKX0pO1AoXCIqXCIsNiwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpKksoYixjKX0pO1AoXCIrXCIsNSwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpK0soYixjKX0pO1AoXCItXCIsNSwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpLUsoYixjKX0pO1AoXCI8XCIsNCwyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTyhmdW5jdGlvbihhLGIpe3JldHVybiBhPGJ9LGEsYixjKX0pO1xuUChcIj5cIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE+Yn0sYSxiLGMpfSk7UChcIjw9XCIsNCwyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTyhmdW5jdGlvbihhLGIpe3JldHVybiBhPD1ifSxhLGIsYyl9KTtQKFwiPj1cIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE+PWJ9LGEsYixjKX0pO3ZhciBXYT1QKFwiPVwiLDMsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE8oZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn0sYSxiLGMsITApfSk7UChcIiE9XCIsMywyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTyhmdW5jdGlvbihhLGIpe3JldHVybiBhIT1ifSxhLGIsYywhMCl9KTtQKFwiYW5kXCIsMiwyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTShhLGMpJiZNKGIsYyl9KTtQKFwib3JcIiwxLDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBNKGEsYyl8fE0oYixjKX0pO2Z1bmN0aW9uIFEoYSxiLGMpe3RoaXMuYT1hO3RoaXMuYj1ifHwxO3RoaXMuZj1jfHwxfTtmdW5jdGlvbiBaYShhLGIpe2lmKGIuYS5sZW5ndGgmJjQhPWEuaSl0aHJvdyBFcnJvcihcIlByaW1hcnkgZXhwcmVzc2lvbiBtdXN0IGV2YWx1YXRlIHRvIG5vZGVzZXQgaWYgZmlsdGVyIGhhcyBwcmVkaWNhdGUocykuXCIpO24uY2FsbCh0aGlzLGEuaSk7dGhpcy5jPWE7dGhpcy5oPWI7dGhpcy5nPWEuZzt0aGlzLmI9YS5ifW0oWmEpO1phLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe2E9dGhpcy5jLmEoYSk7cmV0dXJuICRhKHRoaXMuaCxhKX07WmEucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7dmFyIGE7YT1cIkZpbHRlcjpcIitKKHRoaXMuYyk7cmV0dXJuIGErPUoodGhpcy5oKX07ZnVuY3Rpb24gYWIoYSxiKXtpZihiLmxlbmd0aDxhLkEpdGhyb3cgRXJyb3IoXCJGdW5jdGlvbiBcIithLmorXCIgZXhwZWN0cyBhdCBsZWFzdFwiK2EuQStcIiBhcmd1bWVudHMsIFwiK2IubGVuZ3RoK1wiIGdpdmVuXCIpO2lmKG51bGwhPT1hLnYmJmIubGVuZ3RoPmEudil0aHJvdyBFcnJvcihcIkZ1bmN0aW9uIFwiK2EuaitcIiBleHBlY3RzIGF0IG1vc3QgXCIrYS52K1wiIGFyZ3VtZW50cywgXCIrYi5sZW5ndGgrXCIgZ2l2ZW5cIik7YS5CJiZyKGIsZnVuY3Rpb24oYixkKXtpZig0IT1iLmkpdGhyb3cgRXJyb3IoXCJBcmd1bWVudCBcIitkK1wiIHRvIGZ1bmN0aW9uIFwiK2EuaitcIiBpcyBub3Qgb2YgdHlwZSBOb2Rlc2V0OiBcIitiKTt9KTtuLmNhbGwodGhpcyxhLmkpO3RoaXMuaD1hO3RoaXMuYz1iO1VhKHRoaXMsYS5nfHxqYShiLGZ1bmN0aW9uKGEpe3JldHVybiBhLmd9KSk7VmEodGhpcyxhLkQmJiFiLmxlbmd0aHx8YS5DJiYhIWIubGVuZ3RofHxqYShiLGZ1bmN0aW9uKGEpe3JldHVybiBhLmJ9KSl9bShhYik7XG5hYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5oLm0uYXBwbHkobnVsbCxsYShhLHRoaXMuYykpfTthYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYT1cIkZ1bmN0aW9uOiBcIit0aGlzLmg7aWYodGhpcy5jLmxlbmd0aCl2YXIgYj10KHRoaXMuYyxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiQXJndW1lbnRzOlwiKSxhPWErSihiKTtyZXR1cm4gYX07ZnVuY3Rpb24gYmIoYSxiLGMsZCxlLGYsZyxoLHApe3RoaXMuaj1hO3RoaXMuaT1iO3RoaXMuZz1jO3RoaXMuRD1kO3RoaXMuQz1lO3RoaXMubT1mO3RoaXMuQT1nO3RoaXMudj12b2lkIDAhPT1oP2g6Zzt0aGlzLkI9ISFwfWJiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmp9O3ZhciBjYj17fTtcbmZ1bmN0aW9uIFIoYSxiLGMsZCxlLGYsZyxoKXtpZihjYi5oYXNPd25Qcm9wZXJ0eShhKSl0aHJvdyBFcnJvcihcIkZ1bmN0aW9uIGFscmVhZHkgY3JlYXRlZDogXCIrYStcIi5cIik7Y2JbYV09bmV3IGJiKGEsYixjLGQsITEsZSxmLGcsaCl9UihcImJvb2xlYW5cIiwyLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIE0oYixhKX0sMSk7UihcImNlaWxpbmdcIiwxLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIE1hdGguY2VpbChLKGIsYSkpfSwxKTtSKFwiY29uY2F0XCIsMywhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiB0KG1hKGFyZ3VtZW50cywxKSxmdW5jdGlvbihiLGQpe3JldHVybiBiK0woZCxhKX0sXCJcIil9LDIsbnVsbCk7UihcImNvbnRhaW5zXCIsMiwhMSwhMSxmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHEoTChiLGEpLEwoYyxhKSl9LDIpO1IoXCJjb3VudFwiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYi5hKGEpLmx9LDEsMSwhMCk7XG5SKFwiZmFsc2VcIiwyLCExLCExLGZ1bmN0aW9uKCl7cmV0dXJuITF9LDApO1IoXCJmbG9vclwiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTWF0aC5mbG9vcihLKGIsYSkpfSwxKTtSKFwiaWRcIiw0LCExLCExLGZ1bmN0aW9uKGEsYil7ZnVuY3Rpb24gYyhhKXtpZih3KXt2YXIgYj1lLmFsbFthXTtpZihiKXtpZihiLm5vZGVUeXBlJiZhPT1iLmlkKXJldHVybiBiO2lmKGIubGVuZ3RoKXJldHVybiBrYShiLGZ1bmN0aW9uKGIpe3JldHVybiBhPT1iLmlkfSl9cmV0dXJuIG51bGx9cmV0dXJuIGUuZ2V0RWxlbWVudEJ5SWQoYSl9dmFyIGQ9YS5hLGU9OT09ZC5ub2RlVHlwZT9kOmQub3duZXJEb2N1bWVudCxkPUwoYixhKS5zcGxpdCgvXFxzKy8pLGY9W107cihkLGZ1bmN0aW9uKGEpe2E9YyhhKTshYXx8MDw9aGEoZixhKXx8Zi5wdXNoKGEpfSk7Zi5zb3J0KExhKTt2YXIgZz1uZXcgQztyKGYsZnVuY3Rpb24oYSl7RihnLGEpfSk7cmV0dXJuIGd9LDEpO1xuUihcImxhbmdcIiwyLCExLCExLGZ1bmN0aW9uKCl7cmV0dXJuITF9LDEpO1IoXCJsYXN0XCIsMSwhMCwhMSxmdW5jdGlvbihhKXtpZigxIT1hcmd1bWVudHMubGVuZ3RoKXRocm93IEVycm9yKFwiRnVuY3Rpb24gbGFzdCBleHBlY3RzICgpXCIpO3JldHVybiBhLmZ9LDApO1IoXCJsb2NhbC1uYW1lXCIsMywhMSwhMCxmdW5jdGlvbihhLGIpe3ZhciBjPWI/UmEoYi5hKGEpKTphLmE7cmV0dXJuIGM/Yy5sb2NhbE5hbWV8fGMubm9kZU5hbWUudG9Mb3dlckNhc2UoKTpcIlwifSwwLDEsITApO1IoXCJuYW1lXCIsMywhMSwhMCxmdW5jdGlvbihhLGIpe3ZhciBjPWI/UmEoYi5hKGEpKTphLmE7cmV0dXJuIGM/Yy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOlwiXCJ9LDAsMSwhMCk7UihcIm5hbWVzcGFjZS11cmlcIiwzLCEwLCExLGZ1bmN0aW9uKCl7cmV0dXJuXCJcIn0sMCwxLCEwKTtcblIoXCJub3JtYWxpemUtc3BhY2VcIiwzLCExLCEwLGZ1bmN0aW9uKGEsYil7cmV0dXJuKGI/TChiLGEpOnooYS5hKSkucmVwbGFjZSgvW1xcc1xceGEwXSsvZyxcIiBcIikucmVwbGFjZSgvXlxccyt8XFxzKyQvZyxcIlwiKX0sMCwxKTtSKFwibm90XCIsMiwhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiFNKGIsYSl9LDEpO1IoXCJudW1iZXJcIiwxLCExLCEwLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGI/SyhiLGEpOit6KGEuYSl9LDAsMSk7UihcInBvc2l0aW9uXCIsMSwhMCwhMSxmdW5jdGlvbihhKXtyZXR1cm4gYS5ifSwwKTtSKFwicm91bmRcIiwxLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIE1hdGgucm91bmQoSyhiLGEpKX0sMSk7UihcInN0YXJ0cy13aXRoXCIsMiwhMSwhMSxmdW5jdGlvbihhLGIsYyl7Yj1MKGIsYSk7YT1MKGMsYSk7cmV0dXJuIDA9PWIubGFzdEluZGV4T2YoYSwwKX0sMik7UihcInN0cmluZ1wiLDMsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj9MKGIsYSk6eihhLmEpfSwwLDEpO1xuUihcInN0cmluZy1sZW5ndGhcIiwxLCExLCEwLGZ1bmN0aW9uKGEsYil7cmV0dXJuKGI/TChiLGEpOnooYS5hKSkubGVuZ3RofSwwLDEpO1IoXCJzdWJzdHJpbmdcIiwzLCExLCExLGZ1bmN0aW9uKGEsYixjLGQpe2M9SyhjLGEpO2lmKGlzTmFOKGMpfHxJbmZpbml0eT09Y3x8LUluZmluaXR5PT1jKXJldHVyblwiXCI7ZD1kP0soZCxhKTpJbmZpbml0eTtpZihpc05hTihkKXx8LUluZmluaXR5PT09ZClyZXR1cm5cIlwiO2M9TWF0aC5yb3VuZChjKS0xO3ZhciBlPU1hdGgubWF4KGMsMCk7YT1MKGIsYSk7cmV0dXJuIEluZmluaXR5PT1kP2Euc3Vic3RyaW5nKGUpOmEuc3Vic3RyaW5nKGUsYytNYXRoLnJvdW5kKGQpKX0sMiwzKTtSKFwic3Vic3RyaW5nLWFmdGVyXCIsMywhMSwhMSxmdW5jdGlvbihhLGIsYyl7Yj1MKGIsYSk7YT1MKGMsYSk7Yz1iLmluZGV4T2YoYSk7cmV0dXJuLTE9PWM/XCJcIjpiLnN1YnN0cmluZyhjK2EubGVuZ3RoKX0sMik7XG5SKFwic3Vic3RyaW5nLWJlZm9yZVwiLDMsITEsITEsZnVuY3Rpb24oYSxiLGMpe2I9TChiLGEpO2E9TChjLGEpO2E9Yi5pbmRleE9mKGEpO3JldHVybi0xPT1hP1wiXCI6Yi5zdWJzdHJpbmcoMCxhKX0sMik7UihcInN1bVwiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9SChiLmEoYSkpLGQ9MCxlPUkoYyk7ZTtlPUkoYykpZCs9K3ooZSk7cmV0dXJuIGR9LDEsMSwhMCk7UihcInRyYW5zbGF0ZVwiLDMsITEsITEsZnVuY3Rpb24oYSxiLGMsZCl7Yj1MKGIsYSk7Yz1MKGMsYSk7dmFyIGU9TChkLGEpO2E9e307Zm9yKGQ9MDtkPGMubGVuZ3RoO2QrKyl7dmFyIGY9Yy5jaGFyQXQoZCk7ZiBpbiBhfHwoYVtmXT1lLmNoYXJBdChkKSl9Yz1cIlwiO2ZvcihkPTA7ZDxiLmxlbmd0aDtkKyspZj1iLmNoYXJBdChkKSxjKz1mIGluIGE/YVtmXTpmO3JldHVybiBjfSwzKTtSKFwidHJ1ZVwiLDIsITEsITEsZnVuY3Rpb24oKXtyZXR1cm4hMH0sMCk7ZnVuY3Rpb24gRyhhLGIpe3RoaXMuaD1hO3RoaXMuYz12b2lkIDAhPT1iP2I6bnVsbDt0aGlzLmI9bnVsbDtzd2l0Y2goYSl7Y2FzZSBcImNvbW1lbnRcIjp0aGlzLmI9ODticmVhaztjYXNlIFwidGV4dFwiOnRoaXMuYj0zO2JyZWFrO2Nhc2UgXCJwcm9jZXNzaW5nLWluc3RydWN0aW9uXCI6dGhpcy5iPTc7YnJlYWs7Y2FzZSBcIm5vZGVcIjpicmVhaztkZWZhdWx0OnRocm93IEVycm9yKFwiVW5leHBlY3RlZCBhcmd1bWVudFwiKTt9fWZ1bmN0aW9uIGRiKGEpe3JldHVyblwiY29tbWVudFwiPT1hfHxcInRleHRcIj09YXx8XCJwcm9jZXNzaW5nLWluc3RydWN0aW9uXCI9PWF8fFwibm9kZVwiPT1hfUcucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7cmV0dXJuIG51bGw9PT10aGlzLmJ8fHRoaXMuYj09YS5ub2RlVHlwZX07Ry5wcm90b3R5cGUuZj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmh9O1xuRy5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYT1cIktpbmQgVGVzdDogXCIrdGhpcy5oO251bGw9PT10aGlzLmN8fChhKz1KKHRoaXMuYykpO3JldHVybiBhfTtmdW5jdGlvbiBlYihhKXt0aGlzLmI9YTt0aGlzLmE9MH1mdW5jdGlvbiBmYihhKXthPWEubWF0Y2goZ2IpO2Zvcih2YXIgYj0wO2I8YS5sZW5ndGg7YisrKWhiLnRlc3QoYVtiXSkmJmEuc3BsaWNlKGIsMSk7cmV0dXJuIG5ldyBlYihhKX12YXIgZ2I9L1xcJD8oPzooPyFbMC05LVxcLl0pKD86XFwqfFtcXHctXFwuXSspOik/KD8hWzAtOS1cXC5dKSg/OlxcKnxbXFx3LVxcLl0rKXxcXC9cXC98XFwuXFwufDo6fFxcZCsoPzpcXC5cXGQqKT98XFwuXFxkK3xcIlteXCJdKlwifCdbXiddKid8WyE8Pl09fFxccyt8Li9nLGhiPS9eXFxzLztmdW5jdGlvbiBTKGEsYil7cmV0dXJuIGEuYlthLmErKGJ8fDApXX1mdW5jdGlvbiBUKGEpe3JldHVybiBhLmJbYS5hKytdfWZ1bmN0aW9uIGliKGEpe3JldHVybiBhLmIubGVuZ3RoPD1hLmF9O2Z1bmN0aW9uIGpiKGEpe24uY2FsbCh0aGlzLDMpO3RoaXMuYz1hLnN1YnN0cmluZygxLGEubGVuZ3RoLTEpfW0oamIpO2piLnByb3RvdHlwZS5hPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY307amIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJMaXRlcmFsOiBcIit0aGlzLmN9O2Z1bmN0aW9uIEUoYSxiKXt0aGlzLmo9YS50b0xvd2VyQ2FzZSgpO3ZhciBjO2M9XCIqXCI9PXRoaXMuaj9cIipcIjpcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjt0aGlzLmM9Yj9iLnRvTG93ZXJDYXNlKCk6Y31FLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPWEubm9kZVR5cGU7aWYoMSE9YiYmMiE9YilyZXR1cm4hMTtiPXZvaWQgMCE9PWEubG9jYWxOYW1lP2EubG9jYWxOYW1lOmEubm9kZU5hbWU7cmV0dXJuXCIqXCIhPXRoaXMuaiYmdGhpcy5qIT1iLnRvTG93ZXJDYXNlKCk/ITE6XCIqXCI9PXRoaXMuYz8hMDp0aGlzLmM9PShhLm5hbWVzcGFjZVVSST9hLm5hbWVzcGFjZVVSSS50b0xvd2VyQ2FzZSgpOlwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiKX07RS5wcm90b3R5cGUuZj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmp9O1xuRS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIk5hbWUgVGVzdDogXCIrKFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiPT10aGlzLmM/XCJcIjp0aGlzLmMrXCI6XCIpK3RoaXMuan07ZnVuY3Rpb24ga2IoYSxiKXtuLmNhbGwodGhpcyxhLmkpO3RoaXMuaD1hO3RoaXMuYz1iO3RoaXMuZz1hLmc7dGhpcy5iPWEuYjtpZigxPT10aGlzLmMubGVuZ3RoKXt2YXIgYz10aGlzLmNbMF07Yy51fHxjLmMhPWxifHwoYz1jLm8sXCIqXCIhPWMuZigpJiYodGhpcy5mPXtuYW1lOmMuZigpLHM6bnVsbH0pKX19bShrYik7ZnVuY3Rpb24gbWIoKXtuLmNhbGwodGhpcyw0KX1tKG1iKTttYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj1uZXcgQzthPWEuYTs5PT1hLm5vZGVUeXBlP0YoYixhKTpGKGIsYS5vd25lckRvY3VtZW50KTtyZXR1cm4gYn07bWIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJSb290IEhlbHBlciBFeHByZXNzaW9uXCJ9O2Z1bmN0aW9uIG5iKCl7bi5jYWxsKHRoaXMsNCl9bShuYik7bmIucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9bmV3IEM7RihiLGEuYSk7cmV0dXJuIGJ9O25iLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiQ29udGV4dCBIZWxwZXIgRXhwcmVzc2lvblwifTtcbmZ1bmN0aW9uIG9iKGEpe3JldHVyblwiL1wiPT1hfHxcIi8vXCI9PWF9a2IucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5oLmEoYSk7aWYoIShiIGluc3RhbmNlb2YgQykpdGhyb3cgRXJyb3IoXCJGaWx0ZXIgZXhwcmVzc2lvbiBtdXN0IGV2YWx1YXRlIHRvIG5vZGVzZXQuXCIpO2E9dGhpcy5jO2Zvcih2YXIgYz0wLGQ9YS5sZW5ndGg7YzxkJiZiLmw7YysrKXt2YXIgZT1hW2NdLGY9SChiLGUuYy5hKSxnO2lmKGUuZ3x8ZS5jIT1wYilpZihlLmd8fGUuYyE9cWIpZm9yKGc9SShmKSxiPWUuYShuZXcgUShnKSk7bnVsbCE9KGc9SShmKSk7KWc9ZS5hKG5ldyBRKGcpKSxiPVBhKGIsZyk7ZWxzZSBnPUkoZiksYj1lLmEobmV3IFEoZykpO2Vsc2V7Zm9yKGc9SShmKTsoYj1JKGYpKSYmKCFnLmNvbnRhaW5zfHxnLmNvbnRhaW5zKGIpKSYmYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihnKSY4O2c9Yik7Yj1lLmEobmV3IFEoZykpfX1yZXR1cm4gYn07XG5rYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYTthPVwiUGF0aCBFeHByZXNzaW9uOlwiK0oodGhpcy5oKTtpZih0aGlzLmMubGVuZ3RoKXt2YXIgYj10KHRoaXMuYyxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiU3RlcHM6XCIpO2ErPUooYil9cmV0dXJuIGF9O2Z1bmN0aW9uIHJiKGEpe24uY2FsbCh0aGlzLDQpO3RoaXMuYz1hO1VhKHRoaXMsamEodGhpcy5jLGZ1bmN0aW9uKGEpe3JldHVybiBhLmd9KSk7VmEodGhpcyxqYSh0aGlzLmMsZnVuY3Rpb24oYSl7cmV0dXJuIGEuYn0pKX1tKHJiKTtyYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj1uZXcgQztyKHRoaXMuYyxmdW5jdGlvbihjKXtjPWMuYShhKTtpZighKGMgaW5zdGFuY2VvZiBDKSl0aHJvdyBFcnJvcihcIlBhdGggZXhwcmVzc2lvbiBtdXN0IGV2YWx1YXRlIHRvIE5vZGVTZXQuXCIpO2I9UGEoYixjKX0pO3JldHVybiBifTtyYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdCh0aGlzLmMsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStKKGIpfSxcIlVuaW9uIEV4cHJlc3Npb246XCIpfTtmdW5jdGlvbiBzYihhLGIpe3RoaXMuYT1hO3RoaXMuYj0hIWJ9XG5mdW5jdGlvbiAkYShhLGIsYyl7Zm9yKGM9Y3x8MDtjPGEuYS5sZW5ndGg7YysrKWZvcih2YXIgZD1hLmFbY10sZT1IKGIpLGY9Yi5sLGcsaD0wO2c9SShlKTtoKyspe3ZhciBwPWEuYj9mLWg6aCsxO2c9ZC5hKG5ldyBRKGcscCxmKSk7aWYoXCJudW1iZXJcIj09dHlwZW9mIGcpcD1wPT1nO2Vsc2UgaWYoXCJzdHJpbmdcIj09dHlwZW9mIGd8fFwiYm9vbGVhblwiPT10eXBlb2YgZylwPSEhZztlbHNlIGlmKGcgaW5zdGFuY2VvZiBDKXA9MDxnLmw7ZWxzZSB0aHJvdyBFcnJvcihcIlByZWRpY2F0ZS5ldmFsdWF0ZSByZXR1cm5lZCBhbiB1bmV4cGVjdGVkIHR5cGUuXCIpO2lmKCFwKXtwPWU7Zz1wLmY7dmFyIHk9cC5hO2lmKCF5KXRocm93IEVycm9yKFwiTmV4dCBtdXN0IGJlIGNhbGxlZCBhdCBsZWFzdCBvbmNlIGJlZm9yZSByZW1vdmUuXCIpO3ZhciBEPXkuYix5PXkuYTtEP0QuYT15OmcuYT15O3k/eS5iPUQ6Zy5iPUQ7Zy5sLS07cC5hPW51bGx9fXJldHVybiBifVxuc2IucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHQodGhpcy5hLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGErSihiKX0sXCJQcmVkaWNhdGVzOlwiKX07ZnVuY3Rpb24gVShhLGIsYyxkKXtuLmNhbGwodGhpcyw0KTt0aGlzLmM9YTt0aGlzLm89Yjt0aGlzLmg9Y3x8bmV3IHNiKFtdKTt0aGlzLnU9ISFkO2I9dGhpcy5oO2I9MDxiLmEubGVuZ3RoP2IuYVswXS5mOm51bGw7YS5iJiZiJiYoYT1iLm5hbWUsYT13P2EudG9Mb3dlckNhc2UoKTphLHRoaXMuZj17bmFtZTphLHM6Yi5zfSk7YTp7YT10aGlzLmg7Zm9yKGI9MDtiPGEuYS5sZW5ndGg7YisrKWlmKGM9YS5hW2JdLGMuZ3x8MT09Yy5pfHwwPT1jLmkpe2E9ITA7YnJlYWsgYX1hPSExfXRoaXMuZz1hfW0oVSk7XG5VLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPWEuYSxjPW51bGwsYz10aGlzLmYsZD1udWxsLGU9bnVsbCxmPTA7YyYmKGQ9Yy5uYW1lLGU9Yy5zP0woYy5zLGEpOm51bGwsZj0xKTtpZih0aGlzLnUpaWYodGhpcy5nfHx0aGlzLmMhPXRiKWlmKGE9SCgobmV3IFUodWIsbmV3IEcoXCJub2RlXCIpKSkuYShhKSksYj1JKGEpKWZvcihjPXRoaXMubShiLGQsZSxmKTtudWxsIT0oYj1JKGEpKTspYz1QYShjLHRoaXMubShiLGQsZSxmKSk7ZWxzZSBjPW5ldyBDO2Vsc2UgYz1CKHRoaXMubyxiLGQsZSksYz0kYSh0aGlzLmgsYyxmKTtlbHNlIGM9dGhpcy5tKGEuYSxkLGUsZik7cmV0dXJuIGN9O1UucHJvdG90eXBlLm09ZnVuY3Rpb24oYSxiLGMsZCl7YT10aGlzLmMuZih0aGlzLm8sYSxiLGMpO3JldHVybiBhPSRhKHRoaXMuaCxhLGQpfTtcblUucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7dmFyIGE7YT1cIlN0ZXA6XCIrSihcIk9wZXJhdG9yOiBcIisodGhpcy51P1wiLy9cIjpcIi9cIikpO3RoaXMuYy5qJiYoYSs9SihcIkF4aXM6IFwiK3RoaXMuYykpO2ErPUoodGhpcy5vKTtpZih0aGlzLmguYS5sZW5ndGgpe3ZhciBiPXQodGhpcy5oLmEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStKKGIpfSxcIlByZWRpY2F0ZXM6XCIpO2ErPUooYil9cmV0dXJuIGF9O2Z1bmN0aW9uIHZiKGEsYixjLGQpe3RoaXMuaj1hO3RoaXMuZj1iO3RoaXMuYT1jO3RoaXMuYj1kfXZiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmp9O3ZhciB3Yj17fTtmdW5jdGlvbiBWKGEsYixjLGQpe2lmKHdiLmhhc093blByb3BlcnR5KGEpKXRocm93IEVycm9yKFwiQXhpcyBhbHJlYWR5IGNyZWF0ZWQ6IFwiK2EpO2I9bmV3IHZiKGEsYixjLCEhZCk7cmV0dXJuIHdiW2FdPWJ9XG5WKFwiYW5jZXN0b3JcIixmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz1uZXcgQyxkPWI7ZD1kLnBhcmVudE5vZGU7KWEuYShkKSYmUWEoYyxkKTtyZXR1cm4gY30sITApO1YoXCJhbmNlc3Rvci1vci1zZWxmXCIsZnVuY3Rpb24oYSxiKXt2YXIgYz1uZXcgQyxkPWI7ZG8gYS5hKGQpJiZRYShjLGQpO3doaWxlKGQ9ZC5wYXJlbnROb2RlKTtyZXR1cm4gY30sITApO1xudmFyIGxiPVYoXCJhdHRyaWJ1dGVcIixmdW5jdGlvbihhLGIpe3ZhciBjPW5ldyBDLGQ9YS5mKCk7aWYoXCJzdHlsZVwiPT1kJiZ3JiZiLnN0eWxlKXJldHVybiBGKGMsbmV3IHgoYi5zdHlsZSxiLFwic3R5bGVcIixiLnN0eWxlLmNzc1RleHQpKSxjO3ZhciBlPWIuYXR0cmlidXRlcztpZihlKWlmKGEgaW5zdGFuY2VvZiBHJiZudWxsPT09YS5ifHxcIipcIj09ZClmb3IodmFyIGQ9MCxmO2Y9ZVtkXTtkKyspdz9mLm5vZGVWYWx1ZSYmRihjLERhKGIsZikpOkYoYyxmKTtlbHNlKGY9ZS5nZXROYW1lZEl0ZW0oZCkpJiYodz9mLm5vZGVWYWx1ZSYmRihjLERhKGIsZikpOkYoYyxmKSk7cmV0dXJuIGN9LCExKSx0Yj1WKFwiY2hpbGRcIixmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybih3P0lhOkphKS5jYWxsKG51bGwsYSxiLGwoYyk/YzpudWxsLGwoZCk/ZDpudWxsLGV8fG5ldyBDKX0sITEsITApO1YoXCJkZXNjZW5kYW50XCIsQiwhMSwhMCk7XG52YXIgdWI9VihcImRlc2NlbmRhbnQtb3Itc2VsZlwiLGZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPW5ldyBDO0EoYixjLGQpJiZhLmEoYikmJkYoZSxiKTtyZXR1cm4gQihhLGIsYyxkLGUpfSwhMSwhMCkscGI9VihcImZvbGxvd2luZ1wiLGZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPW5ldyBDO2RvIGZvcih2YXIgZj1iO2Y9Zi5uZXh0U2libGluZzspQShmLGMsZCkmJmEuYShmKSYmRihlLGYpLGU9QihhLGYsYyxkLGUpO3doaWxlKGI9Yi5wYXJlbnROb2RlKTtyZXR1cm4gZX0sITEsITApO1YoXCJmb2xsb3dpbmctc2libGluZ1wiLGZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPW5ldyBDLGQ9YjtkPWQubmV4dFNpYmxpbmc7KWEuYShkKSYmRihjLGQpO3JldHVybiBjfSwhMSk7VihcIm5hbWVzcGFjZVwiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBDfSwhMSk7XG52YXIgeGI9VihcInBhcmVudFwiLGZ1bmN0aW9uKGEsYil7dmFyIGM9bmV3IEM7aWYoOT09Yi5ub2RlVHlwZSlyZXR1cm4gYztpZigyPT1iLm5vZGVUeXBlKXJldHVybiBGKGMsYi5vd25lckVsZW1lbnQpLGM7dmFyIGQ9Yi5wYXJlbnROb2RlO2EuYShkKSYmRihjLGQpO3JldHVybiBjfSwhMSkscWI9VihcInByZWNlZGluZ1wiLGZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPW5ldyBDLGY9W107ZG8gZi51bnNoaWZ0KGIpO3doaWxlKGI9Yi5wYXJlbnROb2RlKTtmb3IodmFyIGc9MSxoPWYubGVuZ3RoO2c8aDtnKyspe3ZhciBwPVtdO2ZvcihiPWZbZ107Yj1iLnByZXZpb3VzU2libGluZzspcC51bnNoaWZ0KGIpO2Zvcih2YXIgeT0wLEQ9cC5sZW5ndGg7eTxEO3krKyliPXBbeV0sQShiLGMsZCkmJmEuYShiKSYmRihlLGIpLGU9QihhLGIsYyxkLGUpfXJldHVybiBlfSwhMCwhMCk7XG5WKFwicHJlY2VkaW5nLXNpYmxpbmdcIixmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz1uZXcgQyxkPWI7ZD1kLnByZXZpb3VzU2libGluZzspYS5hKGQpJiZRYShjLGQpO3JldHVybiBjfSwhMCk7dmFyIHliPVYoXCJzZWxmXCIsZnVuY3Rpb24oYSxiKXt2YXIgYz1uZXcgQzthLmEoYikmJkYoYyxiKTtyZXR1cm4gY30sITEpO2Z1bmN0aW9uIHpiKGEpe24uY2FsbCh0aGlzLDEpO3RoaXMuYz1hO3RoaXMuZz1hLmc7dGhpcy5iPWEuYn1tKHpiKTt6Yi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4tSyh0aGlzLmMsYSl9O3piLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiVW5hcnkgRXhwcmVzc2lvbjogLVwiK0oodGhpcy5jKX07ZnVuY3Rpb24gQWIoYSl7bi5jYWxsKHRoaXMsMSk7dGhpcy5jPWF9bShBYik7QWIucHJvdG90eXBlLmE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jfTtBYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIk51bWJlcjogXCIrdGhpcy5jfTtmdW5jdGlvbiBCYihhLGIpe3RoaXMuYT1hO3RoaXMuYj1ifWZ1bmN0aW9uIENiKGEpe2Zvcih2YXIgYixjPVtdOzspe1coYSxcIk1pc3NpbmcgcmlnaHQgaGFuZCBzaWRlIG9mIGJpbmFyeSBleHByZXNzaW9uLlwiKTtiPURiKGEpO3ZhciBkPVQoYS5hKTtpZighZClicmVhazt2YXIgZT0oZD1ZYVtkXXx8bnVsbCkmJmQudztpZighZSl7YS5hLmEtLTticmVha31mb3IoO2MubGVuZ3RoJiZlPD1jW2MubGVuZ3RoLTFdLnc7KWI9bmV3IE4oYy5wb3AoKSxjLnBvcCgpLGIpO2MucHVzaChiLGQpfWZvcig7Yy5sZW5ndGg7KWI9bmV3IE4oYy5wb3AoKSxjLnBvcCgpLGIpO3JldHVybiBifWZ1bmN0aW9uIFcoYSxiKXtpZihpYihhLmEpKXRocm93IEVycm9yKGIpO31mdW5jdGlvbiBFYihhLGIpe3ZhciBjPVQoYS5hKTtpZihjIT1iKXRocm93IEVycm9yKFwiQmFkIHRva2VuLCBleHBlY3RlZDogXCIrYitcIiBnb3Q6IFwiK2MpO31cbmZ1bmN0aW9uIEZiKGEpe2E9VChhLmEpO2lmKFwiKVwiIT1hKXRocm93IEVycm9yKFwiQmFkIHRva2VuOiBcIithKTt9ZnVuY3Rpb24gR2IoYSl7YT1UKGEuYSk7aWYoMj5hLmxlbmd0aCl0aHJvdyBFcnJvcihcIlVuY2xvc2VkIGxpdGVyYWwgc3RyaW5nXCIpO3JldHVybiBuZXcgamIoYSl9XG5mdW5jdGlvbiBIYihhKXt2YXIgYixjPVtdLGQ7aWYob2IoUyhhLmEpKSl7Yj1UKGEuYSk7ZD1TKGEuYSk7aWYoXCIvXCI9PWImJihpYihhLmEpfHxcIi5cIiE9ZCYmXCIuLlwiIT1kJiZcIkBcIiE9ZCYmXCIqXCIhPWQmJiEvKD8hWzAtOV0pW1xcd10vLnRlc3QoZCkpKXJldHVybiBuZXcgbWI7ZD1uZXcgbWI7VyhhLFwiTWlzc2luZyBuZXh0IGxvY2F0aW9uIHN0ZXAuXCIpO2I9SWIoYSxiKTtjLnB1c2goYil9ZWxzZXthOntiPVMoYS5hKTtkPWIuY2hhckF0KDApO3N3aXRjaChkKXtjYXNlIFwiJFwiOnRocm93IEVycm9yKFwiVmFyaWFibGUgcmVmZXJlbmNlIG5vdCBhbGxvd2VkIGluIEhUTUwgWFBhdGhcIik7Y2FzZSBcIihcIjpUKGEuYSk7Yj1DYihhKTtXKGEsJ3VuY2xvc2VkIFwiKFwiJyk7RWIoYSxcIilcIik7YnJlYWs7Y2FzZSAnXCInOmNhc2UgXCInXCI6Yj1HYihhKTticmVhaztkZWZhdWx0OmlmKGlzTmFOKCtiKSlpZighZGIoYikmJi8oPyFbMC05XSlbXFx3XS8udGVzdChkKSYmXCIoXCI9PVMoYS5hLDEpKXtiPVQoYS5hKTtcbmI9Y2JbYl18fG51bGw7VChhLmEpO2ZvcihkPVtdO1wiKVwiIT1TKGEuYSk7KXtXKGEsXCJNaXNzaW5nIGZ1bmN0aW9uIGFyZ3VtZW50IGxpc3QuXCIpO2QucHVzaChDYihhKSk7aWYoXCIsXCIhPVMoYS5hKSlicmVhaztUKGEuYSl9VyhhLFwiVW5jbG9zZWQgZnVuY3Rpb24gYXJndW1lbnQgbGlzdC5cIik7RmIoYSk7Yj1uZXcgYWIoYixkKX1lbHNle2I9bnVsbDticmVhayBhfWVsc2UgYj1uZXcgQWIoK1QoYS5hKSl9XCJbXCI9PVMoYS5hKSYmKGQ9bmV3IHNiKEpiKGEpKSxiPW5ldyBaYShiLGQpKX1pZihiKWlmKG9iKFMoYS5hKSkpZD1iO2Vsc2UgcmV0dXJuIGI7ZWxzZSBiPUliKGEsXCIvXCIpLGQ9bmV3IG5iLGMucHVzaChiKX1mb3IoO29iKFMoYS5hKSk7KWI9VChhLmEpLFcoYSxcIk1pc3NpbmcgbmV4dCBsb2NhdGlvbiBzdGVwLlwiKSxiPUliKGEsYiksYy5wdXNoKGIpO3JldHVybiBuZXcga2IoZCxjKX1cbmZ1bmN0aW9uIEliKGEsYil7dmFyIGMsZCxlO2lmKFwiL1wiIT1iJiZcIi8vXCIhPWIpdGhyb3cgRXJyb3IoJ1N0ZXAgb3Agc2hvdWxkIGJlIFwiL1wiIG9yIFwiLy9cIicpO2lmKFwiLlwiPT1TKGEuYSkpcmV0dXJuIGQ9bmV3IFUoeWIsbmV3IEcoXCJub2RlXCIpKSxUKGEuYSksZDtpZihcIi4uXCI9PVMoYS5hKSlyZXR1cm4gZD1uZXcgVSh4YixuZXcgRyhcIm5vZGVcIikpLFQoYS5hKSxkO3ZhciBmO2lmKFwiQFwiPT1TKGEuYSkpZj1sYixUKGEuYSksVyhhLFwiTWlzc2luZyBhdHRyaWJ1dGUgbmFtZVwiKTtlbHNlIGlmKFwiOjpcIj09UyhhLmEsMSkpe2lmKCEvKD8hWzAtOV0pW1xcd10vLnRlc3QoUyhhLmEpLmNoYXJBdCgwKSkpdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW46IFwiK1QoYS5hKSk7Yz1UKGEuYSk7Zj13YltjXXx8bnVsbDtpZighZil0aHJvdyBFcnJvcihcIk5vIGF4aXMgd2l0aCBuYW1lOiBcIitjKTtUKGEuYSk7VyhhLFwiTWlzc2luZyBub2RlIG5hbWVcIil9ZWxzZSBmPXRiO2M9UyhhLmEpO2lmKC8oPyFbMC05XSlbXFx3XFwqXS8udGVzdChjLmNoYXJBdCgwKSkpaWYoXCIoXCI9PVxuUyhhLmEsMSkpe2lmKCFkYihjKSl0aHJvdyBFcnJvcihcIkludmFsaWQgbm9kZSB0eXBlOiBcIitjKTtjPVQoYS5hKTtpZighZGIoYykpdGhyb3cgRXJyb3IoXCJJbnZhbGlkIHR5cGUgbmFtZTogXCIrYyk7RWIoYSxcIihcIik7VyhhLFwiQmFkIG5vZGV0eXBlXCIpO2U9UyhhLmEpLmNoYXJBdCgwKTt2YXIgZz1udWxsO2lmKCdcIic9PWV8fFwiJ1wiPT1lKWc9R2IoYSk7VyhhLFwiQmFkIG5vZGV0eXBlXCIpO0ZiKGEpO2M9bmV3IEcoYyxnKX1lbHNlIGlmKGM9VChhLmEpLGU9Yy5pbmRleE9mKFwiOlwiKSwtMT09ZSljPW5ldyBFKGMpO2Vsc2V7dmFyIGc9Yy5zdWJzdHJpbmcoMCxlKSxoO2lmKFwiKlwiPT1nKWg9XCIqXCI7ZWxzZSBpZihoPWEuYihnKSwhaCl0aHJvdyBFcnJvcihcIk5hbWVzcGFjZSBwcmVmaXggbm90IGRlY2xhcmVkOiBcIitnKTtjPWMuc3Vic3RyKGUrMSk7Yz1uZXcgRShjLGgpfWVsc2UgdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW46IFwiK1QoYS5hKSk7ZT1uZXcgc2IoSmIoYSksZi5hKTtyZXR1cm4gZHx8XG5uZXcgVShmLGMsZSxcIi8vXCI9PWIpfWZ1bmN0aW9uIEpiKGEpe2Zvcih2YXIgYj1bXTtcIltcIj09UyhhLmEpOyl7VChhLmEpO1coYSxcIk1pc3NpbmcgcHJlZGljYXRlIGV4cHJlc3Npb24uXCIpO3ZhciBjPUNiKGEpO2IucHVzaChjKTtXKGEsXCJVbmNsb3NlZCBwcmVkaWNhdGUgZXhwcmVzc2lvbi5cIik7RWIoYSxcIl1cIil9cmV0dXJuIGJ9ZnVuY3Rpb24gRGIoYSl7aWYoXCItXCI9PVMoYS5hKSlyZXR1cm4gVChhLmEpLG5ldyB6YihEYihhKSk7dmFyIGI9SGIoYSk7aWYoXCJ8XCIhPVMoYS5hKSlhPWI7ZWxzZXtmb3IoYj1bYl07XCJ8XCI9PVQoYS5hKTspVyhhLFwiTWlzc2luZyBuZXh0IHVuaW9uIGxvY2F0aW9uIHBhdGguXCIpLGIucHVzaChIYihhKSk7YS5hLmEtLTthPW5ldyByYihiKX1yZXR1cm4gYX07ZnVuY3Rpb24gS2IoYSl7c3dpdGNoKGEubm9kZVR5cGUpe2Nhc2UgMTpyZXR1cm4gZWEoTGIsYSk7Y2FzZSA5OnJldHVybiBLYihhLmRvY3VtZW50RWxlbWVudCk7Y2FzZSAxMTpjYXNlIDEwOmNhc2UgNjpjYXNlIDEyOnJldHVybiBNYjtkZWZhdWx0OnJldHVybiBhLnBhcmVudE5vZGU/S2IoYS5wYXJlbnROb2RlKTpNYn19ZnVuY3Rpb24gTWIoKXtyZXR1cm4gbnVsbH1mdW5jdGlvbiBMYihhLGIpe2lmKGEucHJlZml4PT1iKXJldHVybiBhLm5hbWVzcGFjZVVSSXx8XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCI7dmFyIGM9YS5nZXRBdHRyaWJ1dGVOb2RlKFwieG1sbnM6XCIrYik7cmV0dXJuIGMmJmMuc3BlY2lmaWVkP2MudmFsdWV8fG51bGw6YS5wYXJlbnROb2RlJiY5IT1hLnBhcmVudE5vZGUubm9kZVR5cGU/TGIoYS5wYXJlbnROb2RlLGIpOm51bGx9O2Z1bmN0aW9uIE5iKGEsYil7aWYoIWEubGVuZ3RoKXRocm93IEVycm9yKFwiRW1wdHkgWFBhdGggZXhwcmVzc2lvbi5cIik7dmFyIGM9ZmIoYSk7aWYoaWIoYykpdGhyb3cgRXJyb3IoXCJJbnZhbGlkIFhQYXRoIGV4cHJlc3Npb24uXCIpO2I/XCJmdW5jdGlvblwiPT1hYShiKXx8KGI9ZGEoYi5sb29rdXBOYW1lc3BhY2VVUkksYikpOmI9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07dmFyIGQ9Q2IobmV3IEJiKGMsYikpO2lmKCFpYihjKSl0aHJvdyBFcnJvcihcIkJhZCB0b2tlbjogXCIrVChjKSk7dGhpcy5ldmFsdWF0ZT1mdW5jdGlvbihhLGIpe3ZhciBjPWQuYShuZXcgUShhKSk7cmV0dXJuIG5ldyBZKGMsYil9fVxuZnVuY3Rpb24gWShhLGIpe2lmKDA9PWIpaWYoYSBpbnN0YW5jZW9mIEMpYj00O2Vsc2UgaWYoXCJzdHJpbmdcIj09dHlwZW9mIGEpYj0yO2Vsc2UgaWYoXCJudW1iZXJcIj09dHlwZW9mIGEpYj0xO2Vsc2UgaWYoXCJib29sZWFuXCI9PXR5cGVvZiBhKWI9MztlbHNlIHRocm93IEVycm9yKFwiVW5leHBlY3RlZCBldmFsdWF0aW9uIHJlc3VsdC5cIik7aWYoMiE9YiYmMSE9YiYmMyE9YiYmIShhIGluc3RhbmNlb2YgQykpdGhyb3cgRXJyb3IoXCJ2YWx1ZSBjb3VsZCBub3QgYmUgY29udmVydGVkIHRvIHRoZSBzcGVjaWZpZWQgdHlwZVwiKTt0aGlzLnJlc3VsdFR5cGU9Yjt2YXIgYztzd2l0Y2goYil7Y2FzZSAyOnRoaXMuc3RyaW5nVmFsdWU9YSBpbnN0YW5jZW9mIEM/U2EoYSk6XCJcIithO2JyZWFrO2Nhc2UgMTp0aGlzLm51bWJlclZhbHVlPWEgaW5zdGFuY2VvZiBDPytTYShhKTorYTticmVhaztjYXNlIDM6dGhpcy5ib29sZWFuVmFsdWU9YSBpbnN0YW5jZW9mIEM/MDxhLmw6ISFhO2JyZWFrO2Nhc2UgNDpjYXNlIDU6Y2FzZSA2OmNhc2UgNzp2YXIgZD1cbkgoYSk7Yz1bXTtmb3IodmFyIGU9SShkKTtlO2U9SShkKSljLnB1c2goZSBpbnN0YW5jZW9mIHg/ZS5hOmUpO3RoaXMuc25hcHNob3RMZW5ndGg9YS5sO3RoaXMuaW52YWxpZEl0ZXJhdG9yU3RhdGU9ITE7YnJlYWs7Y2FzZSA4OmNhc2UgOTpkPVJhKGEpO3RoaXMuc2luZ2xlTm9kZVZhbHVlPWQgaW5zdGFuY2VvZiB4P2QuYTpkO2JyZWFrO2RlZmF1bHQ6dGhyb3cgRXJyb3IoXCJVbmtub3duIFhQYXRoUmVzdWx0IHR5cGUuXCIpO312YXIgZj0wO3RoaXMuaXRlcmF0ZU5leHQ9ZnVuY3Rpb24oKXtpZig0IT1iJiY1IT1iKXRocm93IEVycm9yKFwiaXRlcmF0ZU5leHQgY2FsbGVkIHdpdGggd3JvbmcgcmVzdWx0IHR5cGVcIik7cmV0dXJuIGY+PWMubGVuZ3RoP251bGw6Y1tmKytdfTt0aGlzLnNuYXBzaG90SXRlbT1mdW5jdGlvbihhKXtpZig2IT1iJiY3IT1iKXRocm93IEVycm9yKFwic25hcHNob3RJdGVtIGNhbGxlZCB3aXRoIHdyb25nIHJlc3VsdCB0eXBlXCIpO3JldHVybiBhPj1jLmxlbmd0aHx8XG4wPmE/bnVsbDpjW2FdfX1ZLkFOWV9UWVBFPTA7WS5OVU1CRVJfVFlQRT0xO1kuU1RSSU5HX1RZUEU9MjtZLkJPT0xFQU5fVFlQRT0zO1kuVU5PUkRFUkVEX05PREVfSVRFUkFUT1JfVFlQRT00O1kuT1JERVJFRF9OT0RFX0lURVJBVE9SX1RZUEU9NTtZLlVOT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEU9NjtZLk9SREVSRURfTk9ERV9TTkFQU0hPVF9UWVBFPTc7WS5BTllfVU5PUkRFUkVEX05PREVfVFlQRT04O1kuRklSU1RfT1JERVJFRF9OT0RFX1RZUEU9OTtmdW5jdGlvbiBPYihhKXt0aGlzLmxvb2t1cE5hbWVzcGFjZVVSST1LYihhKX1cbmZ1bmN0aW9uIFBiKGEsYil7dmFyIGM9YXx8ayxkPWMuRG9jdW1lbnQmJmMuRG9jdW1lbnQucHJvdG90eXBlfHxjLmRvY3VtZW50O2lmKCFkLmV2YWx1YXRlfHxiKWMuWFBhdGhSZXN1bHQ9WSxkLmV2YWx1YXRlPWZ1bmN0aW9uKGEsYixjLGQpe3JldHVybihuZXcgTmIoYSxjKSkuZXZhbHVhdGUoYixkKX0sZC5jcmVhdGVFeHByZXNzaW9uPWZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBOYihhLGIpfSxkLmNyZWF0ZU5TUmVzb2x2ZXI9ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBPYihhKX19dmFyIFFiPVtcIndneHBhdGhcIixcImluc3RhbGxcIl0sWj1rO1FiWzBdaW4gWnx8IVouZXhlY1NjcmlwdHx8Wi5leGVjU2NyaXB0KFwidmFyIFwiK1FiWzBdKTtmb3IodmFyIFJiO1FiLmxlbmd0aCYmKFJiPVFiLnNoaWZ0KCkpOylRYi5sZW5ndGh8fHZvaWQgMD09PVBiP1pbUmJdP1o9WltSYl06Wj1aW1JiXT17fTpaW1JiXT1QYjttb2R1bGUuZXhwb3J0cy5pbnN0YWxsPVBiO21vZHVsZS5leHBvcnRzLlhQYXRoUmVzdWx0VHlwZT17QU5ZX1RZUEU6MCxOVU1CRVJfVFlQRToxLFNUUklOR19UWVBFOjIsQk9PTEVBTl9UWVBFOjMsVU5PUkRFUkVEX05PREVfSVRFUkFUT1JfVFlQRTo0LE9SREVSRURfTk9ERV9JVEVSQVRPUl9UWVBFOjUsVU5PUkRFUkVEX05PREVfU05BUFNIT1RfVFlQRTo2LE9SREVSRURfTk9ERV9TTkFQU0hPVF9UWVBFOjcsQU5ZX1VOT1JERVJFRF9OT0RFX1RZUEU6OCxGSVJTVF9PUkRFUkVEX05PREVfVFlQRTo5fTt9KS5jYWxsKGdsb2JhbClcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuLy8gQmFja3dhcmQgQ29tcGF0IFRhYmxlXG4ndXNlIHN0cmljdCc7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkKG9iaikgeyBpZiAob2JqICYmIG9iai5fX2VzTW9kdWxlKSB7IHJldHVybiBvYmo7IH0gZWxzZSB7IHZhciBuZXdPYmogPSB7fTsgaWYgKG9iaiAhPSBudWxsKSB7IGZvciAodmFyIGtleSBpbiBvYmopIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIG5ld09ialtrZXldID0gb2JqW2tleV07IH0gfSBuZXdPYmpbJ2RlZmF1bHQnXSA9IG9iajsgcmV0dXJuIG5ld09iajsgfSB9XG5cbnZhciBfaHR0cFB5ZGlvVXNlcnNBcGkgPSByZXF1aXJlKCcuL2h0dHAvUHlkaW9Vc2Vyc0FwaScpO1xuXG52YXIgVXNlcnNBcGkgPSBfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZChfaHR0cFB5ZGlvVXNlcnNBcGkpO1xuXG52YXIgQ29ubmV4aW9uID0gcmVxdWlyZSgnLi9odHRwL0Nvbm5leGlvbicpLFxuICAgIE1ldGFDYWNoZVNlcnZpY2UgPSByZXF1aXJlKCcuL2h0dHAvTWV0YUNhY2hlU2VydmljZScpLFxuICAgIFB5ZGlvQXBpID0gcmVxdWlyZSgnLi9odHRwL1B5ZGlvQXBpJyksXG4gICAgUmVzb3VyY2VzTWFuYWdlciA9IHJlcXVpcmUoJy4vaHR0cC9SZXNvdXJjZXNNYW5hZ2VyJyksXG4gICAgTG9nZ2VyID0gcmVxdWlyZSgnLi9sYW5nL0xvZ2dlcicpLFxuICAgIE9ic2VydmFibGUgPSByZXF1aXJlKCcuL2xhbmcvT2JzZXJ2YWJsZScpLFxuICAgIEFjdGlvbiA9IHJlcXVpcmUoJy4vbW9kZWwvQWN0aW9uJyksXG4gICAgQWp4cE5vZGUgPSByZXF1aXJlKCcuL21vZGVsL0FqeHBOb2RlJyksXG4gICAgQ29udHJvbGxlciA9IHJlcXVpcmUoJy4vbW9kZWwvQ29udHJvbGxlcicpLFxuICAgIEVtcHR5Tm9kZVByb3ZpZGVyID0gcmVxdWlyZSgnLi9tb2RlbC9FbXB0eU5vZGVQcm92aWRlcicpLFxuICAgIFB5ZGlvRGF0YU1vZGVsID0gcmVxdWlyZSgnLi9tb2RlbC9QeWRpb0RhdGFNb2RlbCcpLFxuICAgIFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi9tb2RlbC9SZWdpc3RyeScpLFxuICAgIFJlbW90ZU5vZGVQcm92aWRlciA9IHJlcXVpcmUoJy4vbW9kZWwvUmVtb3RlTm9kZVByb3ZpZGVyJyksXG4gICAgUmVwb3NpdG9yeSA9IHJlcXVpcmUoJy4vbW9kZWwvUmVwb3NpdG9yeScpLFxuICAgIFVzZXIgPSByZXF1aXJlKCcuL21vZGVsL1VzZXInKSxcbiAgICBDb250ZXh0TWVudSA9IHJlcXVpcmUoJy4vbW9kZWwvQ29udGV4dE1lbnUnKSxcbiAgICBDb29raWVzTWFuYWdlciA9IHJlcXVpcmUoJy4vdXRpbC9Db29raWVzTWFuYWdlcicpLFxuICAgIERPTVV0aWxzID0gcmVxdWlyZSgnLi91dGlsL0RPTVV0aWxzJyksXG4gICAgRnVuY1V0aWxzID0gcmVxdWlyZSgnLi91dGlsL0Z1bmNVdGlscycpLFxuICAgIEhhc2hlclV0aWxzID0gcmVxdWlyZSgnLi91dGlsL0hhc2hlclV0aWxzJyksXG4gICAgTGFuZ1V0aWxzID0gcmVxdWlyZSgnLi91dGlsL0xhbmdVdGlscycpLFxuICAgIFBhc3NVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9QYXNzVXRpbHMnKSxcbiAgICBQYXRoVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvUGF0aFV0aWxzJyksXG4gICAgUGVyaW9kaWNhbEV4ZWN1dGVyID0gcmVxdWlyZSgnLi91dGlsL1BlcmlvZGljYWxFeGVjdXRlcicpLFxuICAgIEFjdGl2aXR5TW9uaXRvciA9IHJlcXVpcmUoJy4vdXRpbC9BY3Rpdml0eU1vbml0b3InKSxcbiAgICBYTUxVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9YTUxVdGlscycpLFxuICAgIFB5ZGlvID0gcmVxdWlyZSgnLi9QeWRpbycpO1xuXG52YXIgUHlkaW9Vc2VycyA9IHtcbiAgICBDbGllbnQ6IFVzZXJzQXBpLlVzZXJzQXBpLFxuICAgIFVzZXI6IFVzZXJzQXBpLlVzZXJcbn07XG5cbnZhciBuYW1lc3BhY2UgPSB7XG4gICAgQ29ubmV4aW9uOiBDb25uZXhpb24sXG4gICAgTWV0YUNhY2hlU2VydmljZTogTWV0YUNhY2hlU2VydmljZSxcbiAgICBQeWRpb0FwaTogUHlkaW9BcGksXG4gICAgUHlkaW9Vc2VyczogUHlkaW9Vc2VycyxcbiAgICBSZXNvdXJjZXNNYW5hZ2VyOiBSZXNvdXJjZXNNYW5hZ2VyLFxuICAgIExvZ2dlcjogTG9nZ2VyLFxuICAgIE9ic2VydmFibGU6IE9ic2VydmFibGUsXG4gICAgQWN0aW9uOiBBY3Rpb24sXG4gICAgQWp4cE5vZGU6IEFqeHBOb2RlLFxuICAgIENvbnRyb2xsZXI6IENvbnRyb2xsZXIsXG4gICAgRW1wdHlOb2RlUHJvdmlkZXI6IEVtcHR5Tm9kZVByb3ZpZGVyLFxuICAgIFB5ZGlvRGF0YU1vZGVsOiBQeWRpb0RhdGFNb2RlbCxcbiAgICBSZWdpc3RyeTogUmVnaXN0cnksXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyOiBSZW1vdGVOb2RlUHJvdmlkZXIsXG4gICAgUmVwb3NpdG9yeTogUmVwb3NpdG9yeSxcbiAgICBVc2VyOiBVc2VyLFxuICAgIENvbnRleHRNZW51OiBDb250ZXh0TWVudSxcbiAgICBDb29raWVzTWFuYWdlcjogQ29va2llc01hbmFnZXIsXG4gICAgRE9NVXRpbHM6IERPTVV0aWxzLFxuICAgIEZ1bmNVdGlsczogRnVuY1V0aWxzLFxuICAgIEhhc2hlclV0aWxzOiBIYXNoZXJVdGlscyxcbiAgICBMYW5nVXRpbHM6IExhbmdVdGlscyxcbiAgICBQYXNzVXRpbHM6IFBhc3NVdGlscyxcbiAgICBQYXRoVXRpbHM6IFBhdGhVdGlscyxcbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXI6IFBlcmlvZGljYWxFeGVjdXRlcixcbiAgICBBY3Rpdml0eU1vbml0b3I6IEFjdGl2aXR5TW9uaXRvcixcbiAgICBYTUxVdGlsczogWE1MVXRpbHMsXG4gICAgUHlkaW86IFB5ZGlvXG59O1xuXG5PYmplY3QuYXNzaWduKHdpbmRvdywgX2V4dGVuZHMoe30sIG5hbWVzcGFjZSwgeyBQeWRpb0NvcmU6IG5hbWVzcGFjZSB9KSk7XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG4vKipcbiAqIEFQSSBDbGllbnRcbiAqL1xuXG52YXIgUHlkaW9BcGkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFB5ZGlvQXBpKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHlkaW9BcGkpO1xuICAgIH1cblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5zZXRQeWRpb09iamVjdCA9IGZ1bmN0aW9uIHNldFB5ZGlvT2JqZWN0KHB5ZGlvT2JqZWN0KSB7XG4gICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0ID0gcHlkaW9PYmplY3Q7XG4gICAgICAgIHRoaXMuX2Jhc2VVcmwgPSBweWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldCgnc2VydmVyQWNjZXNzUGF0aCcpO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUucmVxdWVzdCA9IGZ1bmN0aW9uIHJlcXVlc3QocGFyYW1ldGVycykge1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBvbkVycm9yID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgLy8gQ29ubmV4aW9uIGFscmVhZHkgaGFuZGxlcyBzZWN1cmVfdG9rZW5cbiAgICAgICAgdmFyIGMgPSBuZXcgQ29ubmV4aW9uKCk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5kaXNjcmV0ZSkge1xuICAgICAgICAgICAgYy5kaXNjcmV0ZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgYy5zZXRQYXJhbWV0ZXJzKHBhcmFtZXRlcnMpO1xuICAgICAgICBpZiAoc2V0dGluZ3MubWV0aG9kKSB7XG4gICAgICAgICAgICBjLnNldE1ldGhvZChzZXR0aW5ncy5tZXRob2QpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghb25Db21wbGV0ZSkge1xuICAgICAgICAgICAgb25Db21wbGV0ZSA9IChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTCkgcmV0dXJuIHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGMub25Db21wbGV0ZSA9IG9uQ29tcGxldGU7XG4gICAgICAgIGlmIChzZXR0aW5ncy5hc3luYyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGMuc2VuZFN5bmMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMuc2VuZEFzeW5jKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmxvYWRGaWxlID0gZnVuY3Rpb24gbG9hZEZpbGUoZmlsZVBhdGgpIHtcbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgb25FcnJvciA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgdmFyIGMgPSBuZXcgQ29ubmV4aW9uKGZpbGVQYXRoKTtcbiAgICAgICAgYy5zZXRNZXRob2QoJ0dFVCcpO1xuICAgICAgICBjLm9uQ29tcGxldGUgPSBvbkNvbXBsZXRlO1xuICAgICAgICBjLnNlbmRBc3luYygpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gZmlsZVxuICAgICAqIEBwYXJhbSBmaWxlUGFyYW1ldGVyTmFtZVxuICAgICAqIEBwYXJhbSBxdWVyeVN0cmluZ1BhcmFtc1xuICAgICAqIEBwYXJhbSBvbkNvbXBsZXRlXG4gICAgICogQHBhcmFtIG9uRXJyb3JcbiAgICAgKiBAcGFyYW0gb25Qcm9ncmVzc1xuICAgICAqIEByZXR1cm5zIFhIUiBIYW5kbGUgdG8gYWJvcnQgdHJhbnNmZXJcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS51cGxvYWRGaWxlID0gZnVuY3Rpb24gdXBsb2FkRmlsZShmaWxlLCBmaWxlUGFyYW1ldGVyTmFtZSkge1xuICAgICAgICB2YXIgcXVlcnlTdHJpbmdQYXJhbXMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBmdW5jdGlvbiAoKSB7fSA6IGFyZ3VtZW50c1szXTtcbiAgICAgICAgdmFyIG9uRXJyb3IgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDQgfHwgYXJndW1lbnRzWzRdID09PSB1bmRlZmluZWQgPyBmdW5jdGlvbiAoKSB7fSA6IGFyZ3VtZW50c1s0XTtcbiAgICAgICAgdmFyIG9uUHJvZ3Jlc3MgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDUgfHwgYXJndW1lbnRzWzVdID09PSB1bmRlZmluZWQgPyBmdW5jdGlvbiAoKSB7fSA6IGFyZ3VtZW50c1s1XTtcbiAgICAgICAgdmFyIHVwbG9hZFVybCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNiB8fCBhcmd1bWVudHNbNl0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzZdO1xuICAgICAgICB2YXIgeGhyU2V0dGluZ3MgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDcgfHwgYXJndW1lbnRzWzddID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1s3XTtcblxuICAgICAgICBpZiAoIXVwbG9hZFVybCkge1xuICAgICAgICAgICAgdXBsb2FkVXJsID0gcHlkaW8uUGFyYW1ldGVycy5nZXQoJ2FqeHBTZXJ2ZXJBY2Nlc3MnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocXVlcnlTdHJpbmdQYXJhbXMpIHtcbiAgICAgICAgICAgIHVwbG9hZFVybCArPSAodXBsb2FkVXJsLmluZGV4T2YoJz8nKSA9PT0gLTEgPyAnPycgOiAnJicpICsgcXVlcnlTdHJpbmdQYXJhbXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAod2luZG93LkNvbm5leGlvbikge1xuICAgICAgICAgICAgdmFyIF9yZXQgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIC8vIFdhcm5pbmcsIGF2b2lkIGRvdWJsZSBlcnJvclxuICAgICAgICAgICAgICAgIHZhciBlcnJvclNlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgbG9jYWxFcnJvciA9IGZ1bmN0aW9uIGxvY2FsRXJyb3IoeGhyKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXJyb3JTZW50KSBvbkVycm9yKCdSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyA6JyArIHhoci5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvclNlbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdmFyIGMgPSBuZXcgQ29ubmV4aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdjogYy51cGxvYWRGaWxlKGZpbGUsIGZpbGVQYXJhbWV0ZXJOYW1lLCB1cGxvYWRVcmwsIG9uQ29tcGxldGUsIGxvY2FsRXJyb3IsIG9uUHJvZ3Jlc3MsIHhoclNldHRpbmdzKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KSgpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIF9yZXQgPT09ICdvYmplY3QnKSByZXR1cm4gX3JldC52O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHVzZXJTZWxlY3Rpb24gVXNlclNlbGVjdGlvbiBBIFB5ZGlvIERhdGFNb2RlbCB3aXRoIHNlbGVjdGVkIGZpbGVzXG4gICAgICogQHBhcmFtIHByb3RvdHlwZUhpZGRlbkZvcm0gRWxlbWVudCBBIGhpZGRlbiBmb3JtIGVsZW1lbnQ6IGN1cnJlbnRseSByZWx5aW5nIG9uIFByb3RvdHlwZUpTLlxuICAgICAqIEBwYXJhbSBkbEFjdGlvbk5hbWUgU3RyaW5nIEFjdGlvbiBuYW1lIHRvIHRyaWdnZXIsIGRvd25sb2FkIGJ5IGRlZmF1bHQuXG4gICAgICogQHBhcmFtIGFkZGl0aW9uYWxQYXJhbWV0ZXJzIE9iamVjdCBPcHRpb25hbCBzZXQgb2Yga2V5L3ZhbHVlcyB0byBwYXNzIHRvIHRoZSBkb3dubG9hZC5cbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5kb3dubG9hZFNlbGVjdGlvbiA9IGZ1bmN0aW9uIGRvd25sb2FkU2VsZWN0aW9uKHVzZXJTZWxlY3Rpb24pIHtcbiAgICAgICAgdmFyIGRsQWN0aW9uTmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/ICdkb3dubG9hZCcgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBhZGRpdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzJdO1xuXG4gICAgICAgIHZhciBhanhwU2VydmVyQWNjZXNzID0gdGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycy5nZXQoXCJhanhwU2VydmVyQWNjZXNzXCIpO1xuICAgICAgICB2YXIgYWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50IHx8ICcnO1xuICAgICAgICB2YXIgYWdlbnRJc01vYmlsZSA9IGFnZW50LmluZGV4T2YoJ2lQaG9uZScpICE9IC0xIHx8IGFnZW50LmluZGV4T2YoJ2lQb2QnKSAhPSAtMSB8fCBhZ2VudC5pbmRleE9mKCdpUGFkJykgIT0gLTEgfHwgYWdlbnQuaW5kZXhPZignaU9zJykgIT0gLTE7XG4gICAgICAgIHZhciBoaWRkZW5Gb3JtID0gcHlkaW8gJiYgcHlkaW8uVUkgJiYgcHlkaW8uVUkuaGFzSGlkZGVuRG93bmxvYWRGb3JtKCk7XG4gICAgICAgIGlmIChhZ2VudElzTW9iaWxlIHx8ICFoaWRkZW5Gb3JtKSB7XG4gICAgICAgICAgICB2YXIgZG93bmxvYWRVcmwgPSBhanhwU2VydmVyQWNjZXNzICsgJyZnZXRfYWN0aW9uPScgKyBkbEFjdGlvbk5hbWU7XG4gICAgICAgICAgICBpZiAoYWRkaXRpb25hbFBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwYXJhbSBpbiBhZGRpdGlvbmFsUGFyYW1ldGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYWRkaXRpb25hbFBhcmFtZXRlcnMuaGFzT3duUHJvcGVydHkocGFyYW0pKSBkb3dubG9hZFVybCArPSBcIiZcIiArIHBhcmFtICsgXCI9XCIgKyBhZGRpdGlvbmFsUGFyYW1ldGVyc1twYXJhbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVzZXJTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBkb3dubG9hZFVybCA9IHVzZXJTZWxlY3Rpb24udXBkYXRlRm9ybU9yVXJsKG51bGwsIGRvd25sb2FkVXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSBkb3dubG9hZFVybDtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgdmFyIHBhcmFtZXRlcnMgPSBfZXh0ZW5kcyh7fSwgYWRkaXRpb25hbFBhcmFtZXRlcnMsIHsgc2VjdXJlX3Rva2VuOiB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldChcIlNFQ1VSRV9UT0tFTlwiKSwgZ2V0X2FjdGlvbjogZGxBY3Rpb25OYW1lIH0pO1xuICAgICAgICAgICAgdmFyIG1pbmlzaXRlX3Nlc3Npb24gPSBQeWRpb0FwaS5kZXRlY3RNaW5pc2l0ZVNlc3Npb24oYWp4cFNlcnZlckFjY2Vzcyk7XG4gICAgICAgICAgICBpZiAobWluaXNpdGVfc2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIHBhcmFtZXRlcnNbJ21pbmlzaXRlX3Nlc3Npb24nXSA9IG1pbmlzaXRlX3Nlc3Npb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHB5ZGlvLlVJLnNlbmREb3dubG9hZFRvSGlkZGVuRm9ybSh1c2VyU2VsZWN0aW9uLCBwYXJhbWV0ZXJzKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAod2luZG93LmNvbnNvbGUpIHdpbmRvdy5jb25zb2xlLmVycm9yKFwiRXJyb3Igd2hpbGUgc3VibWl0dGluZyBoaWRkZW4gZm9ybSBmb3IgZG93bmxvYWRcIiwgZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnBvc3RQbGFpblRleHRDb250ZW50ID0gZnVuY3Rpb24gcG9zdFBsYWluVGV4dENvbnRlbnQoZmlsZVBhdGgsIGNvbnRlbnQsIGZpbmlzaGVkQ2FsbGJhY2spIHtcblxuICAgICAgICB0aGlzLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3B1dF9jb250ZW50JyxcbiAgICAgICAgICAgIGZpbGU6IGZpbGVQYXRoLFxuICAgICAgICAgICAgY29udGVudDogY29udGVudFxuICAgICAgICB9LCAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdmFyIHN1Y2Nlc3MgPSB0aGlzLnBhcnNlWG1sTWVzc2FnZSh0cmFuc3BvcnQucmVzcG9uc2VYTUwpO1xuICAgICAgICAgICAgZmluaXNoZWRDYWxsYmFjayhzdWNjZXNzKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZmluaXNoZWRDYWxsYmFjayhmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgYSBtaW5pc2l0ZV9zZXNzaW9uIHBhcmFtZXRlciBpbiB0aGUgVVJMXG4gICAgICogQHBhcmFtIHNlcnZlckFjY2Vzc1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xib29sXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5kZXRlY3RNaW5pc2l0ZVNlc3Npb24gPSBmdW5jdGlvbiBkZXRlY3RNaW5pc2l0ZVNlc3Npb24oc2VydmVyQWNjZXNzKSB7XG4gICAgICAgIHZhciByZWdleCA9IG5ldyBSZWdFeHAoJy4qP1smXFxcXD9dJyArICdtaW5pc2l0ZV9zZXNzaW9uJyArICc9KC4qPykmPy4qPycpO1xuICAgICAgICB2YXIgdmFsID0gc2VydmVyQWNjZXNzLnJlcGxhY2UocmVnZXgsIFwiJDFcIik7XG4gICAgICAgIHJldHVybiB2YWwgPT09IHNlcnZlckFjY2VzcyA/IGZhbHNlIDogdmFsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3RzIGlmIGN1cnJlbnQgYnJvd3NlciBzdXBwb3J0cyBIVE1MNSBVcGxvYWQuXG4gICAgICogQHJldHVybnMgYm9vbGVhblxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkuc3VwcG9ydHNVcGxvYWQgPSBmdW5jdGlvbiBzdXBwb3J0c1VwbG9hZCgpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5Db25uZXhpb24pIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cuRm9ybURhdGEgfHwgd2luZG93LkZpbGVSZWFkZXI7XG4gICAgICAgIH0gZWxzZSBpZiAod2luZG93LmpRdWVyeSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5Gb3JtRGF0YTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEluc3RhbmNpYXRlIGEgUHlkaW9BcGkgY2xpZW50IGlmIGl0J3Mgbm90IGFscmVhZHkgaW5zdGFuY2lhdGVkIGFuZCByZXR1cm4gaXQuXG4gICAgICogQHJldHVybnMgUHlkaW9BcGlcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLmdldENsaWVudCA9IGZ1bmN0aW9uIGdldENsaWVudCgpIHtcbiAgICAgICAgaWYgKFB5ZGlvQXBpLl9QeWRpb0NsaWVudCkgcmV0dXJuIFB5ZGlvQXBpLl9QeWRpb0NsaWVudDtcbiAgICAgICAgdmFyIGNsaWVudCA9IG5ldyBQeWRpb0FwaSgpO1xuICAgICAgICBQeWRpb0FwaS5fUHlkaW9DbGllbnQgPSBjbGllbnQ7XG4gICAgICAgIHJldHVybiBjbGllbnQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBqYXZhc2NyaXB0IGxpYnJhcnlcbiAgICAgKiBAcGFyYW0gZmlsZU5hbWUgU3RyaW5nXG4gICAgICogQHBhcmFtIG9uTG9hZGVkQ29kZSBGdW5jdGlvbiBDYWxsYmFja1xuICAgICAqIEBwYXJhbSBhU3luYyBCb29sZWFuIGxvYWQgbGlicmFyeSBhc3luY2hyb25lb3VzbHlcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLmxvYWRMaWJyYXJ5ID0gZnVuY3Rpb24gbG9hZExpYnJhcnkoZmlsZU5hbWUsIG9uTG9hZGVkQ29kZSwgYVN5bmMpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5weWRpbyAmJiBweWRpby5QYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpICYmIGZpbGVOYW1lLmluZGV4T2YoXCI/XCIpID09IC0xKSB7XG4gICAgICAgICAgICBmaWxlTmFtZSArPSBcIj92PVwiICsgcHlkaW8uUGFyYW1ldGVycy5nZXQoXCJhanhwVmVyc2lvblwiKTtcbiAgICAgICAgfVxuICAgICAgICBQeWRpb0FwaS5fbGliVXJsID0gZmFsc2U7XG4gICAgICAgIGlmICh3aW5kb3cucHlkaW8gJiYgcHlkaW8uUGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QUkVGSVhfVVJJJykpIHtcbiAgICAgICAgICAgIFB5ZGlvQXBpLl9saWJVcmwgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjb25uID0gbmV3IENvbm5leGlvbigpO1xuICAgICAgICBjb25uLl9saWJVcmwgPSBmYWxzZTtcbiAgICAgICAgaWYgKHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpKSB7XG4gICAgICAgICAgICBjb25uLl9saWJVcmwgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKTtcbiAgICAgICAgfVxuICAgICAgICBjb25uLmxvYWRMaWJyYXJ5KGZpbGVOYW1lLCBvbkxvYWRlZENvZGUsIGFTeW5jKTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnN3aXRjaFJlcG9zaXRvcnkgPSBmdW5jdGlvbiBzd2l0Y2hSZXBvc2l0b3J5KHJlcG9zaXRvcnlJZCwgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3N3aXRjaF9yZXBvc2l0b3J5JyxcbiAgICAgICAgICAgIHJlcG9zaXRvcnlfaWQ6IHJlcG9zaXRvcnlJZFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnN3aXRjaExhbmd1YWdlID0gZnVuY3Rpb24gc3dpdGNoTGFuZ3VhZ2UobGFuZywgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ2dldF9pMThuX21lc3NhZ2VzJyxcbiAgICAgICAgICAgIGxhbmc6IGxhbmcsXG4gICAgICAgICAgICBmb3JtYXQ6ICdqc29uJ1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmxvYWRYbWxSZWdpc3RyeSA9IGZ1bmN0aW9uIGxvYWRYbWxSZWdpc3RyeShjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB4UGF0aCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHsgZ2V0X2FjdGlvbjogJ2dldF94bWxfcmVnaXN0cnknIH07XG4gICAgICAgIGlmICh4UGF0aCkgcGFyYW1zW3hQYXRoXSA9IHhQYXRoO1xuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmdldEJvb3RDb25mID0gZnVuY3Rpb24gZ2V0Qm9vdENvbmYoY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgcGFyYW1zID0geyBnZXRfYWN0aW9uOiAnZ2V0X2Jvb3RfY29uZicgfTtcbiAgICAgICAgdmFyIGNCID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnQucmVzcG9uc2VKU09OICYmIHRyYW5zcG9ydC5yZXNwb25zZUpTT04uU0VDVVJFX1RPS0VOKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycy5zZXQoJ1NFQ1VSRV9UT0tFTicsIHRyYW5zcG9ydC5yZXNwb25zZUpTT04uU0VDVVJFX1RPS0VOKTtcbiAgICAgICAgICAgICAgICBDb25uZXhpb24udXBkYXRlU2VydmVyQWNjZXNzKHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjb21wbGV0ZUNhbGxiYWNrKHRyYW5zcG9ydCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNCKTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnVzZXJTYXZlUHJlZmVyZW5jZSA9IGZ1bmN0aW9uIHVzZXJTYXZlUHJlZmVyZW5jZShwcmVmTmFtZSwgcHJlZlZhbHVlKSB7XG4gICAgICAgIHRoaXMucmVxdWVzdCh7IGdldF9hY3Rpb246IFwic2F2ZV91c2VyX3ByZWZcIiwgXCJwcmVmX25hbWVfMFwiOiBwcmVmTmFtZSwgXCJwcmVmX3ZhbHVlXzBcIjogcHJlZlZhbHVlIH0sIG51bGwsIG51bGwsIHsgZGlzY3JldGU6IHRydWUsIG1ldGhvZDogJ3Bvc3QnIH0pO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUudXNlclNhdmVQcmVmZXJlbmNlcyA9IGZ1bmN0aW9uIHVzZXJTYXZlUHJlZmVyZW5jZXMocHJlZmVyZW5jZXMsIGNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHsgJ2dldF9hY3Rpb24nOiAnc2F2ZV91c2VyX3ByZWYnIH07XG4gICAgICAgIHZhciBpID0gMDtcbiAgICAgICAgcHJlZmVyZW5jZXMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgcGFyYW1zW1wicHJlZl9uYW1lX1wiICsgaV0gPSBrZXk7XG4gICAgICAgICAgICBwYXJhbXNbXCJwcmVmX3ZhbHVlX1wiICsgaV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2ssIG51bGwsIHsgZGlzY3JldGU6IHRydWUsIG1ldGhvZDogJ3Bvc3QnIH0pO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUudXNlclNhdmVQYXNzd29yZCA9IGZ1bmN0aW9uIHVzZXJTYXZlUGFzc3dvcmQob2xkUGFzcywgbmV3UGFzcywgc2VlZCwgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB0aGlzLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3NhdmVfdXNlcl9wcmVmJyxcbiAgICAgICAgICAgIHByZWZfbmFtZV8wOiBcInBhc3N3b3JkXCIsXG4gICAgICAgICAgICBwcmVmX3ZhbHVlXzA6IG5ld1Bhc3MsXG4gICAgICAgICAgICBjcnQ6IG9sZFBhc3MsXG4gICAgICAgICAgICBwYXNzX3NlZWQ6IHNlZWRcbiAgICAgICAgfSwgY29tcGxldGVDYWxsYmFjaywgbnVsbCwgeyBkaXNjcmV0ZTogdHJ1ZSwgbWV0aG9kOiAncG9zdCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5idWlsZFVzZXJBdmF0YXJVcmwgPSBmdW5jdGlvbiBidWlsZFVzZXJBdmF0YXJVcmwodXNlcklkKSB7XG4gICAgICAgIHZhciBhdmF0YXJJZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgaWYgKGF2YXRhcklkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycy5nZXQoJ2FqeHBTZXJ2ZXJBY2Nlc3MnKSArIFwiJmdldF9hY3Rpb249Z2V0X2JpbmFyeV9wYXJhbSZiaW5hcnlfaWQ9XCIgKyBhdmF0YXJJZCArIFwiJnVzZXJfaWQ9XCIgKyB1c2VySWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuYXBwbHlDaGVja0hvb2sgPSBmdW5jdGlvbiBhcHBseUNoZWNrSG9vayhub2RlLCBob29rTmFtZSwgaG9va0FyZywgY29tcGxldGVDYWxsYmFjaywgYWRkaXRpb25hbFBhcmFtcykge1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogXCJhcHBseV9jaGVja19ob29rXCIsXG4gICAgICAgICAgICBmaWxlOiBub2RlLmdldFBhdGgoKSxcbiAgICAgICAgICAgIGhvb2tfbmFtZTogaG9va05hbWUsXG4gICAgICAgICAgICBob29rX2FyZzogaG9va0FyZ1xuICAgICAgICB9O1xuICAgICAgICBpZiAoYWRkaXRpb25hbFBhcmFtcykge1xuICAgICAgICAgICAgcGFyYW1zID0gTGFuZ1V0aWxzLm9iamVjdE1lcmdlKHBhcmFtcywgYWRkaXRpb25hbFBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXF1ZXN0KHBhcmFtcywgY29tcGxldGVDYWxsYmFjaywgbnVsbCwgeyBhc3luYzogZmFsc2UgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFN0YW5kYXJkIHBhcnNlciBmb3Igc2VydmVyIFhNTCBhbnN3ZXJzXG4gICAgICogQHBhcmFtIHhtbFJlc3BvbnNlIERPTURvY3VtZW50XG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUucGFyc2VYbWxNZXNzYWdlID0gZnVuY3Rpb24gcGFyc2VYbWxNZXNzYWdlKHhtbFJlc3BvbnNlKSB7XG4gICAgICAgIGlmICh4bWxSZXNwb25zZSA9PSBudWxsIHx8IHhtbFJlc3BvbnNlLmRvY3VtZW50RWxlbWVudCA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICAgICAgdmFyIGNoaWxkcyA9IHhtbFJlc3BvbnNlLmRvY3VtZW50RWxlbWVudC5jaGlsZE5vZGVzO1xuICAgICAgICB2YXIgcmVsb2FkTm9kZXMgPSBbXSxcbiAgICAgICAgICAgIGVycm9yID0gZmFsc2U7XG4gICAgICAgIHRoaXMuTEFTVF9FUlJPUl9JRCA9IG51bGw7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkc1tpXTtcbiAgICAgICAgICAgIGlmIChjaGlsZC50YWdOYW1lID09PSBcIm1lc3NhZ2VcIikge1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlVHh0ID0gXCJObyBtZXNzYWdlXCI7XG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLmZpcnN0Q2hpbGQpIG1lc3NhZ2VUeHQgPSBjaGlsZC5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZ2V0QXR0cmlidXRlKCd0eXBlJykgPT0gJ0VSUk9SJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IobWVzc2FnZVR4dCk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIubG9nKG1lc3NhZ2VUeHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQudGFnTmFtZSA9PT0gXCJwcm9tcHRcIikge1xuXG4gICAgICAgICAgICAgICAgaWYgKHB5ZGlvICYmIHB5ZGlvLlVJICYmIHB5ZGlvLlVJLm9wZW5Qcm9tcHREaWFsb2cpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGpzb25EYXRhID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoY2hpbGRzW2ldLCBcImRhdGFcIikuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHB5ZGlvLlVJLm9wZW5Qcm9tcHREaWFsb2coSlNPTi5wYXJzZShqc29uRGF0YSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoaWxkLnRhZ05hbWUgPT0gXCJyZWxvYWRfaW5zdHJ1Y3Rpb25cIikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG9iTmFtZSA9IGNoaWxkLmdldEF0dHJpYnV0ZSgnb2JqZWN0Jyk7XG4gICAgICAgICAgICAgICAgaWYgKG9iTmFtZSA9PT0gJ2RhdGEnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlID0gY2hpbGQuZ2V0QXR0cmlidXRlKCdub2RlJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWxvYWROb2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGUgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoJ2ZpbGUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dEhvbGRlcigpLnNldFBlbmRpbmdTZWxlY3Rpb24oZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZWxvYWROb2Rlcy5wdXNoKHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHROb2RlKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvYk5hbWUgPT0gJ3JlcG9zaXRvcnlfbGlzdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QucmVsb2FkUmVwb3NpdG9yaWVzTGlzdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQubm9kZU5hbWUgPT0gJ25vZGVzX2RpZmYnKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgZG0gPSB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKGRtLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2Rlc0RpZmZzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRtLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2Rlc0RpZmZzKGNoaWxkc1tpXSwgZG0sIHRoaXMuX3B5ZGlvT2JqZWN0LnVzZXIuYWN0aXZlUmVwb3NpdG9yeSwgIXdpbmRvdy5jdXJyZW50TGlnaHRCb3gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQudGFnTmFtZSA9PSBcImxvZ2dpbmdfcmVzdWx0XCIpIHtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRBdHRyaWJ1dGUoXCJzZWN1cmVfdG9rZW5cIikpIHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLnNldCgnU0VDVVJFX1RPS0VOJywgY2hpbGQuZ2V0QXR0cmlidXRlKFwic2VjdXJlX3Rva2VuXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgQ29ubmV4aW9uLnVwZGF0ZVNlcnZlckFjY2Vzcyh0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGNoaWxkLmdldEF0dHJpYnV0ZSgndmFsdWUnKTtcbiAgICAgICAgICAgICAgICB2YXIgZXJyb3JJZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJzEnOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QubG9hZFhtbFJlZ2lzdHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnMCc6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJy0xJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySWQgPSAyODU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnMic6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5sb2FkWG1sUmVnaXN0cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICctMic6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcklkID0gMjg1O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJy0zJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySWQgPSAzNjY7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnLTQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JJZCA9IDM4NjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JJZCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuTEFTVF9FUlJPUl9JRCA9IGVycm9ySWQ7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcih0aGlzLl9weWRpb09iamVjdC5NZXNzYWdlSGFzaFtlcnJvcklkXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC50YWdOYW1lID09IFwidHJpZ2dlcl9iZ19hY3Rpb25cIikge1xuXG4gICAgICAgICAgICAgICAgdmFyIF9uYW1lID0gY2hpbGQuZ2V0QXR0cmlidXRlKFwibmFtZVwiKTtcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZUlkID0gY2hpbGQuZ2V0QXR0cmlidXRlKFwibWVzc2FnZUlkXCIpO1xuICAgICAgICAgICAgICAgIHZhciBwYXJhbWV0ZXJzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2hpbGQuY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyYW1DaGlsZCA9IGNoaWxkLmNoaWxkTm9kZXNbal07XG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbUNoaWxkLnRhZ05hbWUgPT0gJ3BhcmFtJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzW3BhcmFtQ2hpbGQuZ2V0QXR0cmlidXRlKFwibmFtZVwiKV0gPSBwYXJhbUNoaWxkLmdldEF0dHJpYnV0ZShcInZhbHVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcmFtQ2hpbGQudGFnTmFtZSA9PSAnY2xpZW50Q2FsbGJhY2snICYmIHBhcmFtQ2hpbGQuZmlyc3RDaGlsZCAmJiBwYXJhbUNoaWxkLmZpcnN0Q2hpbGQubm9kZVZhbHVlKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYWxsYmFja0NvZGUgPSBwYXJhbUNoaWxkLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sgPSBuZXcgRnVuY3Rpb24oY2FsbGJhY2tDb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX25hbWUgPT0gXCJqYXZhc2NyaXB0X2luc3RydWN0aW9uXCIgJiYgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qubm90aWZ5KFwicmVzcG9uc2UueG1sXCIsIHhtbFJlc3BvbnNlKTtcbiAgICAgICAgaWYgKHJlbG9hZE5vZGVzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dEhvbGRlcigpLm11bHRpcGxlTm9kZXNSZWxvYWQocmVsb2FkTm9kZXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhZXJyb3I7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFN1Ym1pdHMgYSBmb3JtIHVzaW5nIENvbm5leGlvbiBjbGFzcy5cbiAgICAgKiBAcGFyYW0gZm9ybU5hbWUgU3RyaW5nIFRoZSBpZCBvZiB0aGUgZm9ybVxuICAgICAqIEBwYXJhbSBwb3N0IEJvb2xlYW4gV2hldGhlciB0byBQT1NUIG9yIEdFVFxuICAgICAqIEBwYXJhbSBjb21wbGV0ZUNhbGxiYWNrIEZ1bmN0aW9uIENhbGxiYWNrIHRvIGJlIGNhbGxlZCBvbiBjb21wbGV0ZVxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnN1Ym1pdEZvcm0gPSBmdW5jdGlvbiBzdWJtaXRGb3JtKGZvcm1OYW1lKSB7XG4gICAgICAgIHZhciBwb3N0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGNvbXBsZXRlQ2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzJdO1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSB7fTtcbiAgICAgICAgLy8gVE9ETzogVUkgSU1QTEVNRU5UQVRJT05cbiAgICAgICAgJChmb3JtTmFtZSkuZ2V0RWxlbWVudHMoKS5lYWNoKGZ1bmN0aW9uIChmRWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGZWYWx1ZSA9IGZFbGVtZW50LmdldFZhbHVlKCk7XG4gICAgICAgICAgICBpZiAoZkVsZW1lbnQubmFtZSA9PSAnZ2V0X2FjdGlvbicgJiYgZlZhbHVlLnN1YnN0cigwLCA0KSA9PSAnaHR0cCcpIHtcbiAgICAgICAgICAgICAgICBmVmFsdWUgPSBQYXRoVXRpbHMuZ2V0QmFzZW5hbWUoZlZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmRWxlbWVudC50eXBlID09ICdyYWRpbycgJiYgIWZFbGVtZW50LmNoZWNrZWQpIHJldHVybjtcbiAgICAgICAgICAgIGlmIChwYXJhbXNbZkVsZW1lbnQubmFtZV0gJiYgZkVsZW1lbnQubmFtZS5lbmRzV2l0aCgnW10nKSkge1xuICAgICAgICAgICAgICAgIHZhciBleGlzdGluZyA9IHBhcmFtc1tmRWxlbWVudC5uYW1lXTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGV4aXN0aW5nID09ICdzdHJpbmcnKSBleGlzdGluZyA9IFtleGlzdGluZ107XG4gICAgICAgICAgICAgICAgZXhpc3RpbmcucHVzaChmVmFsdWUpO1xuICAgICAgICAgICAgICAgIHBhcmFtc1tmRWxlbWVudC5uYW1lXSA9IGV4aXN0aW5nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwYXJhbXNbZkVsZW1lbnQubmFtZV0gPSBmVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dE5vZGUoKSkge1xuICAgICAgICAgICAgcGFyYW1zWydkaXInXSA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHROb2RlKCkuZ2V0UGF0aCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvbkNvbXBsZXRlID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAgICAgb25Db21wbGV0ZSA9IGNvbXBsZXRlQ2FsbGJhY2s7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlWG1sTWVzc2FnZSh0cmFuc3BvcnQucmVzcG9uc2VYTUwpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBvbkNvbXBsZXRlLCBudWxsLCB7IG1ldGhvZDogcG9zdCA/ICdwb3N0JyA6ICdnZXQnIH0pO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUucG9zdFNlbGVjdGlvbldpdGhBY3Rpb24gPSBmdW5jdGlvbiBwb3N0U2VsZWN0aW9uV2l0aEFjdGlvbihhY3Rpb25OYW1lKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBzZWxlY3Rpb25Nb2RlbCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciBhZGRpdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgaWYgKCFzZWxlY3Rpb25Nb2RlbCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uTW9kZWwgPSB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246IGFjdGlvbk5hbWUsXG4gICAgICAgICAgICBkaXI6IHNlbGVjdGlvbk1vZGVsLmdldENvbnRleHROb2RlKCkuZ2V0UGF0aCgpXG4gICAgICAgIH07XG4gICAgICAgIHBhcmFtc1snbm9kZXNbXSddID0gc2VsZWN0aW9uTW9kZWwuZ2V0RmlsZU5hbWVzKCk7XG4gICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1ldGVycykge1xuICAgICAgICAgICAgcGFyYW1zID0gT2JqZWN0LmFzc2lnbihwYXJhbXMsIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgYSBzaW1wbGUgZG93bmxvYWRcbiAgICAgKiBAcGFyYW0gdXJsIFN0cmluZ1xuICAgICAqL1xuXG4gICAgUHlkaW9BcGkudHJpZ2dlckRvd25sb2FkID0gZnVuY3Rpb24gdHJpZ2dlckRvd25sb2FkKHVybCkge1xuICAgICAgICBkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgIH07XG5cbiAgICByZXR1cm4gUHlkaW9BcGk7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBQeWRpb0FwaTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG4vKipcbiAqIFB5ZGlvIGVuY2Fwc3VsYXRpb24gb2YgWEhSIC8gRmV0Y2hcbiAqL1xucmVxdWlyZSgnd2hhdHdnLWZldGNoJyk7XG5cbnZhciBDb25uZXhpb24gPSAoZnVuY3Rpb24gKCkge1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gYmFzZVVybCBTdHJpbmcgVGhlIGJhc2UgdXJsIGZvciBzZXJ2aWNlc1xuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gQ29ubmV4aW9uKGJhc2VVcmwpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbm5leGlvbik7XG5cbiAgICAgICAgdGhpcy5fcHlkaW8gPSB3aW5kb3cucHlkaW87XG4gICAgICAgIHRoaXMuX2Jhc2VVcmwgPSBiYXNlVXJsIHx8IHdpbmRvdy5hanhwU2VydmVyQWNjZXNzUGF0aDtcbiAgICAgICAgdGhpcy5fbGliVXJsID0gd2luZG93LmFqeHBSZXNvdXJjZXNGb2xkZXIgKyAnL2J1aWxkJztcbiAgICAgICAgdGhpcy5fcGFyYW1ldGVycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fbWV0aG9kID0gJ3Bvc3QnO1xuICAgICAgICB0aGlzLmRpc2NyZXRlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgQ29ubmV4aW9uLnVwZGF0ZVNlcnZlckFjY2VzcyA9IGZ1bmN0aW9uIHVwZGF0ZVNlcnZlckFjY2VzcyhwYXJhbWV0ZXJzKSB7XG5cbiAgICAgICAgaWYgKHBhcmFtZXRlcnMuZ2V0KCdTRUNVUkVfVE9LRU4nKSkge1xuICAgICAgICAgICAgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiA9IHBhcmFtZXRlcnMuZ2V0KCdTRUNVUkVfVE9LRU4nKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2VydmVyQWNjZXNzUGF0aCA9IHBhcmFtZXRlcnMuZ2V0KCdhanhwU2VydmVyQWNjZXNzJykuc3BsaXQoJz8nKS5zaGlmdCgpO1xuICAgICAgICBpZiAocGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QUkVGSVhfVVJJJykpIHtcbiAgICAgICAgICAgIHBhcmFtZXRlcnMuc2V0KCdhanhwUmVzb3VyY2VzRm9sZGVyJywgcGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QUkVGSVhfVVJJJykgKyBwYXJhbWV0ZXJzLmdldCgnYWp4cFJlc291cmNlc0ZvbGRlcicpKTtcbiAgICAgICAgICAgIHNlcnZlckFjY2Vzc1BhdGggPSBwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSArIHNlcnZlckFjY2Vzc1BhdGggKyAnPycgKyAoQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiA/ICdzZWN1cmVfdG9rZW49JyArIENvbm5leGlvbi5TRUNVUkVfVE9LRU4gOiAnJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXJ2ZXJBY2Nlc3NQYXRoID0gc2VydmVyQWNjZXNzUGF0aCArICc/JyArIChDb25uZXhpb24uU0VDVVJFX1RPS0VOID8gJ3NlY3VyZV90b2tlbj0nICsgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiA6ICcnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QRVJNQU5FTlRfUEFSQU1TJykpIHtcbiAgICAgICAgICAgIHZhciBwZXJtUGFyYW1zID0gcGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QRVJNQU5FTlRfUEFSQU1TJyk7XG4gICAgICAgICAgICB2YXIgcGVybVN0cmluZ3MgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIHBlcm1hbmVudCBpbiBwZXJtUGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBlcm1QYXJhbXMuaGFzT3duUHJvcGVydHkocGVybWFuZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBwZXJtU3RyaW5ncy5wdXNoKHBlcm1hbmVudCArICc9JyArIHBlcm1QYXJhbXNbcGVybWFuZW50XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGVybVN0cmluZ3MgPSBwZXJtU3RyaW5ncy5qb2luKCcmJyk7XG4gICAgICAgICAgICBpZiAocGVybVN0cmluZ3MpIHtcbiAgICAgICAgICAgICAgICBzZXJ2ZXJBY2Nlc3NQYXRoICs9ICcmJyArIHBlcm1TdHJpbmdzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcGFyYW1ldGVycy5zZXQoJ2FqeHBTZXJ2ZXJBY2Nlc3MnLCBzZXJ2ZXJBY2Nlc3NQYXRoKTtcbiAgICAgICAgLy8gQkFDS1dBUkQgQ09NUEFUXG4gICAgICAgIHdpbmRvdy5hanhwU2VydmVyQWNjZXNzUGF0aCA9IHNlcnZlckFjY2Vzc1BhdGg7XG4gICAgICAgIGlmICh3aW5kb3cucHlkaW9Cb290c3RyYXAgJiYgd2luZG93LnB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgIHB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuc2V0KFwiYWp4cFNlcnZlckFjY2Vzc1wiLCBzZXJ2ZXJBY2Nlc3NQYXRoKTtcbiAgICAgICAgICAgIHB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuc2V0KFwiU0VDVVJFX1RPS0VOXCIsIENvbm5leGlvbi5TRUNVUkVfVE9LRU4pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIENvbm5leGlvbi5sb2cgPSBmdW5jdGlvbiBsb2coYWN0aW9uLCBzeW5jU3RhdHVzKSB7XG4gICAgICAgIGlmICghQ29ubmV4aW9uLlB5ZGlvTG9ncykge1xuICAgICAgICAgICAgQ29ubmV4aW9uLlB5ZGlvTG9ncyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIENvbm5leGlvbi5QeWRpb0xvZ3MucHVzaCh7IGFjdGlvbjogYWN0aW9uLCBzeW5jOiBzeW5jU3RhdHVzIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBwYXJhbWV0ZXIgdG8gdGhlIHF1ZXJ5XG4gICAgICogQHBhcmFtIHBhcmFtTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gcGFyYW1WYWx1ZSBTdHJpbmdcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuYWRkUGFyYW1ldGVyID0gZnVuY3Rpb24gYWRkUGFyYW1ldGVyKHBhcmFtTmFtZSwgcGFyYW1WYWx1ZSkge1xuICAgICAgICBpZiAodGhpcy5fcGFyYW1ldGVycy5nZXQocGFyYW1OYW1lKSAmJiBwYXJhbU5hbWUuZW5kc1dpdGgoJ1tdJykpIHtcbiAgICAgICAgICAgIHZhciBleGlzdGluZyA9IHRoaXMuX3BhcmFtZXRlcnMuZ2V0KHBhcmFtTmFtZSk7XG4gICAgICAgICAgICBpZiAoIWV4aXN0aW5nIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgICAgICBleGlzdGluZyA9IFtleGlzdGluZ107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBleGlzdGluZy5wdXNoKHBhcmFtVmFsdWUpO1xuICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycy5zZXQocGFyYW1OYW1lLCBleGlzdGluZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLnNldChwYXJhbU5hbWUsIHBhcmFtVmFsdWUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHdob2xlIHBhcmFtZXRlciBhcyBhIGJ1bmNoXG4gICAgICogQHBhcmFtIGhQYXJhbWV0ZXJzIE1hcFxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZXRQYXJhbWV0ZXJzID0gZnVuY3Rpb24gc2V0UGFyYW1ldGVycyhoUGFyYW1ldGVycykge1xuICAgICAgICBpZiAoaFBhcmFtZXRlcnMgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICAgIHRoaXMuX3BhcmFtZXRlcnMgPSBoUGFyYW1ldGVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChoUGFyYW1ldGVycy5fb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignUGFzc2VkIGEgbGVnYWN5IEhhc2ggb2JqZWN0IHRvIENvbm5leGlvbi5zZXRQYXJhbWV0ZXJzJyk7XG4gICAgICAgICAgICAgICAgaFBhcmFtZXRlcnMgPSBoUGFyYW1ldGVycy5fb2JqZWN0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGhQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhQYXJhbWV0ZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycy5zZXQoa2V5LCBoUGFyYW1ldGVyc1trZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBxdWVyeSBtZXRob2QgKGdldCBwb3N0KVxuICAgICAqIEBwYXJhbSBtZXRob2QgU3RyaW5nXG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnNldE1ldGhvZCA9IGZ1bmN0aW9uIHNldE1ldGhvZChtZXRob2QpIHtcbiAgICAgICAgdGhpcy5fbWV0aG9kID0gbWV0aG9kO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGQgdGhlIHNlY3VyZSB0b2tlbiBwYXJhbWV0ZXJcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuYWRkU2VjdXJlVG9rZW4gPSBmdW5jdGlvbiBhZGRTZWN1cmVUb2tlbigpIHtcblxuICAgICAgICBpZiAoQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiAmJiB0aGlzLl9iYXNlVXJsLmluZGV4T2YoJ3NlY3VyZV90b2tlbicpID09IC0xICYmICF0aGlzLl9wYXJhbWV0ZXJzLmdldCgnc2VjdXJlX3Rva2VuJykpIHtcblxuICAgICAgICAgICAgdGhpcy5hZGRQYXJhbWV0ZXIoJ3NlY3VyZV90b2tlbicsIENvbm5leGlvbi5TRUNVUkVfVE9LRU4pO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2Jhc2VVcmwuaW5kZXhPZignc2VjdXJlX3Rva2VuPScpICE9PSAtMSkge1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBiYXNlVXJsIGFuZCBzZXQgaW5zaWRlIHBhcmFtc1xuICAgICAgICAgICAgdmFyIHBhcnRzID0gdGhpcy5fYmFzZVVybC5zcGxpdCgnc2VjdXJlX3Rva2VuPScpO1xuICAgICAgICAgICAgdmFyIHRva3MgPSBwYXJ0c1sxXS5zcGxpdCgnJicpO1xuICAgICAgICAgICAgdmFyIHRva2VuID0gdG9rcy5zaGlmdCgpO1xuICAgICAgICAgICAgdmFyIHJlc3QgPSB0b2tzLmpvaW4oJyYnKTtcbiAgICAgICAgICAgIHRoaXMuX2Jhc2VVcmwgPSBwYXJ0c1swXSArIChyZXN0ID8gJyYnICsgcmVzdCA6ICcnKTtcbiAgICAgICAgICAgIHRoaXMuX3BhcmFtZXRlcnMuc2V0KCdzZWN1cmVfdG9rZW4nLCB0b2tlbik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hZGRTZXJ2ZXJQZXJtYW5lbnRQYXJhbXMgPSBmdW5jdGlvbiBhZGRTZXJ2ZXJQZXJtYW5lbnRQYXJhbXMoKSB7XG4gICAgICAgIGlmICghdGhpcy5fcHlkaW8gfHwgIXRoaXMuX3B5ZGlvLlBhcmFtZXRlcnMuaGFzKCdTRVJWRVJfUEVSTUFORU5UX1BBUkFNUycpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBlcm1QYXJhbXMgPSB0aGlzLl9weWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BFUk1BTkVOVF9QQVJBTVMnKTtcbiAgICAgICAgZm9yICh2YXIgcGVybWFuZW50IGluIHBlcm1QYXJhbXMpIHtcbiAgICAgICAgICAgIGlmIChwZXJtUGFyYW1zLmhhc093blByb3BlcnR5KHBlcm1hbmVudCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcihwZXJtYW5lbnQsIHBlcm1QYXJhbXNbcGVybWFuZW50XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2hvdyBhIHNtYWxsIGxvYWRlclxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zaG93TG9hZGVyID0gZnVuY3Rpb24gc2hvd0xvYWRlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzY3JldGUgfHwgIXRoaXMuX3B5ZGlvKSByZXR1cm47XG4gICAgICAgIHRoaXMuX3B5ZGlvLm5vdGlmeShcImNvbm5lY3Rpb24tc3RhcnRcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEhpZGUgYSBzbWFsbCBsb2FkZXJcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuaGlkZUxvYWRlciA9IGZ1bmN0aW9uIGhpZGVMb2FkZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc2NyZXRlIHx8ICF0aGlzLl9weWRpbykgcmV0dXJuO1xuICAgICAgICB0aGlzLl9weWRpby5ub3RpZnkoXCJjb25uZWN0aW9uLWVuZFwiKTtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5fc2VuZCA9IGZ1bmN0aW9uIF9zZW5kKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIHZhciBhU3luYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgQ29ubmV4aW9uLmxvZyh0aGlzLl9wYXJhbWV0ZXJzLmdldChcImdldF9hY3Rpb25cIiksIGFTeW5jID8gJ2FzeW5jJyA6ICdzeW5jJyk7XG4gICAgICAgIHRoaXMuYWRkU2VjdXJlVG9rZW4oKTtcbiAgICAgICAgdGhpcy5hZGRTZXJ2ZXJQZXJtYW5lbnRQYXJhbXMoKTtcbiAgICAgICAgdGhpcy5zaG93TG9hZGVyKCk7XG4gICAgICAgIHZhciBvVGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICAgICAgbWV0aG9kOiB0aGlzLl9tZXRob2QsXG4gICAgICAgICAgICBjcmVkZW50aWFsczogJ3NhbWUtb3JpZ2luJ1xuICAgICAgICB9O1xuICAgICAgICB2YXIgdXJsID0gdGhpcy5fYmFzZVVybDtcbiAgICAgICAgaWYgKCFhU3luYykge1xuICAgICAgICAgICAgb3B0aW9ucy5zeW5jaHJvbm91cyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJvZHlQYXJ0cyA9IFtdO1xuICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAgICAgdmFsdWUubWFwKGZ1bmN0aW9uIChvbmVWKSB7XG4gICAgICAgICAgICAgICAgICAgIGJvZHlQYXJ0cy5wdXNoKGtleSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChvbmVWKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJvZHlQYXJ0cy5wdXNoKGtleSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHF1ZXJ5U3RyaW5nID0gYm9keVBhcnRzLmpvaW4oJyYnKTtcbiAgICAgICAgaWYgKHRoaXMuX21ldGhvZCA9PT0gJ3Bvc3QnKSB7XG4gICAgICAgICAgICBvcHRpb25zLmhlYWRlcnMgPSB7IFwiQ29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04XCIgfTtcbiAgICAgICAgICAgIG9wdGlvbnMuYm9keSA9IHF1ZXJ5U3RyaW5nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXJsICs9ICh1cmwuaW5kZXhPZignPycpID4gLTEgPyAnJicgOiAnPycpICsgcXVlcnlTdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgd2luZG93LmZldGNoKHVybCwgb3B0aW9ucykudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcblxuICAgICAgICAgICAgdmFyIGggPSByZXNwb25zZS5oZWFkZXJzLmdldCgnQ29udGVudC10eXBlJyk7XG4gICAgICAgICAgICBpZiAoaC5pbmRleE9mKCcvanNvbicpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmpzb24oKS50aGVuKGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgICAgICAgICAgICAgIG9UaGlzLmFwcGx5Q29tcGxldGUoeyByZXNwb25zZUpTT046IGpzb24gfSwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChoLmluZGV4T2YoJy94bWwnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXNwb25zZS50ZXh0KCkudGhlbihmdW5jdGlvbiAodGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBvVGhpcy5hcHBseUNvbXBsZXRlKHsgcmVzcG9uc2VYTUw6IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10ucGFyc2VYbWwodGV4dCkgfSwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNwb25zZS50ZXh0KCkudGhlbihmdW5jdGlvbiAodGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBvVGhpcy5hcHBseUNvbXBsZXRlKHsgcmVzcG9uc2VUZXh0OiB0ZXh0IH0sIHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfSlbJ2NhdGNoJ10oZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuX3B5ZGlvKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX3B5ZGlvLmRpc3BsYXlNZXNzYWdlKCdFUlJPUicsICdOZXR3b3JrIGVycm9yICcgKyBlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlbmQgQXN5bmNocm9ub3VzbHlcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuc2VuZEFzeW5jID0gZnVuY3Rpb24gc2VuZEFzeW5jKCkge1xuICAgICAgICB0aGlzLl9zZW5kKHRydWUpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHN5bmNocm9ub3VzbHlcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuc2VuZFN5bmMgPSBmdW5jdGlvbiBzZW5kU3luYygpIHtcbiAgICAgICAgdGhpcy5fc2VuZChmYWxzZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFwcGx5IHRoZSBjb21wbGV0ZSBjYWxsYmFjaywgdHJ5IHRvIGdyYWIgbWF4aW11bSBvZiBlcnJvcnNcbiAgICAgKiBAcGFyYW0gcGFyc2VkQm9keSBUcmFuc3BvdFxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hcHBseUNvbXBsZXRlID0gZnVuY3Rpb24gYXBwbHlDb21wbGV0ZShwYXJzZWRCb2R5LCByZXNwb25zZSkge1xuICAgICAgICB0aGlzLmhpZGVMb2FkZXIoKTtcbiAgICAgICAgdmFyIHB5ZGlvID0gdGhpcy5fcHlkaW87XG4gICAgICAgIHZhciBtZXNzYWdlID0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgdG9rZW5NZXNzYWdlID0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgdG9rMSA9IFwiT29vcHMsIGl0IHNlZW1zIHRoYXQgeW91ciBzZWN1cml0eSB0b2tlbiBoYXMgZXhwaXJlZCEgUGxlYXNlICVzIGJ5IGhpdHRpbmcgcmVmcmVzaCBvciBGNSBpbiB5b3VyIGJyb3dzZXIhXCI7XG4gICAgICAgIHZhciB0b2syID0gXCJyZWxvYWQgdGhlIHBhZ2VcIjtcbiAgICAgICAgaWYgKHdpbmRvdy5NZXNzYWdlSGFzaCAmJiB3aW5kb3cuTWVzc2FnZUhhc2hbNDM3XSkge1xuICAgICAgICAgICAgdG9rMSA9IHdpbmRvdy5NZXNzYWdlSGFzaFs0MzddO1xuICAgICAgICAgICAgdG9rMiA9IHdpbmRvdy5NZXNzYWdlSGFzaFs0MzhdO1xuICAgICAgICB9XG4gICAgICAgIHRva2VuTWVzc2FnZSA9IHRvazEucmVwbGFjZShcIiVzXCIsIFwiPGEgaHJlZj0namF2YXNjcmlwdDpkb2N1bWVudC5sb2NhdGlvbi5yZWxvYWQoKScgc3R5bGU9J3RleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOyc+XCIgKyB0b2syICsgXCI8L2E+XCIpO1xuXG4gICAgICAgIHZhciBjdHlwZSA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdDb250ZW50LXR5cGUnKTtcbiAgICAgICAgaWYgKHBhcnNlZEJvZHkucmVzcG9uc2VYTUwgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgPT0gXCJwYXJzZXJlcnJvclwiKSB7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIlBhcnNpbmcgZXJyb3IgOiBcXG5cIiArIHBhcnNlZEJvZHkucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQudGV4dENvbnRlbnQ7XG4gICAgICAgIH0gZWxzZSBpZiAocGFyc2VkQm9keS5yZXNwb25zZVhNTCAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLnBhcnNlRXJyb3IgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5wYXJzZUVycm9yLmVycm9yQ29kZSAhPSAwKSB7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIlBhcnNpbmcgRXJyb3IgOiBcXG5cIiArIHBhcnNlZEJvZHkucmVzcG9uc2VYTUwucGFyc2VFcnJvci5yZWFzb247XG4gICAgICAgIH0gZWxzZSBpZiAoY3R5cGUuaW5kZXhPZihcInRleHQveG1sXCIpID4gLTEgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTCA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIkV4cGVjdGVkIFhNTCBidXQgZ290IGVtcHR5IHJlc3BvbnNlIVwiO1xuICAgICAgICB9IGVsc2UgaWYgKGN0eXBlLmluZGV4T2YoXCJ0ZXh0L3htbFwiKSA9PSAtMSAmJiBjdHlwZS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSA9PSAtMSAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlVGV4dC5pbmRleE9mKFwiPGI+RmF0YWwgZXJyb3I8L2I+XCIpID4gLTEpIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IHBhcnNlZEJvZHkucmVzcG9uc2VUZXh0LnJlcGxhY2UoXCI8YnIgLz5cIiwgXCJcIik7XG4gICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2Uuc3RhdHVzID09IDUwMCkge1xuXG4gICAgICAgICAgICBtZXNzYWdlID0gXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3I6IHlvdSBzaG91bGQgY2hlY2sgeW91ciB3ZWIgc2VydmVyIGxvZ3MgdG8gZmluZCB3aGF0J3MgZ29pbmcgd3JvbmchXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lc3NhZ2UpIHtcblxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RhcnRzV2l0aChcIllvdSBhcmUgbm90IGFsbG93ZWQgdG8gYWNjZXNzIHRoaXMgcmVzb3VyY2UuXCIpKSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IHRva2VuTWVzc2FnZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChweWRpbykge1xuICAgICAgICAgICAgICAgIHB5ZGlvLmRpc3BsYXlNZXNzYWdlKFwiRVJST1JcIiwgbWVzc2FnZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFsZXJ0KG1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJzZWRCb2R5LnJlc3BvbnNlWE1MICYmIHBhcnNlZEJvZHkucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50KSB7XG5cbiAgICAgICAgICAgIHZhciBhdXRoTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHBhcnNlZEJvZHkucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50LCBcInJlcXVpcmVfYXV0aFwiKTtcbiAgICAgICAgICAgIGlmIChhdXRoTm9kZSAmJiBweWRpbykge1xuICAgICAgICAgICAgICAgIHZhciByb290ID0gcHlkaW8uZ2V0Q29udGV4dEhvbGRlcigpLmdldFJvb3ROb2RlKCk7XG4gICAgICAgICAgICAgICAgaWYgKHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgcHlkaW8uZ2V0Q29udGV4dEhvbGRlcigpLnNldENvbnRleHROb2RlKHJvb3QpO1xuICAgICAgICAgICAgICAgICAgICByb290LmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHB5ZGlvLmdldENvbnRyb2xsZXIoKS5maXJlQWN0aW9uKCdsb2dvdXQnKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcHlkaW8uZ2V0Q29udHJvbGxlcigpLmZpcmVBY3Rpb24oJ2xvZ2luJyk7XG4gICAgICAgICAgICAgICAgfSwgMzUwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG1lc3NhZ2VOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQsIFwibWVzc2FnZVwiKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlTm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlVHlwZSA9IG1lc3NhZ2VOb2RlLmdldEF0dHJpYnV0ZShcInR5cGVcIikudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZUNvbnRlbnQgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLmdldERvbU5vZGVUZXh0KG1lc3NhZ2VOb2RlKTtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZUNvbnRlbnQuc3RhcnRzV2l0aChcIllvdSBhcmUgbm90IGFsbG93ZWQgdG8gYWNjZXNzIHRoaXMgcmVzb3VyY2UuXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VDb250ZW50ID0gdG9rZW5NZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocHlkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgcHlkaW8uZGlzcGxheU1lc3NhZ2UobWVzc2FnZVR5cGUsIG1lc3NhZ2VDb250ZW50KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWVzc2FnZVR5cGUgPT0gXCJFUlJPUlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGVydChtZXNzYWdlVHlwZSArIFwiOlwiICsgbWVzc2FnZUNvbnRlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlVHlwZSA9PSBcIlNVQ0NFU1NcIikgbWVzc2FnZU5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChtZXNzYWdlTm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMub25Db21wbGV0ZSkge1xuXG4gICAgICAgICAgICBwYXJzZWRCb2R5LnN0YXR1cyA9IHJlc3BvbnNlLnN0YXR1cztcbiAgICAgICAgICAgIHBhcnNlZEJvZHkucmVzcG9uc2VPYmplY3QgPSByZXNwb25zZTtcbiAgICAgICAgICAgIHRoaXMub25Db21wbGV0ZShwYXJzZWRCb2R5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocHlkaW8pIHtcbiAgICAgICAgICAgIHB5ZGlvLmZpcmUoXCJzZXJ2ZXJfYW5zd2VyXCIsIHRoaXMpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUudXBsb2FkRmlsZSA9IGZ1bmN0aW9uIHVwbG9hZEZpbGUoZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUsIHVwbG9hZFVybCwgb25Db21wbGV0ZSwgb25FcnJvciwgb25Qcm9ncmVzcywgeGhyU2V0dGluZ3MpIHtcblxuICAgICAgICBpZiAoeGhyU2V0dGluZ3MgPT09IHVuZGVmaW5lZCkgeGhyU2V0dGluZ3MgPSB7fTtcblxuICAgICAgICBpZiAoIW9uQ29tcGxldGUpIG9uQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgaWYgKCFvbkVycm9yKSBvbkVycm9yID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgIGlmICghb25Qcm9ncmVzcykgb25Qcm9ncmVzcyA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICB2YXIgeGhyID0gdGhpcy5pbml0aWFsaXplWEhSRm9yVXBsb2FkKHVwbG9hZFVybCwgb25Db21wbGV0ZSwgb25FcnJvciwgb25Qcm9ncmVzcywgeGhyU2V0dGluZ3MpO1xuICAgICAgICBpZiAod2luZG93LkZvcm1EYXRhKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRGaWxlVXNpbmdGb3JtRGF0YSh4aHIsIGZpbGUsIGZpbGVQYXJhbWV0ZXJOYW1lKTtcbiAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cuRmlsZVJlYWRlcikge1xuICAgICAgICAgICAgdmFyIGZpbGVSZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICAgICAgZmlsZVJlYWRlci5vbmxvYWQgPSAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnhoclNlbmRBc0JpbmFyeSh4aHIsIGZpbGUubmFtZSwgZS50YXJnZXQucmVzdWx0LCBmaWxlUGFyYW1ldGVyTmFtZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgZmlsZVJlYWRlci5yZWFkQXNCaW5hcnlTdHJpbmcoZmlsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZmlsZS5nZXRBc0JpbmFyeSkge1xuICAgICAgICAgICAgdGhpcy54aHJTZW5kQXNCaW5hcnkoeGhyLCBmaWxlLm5hbWUsIGZpbGUuZ2V0QXNCaW5hcnkoKSwgZmlsZVBhcmFtZXRlck5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuaW5pdGlhbGl6ZVhIUkZvclVwbG9hZCA9IGZ1bmN0aW9uIGluaXRpYWxpemVYSFJGb3JVcGxvYWQodXJsLCBvbkNvbXBsZXRlLCBvbkVycm9yLCBvblByb2dyZXNzLCB4aHJTZXR0aW5ncykge1xuXG4gICAgICAgIGlmICh4aHJTZXR0aW5ncyA9PT0gdW5kZWZpbmVkKSB4aHJTZXR0aW5ncyA9IHt9O1xuXG4gICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgdmFyIHVwbG9hZCA9IHhoci51cGxvYWQ7XG4gICAgICAgIGlmICh4aHJTZXR0aW5ncy53aXRoQ3JlZGVudGlhbHMpIHtcbiAgICAgICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHVwbG9hZC5hZGRFdmVudExpc3RlbmVyKFwicHJvZ3Jlc3NcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5sZW5ndGhDb21wdXRhYmxlKSByZXR1cm47XG4gICAgICAgICAgICBvblByb2dyZXNzKGUpO1xuICAgICAgICB9LCBmYWxzZSk7XG4gICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IDQpIHtcbiAgICAgICAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9uQ29tcGxldGUoeGhyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvbkVycm9yKHhocik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB1cGxvYWQub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIG9uRXJyb3IoeGhyKTtcbiAgICAgICAgfTtcbiAgICAgICAgeGhyLm9wZW4oXCJQT1NUXCIsIHVybCwgdHJ1ZSk7XG4gICAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuc2VuZEZpbGVVc2luZ0Zvcm1EYXRhID0gZnVuY3Rpb24gc2VuZEZpbGVVc2luZ0Zvcm1EYXRhKHhociwgZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUpIHtcbiAgICAgICAgdmFyIGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgIGZvcm1EYXRhLmFwcGVuZChmaWxlUGFyYW1ldGVyTmFtZSwgZmlsZSk7XG4gICAgICAgIHhoci5zZW5kKGZvcm1EYXRhKTtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS54aHJTZW5kQXNCaW5hcnkgPSBmdW5jdGlvbiB4aHJTZW5kQXNCaW5hcnkoeGhyLCBmaWxlTmFtZSwgZmlsZURhdGEsIGZpbGVQYXJhbWV0ZXJOYW1lKSB7XG4gICAgICAgIHZhciBib3VuZGFyeSA9ICctLS0tTXVsdGlQYXJ0Rm9ybUJvdW5kYXJ5JyArIG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcIm11bHRpcGFydC9mb3JtLWRhdGEsIGJvdW5kYXJ5PVwiICsgYm91bmRhcnkpO1xuXG4gICAgICAgIHZhciBib2R5ID0gXCItLVwiICsgYm91bmRhcnkgKyBcIlxcclxcblwiO1xuICAgICAgICBib2R5ICs9IFwiQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSdcIiArIGZpbGVQYXJhbWV0ZXJOYW1lICsgXCInOyBmaWxlbmFtZT0nXCIgKyB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoZmlsZU5hbWUpKSArIFwiJ1xcclxcblwiO1xuICAgICAgICBib2R5ICs9IFwiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cXHJcXG5cXHJcXG5cIjtcbiAgICAgICAgYm9keSArPSBmaWxlRGF0YSArIFwiXFxyXFxuXCI7XG4gICAgICAgIGJvZHkgKz0gXCItLVwiICsgYm91bmRhcnkgKyBcIi0tXFxyXFxuXCI7XG5cbiAgICAgICAgeGhyLnNlbmRBc0JpbmFyeShib2R5KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIGphdmFzY3JpcHQgbGlicmFyeVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gb25Mb2FkZWRDb2RlIEZ1bmN0aW9uIENhbGxiYWNrXG4gICAgICAgICogQHBhcmFtIGFTeW5jIEJvb2xlYW4gbG9hZCBsaWJyYXJ5IGFzeW5jaHJvbmVvdXNseVxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5sb2FkTGlicmFyeSA9IGZ1bmN0aW9uIGxvYWRMaWJyYXJ5KGZpbGVOYW1lLCBvbkxvYWRlZENvZGUsIGFTeW5jKSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIGlmICh3aW5kb3cucHlkaW9Cb290c3RyYXAgJiYgd2luZG93LnB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuZ2V0KFwiYWp4cFZlcnNpb25cIikgJiYgZmlsZU5hbWUuaW5kZXhPZihcIj9cIikgPT0gLTEpIHtcbiAgICAgICAgICAgIGZpbGVOYW1lICs9IFwiP3Y9XCIgKyB3aW5kb3cucHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJhanhwVmVyc2lvblwiKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXJsID0gdGhpcy5fbGliVXJsID8gdGhpcy5fbGliVXJsICsgJy8nICsgZmlsZU5hbWUgOiBmaWxlTmFtZTtcbiAgICAgICAgdmFyIHB5ZGlvID0gdGhpcy5fcHlkaW87XG5cbiAgICAgICAgdmFyIHNjcmlwdExvYWRlZCA9IGZ1bmN0aW9uIHNjcmlwdExvYWRlZChzY3JpcHQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHdpbmRvdy5leGVjU2NyaXB0KSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5leGVjU2NyaXB0KHNjcmlwdCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lm15X2NvZGUgPSBzY3JpcHQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoZWFkID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2hlYWQnKVswXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNjcmlwdF90YWcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICAgICAgICAgICAgICAgICAgc2NyaXB0X3RhZy50eXBlID0gJ3RleHQvamF2YXNjcmlwdCc7XG4gICAgICAgICAgICAgICAgICAgIHNjcmlwdF90YWcuaW5uZXJIVE1MID0gJ2V2YWwod2luZG93Lm15X2NvZGUpJztcbiAgICAgICAgICAgICAgICAgICAgaGVhZC5hcHBlbmRDaGlsZChzY3JpcHRfdGFnKTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHdpbmRvdy5teV9jb2RlO1xuICAgICAgICAgICAgICAgICAgICBoZWFkLnJlbW92ZUNoaWxkKHNjcmlwdF90YWcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAob25Mb2FkZWRDb2RlICE9IG51bGwpIG9uTG9hZGVkQ29kZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGFsZXJ0KCdlcnJvciBsb2FkaW5nICcgKyBmaWxlTmFtZSArICc6JyArIGUubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnNvbGUpIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHlkaW8pIHB5ZGlvLmZpcmUoXCJzZXJ2ZXJfYW5zd2VyXCIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChhU3luYykge1xuICAgICAgICAgICAgd2luZG93LmZldGNoKHVybCwge1xuICAgICAgICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAgICAgICAgY3JlZGVudGlhbHM6ICdzYW1lLW9yaWdpbidcbiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnRleHQoKTtcbiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHNjcmlwdCkge1xuICAgICAgICAgICAgICAgIHNjcmlwdExvYWRlZChzY3JpcHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIC8vIFNIT1VMRCBCRSBSRU1PVkVEISFcbiAgICAgICAgICAgICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NyaXB0TG9hZGVkKHhoci5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGVydCgnZXJyb3IgbG9hZGluZyAnICsgZmlsZU5hbWUgKyAnOiBTdGF0dXMgY29kZSB3YXMgJyArIHhoci5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuYmluZChfdGhpczIpO1xuICAgICAgICAgICAgICAgIHhoci5vcGVuKFwiR0VUXCIsIHVybCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHhoci5zZW5kKCk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBDb25uZXhpb247XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBDb25uZXhpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxuLyoqXG4gKiBBUEkgQ2xpZW50XG4gKi9cblxudmFyIE1ldGFDYWNoZVNlcnZpY2UgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKE1ldGFDYWNoZVNlcnZpY2UsIF9PYnNlcnZhYmxlKTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UuZ2V0SW5zdGFuY2UgPSBmdW5jdGlvbiBnZXRJbnN0YW5jZSgpIHtcbiAgICAgICAgaWYgKCFNZXRhQ2FjaGVTZXJ2aWNlLklOU1RBTkNFKSB7XG4gICAgICAgICAgICBNZXRhQ2FjaGVTZXJ2aWNlLklOU1RBTkNFID0gbmV3IE1ldGFDYWNoZVNlcnZpY2UoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWV0YUNhY2hlU2VydmljZS5JTlNUQU5DRTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gTWV0YUNhY2hlU2VydmljZSgpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIE1ldGFDYWNoZVNlcnZpY2UpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuX3N0cmVhbXMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuaGFzS2V5ID0gZnVuY3Rpb24gaGFzS2V5KHN0cmVhbU5hbWUsIGtleU5hbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKS5oYXMoa2V5TmFtZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLmdldEJ5S2V5ID0gZnVuY3Rpb24gZ2V0QnlLZXkoc3RyZWFtTmFtZSwga2V5TmFtZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkuZ2V0KCdkYXRhJykuZ2V0KGtleU5hbWUpO1xuICAgIH07XG5cbiAgICBNZXRhQ2FjaGVTZXJ2aWNlLnByb3RvdHlwZS5kZWxldGVLZXkgPSBmdW5jdGlvbiBkZWxldGVLZXkoc3RyZWFtTmFtZSwga2V5TmFtZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkuZ2V0KCdkYXRhJylbJ2RlbGV0ZSddKGtleU5hbWUpO1xuICAgIH07XG5cbiAgICBNZXRhQ2FjaGVTZXJ2aWNlLnByb3RvdHlwZS5zZXRLZXkgPSBmdW5jdGlvbiBzZXRLZXkoc3RyZWFtTmFtZSwga2V5TmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ1N0cmVhbSAnICsgc3RyZWFtTmFtZSArICcgbm90IHJlZ2lzdGVyZWQsIHBsZWFzZSByZWdpc3RlciBmaXJzdCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLmdldCgnZGF0YScpLnNldChrZXlOYW1lLCB2YWx1ZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLmNsZWFyTWV0YVN0cmVhbUtleXMgPSBmdW5jdGlvbiBjbGVhck1ldGFTdHJlYW1LZXlzKHN0cmVhbU5hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuX3N0cmVhbXMuaGFzKHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5zZXQoJ2RhdGEnLCBuZXcgTWFwKCkpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyTWV0YVN0cmVhbSA9IGZ1bmN0aW9uIHJlZ2lzdGVyTWV0YVN0cmVhbShzdHJlYW1OYW1lLCBleHBpcmF0aW9uUG9saWN5KSB7XG4gICAgICAgIGlmICh0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkYXRhID0gbmV3IE1hcCgpO1xuICAgICAgICBkYXRhLnNldCgnZXhwaXJhdGlvblBvbGljeScsIGV4cGlyYXRpb25Qb2xpY3kpO1xuICAgICAgICBkYXRhLnNldCgnZGF0YScsIG5ldyBNYXAoKSk7XG4gICAgICAgIHRoaXMuX3N0cmVhbXMuc2V0KHN0cmVhbU5hbWUsIGRhdGEpO1xuICAgICAgICBweWRpby5vYnNlcnZlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gQWx3YXlzIGtlZXAgdGhlIGNhY2hlIGF0IHdvcmtzcGFjZSBzY29wZVxuICAgICAgICAgICAgdGhpcy5fc3RyZWFtc1snZGVsZXRlJ10oc3RyZWFtTmFtZSk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgIH07XG5cbiAgICBNZXRhQ2FjaGVTZXJ2aWNlLnByb3RvdHlwZS5tZXRhRm9yTm9kZSA9IGZ1bmN0aW9uIG1ldGFGb3JOb2RlKHN0cmVhbU5hbWUsIGFqeHBOb2RlLCBsb2FkZXJDYWxsYmFjaywgcmVtb3RlUGFyc2VyLCBjYWNoZUxvYWRlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5oYXMoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgbWV0YSBzdHJlYW0gJyArIHN0cmVhbU5hbWUgKyAnLCBwbGVhc2UgcmVnaXN0ZXIgaXQgYmVmb3JlIHVzaW5nIGl0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRlZiA9IHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpO1xuICAgICAgICB2YXIga2V5ID0gYWp4cE5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICB2YXIgZXhwaXJhdGlvblBvbGljeSA9IGRlZi5nZXQoJ2V4cGlyYXRpb25Qb2xpY3knKTtcbiAgICAgICAgaWYgKGRlZi5nZXQoJ2RhdGEnKS5oYXMoa2V5KSkge1xuICAgICAgICAgICAgY2FjaGVMb2FkZXIoZGVmLmdldCgnZGF0YScpLmdldChrZXkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNsZWFyVmFsdWVPYnNlcnZlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlZi5nZXQoJ2RhdGEnKVsnZGVsZXRlJ10oa2V5KTtcbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzKTtcblxuICAgICAgICAgICAgICAgIC8vIENhY2hlIHJlc3BvbnNlIGlmIHN1Y2Nlc3NcbiAgICAgICAgICAgICAgICB2YXIgY2FjaGVDYWxsYmFjayA9IGZ1bmN0aW9uIGNhY2hlQ2FsbGJhY2sodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdEYXRhID0gcmVtb3RlUGFyc2VyKHRyYW5zcG9ydCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdEYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2FjaGVkRGF0YSA9IG5ld0RhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3RGF0YSBpbnN0YW5jZW9mIEFqeHBOb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGVkRGF0YSA9IG5ldyBBanhwTm9kZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZERhdGEucmVwbGFjZUJ5KG5ld0RhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGVmLmdldCgnZGF0YScpLnNldChrZXksIGNhY2hlZERhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4cGlyYXRpb25Qb2xpY3kgPT0gTWV0YUNhY2hlU2VydmljZS5FWFBJUkFUSU9OX0xPQ0FMX05PREUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhanhwTm9kZS5vYnNlcnZlT25jZShcIm5vZGVfcmVtb3ZlZFwiLCBjbGVhclZhbHVlT2JzZXJ2ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFqeHBOb2RlLm9ic2VydmVPbmNlKFwibm9kZV9yZXBsYWNlZFwiLCBjbGVhclZhbHVlT2JzZXJ2ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBsb2FkZXJDYWxsYmFjayhhanhwTm9kZSwgY2FjaGVDYWxsYmFjayk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLmludmFsaWRhdGVNZXRhRm9yS2V5cyA9IGZ1bmN0aW9uIGludmFsaWRhdGVNZXRhRm9yS2V5cyhzdHJlYW1OYW1lLCBrZXlQYXR0ZXJuKSB7XG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5oYXMoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgbWV0YSBzdHJlYW0gJyArIHN0cmVhbU5hbWUgKyAnLCBwbGVhc2UgcmVnaXN0ZXIgaXQgYmVmb3JlIHVzaW5nIGl0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKTtcbiAgICAgICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICBpZiAoa2V5Lm1hdGNoKGtleVBhdHRlcm4pKSB7XG4gICAgICAgICAgICAgICAgZGF0YVsnZGVsZXRlJ10oa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHJldHVybiBNZXRhQ2FjaGVTZXJ2aWNlO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuTWV0YUNhY2hlU2VydmljZS5FWFBJUkFUSU9OX0xPQ0FMX05PREUgPSAnTE9DQUxfTk9ERSc7XG5NZXRhQ2FjaGVTZXJ2aWNlLkVYUElSQVRJT05fTUFOVUFMX1RSSUdHRVIgPSAnTUFOVUFMX1RSSUdHRVInO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBNZXRhQ2FjaGVTZXJ2aWNlO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBTeXN0ZW1KUyA9IHJlcXVpcmUoJ3N5c3RlbWpzJyk7XG5cbi8qKlxuICogQSBtYW5hZ2VyIHRoYXQgY2FuIGhhbmRsZSB0aGUgbG9hZGluZyBvZiBKUywgQ1NTIGFuZCBjaGVja3MgZGVwZW5kZW5jaWVzXG4gKi9cblxudmFyIFJlc291cmNlc01hbmFnZXIgPSAoZnVuY3Rpb24gKCkge1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIFJlc291cmNlc01hbmFnZXIoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSZXNvdXJjZXNNYW5hZ2VyKTtcblxuICAgICAgICB0aGlzLm1haW5Gb3JtQ29udGFpbmVySWQgPSAnYWxsX2Zvcm1zJztcbiAgICAgICAgdGhpcy5yZXNvdXJjZXMgPSB7fTtcbiAgICAgICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgSmF2YXNjcmlwdCByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIFN0cmluZ1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUuYWRkSlNSZXNvdXJjZSA9IGZ1bmN0aW9uIGFkZEpTUmVzb3VyY2UoZmlsZU5hbWUsIGNsYXNzTmFtZSkge1xuICAgICAgICBpZiAoIXRoaXMucmVzb3VyY2VzLmpzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5qcyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzb3VyY2VzLmpzLnB1c2goe1xuICAgICAgICAgICAgZmlsZU5hbWU6IGZpbGVOYW1lLFxuICAgICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsXG4gICAgICAgICAgICBhdXRvbG9hZDogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBDU1MgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0gZmlsZU5hbWUgU3RyaW5nXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGRDU1NSZXNvdXJjZSA9IGZ1bmN0aW9uIGFkZENTU1Jlc291cmNlKGZpbGVOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuY3NzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5jc3MgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc291cmNlcy5jc3MucHVzaChmaWxlTmFtZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBGT1JNIGZyb20gaHRtbCBzbmlwcGVyXG4gICAgICogQHBhcmFtIGZvcm1JZCBTdHJpbmdcbiAgICAgKiBAcGFyYW0gaHRtbFNuaXBwZXQgU3RyaW5nXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGRHdWlGb3JtID0gZnVuY3Rpb24gYWRkR3VpRm9ybShmb3JtSWQsIGh0bWxTbmlwcGV0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuZm9ybXMpIHtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmZvcm1zID0gbmV3IE1hcCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzb3VyY2VzLmZvcm1zLnNldChmb3JtSWQsIGh0bWxTbmlwcGV0KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkIGEgZGVwZW5kZW5jeSB0byBhbm90aGVyIHBsdWdpblxuICAgICAqIEBwYXJhbSBkYXRhIE9iamVjdFxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUuYWRkRGVwZW5kZW5jeSA9IGZ1bmN0aW9uIGFkZERlcGVuZGVuY3koZGF0YSkge1xuICAgICAgICBpZiAoIXRoaXMucmVzb3VyY2VzLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzLnB1c2goZGF0YSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHNvbWUgZGVwZW5kZW5jaWVzIG11c3QgYmUgbG9hZGVkIGJlZm9yZVxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmhhc0RlcGVuZGVuY2llcyA9IGZ1bmN0aW9uIGhhc0RlcGVuZGVuY2llcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb3VyY2VzLmRlcGVuZGVuY2llcyB8fCBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCByZXNvdXJjZXNcbiAgICAgKiBAcGFyYW0gcmVzb3VyY2VzUmVnaXN0cnkgUHlkaW8gcmVzb3VyY2VzIHJlZ2lzdHJ5XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gbG9hZChyZXNvdXJjZXNSZWdpc3RyeSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIHZhciBqc0F1dG9sb2FkT25seSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBGdW5jVXRpbHMuRW1wdHkgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZGVkKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmhhc0RlcGVuZGVuY2llcygpICYmICF0aGlzLmRlcGVuZGVuY2llc0xvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzLmZvckVhY2goKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXNvdXJjZXNSZWdpc3RyeVtlbF0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTG9hZCBkZXBlbmRlbmNpZXMgYW5kIHRyeSBhZ2FpblxuICAgICAgICAgICAgICAgICAgICByZXNvdXJjZXNSZWdpc3RyeVtlbF0ubG9hZChyZXNvdXJjZXNSZWdpc3RyeSwgZmFsc2UsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWQocmVzb3VyY2VzUmVnaXN0cnksIGZhbHNlLCBjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnJlc291cmNlcy5mb3Jtcykge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9ybXMuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgICAgICAvLyBSRU1PVkVEXG4gICAgICAgICAgICAgICAgLy90aGlzLmxvYWRHdWlGb3JtKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VzLmpzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBpdCA9IF90aGlzLnJlc291cmNlcy5qcy52YWx1ZXMoKTtcbiAgICAgICAgICAgICAgICB2YXIgY2IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0ID0gaXQubmV4dCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0LnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoanNBdXRvbG9hZE9ubHkgJiYgIW9iamVjdC52YWx1ZS5hdXRvbG9hZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkSlNSZXNvdXJjZShvYmplY3QudmFsdWUuZmlsZU5hbWUsIG9iamVjdC52YWx1ZS5jbGFzc05hbWUsIGNiLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzKTtcbiAgICAgICAgICAgICAgICBjYigpO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VzLmNzcykge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuY3NzLmZvckVhY2goKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZENTU1Jlc291cmNlKHZhbHVlKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBqYXZhc2NyaXB0IGZpbGVcbiAgICAgKiBAcGFyYW0gZmlsZU5hbWUgU3RyaW5nXG4gICAgICogQHBhcmFtIGNsYXNzTmFtZSBTdHJpbmdcbiAgICAgICAgKiBAcGFyYW0gY2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgICAgKiBAcGFyYW0gYVN5bmMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUubG9hZEpTUmVzb3VyY2UgPSBmdW5jdGlvbiBsb2FkSlNSZXNvdXJjZShmaWxlTmFtZSwgY2xhc3NOYW1lLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgYVN5bmMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIGlmICghUmVzb3VyY2VzTWFuYWdlci5fX2NvbmZpZ3NQYXJzZWQpIHtcbiAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIubG9hZEF1dG9Mb2FkUmVzb3VyY2VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgU3lzdGVtSlNbJ2ltcG9ydCddKGNsYXNzTmFtZSkudGhlbihjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBDU1MgZmlsZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmxvYWRDU1NSZXNvdXJjZSA9IGZ1bmN0aW9uIGxvYWRDU1NSZXNvdXJjZShmaWxlTmFtZSkge1xuXG4gICAgICAgIGlmIChweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSkge1xuICAgICAgICAgICAgZmlsZU5hbWUgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSArIGZpbGVOYW1lO1xuICAgICAgICB9XG4gICAgICAgIGZpbGVOYW1lID0gZmlsZU5hbWUgKyBcIj92PVwiICsgcHlkaW8uUGFyYW1ldGVycy5nZXQoXCJhanhwVmVyc2lvblwiKTtcblxuICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGxpbmtzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2xpbmsnKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5rcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGxpbmsgPSBsaW5rc1tpXTtcbiAgICAgICAgICAgIGlmIChsaW5rLnJlbCA9PT0gJ3N0eWxlc2hlZXQnICYmIGxpbmsuaHJlZi5lbmRzV2l0aChmaWxlTmFtZSkpIHtcbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7YnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdO1xuICAgICAgICAgICAgdmFyIGNzc05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaW5rJyk7XG4gICAgICAgICAgICBjc3NOb2RlLnR5cGUgPSAndGV4dC9jc3MnO1xuICAgICAgICAgICAgY3NzTm9kZS5yZWwgPSAnc3R5bGVzaGVldCc7XG4gICAgICAgICAgICBjc3NOb2RlLmhyZWYgPSBmaWxlTmFtZTtcbiAgICAgICAgICAgIGNzc05vZGUubWVkaWEgPSAnc2NyZWVuJztcbiAgICAgICAgICAgIGhlYWQuYXBwZW5kQ2hpbGQoY3NzTm9kZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCB0aGUgcmVzb3VyY2VzIGZyb20gWE1MXG4gICAgICogQHBhcmFtIG5vZGUgWE1MTm9kZVxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUubG9hZEZyb21YbWxOb2RlID0gZnVuY3Rpb24gbG9hZEZyb21YbWxOb2RlKG5vZGUpIHtcbiAgICAgICAgdmFyIGNsRm9ybSA9IHt9LFxuICAgICAgICAgICAgayA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJyZXNvdXJjZXNcIikge1xuICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmNoaWxkTm9kZXNba10ubm9kZU5hbWUgPT0gJ2pzJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEpTUmVzb3VyY2UoUmVzb3VyY2VzTWFuYWdlci5nZXRGaWxlT3JGYWxsYmFjayhub2RlLmNoaWxkTm9kZXNba10pLCBub2RlLmNoaWxkTm9kZXNba10uZ2V0QXR0cmlidXRlKCdjbGFzc05hbWUnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlLmNoaWxkTm9kZXNba10ubm9kZU5hbWUgPT0gJ2NzcycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRDU1NSZXNvdXJjZShSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrKG5vZGUuY2hpbGROb2Rlc1trXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwiZGVwZW5kZW5jaWVzXCIpIHtcbiAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZS5jaGlsZE5vZGVzW2tdLm5vZGVOYW1lID09IFwicGx1Z2luUmVzb3VyY2VzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGREZXBlbmRlbmN5KG5vZGUuY2hpbGROb2Rlc1trXS5nZXRBdHRyaWJ1dGUoXCJwbHVnaW5OYW1lXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZS5ub2RlTmFtZSA9PSBcImNsaWVudEZvcm1cIikge1xuICAgICAgICAgICAgaWYgKCFub2RlLmdldEF0dHJpYnV0ZShcInRoZW1lXCIpIHx8IG5vZGUuZ2V0QXR0cmlidXRlKFwidGhlbWVcIikgPT0gcHlkaW8uUGFyYW1ldGVycy5nZXQoXCJ0aGVtZVwiKSkge1xuICAgICAgICAgICAgICAgIGNsRm9ybSA9IHsgZm9ybUlkOiBub2RlLmdldEF0dHJpYnV0ZShcImlkXCIpLCBmb3JtQ29kZTogbm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChjbEZvcm0uZm9ybUlkKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEd1aUZvcm0oY2xGb3JtLmZvcm1JZCwgY2xGb3JtLmZvcm1Db2RlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBhbGlhc05hbWVcbiAgICAgKiBAcGFyYW0gYWxpYXNQYXRoXG4gICAgICogQHRvZG8gTU9WRSBPVVRTSURFP1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5hZGRJbWFnZUxpYnJhcnkgPSBmdW5jdGlvbiBhZGRJbWFnZUxpYnJhcnkoYWxpYXNOYW1lLCBhbGlhc1BhdGgpIHtcbiAgICAgICAgaWYgKCF3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzKSB3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzID0ge307XG4gICAgICAgIHdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXNbYWxpYXNOYW1lXSA9IGFsaWFzUGF0aDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCB0aGUgZGVmYXVsdCBpbWFnZXMgcGF0aFxuICAgICAqIEBwYXJhbSBzcmMgSWNvbiBzb3VyY2VcbiAgICAgKiBAcGFyYW0gZGVmYXVsdFBhdGggRGVmYXVsdCBwYXRoLCBjYW4gY29udGFpbiBJQ09OX1NJWkVcbiAgICAgKiBAcGFyYW0gc2l6ZSBJbnRlZ2VyIHNpemUgb3B0aW9uYWxcbiAgICAgKiBAcmV0dXJucyBzdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucmVzb2x2ZUltYWdlU291cmNlID0gZnVuY3Rpb24gcmVzb2x2ZUltYWdlU291cmNlKHNyYywgZGVmYXVsdFBhdGgsIHNpemUpIHtcbiAgICAgICAgaWYgKCFzcmMpIHJldHVybiBcIlwiO1xuICAgICAgICB2YXIgaW1hZ2VzRm9sZGVyID0gYWp4cFJlc291cmNlc0ZvbGRlciArICcvaW1hZ2VzJztcbiAgICAgICAgaWYgKHB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuZ2V0KCdhanhwSW1hZ2VzQ29tbW9uJykpIHtcbiAgICAgICAgICAgIGltYWdlc0ZvbGRlciA9IGltYWdlc0ZvbGRlci5yZXBsYWNlKCcvJyArIHB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuZ2V0KCd0aGVtZScpICsgJy8nLCAnL2NvbW1vbi8nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkZWZhdWx0UGF0aCAmJiBkZWZhdWx0UGF0aFswXSAhPT0gJy8nKSB7XG4gICAgICAgICAgICBkZWZhdWx0UGF0aCA9ICcvJyArIGRlZmF1bHRQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzIHx8IHNyYy5pbmRleE9mKFwiL1wiKSA9PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlc0ZvbGRlciArIChkZWZhdWx0UGF0aCA/IHNpemUgPyBkZWZhdWx0UGF0aC5yZXBsYWNlKFwiSUNPTl9TSVpFXCIsIHNpemUpIDogZGVmYXVsdFBhdGggOiAnJykgKyAnLycgKyBzcmM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJhZGljID0gc3JjLnN1YnN0cmluZygwLCBzcmMuaW5kZXhPZihcIi9cIikpO1xuICAgICAgICBpZiAod2luZG93LkFqeHBJbWFnZUxpYnJhcmllc1tyYWRpY10pIHtcbiAgICAgICAgICAgIHNyYyA9IHNyYy5yZXBsYWNlKHJhZGljLCB3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzW3JhZGljXSk7XG4gICAgICAgICAgICBpZiAocHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJTRVJWRVJfUFJFRklYX1VSSVwiKSkge1xuICAgICAgICAgICAgICAgIHNyYyA9IHB5ZGlvQm9vdHN0cmFwLnBhcmFtZXRlcnMuZ2V0KFwiU0VSVkVSX1BSRUZJWF9VUklcIikgKyBzcmM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc2l6ZSA/IHNyYy5yZXBsYWNlKFwiSUNPTl9TSVpFXCIsIHNpemUpIDogc3JjO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlc0ZvbGRlciArIChkZWZhdWx0UGF0aCA/IHNpemUgPyBkZWZhdWx0UGF0aC5yZXBsYWNlKFwiSUNPTl9TSVpFXCIsIHNpemUpIDogZGVmYXVsdFBhdGggOiAnJykgKyAnLycgKyBzcmM7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgKiBDaGVjayBpZiByZXNvdXJjZXMgYXJlIHRhZ2dlZCBhdXRvbG9hZCBhbmQgbG9hZCB0aGVtXG4gICAgKiBAcGFyYW0gcmVnaXN0cnkgRE9NRG9jdW1lbnQgWE1MIFJlZ2lzdHJ5XG4gICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIubG9hZEF1dG9Mb2FkUmVzb3VyY2VzID0gZnVuY3Rpb24gbG9hZEF1dG9Mb2FkUmVzb3VyY2VzKCkge1xuICAgICAgICB2YXIgcmVnaXN0cnkgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICAgIGlmICghcmVnaXN0cnkpIHtcbiAgICAgICAgICAgIHJlZ2lzdHJ5ID0gd2luZG93LnB5ZGlvLlJlZ2lzdHJ5LmdldFhNTCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtYW5hZ2VyID0gbmV3IFJlc291cmNlc01hbmFnZXIoKTtcbiAgICAgICAgdmFyIGpzTm9kZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMocmVnaXN0cnksICdwbHVnaW5zLyovY2xpZW50X3NldHRpbmdzL3Jlc291cmNlcy9qcycpO1xuICAgICAgICB2YXIgbm9kZSA9IHVuZGVmaW5lZDtcblxuICAgICAgICB2YXIgc3lzanNNYXAgPSB7fTtcbiAgICAgICAgdmFyIHN5c2pzTWV0YSA9IHtcbiAgICAgICAgICAgICcqJzogeyBhdXRob3JpemF0aW9uOiB0cnVlIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHJlcXVpcmVzID0ge307XG5cbiAgICAgICAgZm9yICh2YXIgX2l0ZXJhdG9yID0ganNOb2RlcywgX2lzQXJyYXkgPSBBcnJheS5pc0FycmF5KF9pdGVyYXRvciksIF9pID0gMCwgX2l0ZXJhdG9yID0gX2lzQXJyYXkgPyBfaXRlcmF0b3IgOiBfaXRlcmF0b3JbU3ltYm9sLml0ZXJhdG9yXSgpOzspIHtcbiAgICAgICAgICAgIGlmIChfaXNBcnJheSkge1xuICAgICAgICAgICAgICAgIGlmIChfaSA+PSBfaXRlcmF0b3IubGVuZ3RoKSBicmVhaztcbiAgICAgICAgICAgICAgICBub2RlID0gX2l0ZXJhdG9yW19pKytdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfaSA9IF9pdGVyYXRvci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgaWYgKF9pLmRvbmUpIGJyZWFrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBfaS52YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG5hbWVzcGFjZSA9IG5vZGUuZ2V0QXR0cmlidXRlKCdjbGFzc05hbWUnKTtcbiAgICAgICAgICAgIHZhciBmaWxlcGF0aCA9IFJlc291cmNlc01hbmFnZXIuZ2V0RmlsZU9yRmFsbGJhY2sobm9kZSk7XG4gICAgICAgICAgICB2YXIgZGVwcyA9IFtdO1xuICAgICAgICAgICAgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdkZXBlbmRzJykpIHtcbiAgICAgICAgICAgICAgICBkZXBzID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2RlcGVuZHMnKS5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdleHBvc2UnKSkge1xuICAgICAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIuX19yZXF1aXJlc1tub2RlLmdldEF0dHJpYnV0ZSgnZXhwb3NlJyldID0gbmFtZXNwYWNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3lzanNNYXBbbmFtZXNwYWNlXSA9IGZpbGVwYXRoO1xuICAgICAgICAgICAgc3lzanNNZXRhW25hbWVzcGFjZV0gPSB7IGZvcm1hdDogJ2dsb2JhbCcsIGRlcHM6IGRlcHMgfTtcbiAgICAgICAgfVxuICAgICAgICBTeXN0ZW1KUy5jb25maWcoeyBtYXA6IHN5c2pzTWFwLCBtZXRhOiBzeXNqc01ldGEgfSk7XG4gICAgICAgIFJlc291cmNlc01hbmFnZXIuX19jb25maWdzUGFyc2VkID0gdHJ1ZTtcblxuICAgICAgICB2YXIgY3NzTm9kZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMocmVnaXN0cnksICdwbHVnaW5zLyovY2xpZW50X3NldHRpbmdzL3Jlc291cmNlcy9jc3NbQGF1dG9sb2FkPVwidHJ1ZVwiXScpO1xuICAgICAgICBmb3IgKHZhciBfaXRlcmF0b3IyID0gY3NzTm9kZXMsIF9pc0FycmF5MiA9IEFycmF5LmlzQXJyYXkoX2l0ZXJhdG9yMiksIF9pMiA9IDAsIF9pdGVyYXRvcjIgPSBfaXNBcnJheTIgPyBfaXRlcmF0b3IyIDogX2l0ZXJhdG9yMltTeW1ib2wuaXRlcmF0b3JdKCk7Oykge1xuICAgICAgICAgICAgaWYgKF9pc0FycmF5Mikge1xuICAgICAgICAgICAgICAgIGlmIChfaTIgPj0gX2l0ZXJhdG9yMi5sZW5ndGgpIGJyZWFrO1xuICAgICAgICAgICAgICAgIG5vZGUgPSBfaXRlcmF0b3IyW19pMisrXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgX2kyID0gX2l0ZXJhdG9yMi5uZXh0KCk7XG4gICAgICAgICAgICAgICAgaWYgKF9pMi5kb25lKSBicmVhaztcbiAgICAgICAgICAgICAgICBub2RlID0gX2kyLnZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtYW5hZ2VyLmxvYWRDU1NSZXNvdXJjZShSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrKG5vZGUpKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrID0gZnVuY3Rpb24gZ2V0RmlsZU9yRmFsbGJhY2sobm9kZSkge1xuICAgICAgICBpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ2ZhbGxiYWNrQ29uZGl0aW9uJykgJiYgZXZhbChub2RlLmdldEF0dHJpYnV0ZSgnZmFsbGJhY2tDb25kaXRpb24nKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBub2RlLmdldEF0dHJpYnV0ZSgnZmFsbGJhY2tGaWxlJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZS5nZXRBdHRyaWJ1dGUoJ2ZpbGUnKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnJlcXVpcmVMaWIgPSBmdW5jdGlvbiByZXF1aXJlTGliKG1vZHVsZSkge1xuICAgICAgICB2YXIgcHJvbWlzZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIGlmICh3aW5kb3dbbW9kdWxlXSkgcmV0dXJuIHdpbmRvd1ttb2R1bGVdO1xuICAgICAgICBpZiAoUmVzb3VyY2VzTWFuYWdlci5fX3JlcXVpcmVzICYmIFJlc291cmNlc01hbmFnZXIuX19yZXF1aXJlc1ttb2R1bGVdKSB7XG4gICAgICAgICAgICB2YXIgZ2xvYmFsTlMgPSBSZXNvdXJjZXNNYW5hZ2VyLl9fcmVxdWlyZXNbbW9kdWxlXTtcbiAgICAgICAgICAgIGlmIChwcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFN5c3RlbUpTWydpbXBvcnQnXShnbG9iYWxOUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAod2luZG93W2dsb2JhbE5TXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3aW5kb3dbZ2xvYmFsTlNdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlcXVpcmluZyBhIHJlbW90ZSBsaWIgdGhhdCB3YXMgbm90IHByZXZpb3VzbHkgbG9hZGVkICgnICsgZ2xvYmFsTlMgKyAnKS4gWW91IG1heSBiZSBtaXNzaW5nIGEgZGVwZW5kZW5jeSBkZWNsYXJhdGlvbiBpbiBtYW5pZmVzdCwgb3IgeW91IGNhbiB1c2UgcmVxdWlyZUxpYihtb2R1bGVOYW1lLCB0cnVlKSB0byByZWNlaXZlIGEgUHJvbWlzZS4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgYW55IHJlZmVyZW5jZSB0byBsaWIgJyArIG1vZHVsZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBtb2R1bGUgaXMgcmVnaXN0ZXJlZCAobm90IG5lY2Vzc2FyaWx5IGxvYWRlZCB5ZXQpXG4gICAgICogQHBhcmFtIGNsYXNzTmFtZVxuICAgICAqIEByZXR1cm5zIHtNYXB8Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIubW9kdWxlSXNBdmFpbGFibGUgPSBmdW5jdGlvbiBtb2R1bGVJc0F2YWlsYWJsZShjbGFzc05hbWUpIHtcbiAgICAgICAgdmFyIGNvbmZpZyA9IFN5c3RlbUpTLmdldENvbmZpZygpO1xuICAgICAgICByZXR1cm4gY29uZmlnLm1hcCAmJiBjb25maWcubWFwW2NsYXNzTmFtZV07XG4gICAgfTtcblxuICAgIFJlc291cmNlc01hbmFnZXIubG9hZENsYXNzZXNBbmRBcHBseSA9IGZ1bmN0aW9uIGxvYWRDbGFzc2VzQW5kQXBwbHkoY2xhc3NOYW1lcywgY2FsbGJhY2tGdW5jKSB7XG4gICAgICAgIGlmICghUmVzb3VyY2VzTWFuYWdlci5fX2NvbmZpZ3NQYXJzZWQpIHtcbiAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIubG9hZEF1dG9Mb2FkUmVzb3VyY2VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgUHJvbWlzZS5hbGwoY2xhc3NOYW1lcy5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgIHJldHVybiBTeXN0ZW1KU1snaW1wb3J0J10oYyk7XG4gICAgICAgIH0pKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrRnVuYygpO1xuICAgICAgICB9KVsnY2F0Y2gnXShmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgTG9hZGluZyAnICsgY2xhc3NOYW1lcy5qb2luKCcsICcpICsgJyA6ICcsIHJlYXNvbik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfTtcblxuICAgIFJlc291cmNlc01hbmFnZXIuZGV0ZWN0TW9kdWxlVG9Mb2FkQW5kQXBwbHkgPSBmdW5jdGlvbiBkZXRlY3RNb2R1bGVUb0xvYWRBbmRBcHBseShjYWxsYmFja1N0cmluZywgY2FsbGJhY2tGdW5jKSB7XG4gICAgICAgIHZhciBhc3luYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgaWYgKCFSZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCkge1xuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2xhc3NOYW1lID0gY2FsbGJhY2tTdHJpbmcuc3BsaXQoJy4nLCAxKS5zaGlmdCgpO1xuICAgICAgICBpZiAoYXN5bmMpIHtcbiAgICAgICAgICAgIFN5c3RlbUpTWydpbXBvcnQnXShjbGFzc05hbWUpLnRoZW4oY2FsbGJhY2tGdW5jKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIubG9hZFNjcmlwdFN5bmMoY2xhc3NOYW1lLCBjYWxsYmFja0Z1bmMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9O1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkU2NyaXB0U3luYyA9IGZ1bmN0aW9uIGxvYWRTY3JpcHRTeW5jKG5hbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiByZWdlbmVyYXRvclJ1bnRpbWUuYXN5bmMoZnVuY3Rpb24gbG9hZFNjcmlwdFN5bmMkKGNvbnRleHQkMiQwKSB7XG4gICAgICAgICAgICB3aGlsZSAoMSkgc3dpdGNoIChjb250ZXh0JDIkMC5wcmV2ID0gY29udGV4dCQyJDAubmV4dCkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dCQyJDAubmV4dCA9IDI7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWdlbmVyYXRvclJ1bnRpbWUuYXdyYXAoU3lzdGVtSlNbJ2ltcG9ydCddKG5hbWUpKTtcblxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcblxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBjYXNlICdlbmQnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29udGV4dCQyJDAuc3RvcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBudWxsLCB0aGlzKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFJlc291cmNlc01hbmFnZXI7XG59KSgpO1xuXG5SZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCA9IGZhbHNlO1xuUmVzb3VyY2VzTWFuYWdlci5fX3JlcXVpcmVzID0ge307XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJlc291cmNlc01hbmFnZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9QeWRpb0FwaSA9IHJlcXVpcmUoJy4vUHlkaW9BcGknKTtcblxudmFyIF9QeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9QeWRpb0FwaSk7XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgVXNlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVXNlcihpZCwgbGFiZWwsIHR5cGUsIGdyb3VwLCBhdmF0YXIsIHRlbXBvcmFyeSwgZXh0ZXJuYWwsIGV4dGVuZGVkTGFiZWwpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFVzZXIpO1xuXG4gICAgICAgIHRoaXMuX2lkID0gaWQ7XG4gICAgICAgIHRoaXMuX2xhYmVsID0gbGFiZWw7XG4gICAgICAgIHRoaXMuX3R5cGUgPSB0eXBlO1xuICAgICAgICBpZiAodGhpcy5fdHlwZSA9PT0gJ2dyb3VwJykge1xuICAgICAgICAgICAgdGhpcy5fZ3JvdXAgPSBpZDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9hdmF0YXIgPSBhdmF0YXI7XG4gICAgICAgIHRoaXMuX3RlbXBvcmFyeSA9IHRlbXBvcmFyeTtcbiAgICAgICAgdGhpcy5fZXh0ZXJuYWwgPSBleHRlcm5hbDtcbiAgICAgICAgdGhpcy5fZXh0ZW5kZWRMYWJlbCA9IGV4dGVuZGVkTGFiZWw7XG4gICAgfVxuXG4gICAgVXNlci5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdCh1c2VyKSB7XG4gICAgICAgIHJldHVybiBuZXcgVXNlcih1c2VyLmlkLCB1c2VyLmxhYmVsLCB1c2VyLnR5cGUsIHVzZXIuZ3JvdXAsIHVzZXIuYXZhdGFyLCB1c2VyLnRlbXBvcmFyeSwgdXNlci5leHRlcm5hbCk7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmFzT2JqZWN0ID0gZnVuY3Rpb24gYXNPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogdGhpcy5faWQsXG4gICAgICAgICAgICBsYWJlbDogdGhpcy5fbGFiZWwsXG4gICAgICAgICAgICB0eXBlOiB0aGlzLl90eXBlLFxuICAgICAgICAgICAgZ3JvdXA6IHRoaXMuX2dyb3VwLFxuICAgICAgICAgICAgYXZhdGFyOiB0aGlzLl9hdmF0YXIsXG4gICAgICAgICAgICB0ZW1wb3Jhcnk6IHRoaXMuX3RlbXBvcmFyeSxcbiAgICAgICAgICAgIGV4dGVybmFsOiB0aGlzLl9leHRlcm5hbCxcbiAgICAgICAgICAgIGV4dGVuZGVkTGFiZWw6IHRoaXMuX2V4dGVuZGVkTGFiZWxcbiAgICAgICAgfTtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0SWQgPSBmdW5jdGlvbiBnZXRJZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lkO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRMYWJlbCA9IGZ1bmN0aW9uIGdldExhYmVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGFiZWw7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiBnZXRUeXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdHlwZTtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0R3JvdXAgPSBmdW5jdGlvbiBnZXRHcm91cCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dyb3VwO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRBdmF0YXIgPSBmdW5jdGlvbiBnZXRBdmF0YXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hdmF0YXI7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldFRlbXBvcmFyeSA9IGZ1bmN0aW9uIGdldFRlbXBvcmFyeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RlbXBvcmFyeTtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0RXh0ZXJuYWwgPSBmdW5jdGlvbiBnZXRFeHRlcm5hbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4dGVybmFsO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRFeHRlbmRlZExhYmVsID0gZnVuY3Rpb24gZ2V0RXh0ZW5kZWRMYWJlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4dGVuZGVkTGFiZWw7XG4gICAgfTtcblxuICAgIHJldHVybiBVc2VyO1xufSkoKTtcblxudmFyIFVzZXJzQXBpID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBVc2Vyc0FwaSgpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFVzZXJzQXBpKTtcbiAgICB9XG5cbiAgICBVc2Vyc0FwaS5hdXRob3JpemVkVXNlcnNTdGFydGluZ1dpdGggPSBmdW5jdGlvbiBhdXRob3JpemVkVXNlcnNTdGFydGluZ1dpdGgodG9rZW4sIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB1c2Vyc09ubHkgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGV4aXN0aW5nT25seSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl9saXN0X2F1dGhvcml6ZWRfdXNlcnMnLFxuICAgICAgICAgICAgdmFsdWU6IHRva2VuLFxuICAgICAgICAgICAgZm9ybWF0OiAnanNvbidcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHVzZXJzT25seSkge1xuICAgICAgICAgICAgcGFyYW1zWyd1c2Vyc19vbmx5J10gPSAndHJ1ZSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4aXN0aW5nT25seSkge1xuICAgICAgICAgICAgcGFyYW1zWydleGlzdGluZ19vbmx5J10gPSAndHJ1ZSc7XG4gICAgICAgIH1cbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB2YXIgc3VnZ2VzdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIGlmICh0cmFuc3BvcnQucmVzcG9uc2VYTUwpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGlzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHRyYW5zcG9ydC5yZXNwb25zZVhNTCwgJy8vbGknKTtcbiAgICAgICAgICAgICAgICBsaXMubWFwKGZ1bmN0aW9uIChsaSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3BhbkxhYmVsID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aEdldFNpbmdsZU5vZGVUZXh0KGxpLCAnc3BhbltAY2xhc3M9XCJ1c2VyX2VudHJ5X2xhYmVsXCJdJyk7XG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zLnB1c2gobmV3IFVzZXIobGkuZ2V0QXR0cmlidXRlKCdkYXRhLWVudHJ5X2lkJyksIGxpLmdldEF0dHJpYnV0ZSgnZGF0YS1sYWJlbCcpLCBsaS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJyksIGxpLmdldEF0dHJpYnV0ZSgnZGF0YS1ncm91cCcpLCBsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXZhdGFyJyksIGxpLmdldEF0dHJpYnV0ZSgnZGF0YS10ZW1wb3JhcnknKSA/IHRydWUgOiBmYWxzZSwgbGkuZ2V0QXR0cmlidXRlKCdkYXRhLWV4dGVybmFsJykgPT0gJ3RydWUnLCBzcGFuTGFiZWwpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHJhbnNwb3J0LnJlc3BvbnNlSlNPTikge1xuICAgICAgICAgICAgICAgIHZhciBkYXRhID0gdHJhbnNwb3J0LnJlc3BvbnNlSlNPTjtcbiAgICAgICAgICAgICAgICBkYXRhLm1hcChmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkID0gZW50cnkuaWQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsYWJlbCA9IGVudHJ5LmxhYmVsO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IGVudHJ5LnR5cGU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBncm91cCA9IGVudHJ5Lmdyb3VwO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXZhdGFyID0gZW50cnkuYXZhdGFyO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGVtcG9yYXJ5ID0gZW50cnkudGVtcG9yYXJ5O1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXh0ZXJuYWwgPSBlbnRyeS5leHRlcm5hbDtcblxuICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucy5wdXNoKG5ldyBVc2VyKGlkLCBsYWJlbCwgdHlwZSwgZ3JvdXAsIGF2YXRhciwgdGVtcG9yYXJ5LCBleHRlcm5hbCwgbGFiZWwpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxiYWNrKHN1Z2dlc3Rpb25zKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLmNyZWF0ZVVzZXJGcm9tUG9zdCA9IGZ1bmN0aW9uIGNyZWF0ZVVzZXJGcm9tUG9zdChwb3N0VmFsdWVzLCBjYWxsYmFjaykge1xuICAgICAgICBwb3N0VmFsdWVzWydnZXRfYWN0aW9uJ10gPSAndXNlcl9jcmVhdGVfdXNlcic7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBvc3RWYWx1ZXMsIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayhwb3N0VmFsdWVzLCB0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLmRlbGV0ZVVzZXIgPSBmdW5jdGlvbiBkZWxldGVVc2VyKHVzZXJJZCwgY2FsbGJhY2spIHtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfZGVsZXRlX3VzZXInLFxuICAgICAgICAgICAgdXNlcl9pZDogdXNlcklkXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5zYXZlU2VsZWN0aW9uU3VwcG9ydGVkID0gZnVuY3Rpb24gc2F2ZVNlbGVjdGlvblN1cHBvcnRlZCgpIHtcbiAgICAgICAgcmV0dXJuIGdsb2JhbC5weWRpby5nZXRDb250cm9sbGVyKCkuYWN0aW9ucy5nZXQoJ3VzZXJfdGVhbV9jcmVhdGUnKSAhPT0gdW5kZWZpbmVkO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5kZWxldGVUZWFtID0gZnVuY3Rpb24gZGVsZXRlVGVhbSh0ZWFtSWQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRlYW1JZCA9IHRlYW1JZC5yZXBsYWNlKCcvQUpYUF9URUFNLycsICcnKTtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfdGVhbV9kZWxldGUnLFxuICAgICAgICAgICAgdGVhbV9pZDogdGVhbUlkXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuc2F2ZVNlbGVjdGlvbkFzVGVhbSA9IGZ1bmN0aW9uIHNhdmVTZWxlY3Rpb25Bc1RlYW0odGVhbU5hbWUsIHVzZXJJZHMsIGNhbGxiYWNrKSB7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX3RlYW1fY3JlYXRlJyxcbiAgICAgICAgICAgIHRlYW1fbGFiZWw6IHRlYW1OYW1lLFxuICAgICAgICAgICAgJ3VzZXJfaWRzW10nOiB1c2VySWRzXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuYWRkVXNlclRvVGVhbSA9IGZ1bmN0aW9uIGFkZFVzZXJUb1RlYW0odGVhbUlkLCB1c2VySWQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRlYW1JZCA9IHRlYW1JZC5yZXBsYWNlKCcvQUpYUF9URUFNLycsICcnKTtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfdGVhbV9hZGRfdXNlcicsXG4gICAgICAgICAgICB0ZWFtX2lkOiB0ZWFtSWQsXG4gICAgICAgICAgICB1c2VyX2lkOiB1c2VySWRcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5yZW1vdmVVc2VyRnJvbVRlYW0gPSBmdW5jdGlvbiByZW1vdmVVc2VyRnJvbVRlYW0odGVhbUlkLCB1c2VySWQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRlYW1JZCA9IHRlYW1JZC5yZXBsYWNlKCcvQUpYUF9URUFNLycsICcnKTtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfdGVhbV9kZWxldGVfdXNlcicsXG4gICAgICAgICAgICB0ZWFtX2lkOiB0ZWFtSWQsXG4gICAgICAgICAgICB1c2VyX2lkOiB1c2VySWRcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS51cGRhdGVUZWFtTGFiZWwgPSBmdW5jdGlvbiB1cGRhdGVUZWFtTGFiZWwodGVhbUlkLCBuZXdMYWJlbCwgY2FsbGJhY2spIHtcbiAgICAgICAgdGVhbUlkID0gdGVhbUlkLnJlcGxhY2UoJy9BSlhQX1RFQU0vJywgJycpO1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl90ZWFtX3VwZGF0ZV9sYWJlbCcsXG4gICAgICAgICAgICB0ZWFtX2lkOiB0ZWFtSWQsXG4gICAgICAgICAgICB0ZWFtX2xhYmVsOiBuZXdMYWJlbFxuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHJldHVybiBVc2Vyc0FwaTtcbn0pKCk7XG5cbmV4cG9ydHMuVXNlciA9IFVzZXI7XG5leHBvcnRzLlVzZXJzQXBpID0gVXNlcnNBcGk7XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cblwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgTG9nZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMb2dnZXIoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBMb2dnZXIpO1xuICAgIH1cblxuICAgIExvZ2dlci5sb2cgPSBmdW5jdGlvbiBsb2cobWVzc2FnZSkge1xuICAgICAgICBpZiAod2luZG93LmNvbnNvbGUpIGNvbnNvbGUubG9nKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICBMb2dnZXIuZXJyb3IgPSBmdW5jdGlvbiBlcnJvcihtZXNzYWdlKSB7XG4gICAgICAgIGlmICh3aW5kb3cuY29uc29sZSkgY29uc29sZS5lcnJvcihtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgTG9nZ2VyLmRlYnVnID0gZnVuY3Rpb24gZGVidWcobWVzc2FnZSkge1xuICAgICAgICBpZiAod2luZG93LmNvbnNvbGUpIGNvbnNvbGUuZGVidWcobWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHJldHVybiBMb2dnZXI7XG59KSgpO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IExvZ2dlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1tcImRlZmF1bHRcIl07XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBPYnNlcnZhYmxlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBPYnNlcnZhYmxlKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgT2JzZXJ2YWJsZSk7XG4gICAgfVxuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUuX29iamVjdEV2ZW50U2V0dXAgPSBmdW5jdGlvbiBfb2JqZWN0RXZlbnRTZXR1cChldmVudF9uYW1lKSB7XG4gICAgICAgIHRoaXMuX29ic2VydmVycyA9IHRoaXMuX29ic2VydmVycyB8fCB7fTtcbiAgICAgICAgdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdID0gdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdIHx8IFtdO1xuICAgIH07XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gb2JzZXJ2ZShldmVudF9uYW1lLCBvYnNlcnZlcikge1xuICAgICAgICBpZiAodHlwZW9mIGV2ZW50X25hbWUgPT0gJ3N0cmluZycgJiYgdHlwZW9mIG9ic2VydmVyICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aGlzLl9vYmplY3RFdmVudFNldHVwKGV2ZW50X25hbWUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXS5pbmRleE9mKG9ic2VydmVyKSA9PSAtMSkgdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdLnB1c2gob2JzZXJ2ZXIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yICh2YXIgZSBpbiBldmVudF9uYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50X25hbWUuaGFzT3duUHJvcGVydHkoZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vYnNlcnZlKGUsIGV2ZW50X25hbWVbZV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5zdG9wT2JzZXJ2aW5nID0gZnVuY3Rpb24gc3RvcE9ic2VydmluZyhldmVudF9uYW1lLCBvYnNlcnZlcikge1xuICAgICAgICB0aGlzLl9vYmplY3RFdmVudFNldHVwKGV2ZW50X25hbWUpO1xuICAgICAgICBpZiAoZXZlbnRfbmFtZSAmJiBvYnNlcnZlcikgdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdID0gdGhpcy5fb2JzZXJ2ZXJzW2V2ZW50X25hbWVdLmZpbHRlcihmdW5jdGlvbiAobykge1xuICAgICAgICAgICAgcmV0dXJuIG8gIT0gb2JzZXJ2ZXI7XG4gICAgICAgIH0pO2Vsc2UgaWYgKGV2ZW50X25hbWUpIHtcbiAgICAgICAgICAgIHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXSA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fb2JzZXJ2ZXJzID0ge307XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUub2JzZXJ2ZU9uY2UgPSBmdW5jdGlvbiBvYnNlcnZlT25jZShldmVudF9uYW1lLCBvdXRlcl9vYnNlcnZlcikge1xuICAgICAgICB2YXIgaW5uZXJfb2JzZXJ2ZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb3V0ZXJfb2JzZXJ2ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHRoaXMuc3RvcE9ic2VydmluZyhldmVudF9uYW1lLCBpbm5lcl9vYnNlcnZlcik7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuX29iamVjdEV2ZW50U2V0dXAoZXZlbnRfbmFtZSk7XG4gICAgICAgIHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXS5wdXNoKGlubmVyX29ic2VydmVyKTtcbiAgICB9O1xuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUubm90aWZ5ID0gZnVuY3Rpb24gbm90aWZ5KGV2ZW50X25hbWUpIHtcbiAgICAgICAgdGhpcy5fb2JqZWN0RXZlbnRTZXR1cChldmVudF9uYW1lKTtcbiAgICAgICAgdmFyIGNvbGxlY3RlZF9yZXR1cm5fdmFsdWVzID0gW107XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkuZnJvbShhcmd1bWVudHMpLnNsaWNlKDEpO1xuICAgICAgICB2YXIgb2JzZXJ2ZXJzQ29weSA9IHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXS5zbGljZSgwKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYnNlcnZlcnNDb3B5Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBjb2xsZWN0ZWRfcmV0dXJuX3ZhbHVlcy5wdXNoKG9ic2VydmVyc0NvcHlbaV0uYXBwbHkob2JzZXJ2ZXJzQ29weVtpXSwgYXJncykgfHwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbGxlY3RlZF9yZXR1cm5fdmFsdWVzO1xuICAgIH07XG5cbiAgICBPYnNlcnZhYmxlLnByb3RvdHlwZS5oYXNPYnNlcnZlcnMgPSBmdW5jdGlvbiBoYXNPYnNlcnZlcnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vYnNlcnZlcnMubGVuZ3RoO1xuICAgIH07XG5cbiAgICByZXR1cm4gT2JzZXJ2YWJsZTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IE9ic2VydmFibGU7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL0xhbmdVdGlscycpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbExhbmdVdGlscyk7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIgPSByZXF1aXJlKCcuLi9odHRwL1Jlc291cmNlc01hbmFnZXInKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUmVzb3VyY2VzTWFuYWdlcik7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBfdXRpbEZ1bmNVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvRnVuY1V0aWxzJyk7XG5cbnZhciBfdXRpbEZ1bmNVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsRnVuY1V0aWxzKTtcblxuLyoqXG4gKiBBIFwiQ29tbWFuZFwiIG9iamVjdCwgZW5jYXBzdWxhdGluZyBpdHMgY2FsbGJhY2tzLCBkaXNwbGF5IGF0dHJpYnV0ZXMsIGV0Yy5cbiAqL1xuXG52YXIgQWN0aW9uID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuXHRfaW5oZXJpdHMoQWN0aW9uLCBfT2JzZXJ2YWJsZSk7XG5cblx0LyoqXG4gICogU3RhbmRhcmQgY29uc3RydWN0b3JcbiAgKi9cblxuXHRmdW5jdGlvbiBBY3Rpb24oKSB7XG5cdFx0X2NsYXNzQ2FsbENoZWNrKHRoaXMsIEFjdGlvbik7XG5cblx0XHRfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuXHRcdHRoaXMuX19ERUZBVUxUX0lDT05fUEFUSCA9IFwiYWN0aW9ucy9JQ09OX1NJWkVcIjtcblx0XHR0aGlzLm9wdGlvbnMgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5vYmplY3RNZXJnZSh7XG5cdFx0XHRuYW1lOiAnJyxcblx0XHRcdGljb25fY2xhc3M6ICcnLFxuXHRcdFx0dGV4dDogJycsXG5cdFx0XHR0aXRsZTogJycsXG5cdFx0XHR0ZXh0X2lkOiAnJyxcblx0XHRcdHRpdGxlX2lkOiAnJyxcblx0XHRcdHdlaWdodDogMCxcblx0XHRcdGhhc0FjY2Vzc0tleTogZmFsc2UsXG5cdFx0XHRhY2Nlc3NLZXk6ICcnLFxuXHRcdFx0c3ViTWVudTogZmFsc2UsXG5cdFx0XHRzdWJNZW51VXBkYXRlSW1hZ2U6IGZhbHNlLFxuXHRcdFx0c3ViTWVudVVwZGF0ZVRpdGxlOiBmYWxzZSxcblx0XHRcdGNhbGxiYWNrQ29kZTogJycsXG5cdFx0XHRjYWxsYmFjazogZnVuY3Rpb24gY2FsbGJhY2soKSB7fSxcblx0XHRcdGxpc3RlbmVyczogW10sXG5cdFx0XHRhY3RpdmVDb25kaXRpb246IG51bGxcblx0XHR9LCBhcmd1bWVudHNbMF0gfHwge30pO1xuXG5cdFx0dGhpcy5jb250ZXh0ID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ub2JqZWN0TWVyZ2Uoe1xuXHRcdFx0c2VsZWN0aW9uOiB0cnVlLFxuXHRcdFx0ZGlyOiBmYWxzZSxcblx0XHRcdGFsbG93ZWRNaW1lczogW10sXG5cdFx0XHRldmFsTWV0YWRhdGE6ICcnLFxuXHRcdFx0cm9vdDogdHJ1ZSxcblx0XHRcdGluWmlwOiB0cnVlLFxuXHRcdFx0cmVjeWNsZTogZmFsc2UsXG5cdFx0XHRiZWhhdmlvdXI6ICdoaWRkZW4nLFxuXHRcdFx0YWN0aW9uQmFyOiBmYWxzZSxcblx0XHRcdGFjdGlvbkJhckdyb3VwOiAnZGVmYXVsdCcsXG5cdFx0XHRjb250ZXh0TWVudTogZmFsc2UsXG5cdFx0XHRhanhwV2lkZ2V0czogbnVsbCxcblx0XHRcdGluZm9QYW5lbDogZmFsc2Vcblx0XHR9LCBhcmd1bWVudHNbMV0gfHwge30pO1xuXG5cdFx0dGhpcy5zZWxlY3Rpb25Db250ZXh0ID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ub2JqZWN0TWVyZ2Uoe1xuXHRcdFx0ZGlyOiBmYWxzZSxcblx0XHRcdGZpbGU6IHRydWUsXG5cdFx0XHRyZWN5Y2xlOiBmYWxzZSxcblx0XHRcdGJlaGF2aW91cjogJ2Rpc2FibGVkJyxcblx0XHRcdGFsbG93ZWRNaW1lczogW10sXG5cdFx0XHRldmFsTWV0YWRhdGE6ICcnLFxuXHRcdFx0dW5pcXVlOiB0cnVlLFxuXHRcdFx0bXVsdGlwbGVPbmx5OiBmYWxzZSxcblx0XHRcdGVuYWJsZVJvb3Q6IGZhbHNlXG5cdFx0fSwgYXJndW1lbnRzWzJdIHx8IHt9KTtcblxuXHRcdHRoaXMucmlnaHRzQ29udGV4dCA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLm9iamVjdE1lcmdlKHtcblx0XHRcdG5vVXNlcjogdHJ1ZSxcblx0XHRcdHVzZXJMb2dnZWQ6IHRydWUsXG5cdFx0XHRndWVzdExvZ2dlZDogZmFsc2UsXG5cdFx0XHRyZWFkOiBmYWxzZSxcblx0XHRcdHdyaXRlOiBmYWxzZSxcblx0XHRcdGFkbWluT25seTogZmFsc2Vcblx0XHR9LCBhcmd1bWVudHNbM10gfHwge30pO1xuXG5cdFx0dGhpcy5zdWJNZW51SXRlbXMgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5vYmplY3RNZXJnZSh7XG5cdFx0XHRzdGF0aWNJdGVtczogbnVsbCxcblx0XHRcdGR5bmFtaWNJdGVtczogbnVsbCxcblx0XHRcdGR5bmFtaWNCdWlsZGVyQ29kZTogbnVsbCxcblx0XHRcdHBvcG92ZXJDb250ZW50OiBudWxsXG5cdFx0fSwgYXJndW1lbnRzWzRdIHx8IHt9KTtcblxuXHRcdHRoaXMuZWxlbWVudHMgPSBbXTtcblx0XHR0aGlzLmNvbnRleHRIaWRkZW4gPSBmYWxzZTtcblx0XHR0aGlzLmRlbnkgPSBmYWxzZTtcblx0XHRpZiAodGhpcy5jb250ZXh0LnN1Yk1lbnUpIHtcblx0XHRcdGlmICghdGhpcy5vcHRpb25zLmFjdGlvbkJhcikge1xuXHRcdFx0XHRhbGVydCgnV2FybmluZywgd3JvbmcgYWN0aW9uIGRlZmluaXRpb24uIENhbm5vdCB1c2UgYSBzdWJNZW51IGlmIG5vdCBkaXNwbGF5ZWQgaW4gdGhlIGFjdGlvbkJhciEnKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRBY3Rpb24ucHJvdG90eXBlLl9ldmFsU2NyaXB0cyA9IGZ1bmN0aW9uIF9ldmFsU2NyaXB0cyhkYXRhLCBsb2NhbFNjb3BlTWV0YWRhdGEpIHtcblx0XHR2YXIgbWV0YWRhdGEgPSBsb2NhbFNjb3BlTWV0YWRhdGE7XG5cdFx0cmV0dXJuIGV2YWwoZGF0YSk7XG5cdH07XG5cblx0LyoqXG4gICogU2V0cyB0aGUgbWFuYWdlciBmb3IgdGhpcyBhY3Rpb25cbiAgKiBAcGFyYW0gbWFuYWdlciBBY3Rpb25zTWFuYWdlclxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuc2V0TWFuYWdlciA9IGZ1bmN0aW9uIHNldE1hbmFnZXIobWFuYWdlcikge1xuXHRcdHRoaXMubWFuYWdlciA9IG1hbmFnZXI7XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5zdWJNZW51KSB7XG5cdFx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuc3RhdGljSXRlbXMpIHtcblx0XHRcdFx0dGhpcy5idWlsZFN1Ym1lbnVTdGF0aWNJdGVtcygpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNJdGVtcyB8fCB0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlckNvZGUpIHtcblx0XHRcdFx0dGhpcy5wcmVwYXJlU3VibWVudUR5bmFtaWNCdWlsZGVyKCk7XG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyTW9kdWxlKSB7XG5cdFx0XHRcdF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5kZXRlY3RNb2R1bGVUb0xvYWRBbmRBcHBseSh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlck1vZHVsZSwgdGhpcy5wcmVwYXJlU3VibWVudUR5bmFtaWNCdWlsZGVyLmJpbmQodGhpcykpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLmxpc3RlbmVyc1snaW5pdCddKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR3aW5kb3cubGlzdGVuZXJDb250ZXh0ID0gdGhpcztcblx0XHRcdFx0aWYgKHR5cGVvZiB0aGlzLm9wdGlvbnMubGlzdGVuZXJzWydpbml0J10gPT0gXCJzdHJpbmdcIikge1xuXHRcdFx0XHRcdHRoaXMuX2V2YWxTY3JpcHRzKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbJ2luaXQnXSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLmxpc3RlbmVyc1snaW5pdCddKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoJ0Vycm9yIHdoaWxlIGV2YWx1YXRpbmcgaW5pdCBzY3JpcHQgZm9yIGFjdGlvbiAnICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBFeGVjdXRlIHRoZSBhY3Rpb24gY29kZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiBhcHBseSgpIHtcblx0XHRpZiAodGhpcy5kZW55KSByZXR1cm47XG5cdFx0dGhpcy5tYW5hZ2VyLnB1Ymxpc2hBY3Rpb25FdmVudChcImJlZm9yZUFwcGx5LVwiICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHRcdHdpbmRvdy5hY3Rpb25Bcmd1bWVudHMgPSBbXTtcblx0XHR3aW5kb3cuYWN0aW9uTWFuYWdlciA9IHRoaXMubWFuYWdlcjtcblx0XHRpZiAoYXJndW1lbnRzWzBdKSB3aW5kb3cuYWN0aW9uQXJndW1lbnRzID0gYXJndW1lbnRzWzBdO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuY2FsbGJhY2tDb2RlKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR0aGlzLl9ldmFsU2NyaXB0cyh0aGlzLm9wdGlvbnMuY2FsbGJhY2tDb2RlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmICh0aGlzLm9wdGlvbnMuY2FsbGJhY2spIHtcblx0XHRcdHRoaXMub3B0aW9ucy5jYWxsYmFjayh0aGlzLm1hbmFnZXIsIGFyZ3VtZW50c1swXSk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMuc3ViTWVudSAmJiBhcmd1bWVudHNbMF0gJiYgYXJndW1lbnRzWzBdWzBdKSB7XG5cdFx0XHR0aGlzLm5vdGlmeShcInN1Ym1lbnVfYWN0aXZlXCIsIGFyZ3VtZW50c1swXVswXSk7XG5cdFx0fVxuXHRcdHdpbmRvdy5hY3Rpb25Bcmd1bWVudHMgPSBudWxsO1xuXHRcdHdpbmRvdy5hY3Rpb25NYW5hZ2VyID0gbnVsbDtcblx0XHR0aGlzLm1hbmFnZXIucHVibGlzaEFjdGlvbkV2ZW50KFwiYWZ0ZXJBcHBseS1cIiArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0fTtcblxuXHQvKipcbiAgKiBVcGRhdGVzIHRoZSBhY3Rpb24gc3RhdHVzIG9uIGNvbnRleHQgY2hhbmdlXG4gICAgICogQHBhcmFtIFB5ZGlvRGF0YU1vZGVsIGRhdGFNb2RlbFxuICAgICAqIEBwYXJhbSBib29sZWFuIHVzZXJzRW5hYmxlZFxuICAgICAqIEBwYXJhbSBzdHJpbmcgY3J0VXNlclxuICAqIEByZXR1cm5zIHZvaWRcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmZpcmVDb250ZXh0Q2hhbmdlID0gZnVuY3Rpb24gZmlyZUNvbnRleHRDaGFuZ2UoZGF0YU1vZGVsLCB1c2Vyc0VuYWJsZWQsIGNydFVzZXIpIHtcblxuXHRcdHZhciBjcnRJc1JlY3ljbGUgPSBmYWxzZTtcblx0XHR2YXIgY3J0SW5aaXAgPSBmYWxzZTtcblx0XHR2YXIgY3J0SXNSb290ID0gZmFsc2U7XG5cdFx0dmFyIGNydEFqeHBNaW1lID0gJyc7XG5cdFx0dmFyIGNydElzUmVhZE9ubHkgPSBmYWxzZTtcblxuXHRcdHZhciBjcnROb2RlID0gZGF0YU1vZGVsLmdldENvbnRleHROb2RlKCk7XG5cdFx0aWYgKGNydE5vZGUpIHtcblx0XHRcdGNydElzUmVjeWNsZSA9IGNydE5vZGUuZ2V0QWp4cE1pbWUoKSA9PSBcImFqeHBfcmVjeWNsZVwiO1xuXHRcdFx0Y3J0SW5aaXAgPSBjcnROb2RlLmhhc0FqeHBNaW1lSW5CcmFuY2goXCJhanhwX2Jyb3dzYWJsZV9hcmNoaXZlXCIpO1xuXHRcdFx0Y3J0SXNSb290ID0gY3J0Tm9kZS5pc1Jvb3QoKTtcblx0XHRcdGNydEFqeHBNaW1lID0gY3J0Tm9kZS5nZXRBanhwTWltZSgpO1xuXHRcdFx0Y3J0SXNSZWFkT25seSA9IGNydE5vZGUuaGFzTWV0YWRhdGFJbkJyYW5jaChcImFqeHBfcmVhZG9ubHlcIiwgXCJ0cnVlXCIpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wiY29udGV4dENoYW5nZVwiXSkge1xuXHRcdFx0aWYgKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJjb250ZXh0Q2hhbmdlXCJdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcblx0XHRcdFx0dGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcImNvbnRleHRDaGFuZ2VcIl0oKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdpbmRvdy5saXN0ZW5lckNvbnRleHQgPSB0aGlzO1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHRoaXMuX2V2YWxTY3JpcHRzKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJjb250ZXh0Q2hhbmdlXCJdKTtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKFwiRXJyb3Igd2hpbGUgZXZhbHVhdGluZyBzY3JpcHQgZm9yIGNvbnRleHRDaGFuZ2UgZXZlbnQgLSBhY3Rpb24gXCIgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0dmFyIHJpZ2h0c0NvbnRleHQgPSB0aGlzLnJpZ2h0c0NvbnRleHQ7XG5cdFx0aWYgKCFyaWdodHNDb250ZXh0Lm5vVXNlciAmJiAhdXNlcnNFbmFibGVkKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC51c2VyTG9nZ2VkID09ICdvbmx5JyAmJiBjcnRVc2VyID09IG51bGwgfHwgcmlnaHRzQ29udGV4dC5ndWVzdExvZ2dlZCAmJiByaWdodHNDb250ZXh0Lmd1ZXN0TG9nZ2VkID09ICdoaWRkZW4nICYmIGNydFVzZXIgIT0gbnVsbCAmJiBjcnRVc2VyLmlkID09ICdndWVzdCcpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LnVzZXJMb2dnZWQgPT0gJ2hpZGRlbicgJiYgY3J0VXNlciAhPSBudWxsICYmICEoY3J0VXNlci5pZCA9PSAnZ3Vlc3QnICYmIHJpZ2h0c0NvbnRleHQuZ3Vlc3RMb2dnZWQgJiYgcmlnaHRzQ29udGV4dC5ndWVzdExvZ2dlZCA9PSAnc2hvdycpKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC5hZG1pbk9ubHkgJiYgKGNydFVzZXIgPT0gbnVsbCB8fCAhY3J0VXNlci5pc0FkbWluKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQucmVhZCAmJiBjcnRVc2VyICE9IG51bGwgJiYgIWNydFVzZXIuY2FuUmVhZCgpKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC53cml0ZSAmJiBjcnRVc2VyICE9IG51bGwgJiYgIWNydFVzZXIuY2FuV3JpdGUoKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQud3JpdGUgJiYgY3J0SXNSZWFkT25seSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuY29udGV4dC5hbGxvd2VkTWltZXMubGVuZ3RoKSB7XG5cdFx0XHRpZiAodGhpcy5jb250ZXh0LmFsbG93ZWRNaW1lcy5pbmRleE9mKFwiKlwiKSA9PSAtMSAmJiB0aGlzLmNvbnRleHQuYWxsb3dlZE1pbWVzLmluZGV4T2YoY3J0QWp4cE1pbWUpID09IC0xKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5jb250ZXh0LmFsbG93ZWRNaW1lcy5pbmRleE9mKFwiXlwiICsgY3J0QWp4cE1pbWUpICE9IC0xKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICh0aGlzLmNvbnRleHQucmVjeWNsZSkge1xuXHRcdFx0aWYgKHRoaXMuY29udGV4dC5yZWN5Y2xlID09ICdvbmx5JyAmJiAhY3J0SXNSZWN5Y2xlKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5jb250ZXh0LnJlY3ljbGUgPT0gJ2hpZGRlbicgJiYgY3J0SXNSZWN5Y2xlKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghdGhpcy5jb250ZXh0LmluWmlwICYmIGNydEluWmlwKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMuY29udGV4dC5yb290ICYmIGNydElzUm9vdCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cblx0XHR0aGlzLnNob3dGb3JDb250ZXh0KGRhdGFNb2RlbCk7XG5cdH07XG5cblx0LyoqXG4gICogVXBhdGVzIHRoZSBhY3Rpb24gc3RhdHVzIG9uIHNlbGVjdGlvbiBjaGFuZ2VcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmZpcmVTZWxlY3Rpb25DaGFuZ2UgPSBmdW5jdGlvbiBmaXJlU2VsZWN0aW9uQ2hhbmdlKCkge1xuXHRcdGlmICh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wic2VsZWN0aW9uQ2hhbmdlXCJdKSB7XG5cdFx0XHRpZiAodGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcInNlbGVjdGlvbkNoYW5nZVwiXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJzZWxlY3Rpb25DaGFuZ2VcIl0oKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdpbmRvdy5saXN0ZW5lckNvbnRleHQgPSB0aGlzO1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHRoaXMuX2V2YWxTY3JpcHRzKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJzZWxlY3Rpb25DaGFuZ2VcIl0pO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoXCJFcnJvciB3aGlsZSBldmFsdWF0aW5nIHNjcmlwdCBmb3Igc2VsZWN0aW9uQ2hhbmdlIGV2ZW50IC0gYWN0aW9uIFwiICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMuYWN0aXZlQ29uZGl0aW9uKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR2YXIgcmVzdWx0ID0gdGhpcy5vcHRpb25zLmFjdGl2ZUNvbmRpdGlvbigpO1xuXHRcdFx0XHRpZiAocmVzdWx0ID09PSBmYWxzZSkgdGhpcy5kaXNhYmxlKCk7ZWxzZSBpZiAocmVzdWx0ID09PSB0cnVlKSB0aGlzLmVuYWJsZSgpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihcIkVycm9yIHdoaWxlIGV2YWx1YXRpbmcgYWN0aXZlQ29uZGl0aW9uKCkgc2NyaXB0IGZvciBhY3Rpb24gXCIgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICh0aGlzLmNvbnRleHRIaWRkZW4gfHwgIXRoaXMuY29udGV4dC5zZWxlY3Rpb24pIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyIHVzZXJTZWxlY3Rpb24gPSBhcmd1bWVudHNbMF07XG5cdFx0dmFyIGhhc1Jvb3QgPSBmYWxzZTtcblx0XHRpZiAodXNlclNlbGVjdGlvbiAhPSBudWxsKSB7XG5cdFx0XHRoYXNSb290ID0gdXNlclNlbGVjdGlvbi5zZWxlY3Rpb25IYXNSb290Tm9kZSgpO1xuXHRcdFx0dmFyIGJVbmlxdWUgPSB1c2VyU2VsZWN0aW9uLmlzVW5pcXVlKCk7XG5cdFx0XHR2YXIgYkZpbGUgPSB1c2VyU2VsZWN0aW9uLmhhc0ZpbGUoKTtcblx0XHRcdHZhciBiRGlyID0gdXNlclNlbGVjdGlvbi5oYXNEaXIoKTtcblx0XHRcdHZhciBiUmVjeWNsZSA9IHVzZXJTZWxlY3Rpb24uaXNSZWN5Y2xlKCk7XG5cdFx0fVxuXHRcdHZhciBzZWxlY3Rpb25Db250ZXh0ID0gdGhpcy5zZWxlY3Rpb25Db250ZXh0O1xuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5sZW5ndGgpIHtcblx0XHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmJlaGF2aW91ciA9PSAnaGlkZGVuJykgdGhpcy5oaWRlKCk7ZWxzZSB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuZXZhbE1ldGFkYXRhICYmIHVzZXJTZWxlY3Rpb24gJiYgdXNlclNlbGVjdGlvbi5pc1VuaXF1ZSgpKSB7XG5cdFx0XHR2YXIgcmVzdWx0ID0gdGhpcy5fZXZhbFNjcmlwdHMoc2VsZWN0aW9uQ29udGV4dC5ldmFsTWV0YWRhdGEsIHVzZXJTZWxlY3Rpb24uZ2V0VW5pcXVlTm9kZSgpLmdldE1ldGFkYXRhKCkpO1xuXHRcdFx0aWYgKCFyZXN1bHQpIHtcblx0XHRcdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYmVoYXZpb3VyID09ICdoaWRkZW4nKSB0aGlzLmhpZGUoKTtlbHNlIHRoaXMuZGlzYWJsZSgpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghc2VsZWN0aW9uQ29udGV4dC5lbmFibGVSb290ICYmIGhhc1Jvb3QpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQudW5pcXVlICYmICFiVW5pcXVlKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0Lm11bHRpcGxlT25seSAmJiBiVW5pcXVlKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmICgoc2VsZWN0aW9uQ29udGV4dC5maWxlIHx8IHNlbGVjdGlvbkNvbnRleHQuZGlyKSAmJiAhYkZpbGUgJiYgIWJEaXIpIHtcblx0XHRcdHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuZGlyICYmICFzZWxlY3Rpb25Db250ZXh0LmZpbGUgJiYgYkZpbGUgfHwgIXNlbGVjdGlvbkNvbnRleHQuZGlyICYmIHNlbGVjdGlvbkNvbnRleHQuZmlsZSAmJiBiRGlyKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmICghc2VsZWN0aW9uQ29udGV4dC5yZWN5Y2xlICYmIGJSZWN5Y2xlKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLnJpZ2h0c0NvbnRleHQud3JpdGUgJiYgdXNlclNlbGVjdGlvbi5oYXNSZWFkT25seSgpKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5sZW5ndGggJiYgdXNlclNlbGVjdGlvbiAmJiBzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcy5pbmRleE9mKCcqJykgPT0gLTEgJiYgIXVzZXJTZWxlY3Rpb24uaGFzTWltZShzZWxlY3Rpb25Db250ZXh0LmFsbG93ZWRNaW1lcykpIHtcblx0XHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmJlaGF2aW91ciA9PSAnaGlkZGVuJykgcmV0dXJuIHRoaXMuaGlkZSgpO2Vsc2UgcmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMubGVuZ3RoICYmIHVzZXJTZWxlY3Rpb24gJiYgc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMuaW5kZXhPZihcIl5cIikgIT09IC0xKSB7XG5cdFx0XHR2YXIgZm9yYmlkZGVuVmFsdWVGb3VuZCA9IGZhbHNlO1xuXHRcdFx0c2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMuZm9yRWFjaChmdW5jdGlvbiAobSkge1xuXHRcdFx0XHRpZiAobS5pbmRleE9mKFwiXlwiKSA9PSAtMSkgcmV0dXJuO1xuXHRcdFx0XHRpZiAodXNlclNlbGVjdGlvbi5oYXNNaW1lKFttLnJlcGxhY2UoXCJeXCIsIFwiXCIpXSkpIHtcblx0XHRcdFx0XHRmb3JiaWRkZW5WYWx1ZUZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHQvL3Rocm93ICRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHRpZiAoZm9yYmlkZGVuVmFsdWVGb3VuZCkge1xuXHRcdFx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5iZWhhdmlvdXIgPT0gJ2hpZGRlbicpIHJldHVybiB0aGlzLmhpZGUoKTtlbHNlIHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5zaG93KCk7XG5cdFx0dGhpcy5lbmFibGUoKTtcblx0fTtcblxuXHRBY3Rpb24ucHJvdG90eXBlLmdldE1lbnVEYXRhID0gZnVuY3Rpb24gZ2V0TWVudURhdGEoKSB7XG5cdFx0dmFyIG1lbnVJdGVtID0ge1xuXHRcdFx0bmFtZTogdGhpcy5nZXRLZXllZFRleHQoKSxcblx0XHRcdHJhd19uYW1lOiB0aGlzLm9wdGlvbnMudGV4dCxcblx0XHRcdGFsdDogdGhpcy5vcHRpb25zLnRpdGxlLFxuXHRcdFx0YWN0aW9uX2lkOiB0aGlzLm9wdGlvbnMubmFtZSxcblx0XHRcdHdlaWdodDogdGhpcy5vcHRpb25zLndlaWdodCB8fCAwLFxuXHRcdFx0Y2FsbGJhY2s6IChmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHR0aGlzLmFwcGx5KCk7XG5cdFx0XHR9KS5iaW5kKHRoaXMpXG5cdFx0fTtcblx0XHRpZiAodGhpcy5vcHRpb25zLmljb25fY2xhc3MpIHtcblx0XHRcdG1lbnVJdGVtLmljb25fY2xhc3MgPSB0aGlzLm9wdGlvbnMuaWNvbl9jbGFzcztcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5zdWJNZW51KSB7XG5cdFx0XHRtZW51SXRlbS5zdWJNZW51ID0gW107XG5cdFx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuc3RhdGljT3B0aW9ucykge1xuXHRcdFx0XHRtZW51SXRlbS5zdWJNZW51ID0gdGhpcy5zdWJNZW51SXRlbXMuc3RhdGljT3B0aW9ucztcblx0XHRcdH1cblx0XHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlcikge1xuXHRcdFx0XHRtZW51SXRlbS5zdWJNZW51QmVmb3JlU2hvdyA9IHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gbWVudUl0ZW07XG5cdH07XG5cblx0LyoqXG4gICogUGFyc2VzIGFuIFhNTCBmcmFnbWVudCB0byBjb25maWd1cmUgdGhpcyBhY3Rpb25cbiAgKiBAcGFyYW0geG1sTm9kZSBOb2RlIFhNTCBGcmFnbWVudCBkZXNjcmliaW5nIHRoZSBhY3Rpb25cbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmNyZWF0ZUZyb21YTUwgPSBmdW5jdGlvbiBjcmVhdGVGcm9tWE1MKHhtbE5vZGUpIHtcblx0XHR2YXIgX3RoaXMgPSB0aGlzO1xuXG5cdFx0dGhpcy5vcHRpb25zLm5hbWUgPSB4bWxOb2RlLmdldEF0dHJpYnV0ZSgnbmFtZScpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgeG1sTm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgbm9kZSA9IHhtbE5vZGUuY2hpbGROb2Rlc1tpXTtcblx0XHRcdHZhciBkZWZhdWx0QXR0cmlidXRlcyA9IHtcblx0XHRcdFx0ZGlyOiBcImRpckRlZmF1bHRcIixcblx0XHRcdFx0ZmlsZTogXCJmaWxlRGVmYXVsdFwiLFxuXHRcdFx0XHRkcmFnbmRyb3A6IFwiZHJhZ25kcm9wRGVmYXVsdFwiLFxuXHRcdFx0XHRjdHJsZHJhZ25kcm9wOiBcImN0cmxEcmFnbmRyb3BEZWZhdWx0XCIsXG5cdFx0XHRcdGV4cGlyZTogXCJleHBpcmVEZWZhdWx0XCJcblx0XHRcdH07XG5cdFx0XHRmb3IgKHZhciBrZXkgaW4gZGVmYXVsdEF0dHJpYnV0ZXMpIHtcblx0XHRcdFx0aWYgKCFkZWZhdWx0QXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSBjb250aW51ZTtcblx0XHRcdFx0dmFyIHZhbHVlID0gZGVmYXVsdEF0dHJpYnV0ZXNba2V5XTtcblx0XHRcdFx0aWYgKHhtbE5vZGUuZ2V0QXR0cmlidXRlKHZhbHVlKSAmJiB4bWxOb2RlLmdldEF0dHJpYnV0ZSh2YWx1ZSkgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdFx0XHRpZiAoIXRoaXMuZGVmYXVsdHMpIHRoaXMuZGVmYXVsdHMgPSB7fTtcblx0XHRcdFx0XHR0aGlzLmRlZmF1bHRzW2tleV0gPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHR2YXIgajtcblx0XHRcdGlmIChub2RlLm5vZGVOYW1lID09IFwicHJvY2Vzc2luZ1wiKSB7XG5cdFx0XHRcdHZhciBjbGllbnRGb3JtRGF0YSA9IHt9O1xuXHRcdFx0XHRmb3IgKGogPSAwOyBqIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0dmFyIHByb2Nlc3NOb2RlID0gbm9kZS5jaGlsZE5vZGVzW2pdO1xuXHRcdFx0XHRcdGlmIChwcm9jZXNzTm9kZS5ub2RlTmFtZSA9PSBcImNsaWVudENhbGxiYWNrXCIpIHtcblx0XHRcdFx0XHRcdGlmIChwcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpKSB7XG5cdFx0XHRcdFx0XHRcdChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIGZOYW1lID0gcHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCdtb2R1bGUnKTtcblx0XHRcdFx0XHRcdFx0XHRfdGhpcy5vcHRpb25zLmNhbGxiYWNrID0gZnVuY3Rpb24gKG1hbmFnZXIsIG90aGVyQXJndW1lbnRzKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10uZGV0ZWN0TW9kdWxlVG9Mb2FkQW5kQXBwbHkoZk5hbWUsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0X3V0aWxGdW5jVXRpbHMyWydkZWZhdWx0J10uZXhlY3V0ZUZ1bmN0aW9uQnlOYW1lKGZOYW1lLCB3aW5kb3csIG1hbmFnZXIsIG90aGVyQXJndW1lbnRzKTtcblx0XHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRcdFx0aWYgKF90aGlzLmRlZmF1bHRzICYmIChfdGhpcy5kZWZhdWx0c1snZHJhZ25kcm9wJ10gfHwgX3RoaXMuZGVmYXVsdHNbJ2N0cmxkcmFnbmRyb3AnXSkpIHtcblx0XHRcdFx0XHRcdFx0XHRcdF90aGlzLm9wdGlvbnMuZHJhZ25kcm9wQ2hlY2tNb2R1bGUgPSBmTmFtZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdH0pKCk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5vcHRpb25zLmNhbGxiYWNrQ29kZSA9IHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlLnRyaW0oKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYgKHByb2Nlc3NOb2RlLm5vZGVOYW1lID09IFwiY2xpZW50TGlzdGVuZXJcIikge1xuXHRcdFx0XHRcdFx0aWYgKHByb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbW9kdWxlJykpIHtcblx0XHRcdFx0XHRcdFx0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgbW9kdWxlTmFtZSA9IHByb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbW9kdWxlJyk7XG5cdFx0XHRcdFx0XHRcdFx0X3RoaXMub3B0aW9ucy5saXN0ZW5lcnNbcHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCduYW1lJyldID0gKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0XHRcdF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5kZXRlY3RNb2R1bGVUb0xvYWRBbmRBcHBseShtb2R1bGVOYW1lLCAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR2YXIgZnVuYyA9IF91dGlsRnVuY1V0aWxzMlsnZGVmYXVsdCddLmdldEZ1bmN0aW9uQnlOYW1lKG1vZHVsZU5hbWUsIHdpbmRvdyk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChmdW5jKSBmdW5jLmFwcGx5KHRoaXMpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fSkuYmluZCh0aGlzKSk7XG5cdFx0XHRcdFx0XHRcdFx0fSkuYmluZChfdGhpcyk7XG5cdFx0XHRcdFx0XHRcdH0pKCk7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5vcHRpb25zLmxpc3RlbmVyc1twcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ25hbWUnKV0gPSBwcm9jZXNzTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZS50cmltKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwcm9jZXNzTm9kZS5ub2RlTmFtZSA9PSBcImFjdGl2ZUNvbmRpdGlvblwiICYmIHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQpIHtcblx0XHRcdFx0XHRcdHRoaXMub3B0aW9ucy5hY3RpdmVDb25kaXRpb24gPSBuZXcgRnVuY3Rpb24ocHJvY2Vzc05vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUudHJpbSgpKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAobm9kZS5ub2RlTmFtZSA9PSBcImd1aVwiKSB7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy50ZXh0X2lkID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3RleHQnKTtcblx0XHRcdFx0dGhpcy5vcHRpb25zLnRpdGxlX2lkID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3RpdGxlJyk7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy50ZXh0ID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2Uobm9kZS5nZXRBdHRyaWJ1dGUoJ3RleHQnKSkgfHwgJ25vdF9mb3VuZCc7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy50aXRsZSA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKG5vZGUuZ2V0QXR0cmlidXRlKCd0aXRsZScpKSB8fCAnbm90X2ZvdW5kJztcblx0XHRcdFx0dGhpcy5vcHRpb25zLnNyYyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdzcmMnKTtcblx0XHRcdFx0dGhpcy5vcHRpb25zLmljb25fY2xhc3MgPSBub2RlLmdldEF0dHJpYnV0ZSgnaWNvbkNsYXNzJyk7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy53ZWlnaHQgPSBub2RlLmdldEF0dHJpYnV0ZSgnd2VpZ2h0JykgfHwgMDtcblx0XHRcdFx0aWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdoYXNBY2Nlc3NLZXknKSAmJiBub2RlLmdldEF0dHJpYnV0ZSgnaGFzQWNjZXNzS2V5JykgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuYWNjZXNzS2V5ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2FjY2Vzc0tleScpO1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5oYXNBY2Nlc3NLZXkgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChub2RlLmdldEF0dHJpYnV0ZSgnc3BlY2lhbEFjY2Vzc0tleScpKSB7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnNwZWNpYWxBY2Nlc3NLZXkgPSBub2RlLmdldEF0dHJpYnV0ZSgnc3BlY2lhbEFjY2Vzc0tleScpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCBub2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHRpZiAobm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lID09IFwiY29udGV4dFwiKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmF0dHJpYnV0ZXNUb09iamVjdCh0aGlzLmNvbnRleHQsIG5vZGUuY2hpbGROb2Rlc1tqXSk7XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cyA9IHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cy5zcGxpdCgnLCcpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzID0gW107XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHQvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5XG5cdFx0XHRcdFx0XHRpZiAodGhpcy5jb250ZXh0LmluZm9QYW5lbCkgdGhpcy5jb250ZXh0LmFqeHBXaWRnZXRzLnB1c2goJ0luZm9QYW5lbCcpO1xuXHRcdFx0XHRcdFx0aWYgKHRoaXMuY29udGV4dC5hY3Rpb25CYXIpIHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cy5wdXNoKCdBY3Rpb25zVG9vbGJhcicpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAobm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lID09IFwic2VsZWN0aW9uQ29udGV4dFwiKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmF0dHJpYnV0ZXNUb09iamVjdCh0aGlzLnNlbGVjdGlvbkNvbnRleHQsIG5vZGUuY2hpbGROb2Rlc1tqXSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJyaWdodHNDb250ZXh0XCIpIHtcblx0XHRcdFx0dGhpcy5hdHRyaWJ1dGVzVG9PYmplY3QodGhpcy5yaWdodHNDb250ZXh0LCBub2RlKTtcblx0XHRcdH0gZWxzZSBpZiAobm9kZS5ub2RlTmFtZSA9PSBcInN1Yk1lbnVcIikge1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMuc3ViTWVudSA9IHRydWU7XG5cdFx0XHRcdGlmIChub2RlLmdldEF0dHJpYnV0ZShcInVwZGF0ZUltYWdlT25TZWxlY3RcIikgJiYgbm9kZS5nZXRBdHRyaWJ1dGUoXCJ1cGRhdGVJbWFnZU9uU2VsZWN0XCIpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnN1Yk1lbnVVcGRhdGVJbWFnZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKG5vZGUuZ2V0QXR0cmlidXRlKFwidXBkYXRlVGl0bGVPblNlbGVjdFwiKSAmJiBub2RlLmdldEF0dHJpYnV0ZShcInVwZGF0ZVRpdGxlT25TZWxlY3RcIikgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuc3ViTWVudVVwZGF0ZVRpdGxlID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRmb3IgKGogPSAwOyBqIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0aWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZSA9PSBcInN0YXRpY0l0ZW1zXCIgfHwgbm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lID09IFwiZHluYW1pY0l0ZW1zXCIpIHtcblx0XHRcdFx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zW25vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZV0gPSBbXTtcblx0XHRcdFx0XHRcdGZvciAodmFyIGsgPSAwOyBrIDwgbm9kZS5jaGlsZE5vZGVzW2pdLmNoaWxkTm9kZXMubGVuZ3RoOyBrKyspIHtcblx0XHRcdFx0XHRcdFx0aWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5jaGlsZE5vZGVzW2tdLm5vZGVOYW1lLnN0YXJ0c1dpdGgoXCJpdGVtXCIpKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIGl0ZW0gPSB7fTtcblx0XHRcdFx0XHRcdFx0XHRmb3IgKHZhciB6ID0gMDsgeiA8IG5vZGUuY2hpbGROb2Rlc1tqXS5jaGlsZE5vZGVzW2tdLmF0dHJpYnV0ZXMubGVuZ3RoOyB6KyspIHtcblx0XHRcdFx0XHRcdFx0XHRcdHZhciBhdHRyaWJ1dGUgPSBub2RlLmNoaWxkTm9kZXNbal0uY2hpbGROb2Rlc1trXS5hdHRyaWJ1dGVzW3pdO1xuXHRcdFx0XHRcdFx0XHRcdFx0aXRlbVthdHRyaWJ1dGUubm9kZU5hbWVdID0gYXR0cmlidXRlLnZhbHVlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR0aGlzLnN1Yk1lbnVJdGVtc1tub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWVdLnB1c2goaXRlbSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZSA9PSBcImR5bmFtaWNCdWlsZGVyXCIpIHtcblx0XHRcdFx0XHRcdGlmIChub2RlLmNoaWxkTm9kZXNbal0uZ2V0QXR0cmlidXRlKFwibW9kdWxlXCIpKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyTW9kdWxlID0gbm9kZS5jaGlsZE5vZGVzW2pdLmdldEF0dHJpYnV0ZShcIm1vZHVsZVwiKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyQ29kZSA9IG5vZGUuY2hpbGROb2Rlc1tqXS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMuaGFzQWNjZXNzS2V5KSByZXR1cm47XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkgPT0gJycgfHwgIXRoaXMubWFuYWdlci5nZXRNZXNzYWdlKHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkpIHx8IHRoaXMub3B0aW9ucy50ZXh0LmluZGV4T2YodGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UodGhpcy5vcHRpb25zLmFjY2Vzc0tleSkpID09IC0xKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuYWNjZXNzS2V5ID0gdGhpcy5vcHRpb25zLnRleHQuY2hhckF0KDApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuYWNjZXNzS2V5ID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UodGhpcy5vcHRpb25zLmFjY2Vzc0tleSk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIENyZWF0ZXMgdGhlIHN1Ym1lbnUgaXRlbXNcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmJ1aWxkU3VibWVudVN0YXRpY0l0ZW1zID0gZnVuY3Rpb24gYnVpbGRTdWJtZW51U3RhdGljSXRlbXMoKSB7XG5cdFx0dmFyIG1lbnVJdGVtcyA9IFtdO1xuXHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5zdGF0aWNJdGVtcykge1xuXHRcdFx0dGhpcy5zdWJNZW51SXRlbXMuc3RhdGljSXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuXHRcdFx0XHR2YXIgaXRlbVRleHQgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLnRleHQpO1xuXHRcdFx0XHRpZiAoaXRlbS5oYXNBY2Nlc3NLZXkgJiYgKGl0ZW0uaGFzQWNjZXNzS2V5ID09ICd0cnVlJyB8fCBpdGVtLmhhc0FjY2Vzc0tleSA9PT0gdHJ1ZSkgJiYgdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS5hY2Nlc3NLZXkpKSB7XG5cdFx0XHRcdFx0aXRlbVRleHQgPSB0aGlzLmdldEtleWVkVGV4dCh0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLnRleHQpLCB0cnVlLCB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLmFjY2Vzc0tleSkpO1xuXHRcdFx0XHRcdGlmICghdGhpcy5zdWJNZW51SXRlbXMuYWNjZXNzS2V5cykgdGhpcy5zdWJNZW51SXRlbXMuYWNjZXNzS2V5cyA9IFtdO1xuXHRcdFx0XHRcdHRoaXMubWFuYWdlci5yZWdpc3RlcktleSh0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLmFjY2Vzc0tleSksIHRoaXMub3B0aW9ucy5uYW1lLCBpdGVtLmNvbW1hbmQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG1lbnVJdGVtcy5wdXNoKHtcblx0XHRcdFx0XHRuYW1lOiBpdGVtVGV4dCxcblx0XHRcdFx0XHRhbHQ6IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0udGl0bGUpLFxuXHRcdFx0XHRcdGltYWdlX3VucmVzb2x2ZWQ6IGl0ZW0uc3JjLFxuXHRcdFx0XHRcdGljb25fY2xhc3M6IGl0ZW0uaWNvbl9jbGFzcyxcblx0XHRcdFx0XHRpc0RlZmF1bHQ6IGl0ZW0uaXNEZWZhdWx0ID8gdHJ1ZSA6IGZhbHNlLFxuXHRcdFx0XHRcdGNhbGxiYWNrOiAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0dGhpcy5hcHBseShbaXRlbV0pO1xuXHRcdFx0XHRcdH0pLmJpbmQodGhpcylcblx0XHRcdFx0fSk7XG5cdFx0XHR9LCB0aGlzKTtcblx0XHR9XG5cdFx0dGhpcy5zdWJNZW51SXRlbXMuc3RhdGljT3B0aW9ucyA9IG1lbnVJdGVtcztcblx0fTtcblxuXHQvKipcbiAgKiBDYWNoZXMgc29tZSBkYXRhIGZvciBkeW5hbWljYWxseSBidWlsdCBtZW51c1xuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUucHJlcGFyZVN1Ym1lbnVEeW5hbWljQnVpbGRlciA9IGZ1bmN0aW9uIHByZXBhcmVTdWJtZW51RHluYW1pY0J1aWxkZXIoKSB7XG5cdFx0dGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXIgPSAoZnVuY3Rpb24gKGNvbnRyb2xsZXIpIHtcblx0XHRcdHZhciBtZW51SXRlbXMgPSBbXTtcblx0XHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlckNvZGUpIHtcblx0XHRcdFx0d2luZG93LmJ1aWxkZXJDb250ZXh0ID0gdGhpcztcblx0XHRcdFx0dGhpcy5fZXZhbFNjcmlwdHModGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJDb2RlKTtcblx0XHRcdFx0bWVudUl0ZW1zID0gdGhpcy5idWlsZGVyTWVudUl0ZW1zIHx8IFtdO1xuXHRcdFx0fSBlbHNlIGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlck1vZHVsZSkge1xuXHRcdFx0XHR2YXIgZnVuYyA9IF91dGlsRnVuY1V0aWxzMlsnZGVmYXVsdCddLmdldEZ1bmN0aW9uQnlOYW1lKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyTW9kdWxlLCB3aW5kb3cpO1xuXHRcdFx0XHRpZiAoZnVuYykge1xuXHRcdFx0XHRcdG1lbnVJdGVtcyA9IGZ1bmMuYXBwbHkodGhpcyk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG1lbnVJdGVtcyA9IFtdO1xuXHRcdFx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljSXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuXHRcdFx0XHRcdGlmIChpdGVtLnNlcGFyYXRvcikge1xuXHRcdFx0XHRcdFx0bWVudUl0ZW1zLnB1c2goaXRlbSk7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHZhciBhY3Rpb24gPSB1bmRlZmluZWQ7XG5cdFx0XHRcdFx0aWYgKGl0ZW1bJ2FjdGlvbklkJ10gaW5zdGFuY2VvZiBBY3Rpb24pIHtcblx0XHRcdFx0XHRcdGFjdGlvbiA9IGl0ZW1bJ2FjdGlvbklkJ107XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGFjdGlvbiA9IHRoaXMubWFuYWdlci5hY3Rpb25zLmdldChpdGVtWydhY3Rpb25JZCddKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKGFjdGlvbi5kZW55KSByZXR1cm47XG5cdFx0XHRcdFx0dmFyIGl0ZW1EYXRhID0ge1xuXHRcdFx0XHRcdFx0bmFtZTogYWN0aW9uLmdldEtleWVkVGV4dCgpLFxuXHRcdFx0XHRcdFx0YWx0OiBhY3Rpb24ub3B0aW9ucy50aXRsZSxcblx0XHRcdFx0XHRcdGljb25fY2xhc3M6IGFjdGlvbi5vcHRpb25zLmljb25fY2xhc3MsXG5cdFx0XHRcdFx0XHRpbWFnZV91bnJlc29sdmVkOiBhY3Rpb24ub3B0aW9ucy5zcmMsXG5cdFx0XHRcdFx0XHRjYWxsYmFjazogKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5hcHBseSgpO1xuXHRcdFx0XHRcdFx0fSkuYmluZChhY3Rpb24pXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRpZiAoYWN0aW9uLm9wdGlvbnMuc3ViTWVudSkge1xuXHRcdFx0XHRcdFx0aXRlbURhdGEuc3ViTWVudSA9IFtdO1xuXHRcdFx0XHRcdFx0aWYgKGFjdGlvbi5zdWJNZW51SXRlbXMuc3RhdGljT3B0aW9ucykge1xuXHRcdFx0XHRcdFx0XHRpdGVtRGF0YS5zdWJNZW51ID0gYWN0aW9uLnN1Yk1lbnVJdGVtcy5zdGF0aWNPcHRpb25zO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKGFjdGlvbi5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXIpIHtcblx0XHRcdFx0XHRcdFx0aXRlbURhdGEuc3ViTWVudUJlZm9yZVNob3cgPSBhY3Rpb24uc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRtZW51SXRlbXMucHVzaChpdGVtRGF0YSk7XG5cdFx0XHRcdH0sIHRoaXMpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1lbnVJdGVtcztcblx0XHR9KS5iaW5kKHRoaXMpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJlZnJlc2ggaWNvbiBpbWFnZSBzb3VyY2VcbiAgKiBAcGFyYW0gbmV3U3JjIFN0cmluZyBUaGUgaW1hZ2Ugc291cmNlLiBDYW4gcmVmZXJlbmNlIGFuIGltYWdlIGxpYnJhcnlcbiAgICAgKiBAcGFyYW0gaWNvbkNsYXNzIFN0cmluZyBPcHRpb25hbCBjbGFzcyB0byByZXBsYWNlIGltYWdlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5zZXRJY29uQ2xhc3NOYW1lID0gZnVuY3Rpb24gc2V0SWNvbkNsYXNzTmFtZShpY29uQ2xhc3MpIHtcblx0XHR2YXIgaWNvbl9jbGFzcyA9IHRoaXMub3B0aW9ucy5pY29uX2NsYXNzO1xuXG5cdFx0dGhpcy5ub3RpZnkoXCJ1cGRhdGVfaWNvblwiLCB7IG5ld19jbGFzczogaWNvbkNsYXNzLCBwcmV2aW91c19jbGFzczogaWNvbl9jbGFzcyB9KTtcblx0XHR0aGlzLm9wdGlvbnMuaWNvbl9jbGFzcyA9IGljb25DbGFzcztcblx0fTtcblxuXHQvKipcbiAgKiBSZWZyZXNoIHRoZSBhY3Rpb24gbGFiZWxcbiAgKiBAcGFyYW0gbmV3TGFiZWwgU3RyaW5nIHRoZSBuZXcgbGFiZWxcbiAgKiBAcGFyYW0gbmV3VGl0bGUgU3RyaW5nIHRoZSBuZXcgdG9vbHRpcFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuc2V0TGFiZWwgPSBmdW5jdGlvbiBzZXRMYWJlbChuZXdMYWJlbCwgbmV3VGl0bGUpIHtcblx0XHR0aGlzLm9wdGlvbnMudGV4dCA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKG5ld0xhYmVsKTtcblx0XHR0aGlzLm5vdGlmeShcInVwZGF0ZV9sYWJlbFwiLCB0aGlzLmdldEtleWVkVGV4dCgpKTtcblx0XHRpZiAobmV3VGl0bGUpIHtcblx0XHRcdHRoaXMub3B0aW9ucy50aXRsZSA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKG5ld1RpdGxlKTtcblx0XHRcdHRoaXMubm90aWZ5KFwidXBkYXRlX3RpdGxlXCIsIHRoaXMub3B0aW9ucy50aXRsZSk7XG5cdFx0fVxuXHR9O1xuXG5cdEFjdGlvbi5wcm90b3R5cGUucmVmcmVzaEluc3RhbmNlcyA9IGZ1bmN0aW9uIHJlZnJlc2hJbnN0YW5jZXMoKSB7fTtcblxuXHQvKipcbiAgKiBHcmFiIGl0cyBsYWJlbCBmcm9tIHRoZSBpMThuXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5yZWZyZXNoRnJvbUkxOE5IYXNoID0gZnVuY3Rpb24gcmVmcmVzaEZyb21JMThOSGFzaCgpIHtcblx0XHR0aGlzLnNldExhYmVsKHRoaXMub3B0aW9ucy50ZXh0X2lkLCB0aGlzLm9wdGlvbnMudGl0bGVfaWQpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybiBkYXRhIG5lY2Vzc2FyeSB0byBidWlsZCBJbmZvUGFuZWxcbiAgKiBAcmV0dXJucyBPYmplY3RcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnRvSW5mb1BhbmVsID0gZnVuY3Rpb24gdG9JbmZvUGFuZWwoKSB7XG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucztcblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm4gbmVjZXNzYXJ5IGRhdGEgdG8gYnVpbGQgY29udGV4dHVhbCBtZW51XG4gICogQHJldHVybnMgT2JqZWN0XG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS50b0NvbnRleHRNZW51ID0gZnVuY3Rpb24gdG9Db250ZXh0TWVudSgpIHtcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgc2hvdy9oaWRlIHN0YXRlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5oaWRlRm9yQ29udGV4dCA9IGZ1bmN0aW9uIGhpZGVGb3JDb250ZXh0KCkge1xuXHRcdHRoaXMuaGlkZSgpO1xuXHRcdHRoaXMuY29udGV4dEhpZGRlbiA9IHRydWU7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBzaG93L2hpZGUgc3RhdGVcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnNob3dGb3JDb250ZXh0ID0gZnVuY3Rpb24gc2hvd0ZvckNvbnRleHQoZGF0YU1vZGVsKSB7XG5cdFx0dGhpcy5jb250ZXh0SGlkZGVuID0gZmFsc2U7XG5cdFx0dGhpcy5zaG93KCk7XG5cdFx0aWYgKHRoaXMuc2VsZWN0aW9uQ29udGV4dCkge1xuXHRcdFx0dGhpcy5maXJlU2VsZWN0aW9uQ2hhbmdlKGRhdGFNb2RlbCk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgc2hvdy9oaWRlIHN0YXRlXG4gICogTm90aWZpZXMgXCJoaWRlXCIgRXZlbnRcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmhpZGUgPSBmdW5jdGlvbiBoaWRlKCkge1xuXHRcdHRoaXMuZGVueSA9IHRydWU7XG5cdFx0dGhpcy5ub3RpZnkoJ2hpZGUnKTtcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIHNob3cvaGlkZSBzdGF0ZVxuICAqIE5vdGlmaWVzIFwic2hvd1wiIEV2ZW50IFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uIHNob3coKSB7XG5cdFx0dGhpcy5kZW55ID0gZmFsc2U7XG5cdFx0dGhpcy5ub3RpZnkoJ3Nob3cnKTtcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIGVuYWJsZS9kaXNhYmxlIHN0YXRlXG4gICogTm90aWZpZXMgXCJkaXNhYmxlXCIgRXZlbnQgXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gZGlzYWJsZSgpIHtcblx0XHR0aGlzLmRlbnkgPSB0cnVlO1xuXHRcdHRoaXMubm90aWZ5KCdkaXNhYmxlJyk7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBlbmFibGUvZGlzYWJsZSBzdGF0ZVxuICAqIE5vdGlmaWVzIFwiZW5hYmxlXCIgRXZlbnQgXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbiBlbmFibGUoKSB7XG5cdFx0dGhpcy5kZW55ID0gZmFsc2U7XG5cdFx0dGhpcy5ub3RpZnkoJ2VuYWJsZScpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFRvIGJlIGNhbGxlZCB3aGVuIHJlbW92aW5nXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiByZW1vdmUoKSB7XG5cdFx0dGhpcy5ub3RpZnkoXCJyZW1vdmVcIik7XG5cdH07XG5cblx0LyoqXG4gICogQ3JlYXRlIGEgdGV4dCBsYWJlbCB3aXRoIGFjY2Vzcy1rZXkgdW5kZXJsaW5lZC5cbiAgKiBAcGFyYW0gZGlzcGxheVN0cmluZyBTdHJpbmcgdGhlIGxhYmVsXG4gICogQHBhcmFtIGhhc0FjY2Vzc0tleSBCb29sZWFuIHdoZXRoZXIgdGhlcmUgaXMgYW4gYWNjZXNzS2V5IG9yIG5vdFxuICAqIEBwYXJhbSBhY2Nlc3NLZXkgU3RyaW5nIFRoZSBrZXkgdG8gdW5kZXJsaW5lXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5nZXRLZXllZFRleHQgPSBmdW5jdGlvbiBnZXRLZXllZFRleHQoZGlzcGxheVN0cmluZywgaGFzQWNjZXNzS2V5LCBhY2Nlc3NLZXkpIHtcblx0XHRpZiAoIWRpc3BsYXlTdHJpbmcpIHtcblx0XHRcdGRpc3BsYXlTdHJpbmcgPSB0aGlzLm9wdGlvbnMudGV4dDtcblx0XHR9XG5cdFx0aWYgKCFoYXNBY2Nlc3NLZXkpIHtcblx0XHRcdGhhc0FjY2Vzc0tleSA9IHRoaXMub3B0aW9ucy5oYXNBY2Nlc3NLZXk7XG5cdFx0fVxuXHRcdGlmICghYWNjZXNzS2V5KSB7XG5cdFx0XHRhY2Nlc3NLZXkgPSB0aGlzLm9wdGlvbnMuYWNjZXNzS2V5O1xuXHRcdH1cblx0XHRpZiAoIWhhc0FjY2Vzc0tleSkgcmV0dXJuIGRpc3BsYXlTdHJpbmc7XG5cdFx0dmFyIGtleVBvcyA9IGRpc3BsYXlTdHJpbmcudG9Mb3dlckNhc2UoKS5pbmRleE9mKGFjY2Vzc0tleS50b0xvd2VyQ2FzZSgpKTtcblx0XHRpZiAoa2V5UG9zID09IC0xKSB7XG5cdFx0XHRyZXR1cm4gZGlzcGxheVN0cmluZyArICcgKDx1PicgKyBhY2Nlc3NLZXkgKyAnPC91PiknO1xuXHRcdH1cblx0XHRpZiAoZGlzcGxheVN0cmluZy5jaGFyQXQoa2V5UG9zKSAhPSBhY2Nlc3NLZXkpIHtcblx0XHRcdC8vIGNhc2UgZGlmZmVyXG5cdFx0XHRhY2Nlc3NLZXkgPSBkaXNwbGF5U3RyaW5nLmNoYXJBdChrZXlQb3MpO1xuXHRcdH1cblx0XHR2YXIgcmV0dXJuU3RyaW5nID0gZGlzcGxheVN0cmluZy5zdWJzdHJpbmcoMCwgZGlzcGxheVN0cmluZy5pbmRleE9mKGFjY2Vzc0tleSkpO1xuXHRcdHJldHVyblN0cmluZyArPSAnPHU+JyArIGFjY2Vzc0tleSArICc8L3U+Jztcblx0XHRyZXR1cm5TdHJpbmcgKz0gZGlzcGxheVN0cmluZy5zdWJzdHJpbmcoZGlzcGxheVN0cmluZy5pbmRleE9mKGFjY2Vzc0tleSkgKyAxLCBkaXNwbGF5U3RyaW5nLmxlbmd0aCk7XG5cdFx0cmV0dXJuIHJldHVyblN0cmluZztcblx0fTtcblxuXHQvKipcbiAgKiBVdGlsaXRhcnkgZnVuY3Rpb24gdG8gdHJhbnNmb3JtIFhNTCBOb2RlIGF0dHJpYnV0ZXMgaW50byBPYmplY3QgbWFwcGluZyBrZXlzLlxuICAqIEBwYXJhbSBvYmplY3QgT2JqZWN0IFRoZSB0YXJnZXQgb2JqZWN0XG4gICogQHBhcmFtIG5vZGUgTm9kZSBUaGUgc291cmNlIG5vZGVcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmF0dHJpYnV0ZXNUb09iamVjdCA9IGZ1bmN0aW9uIGF0dHJpYnV0ZXNUb09iamVjdChvYmplY3QsIG5vZGUpIHtcblx0XHRmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG5cdFx0XHRpZiAoIW9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpIHx8ICFub2RlLmdldEF0dHJpYnV0ZShrZXkpKSBjb250aW51ZTtcblx0XHRcdHZhciB2YWx1ZSA9IG5vZGUuZ2V0QXR0cmlidXRlKGtleSk7XG5cdFx0XHRpZiAodmFsdWUgPT0gJ3RydWUnKSB2YWx1ZSA9IHRydWU7ZWxzZSBpZiAodmFsdWUgPT0gJ2ZhbHNlJykgdmFsdWUgPSBmYWxzZTtcblx0XHRcdGlmIChrZXkgPT0gJ2FsbG93ZWRNaW1lcycpIHtcblx0XHRcdFx0aWYgKHZhbHVlICYmIHZhbHVlLnNwbGl0KCcsJykubGVuZ3RoKSB7XG5cdFx0XHRcdFx0dmFsdWUgPSB2YWx1ZS5zcGxpdCgnLCcpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhbHVlID0gW107XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdG9iamVjdFtrZXldID0gdmFsdWU7XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiBBY3Rpb247XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBBY3Rpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IFwiZGVmYXVsdFwiOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIENvbnRleHRNZW51TW9kZWwgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKENvbnRleHRNZW51TW9kZWwsIF9PYnNlcnZhYmxlKTtcblxuICAgIGZ1bmN0aW9uIENvbnRleHRNZW51TW9kZWwoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDb250ZXh0TWVudU1vZGVsKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlW1wic3VwZXJcIl0gPSBmdW5jdGlvbiBfc3VwZXIoKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgdGhpcy5fcG9zaXRpb24gPSBudWxsO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLmdldEluc3RhbmNlID0gZnVuY3Rpb24gZ2V0SW5zdGFuY2UoKSB7XG4gICAgICAgIGlmICghQ29udGV4dE1lbnVNb2RlbC5fX0lOU1RBTkNFKSB7XG4gICAgICAgICAgICBDb250ZXh0TWVudU1vZGVsLl9fSU5TVEFOQ0UgPSBuZXcgQ29udGV4dE1lbnVNb2RlbCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBDb250ZXh0TWVudU1vZGVsLl9fSU5TVEFOQ0U7XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlLm9wZW5BdFBvc2l0aW9uID0gZnVuY3Rpb24gb3BlbkF0UG9zaXRpb24oY2xpZW50WCwgY2xpZW50WSkge1xuICAgICAgICB0aGlzLl9jdXJyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMuX3Bvc2l0aW9uID0geyB4OiBjbGllbnRYLCB5OiBjbGllbnRZIH07XG4gICAgICAgIHRoaXMubm90aWZ5KFwib3BlblwiKTtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGUub3Blbk5vZGVBdFBvc2l0aW9uID0gZnVuY3Rpb24gb3Blbk5vZGVBdFBvc2l0aW9uKG5vZGUsIGNsaWVudFgsIGNsaWVudFkpIHtcbiAgICAgICAgdGhpcy5fY3VycmVudE5vZGUgPSBub2RlO1xuICAgICAgICB0aGlzLl9wb3NpdGlvbiA9IHsgeDogY2xpZW50WCwgeTogY2xpZW50WSB9O1xuICAgICAgICB0aGlzLm5vdGlmeShcIm9wZW5cIiwgbm9kZSk7XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlLmdldE5vZGUgPSBmdW5jdGlvbiBnZXROb2RlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY3VycmVudE5vZGU7XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlLmdldFBvc2l0aW9uID0gZnVuY3Rpb24gZ2V0UG9zaXRpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wb3NpdGlvbjtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbiBjbG9zZSgpIHtcbiAgICAgICAgdGhpcy5fY3VycmVudE5vZGUgPSBudWxsO1xuICAgICAgICB0aGlzLm5vdGlmeShcImNsb3NlXCIpO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ29udGV4dE1lbnVNb2RlbDtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbXCJkZWZhdWx0XCJdKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBDb250ZXh0TWVudU1vZGVsO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzW1wiZGVmYXVsdFwiXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIF9BY3Rpb24gPSByZXF1aXJlKCcuL0FjdGlvbicpO1xuXG52YXIgX0FjdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9BY3Rpb24pO1xuXG4vKipcbiAqIFNpbmdsZXRvbiBjbGFzcyB0aGF0IG1hbmFnZXMgYWxsIGFjdGlvbnMuIENhbiBiZSBjYWxsZWQgZGlyZWN0bHkgdXNpbmcgcHlkaW8uZ2V0Q29udHJvbGxlcigpLlxuICovXG5cbnZhciBDb250cm9sbGVyID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhDb250cm9sbGVyLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICAvKipcbiAgICAgKiBTdGFuZGFyZCBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSBweWRpb09iamVjdCBQeWRpb1xuICAgICAqIEBwYXJhbSBkYXRhTW9kZWxFbGVtZW50SWRcbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIENvbnRyb2xsZXIocHlkaW9PYmplY3QpIHtcbiAgICAgICAgdmFyIGRhdGFNb2RlbEVsZW1lbnRJZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbnRyb2xsZXIpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0ID0gcHlkaW9PYmplY3Q7XG4gICAgICAgIHRoaXMuX3JlZ2lzdGVyZWRLZXlzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnVzZXJzRW5hYmxlZCA9IHB5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KFwidXNlcnNFbmFibGVkXCIpO1xuXG4gICAgICAgIHRoaXMuc3ViTWVudXMgPSBbXTtcbiAgICAgICAgdGhpcy5hY3Rpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmRlZmF1bHRBY3Rpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnRvb2xiYXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLl9ndWlBY3Rpb25zID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMuY29udGV4dENoYW5nZWRPYnMgPSAoZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNvbnRleHRDaGFuZ2UoKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyksIDApO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZWRPYnMgPSAoZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZVNlbGVjdGlvbkNoYW5nZSgpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSwgMCk7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG5cbiAgICAgICAgaWYgKGRhdGFNb2RlbEVsZW1lbnRJZCkge1xuICAgICAgICAgICAgdGhpcy5sb2NhbERhdGFNb2RlbCA9IHRydWU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRhdGFNb2RlbEVsZW1lbnRJZCkuYWp4cFBhbmVPYmplY3QuZ2V0RGF0YU1vZGVsKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgaWYgKHRoaXMuX2RhdGFNb2RlbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Nvbm5lY3REYXRhTW9kZWwoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qub2JzZXJ2ZU9uY2UoXCJkYXRhbW9kZWwtbG9hZGVkLVwiICsgZGF0YU1vZGVsRWxlbWVudElkLCAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkYXRhTW9kZWxFbGVtZW50SWQpLmFqeHBQYW5lT2JqZWN0LmdldERhdGFNb2RlbCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb25uZWN0RGF0YU1vZGVsKCk7XG4gICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsRGF0YU1vZGVsID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9jb25uZWN0RGF0YU1vZGVsKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy51c2Vyc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0Lm9ic2VydmUoXCJ1c2VyX2xvZ2dlZFwiLCAoZnVuY3Rpb24gKHVzZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodXNlcik7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9weWRpb09iamVjdC51c2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKHRoaXMuX3B5ZGlvT2JqZWN0LnVzZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucHVibGlzaEFjdGlvbkV2ZW50ID0gZnVuY3Rpb24gcHVibGlzaEFjdGlvbkV2ZW50KGV2ZW50TmFtZSwgZGF0YSkge1xuICAgICAgICB0aGlzLl9weWRpb09iamVjdC5maXJlKGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLl9jb25uZWN0RGF0YU1vZGVsID0gZnVuY3Rpb24gX2Nvbm5lY3REYXRhTW9kZWwoKSB7XG4gICAgICAgIGlmICh0aGlzLmxvY2FsRGF0YU1vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwub2JzZXJ2ZShcImNvbnRleHRfY2hhbmdlZFwiLCB0aGlzLmNvbnRleHRDaGFuZ2VkT2JzKTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbC5vYnNlcnZlKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkT2JzKTtcbiAgICAgICAgICAgIHRoaXMubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoKTtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0Lm9ic2VydmUoXCJyZWdpc3RyeV9sb2FkZWRcIiwgKGZ1bmN0aW9uIChyZWdpc3RyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkocmVnaXN0cnkpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5vYnNlcnZlKFwiY29udGV4dF9jaGFuZ2VkXCIsIHRoaXMuY29udGV4dENoYW5nZWRPYnMpO1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qub2JzZXJ2ZShcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZE9icyk7XG4gICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwgPSB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUudXBkYXRlR3VpQWN0aW9ucyA9IGZ1bmN0aW9uIHVwZGF0ZUd1aUFjdGlvbnMoYWN0aW9ucykge1xuICAgICAgICBhY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uICh2LCBrKSB7XG4gICAgICAgICAgICB0aGlzLl9ndWlBY3Rpb25zLnNldChrLCB2KTtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJBY3Rpb24odik7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAvL3RoaXMubm90aWZ5KFwiYWN0aW9uc19yZWZyZXNoZWRcIik7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmRlbGV0ZUZyb21HdWlBY3Rpb25zID0gZnVuY3Rpb24gZGVsZXRlRnJvbUd1aUFjdGlvbnMoYWN0aW9uTmFtZSkge1xuICAgICAgICB0aGlzLl9ndWlBY3Rpb25zWydkZWxldGUnXShhY3Rpb25OYW1lKTtcbiAgICAgICAgLy90aGlzLm5vdGlmeShcImFjdGlvbnNfcmVmcmVzaGVkXCIpO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5yZWZyZXNoR3VpQWN0aW9uc0kxOG4gPSBmdW5jdGlvbiByZWZyZXNoR3VpQWN0aW9uc0kxOG4oKSB7XG4gICAgICAgIHRoaXMuX2d1aUFjdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgdmFsdWUucmVmcmVzaEZyb21JMThOSGFzaCgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0RGF0YU1vZGVsID0gZnVuY3Rpb24gZ2V0RGF0YU1vZGVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZGF0YU1vZGVsO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWxEYXRhTW9kZWwgJiYgdGhpcy5fZGF0YU1vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwuc3RvcE9ic2VydmluZyhcImNvbnRleHRfY2hhbmdlZFwiLCB0aGlzLmNvbnRleHRDaGFuZ2VkT2JzKTtcbiAgICAgICAgICAgIHRoaXMuX2RhdGFNb2RlbC5zdG9wT2JzZXJ2aW5nKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkT2JzKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXRNZXNzYWdlID0gZnVuY3Rpb24gZ2V0TWVzc2FnZShtZXNzYWdlSWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9weWRpb09iamVjdC5NZXNzYWdlSGFzaFttZXNzYWdlSWRdO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZUlkO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENPTVBBVElCSUxJVFkgTUVUSERcbiAgICAgKiBAcGFyYW0geG1sRG9jXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5wYXJzZVhtbE1lc3NhZ2UgPSBmdW5jdGlvbiBwYXJzZVhtbE1lc3NhZ2UoeG1sRG9jKSB7XG4gICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmRlYnVnKFwiQ29udHJvbGxlci5wYXJzZVhtbE1lc3NhZ2UoKSBpcyBkZXByZWNhdGVkLCB1c2UgUHlkaW9BcGkgaW5zdGVhZFwiKTtcbiAgICAgICAgcmV0dXJuIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucGFyc2VYbWxNZXNzYWdlKHhtbERvYyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFN1Ym1pdHMgYSBmb3JtIHVzaW5nIENvbm5leGlvbiBjbGFzcy5cbiAgICAgKiBAcGFyYW0gZm9ybU5hbWUgU3RyaW5nIFRoZSBpZCBvZiB0aGUgZm9ybVxuICAgICAqIEBwYXJhbSBwb3N0IEJvb2xlYW4gV2hldGhlciB0byBQT1NUIG9yIEdFVFxuICAgICAqIEBwYXJhbSBjb21wbGV0ZUNhbGxiYWNrIEZ1bmN0aW9uIENhbGxiYWNrIHRvIGJlIGNhbGxlZCBvbiBjb21wbGV0ZVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuc3VibWl0Rm9ybSA9IGZ1bmN0aW9uIHN1Ym1pdEZvcm0oZm9ybU5hbWUsIHBvc3QsIGNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZGVidWcoXCJDb250cm9sbGVyLnN1Ym1pdEZvcm0oKSBpcyBkZXByZWNhdGVkLCB1c2UgUHlkaW9BcGkgaW5zdGVhZFwiKTtcbiAgICAgICAgcmV0dXJuIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkuc3VibWl0Rm9ybShmb3JtTmFtZSwgcG9zdCwgY29tcGxldGVDYWxsYmFjayk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFN0b3JlcyB0aGUgY3VycmVudGx5IGxvZ2dlZCB1c2VyIG9iamVjdFxuICAgICAqIEBwYXJhbSBvVXNlciBVc2VyIFVzZXIgaW5zdGFuY2VcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnNldFVzZXIgPSBmdW5jdGlvbiBzZXRVc2VyKG9Vc2VyKSB7XG4gICAgICAgIHRoaXMub1VzZXIgPSBvVXNlcjtcbiAgICAgICAgaWYgKG9Vc2VyICE9IG51bGwgJiYgb1VzZXIuaWQgIT0gJ2d1ZXN0JyAmJiBvVXNlci5nZXRQcmVmZXJlbmNlKCdsYW5nJykgIT0gbnVsbCAmJiBvVXNlci5nZXRQcmVmZXJlbmNlKCdsYW5nJykgIT0gXCJcIiAmJiBvVXNlci5nZXRQcmVmZXJlbmNlKCdsYW5nJykgIT0gdGhpcy5fcHlkaW9PYmplY3QuY3VycmVudExhbmd1YWdlICYmICFvVXNlci5sb2NrKSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5sb2FkSTE4Tk1lc3NhZ2VzKG9Vc2VyLmdldFByZWZlcmVuY2UoJ2xhbmcnKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmlsdGVyIHRoZSBhY3Rpb25zIGdpdmVuIHRoZSBzcmNFbGVtZW50IHBhc3NlZCBhcyBhcmd1bWVudHMuXG4gICAgICogQHBhcmFtIGFjdGlvbnNTZWxlY3RvckF0dCBTdHJpbmcgQW4gaWRlbnRpZmllciBhbW9uZyBzZWxlY3Rpb25Db250ZXh0LCBnZW5lcmljQ29udGV4dCwgYSB3ZWJmeCBvYmplY3QgaWRcbiAgICAgICAgKiBAcGFyYW0gaWdub3JlR3JvdXBzIEFycmF5IGEgbGlzdCBvZiBncm91cHMgdG8gaWdub3JlXG4gICAgICogQHJldHVybnMgQXJyYXlcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldENvbnRleHRBY3Rpb25zID0gZnVuY3Rpb24gZ2V0Q29udGV4dEFjdGlvbnMoYWN0aW9uc1NlbGVjdG9yQXR0LCBpZ25vcmVHcm91cHMsIG9ubHlHcm91cHMpIHtcbiAgICAgICAgdmFyIGNvbnRleHRBY3Rpb25zID0gW107XG4gICAgICAgIHZhciBkZWZhdWx0R3JvdXAgPSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciBjb250ZXh0QWN0aW9uc0dyb3VwID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgaWYgKCFhY3Rpb24uY29udGV4dC5jb250ZXh0TWVudSAmJiAhKG9ubHlHcm91cHMgJiYgb25seUdyb3Vwcy5sZW5ndGgpKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1NlbGVjdG9yQXR0ID09ICdzZWxlY3Rpb25Db250ZXh0JyAmJiAhYWN0aW9uLmNvbnRleHQuc2VsZWN0aW9uKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1NlbGVjdG9yQXR0ID09ICdkaXJlY3RvcnlDb250ZXh0JyAmJiAhYWN0aW9uLmNvbnRleHQuZGlyKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1NlbGVjdG9yQXR0ID09ICdnZW5lcmljQ29udGV4dCcgJiYgYWN0aW9uLmNvbnRleHQuc2VsZWN0aW9uKSByZXR1cm47XG4gICAgICAgICAgICBpZiAoYWN0aW9uLmNvbnRleHRIaWRkZW4gfHwgYWN0aW9uLmRlbnkpIHJldHVybjtcbiAgICAgICAgICAgIGFjdGlvbi5jb250ZXh0LmFjdGlvbkJhckdyb3VwLnNwbGl0KCcsJykuZm9yRWFjaChmdW5jdGlvbiAoYmFyR3JvdXApIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbnRleHRBY3Rpb25zR3JvdXAuaGFzKGJhckdyb3VwKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0QWN0aW9uc0dyb3VwLnNldChiYXJHcm91cCwgW10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGlzRGVmYXVsdCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNTZWxlY3RvckF0dCA9PSAnc2VsZWN0aW9uQ29udGV4dCcpIHtcbiAgICAgICAgICAgICAgICAvLyBzZXQgZGVmYXVsdCBpbiBib2xkXG4gICAgICAgICAgICAgICAgdmFyIHVzZXJTZWxlY3Rpb24gPSB0aGlzLl9kYXRhTW9kZWw7XG4gICAgICAgICAgICAgICAgaWYgKCF1c2VyU2VsZWN0aW9uLmlzRW1wdHkoKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVmYXVsdEFjdGlvbiA9ICdmaWxlJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJTZWxlY3Rpb24uaXNVbmlxdWUoKSAmJiAodXNlclNlbGVjdGlvbi5oYXNEaXIoKSB8fCB1c2VyU2VsZWN0aW9uLmhhc01pbWUoWydhanhwX2Jyb3dzYWJsZV9hcmNoaXZlJ10pKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdEFjdGlvbiA9ICdkaXInO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlZmF1bHRBY3Rpb25zLmdldChkZWZhdWx0QWN0aW9uKSAmJiBhY3Rpb24ub3B0aW9ucy5uYW1lID09IHRoaXMuZGVmYXVsdEFjdGlvbnMuZ2V0KGRlZmF1bHRBY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0RlZmF1bHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYWN0aW9uLmNvbnRleHQuYWN0aW9uQmFyR3JvdXAuc3BsaXQoJywnKS5mb3JFYWNoKGZ1bmN0aW9uIChiYXJHcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBtZW51SXRlbSA9IGFjdGlvbi5nZXRNZW51RGF0YSgpO1xuICAgICAgICAgICAgICAgIG1lbnVJdGVtLmlzRGVmYXVsdCA9IGlzRGVmYXVsdDtcbiAgICAgICAgICAgICAgICBjb250ZXh0QWN0aW9uc0dyb3VwLmdldChiYXJHcm91cCkucHVzaChtZW51SXRlbSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzRGVmYXVsdCkge1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0R3JvdXAgPSBiYXJHcm91cDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIHZhciBmaXJzdCA9IHRydWUsXG4gICAgICAgICAgICBrZXlzID0gW107XG4gICAgICAgIGNvbnRleHRBY3Rpb25zR3JvdXAgPSB0aGlzLl9zb3J0VG9vbGJhcnNBY3Rpb25zKGNvbnRleHRBY3Rpb25zR3JvdXApO1xuICAgICAgICBjb250ZXh0QWN0aW9uc0dyb3VwLmZvckVhY2goZnVuY3Rpb24gKHYsIGspIHtcbiAgICAgICAgICAgIGlmIChkZWZhdWx0R3JvdXAgJiYgayA9PSBkZWZhdWx0R3JvdXApIHJldHVybjtcbiAgICAgICAgICAgIGtleXMucHVzaChrKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGtleXMuc29ydCgpO1xuICAgICAgICBpZiAoZGVmYXVsdEdyb3VwICYmIGNvbnRleHRBY3Rpb25zR3JvdXAuaGFzKGRlZmF1bHRHcm91cCkpIHtcbiAgICAgICAgICAgIGtleXMudW5zaGlmdChkZWZhdWx0R3JvdXApO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhY3Rpb25zUHVzaGVkID0ge307XG4gICAgICAgIGtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGNvbnRleHRBY3Rpb25zR3JvdXAuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAoIWZpcnN0KSB7XG4gICAgICAgICAgICAgICAgY29udGV4dEFjdGlvbnMucHVzaCh7IHNlcGFyYXRvcjogdHJ1ZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpZ25vcmVHcm91cHMgJiYgaWdub3JlR3JvdXBzLmluZGV4T2Yoa2V5KSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob25seUdyb3VwcyAmJiBvbmx5R3JvdXBzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAobUl0ZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aW9uSWQgPSBtSXRlbS5hY3Rpb25faWQ7XG4gICAgICAgICAgICAgICAgaWYgKCFhY3Rpb25zUHVzaGVkW2FjdGlvbklkXSkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0QWN0aW9ucy5wdXNoKG1JdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uc1B1c2hlZFthY3Rpb25JZF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbnRleHRBY3Rpb25zO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXRUb29sYmFyc0FjdGlvbnMgPSBmdW5jdGlvbiBnZXRUb29sYmFyc0FjdGlvbnMoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIHRvb2xiYXJzTGlzdCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IFtdIDogYXJndW1lbnRzWzBdO1xuICAgICAgICB2YXIgZ3JvdXBPdGhlckxpc3QgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBbXSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICB2YXIgdG9vbGJhcnMgPSBuZXcgTWFwKCksXG4gICAgICAgICAgICBncm91cE90aGVyQmFycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdmFyIGxhc3RUYmFyQWRkZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoYWN0aW9uLmNvbnRleHQuYWN0aW9uQmFyKSB7XG4gICAgICAgICAgICAgICAgYWN0aW9uLmNvbnRleHQuYWN0aW9uQmFyR3JvdXAuc3BsaXQoXCIsXCIpLm1hcCgoZnVuY3Rpb24gKGJhckdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b29sYmFyc0xpc3QuaW5kZXhPZihiYXJHcm91cCkgPT09IC0xICYmIGdyb3VwT3RoZXJMaXN0LmluZGV4T2YoYmFyR3JvdXApID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciB0QmFyVXBkYXRlID0gdG9vbGJhcnNMaXN0LmluZGV4T2YoYmFyR3JvdXApICE9PSAtMSA/IHRvb2xiYXJzIDogZ3JvdXBPdGhlckJhcnM7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0QmFyVXBkYXRlLmdldChiYXJHcm91cCkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdEJhclVwZGF0ZS5zZXQoYmFyR3JvdXAsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0QmFyVXBkYXRlLmdldChiYXJHcm91cCkucHVzaChhY3Rpb24pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodEJhclVwZGF0ZSA9PT0gdG9vbGJhcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RUYmFyQWRkZWQgPSBiYXJHcm91cDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcblxuICAgICAgICAvLyBSZWdyb3VwIGFjdGlvbnMgYXJ0aWZpY2lhbGx5XG4gICAgICAgIGlmIChncm91cE90aGVyTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN1Ym1lbnVJdGVtcyA9IFtdO1xuICAgICAgICAgICAgICAgIGdyb3VwT3RoZXJMaXN0Lm1hcCgoZnVuY3Rpb24gKG90aGVyVG9vbGJhcikge1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBvdGhlckFjdGlvbnMgPSBncm91cE90aGVyQmFycy5nZXQob3RoZXJUb29sYmFyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvdGhlckFjdGlvbnMpIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBY3Rpb25zLm1hcChmdW5jdGlvbiAoYWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJtZW51SXRlbXMucHVzaCh7IGFjdGlvbklkOiBhY3QgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ3JvdXBPdGhlckxpc3QuaW5kZXhPZihvdGhlclRvb2xiYXIpIDwgZ3JvdXBPdGhlckxpc3QubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VibWVudUl0ZW1zLnB1c2goeyBzZXBhcmF0b3I6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzKSk7XG4gICAgICAgICAgICAgICAgdmFyIG1vcmVBY3Rpb24gPSBuZXcgX0FjdGlvbjJbJ2RlZmF1bHQnXSh7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6ICdncm91cF9tb3JlX2FjdGlvbicsXG4gICAgICAgICAgICAgICAgICAgIGljb25fY2xhc3M6ICdpY29uLW5vbmUnLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0OiBNZXNzYWdlSGFzaFs0NTZdLFxuICAgICAgICAgICAgICAgICAgICB0aXRsZTogTWVzc2FnZUhhc2hbNDU2XSxcbiAgICAgICAgICAgICAgICAgICAgaGFzQWNjZXNzS2V5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgc3ViTWVudTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKCkge31cbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGRpcjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uQmFyOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb25CYXJHcm91cDogJycsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHRNZW51OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgaW5mb1BhbmVsOiBmYWxzZVxuXG4gICAgICAgICAgICAgICAgfSwge30sIHt9LCB7IGR5bmFtaWNJdGVtczogc3VibWVudUl0ZW1zIH0pO1xuICAgICAgICAgICAgICAgIF90aGlzLnJlZ2lzdGVyQWN0aW9uKG1vcmVBY3Rpb24pO1xuICAgICAgICAgICAgICAgIF90aGlzLmFjdGlvbnMuc2V0KFwiZ3JvdXBfbW9yZV9hY3Rpb25cIiwgbW9yZUFjdGlvbik7XG4gICAgICAgICAgICAgICAgdG9vbGJhcnMuc2V0KCdNT1JFX0FDVElPTicsIFttb3JlQWN0aW9uXSk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3NvcnRUb29sYmFyc0FjdGlvbnModG9vbGJhcnMpO1xuICAgICAgICByZXR1cm4gdG9vbGJhcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdlbmVyaWMgbWV0aG9kIHRvIGdldCBhY3Rpb25zIGZvciBhIGdpdmVuIGNvbXBvbmVudCBwYXJ0LlxuICAgICAqIEBwYXJhbSBhanhwQ2xhc3NOYW1lIFN0cmluZyBcbiAgICAgKiBAcGFyYW0gd2lkZ2V0SWQgU3RyaW5nXG4gICAgICogQHJldHVybnMgW11cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldEFjdGlvbnNGb3JBanhwV2lkZ2V0ID0gZnVuY3Rpb24gZ2V0QWN0aW9uc0ZvckFqeHBXaWRnZXQoYWp4cENsYXNzTmFtZSwgd2lkZ2V0SWQpIHtcbiAgICAgICAgdmFyIGFjdGlvbnMgPSBbXTtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5jb250ZXh0LmFqeHBXaWRnZXRzICYmIChhY3Rpb24uY29udGV4dC5hanhwV2lkZ2V0cy5pbmRleE9mKGFqeHBDbGFzc05hbWUgKyAnOjonICsgd2lkZ2V0SWQpICE9IC0xIHx8IGFjdGlvbi5jb250ZXh0LmFqeHBXaWRnZXRzLmluZGV4T2YoYWp4cENsYXNzTmFtZSkgIT0gLTEpICYmICFhY3Rpb24uZGVueSkgYWN0aW9ucy5wdXNoKGFjdGlvbik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYWN0aW9ucztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgYSBkZWZhdWx0IGFjdGlvbiBhbmQgZmlyZXMgaXQuXG4gICAgICogQHBhcmFtIGRlZmF1bHROYW1lIFN0cmluZyAoXCJmaWxlXCIsIFwiZGlyXCIsIFwiZHJhZ25kcm9wXCIsIFwiY3RybGRyYWduZHJvcFwiKVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZmlyZURlZmF1bHRBY3Rpb24gPSBmdW5jdGlvbiBmaXJlRGVmYXVsdEFjdGlvbihkZWZhdWx0TmFtZSkge1xuICAgICAgICB2YXIgYWN0aW9uTmFtZSA9IHRoaXMuZGVmYXVsdEFjdGlvbnMuZ2V0KGRlZmF1bHROYW1lKTtcbiAgICAgICAgaWYgKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgICAgIGFyZ3VtZW50c1swXSA9IGFjdGlvbk5hbWU7XG4gICAgICAgICAgICBpZiAoYWN0aW9uTmFtZSA9PT0gXCJsc1wiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjdGlvbiA9IHRoaXMuYWN0aW9ucy5nZXQoYWN0aW9uTmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbikgYWN0aW9uLmVuYWJsZSgpOyAvLyBGb3JjZSBlbmFibGUgb24gZGVmYXVsdCBhY3Rpb25cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZmlyZUFjdGlvbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpcmUgYW4gYWN0aW9uIGJhc2VkIG9uIGl0cyBuYW1lXG4gICAgICogQHBhcmFtIGFjdGlvbk5hbWUgU3RyaW5nIFRoZSBuYW1lIG9mIHRoZSBhY3Rpb25cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmZpcmVBY3Rpb24gPSBmdW5jdGlvbiBmaXJlQWN0aW9uKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgdmFyIGFjdGlvbiA9IHRoaXMuYWN0aW9ucy5nZXQoYWN0aW9uTmFtZSk7XG4gICAgICAgIGlmIChhY3Rpb24gIT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5mcm9tKGFyZ3VtZW50cykuc2xpY2UoMSk7XG4gICAgICAgICAgICBhY3Rpb24uYXBwbHkoYXJncyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGFuIGFjY2Vzc2tleSBmb3IgYSBnaXZlbiBhY3Rpb24uIFxuICAgICAqIEBwYXJhbSBrZXkgU3RyaW5nIFRoZSBhY2Nlc3Mga2V5XG4gICAgICogQHBhcmFtIGFjdGlvbk5hbWUgU3RyaW5nIFRoZSBuYW1lIG9mIHRoZSBhY3Rpb25cbiAgICAgKiBAcGFyYW0gb3B0aW9ubmFsQ29tbWFuZCBTdHJpbmcgQW4gb3B0aW9ubmFsIGFyZ3VtZW50IFxuICAgICAqIHRoYXQgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIGFjdGlvbiB3aGVuIGZpcmVkLlxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucmVnaXN0ZXJLZXkgPSBmdW5jdGlvbiByZWdpc3RlcktleShrZXksIGFjdGlvbk5hbWUsIG9wdGlvbm5hbENvbW1hbmQpIHtcbiAgICAgICAgaWYgKG9wdGlvbm5hbENvbW1hbmQpIHtcbiAgICAgICAgICAgIGFjdGlvbk5hbWUgPSBhY3Rpb25OYW1lICsgXCI6OlwiICsgb3B0aW9ubmFsQ29tbWFuZDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZWdpc3RlcmVkS2V5cy5zZXQoa2V5LnRvTG93ZXJDYXNlKCksIGFjdGlvbk5hbWUpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIHJlZ2lzdGVyZWQga2V5cy5cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmNsZWFyUmVnaXN0ZXJlZEtleXMgPSBmdW5jdGlvbiBjbGVhclJlZ2lzdGVyZWRLZXlzKCkge1xuICAgICAgICB0aGlzLl9yZWdpc3RlcmVkS2V5cyA9IG5ldyBNYXAoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlcnMgYW4gYWN0aW9uIGJ5IGl0cyBhY2Nlc3Mga2V5LlxuICAgICAqIEBwYXJhbSBrZXlOYW1lIFN0cmluZyBBIGtleSBuYW1lXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5maXJlQWN0aW9uQnlLZXkgPSBmdW5jdGlvbiBmaXJlQWN0aW9uQnlLZXkoa2V5TmFtZSkge1xuICAgICAgICBpZiAodGhpcy5fcmVnaXN0ZXJlZEtleXMuZ2V0KGtleU5hbWUpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fcmVnaXN0ZXJlZEtleXMuZ2V0KGtleU5hbWUpLmluZGV4T2YoXCI6OlwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFydHMgPSB0aGlzLl9yZWdpc3RlcmVkS2V5cy5nZXQoa2V5TmFtZSkuc3BsaXQoXCI6OlwiKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVBY3Rpb24ocGFydHNbMF0sIHBhcnRzWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQWN0aW9uKHRoaXMuX3JlZ2lzdGVyZWRLZXlzLmdldChrZXlOYW1lKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENvbXBsZXggZnVuY3Rpb24gY2FsbGVkIHdoZW4gZHJhZyduJ2Ryb3BwaW5nLiBCYXNpYyBjaGVja3Mgb2Ygd2hvIGlzIGNoaWxkIG9mIHdoby5cbiAgICAgKiBAcGFyYW0gZmlsZU5hbWUgU3RyaW5nIFRoZSBkcmFnZ2VkIGVsZW1lbnQgXG4gICAgICogQHBhcmFtIGRlc3REaXIgU3RyaW5nIFRoZSBkcm9wIHRhcmdldCBub2RlIHBhdGhcbiAgICAgKiBAcGFyYW0gZGVzdE5vZGVOYW1lIFN0cmluZyBUaGUgZHJvcCB0YXJnZXQgbm9kZSBuYW1lXG4gICAgICogQHBhcmFtIGNvcHkgQm9vbGVhbiBDb3B5IG9yIE1vdmVcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmFwcGx5RHJhZ01vdmUgPSBmdW5jdGlvbiBhcHBseURyYWdNb3ZlKGZpbGVOYW1lLCBkZXN0RGlyLCBkZXN0Tm9kZU5hbWUsIGNvcHkpIHtcbiAgICAgICAgaWYgKCFjb3B5ICYmICghdGhpcy5kZWZhdWx0QWN0aW9ucy5oYXMoJ2RyYWduZHJvcCcpIHx8IHRoaXMuZ2V0RGVmYXVsdEFjdGlvbignZHJhZ25kcm9wJykuZGVueSkgfHwgY29weSAmJiAoIXRoaXMuZGVmYXVsdEFjdGlvbnMuaGFzKCdjdHJsZHJhZ25kcm9wJykgfHwgdGhpcy5nZXREZWZhdWx0QWN0aW9uKCdjdHJsZHJhZ25kcm9wJykuZGVueSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlsZU5hbWVzID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT0gbnVsbCkgZmlsZU5hbWVzID0gdGhpcy5fZGF0YU1vZGVsLmdldEZpbGVOYW1lcygpO2Vsc2UgZmlsZU5hbWVzID0gW2ZpbGVOYW1lXTtcbiAgICAgICAgLy8gQ2hlY2sgdGhhdCBkZXN0IGlzIG5vdCB0aGUgZGlyZWN0IHBhcmVudCBvZiBzb3VyY2UsIGllIGN1cnJlbnQgcmVwIVxuICAgICAgICBpZiAoZGVzdERpciA9PSB0aGlzLl9kYXRhTW9kZWwuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmRpc3BsYXlNZXNzYWdlKCdFUlJPUicsIE1lc3NhZ2VIYXNoWzIwM10pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIHRoYXQgZGVzdCBpcyBub3QgY2hpbGQgb2Ygc291cmNlIGl0IHNlbGZcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaWxlTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChkZXN0RGlyLmxhc3RJbmRleE9mKGZpbGVOYW1lc1tpXSwgMCkgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5kaXNwbGF5TWVzc2FnZSgnRVJST1InLCBNZXNzYWdlSGFzaFsyMDJdKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHt9O1xuICAgICAgICBwYXJhbXNbJ2dldF9hY3Rpb24nXSA9IHRoaXMuZGVmYXVsdEFjdGlvbnMuZ2V0KGNvcHkgPyAnY3RybGRyYWduZHJvcCcgOiAnZHJhZ25kcm9wJyk7XG4gICAgICAgIHBhcmFtc1snbm9kZXNbXSddID0gZmlsZU5hbWVzO1xuICAgICAgICBwYXJhbXNbJ2Rlc3QnXSA9IGRlc3REaXI7XG4gICAgICAgIHBhcmFtc1snZGlyJ10gPSB0aGlzLl9kYXRhTW9kZWwuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKCk7XG4gICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB0aGlzLnBhcnNlWG1sTWVzc2FnZSh0cmFuc3BvcnQucmVzcG9uc2VYTUwpO1xuICAgICAgICB9KS5iaW5kKF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBhY3Rpb24gZGVmaW5lZCBhcyBkZWZhdWx0IGZvciBhIGdpdmVuIGRlZmF1bHQgc3RyaW5nXG4gICAgICogQHBhcmFtIGRlZmF1bHROYW1lIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEFjdGlvblxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEFjdGlvbiA9IGZ1bmN0aW9uIGdldERlZmF1bHRBY3Rpb24oZGVmYXVsdE5hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuZGVmYXVsdEFjdGlvbnMuaGFzKGRlZmF1bHROYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWN0aW9ucy5nZXQodGhpcy5kZWZhdWx0QWN0aW9ucy5nZXQoZGVmYXVsdE5hbWUpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3ByZWFkcyBhIHNlbGVjdGlvbiBjaGFuZ2UgdG8gYWxsIGFjdGlvbnMgYW5kIHRvIHJlZ2lzdGVyZWQgY29tcG9uZW50cyBcbiAgICAgKiBieSB0cmlnZ2VyaW5nIGFqYXhwbG9yZXI6YWN0aW9uc19yZWZyZXNoZWQgZXZlbnQuXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5maXJlU2VsZWN0aW9uQ2hhbmdlID0gZnVuY3Rpb24gZmlyZVNlbGVjdGlvbkNoYW5nZSgpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGFjdGlvbi5maXJlU2VsZWN0aW9uQ2hhbmdlKHRoaXMuX2RhdGFNb2RlbCk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm5vdGlmeShcImFjdGlvbnNfcmVmcmVzaGVkXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTcHJlYWRzIGEgY29udGV4dCBjaGFuZ2UgdG8gYWxsIGFjdGlvbnMgYW5kIHRvIHJlZ2lzdGVyZWQgY29tcG9uZW50cyBcbiAgICAgKiBieSB0cmlnZ2VyaW5nIGFqYXhwbG9yZXI6YWN0aW9uc19yZWZyZXNoZWQgZXZlbnQuXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5maXJlQ29udGV4dENoYW5nZSA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0Q2hhbmdlKCkge1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgYWN0aW9uLmZpcmVDb250ZXh0Q2hhbmdlKHRoaXMuX2RhdGFNb2RlbCwgdGhpcy51c2Vyc0VuYWJsZWQsIHRoaXMub1VzZXIpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJhY3Rpb25zX3JlZnJlc2hlZFwiKTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUubm90aWZ5ID0gZnVuY3Rpb24gbm90aWZ5KGV2ZW50TmFtZSwgbWVtbykge1xuICAgICAgICBpZiAodGhpcy5sb2NhbERhdGFNb2RlbCkge1xuICAgICAgICAgICAgX09ic2VydmFibGUucHJvdG90eXBlLm5vdGlmeS5jYWxsKHRoaXMsIFwiYWN0aW9uc19yZWZyZXNoZWRcIiwgbWVtbyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5maXJlKFwiYWN0aW9uc19yZWZyZXNoZWRcIik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCBhY3Rpb25zXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5yZW1vdmVBY3Rpb25zID0gZnVuY3Rpb24gcmVtb3ZlQWN0aW9ucygpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgYWN0aW9uLnJlbW92ZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hY3Rpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmNsZWFyUmVnaXN0ZXJlZEtleXMoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGFjdGlvbnMgZnJvbSBYTUwgUmVnaXN0cnlcbiAgICAgKiBAcGFyYW0gcmVnaXN0cnkgRE9NRG9jdW1lbnRcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5ID0gZnVuY3Rpb24gbG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoKSB7XG4gICAgICAgIHZhciByZWdpc3RyeSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgaWYgKCFyZWdpc3RyeSkge1xuICAgICAgICAgICAgcmVnaXN0cnkgPSBweWRpby5nZXRYbWxSZWdpc3RyeSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWN0aW9ucygpO1xuICAgICAgICB0aGlzLnBhcnNlQWN0aW9ucyhyZWdpc3RyeSk7XG4gICAgICAgIHRoaXMuX2d1aUFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKGFjdCkge1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlckFjdGlvbihhY3QpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJhY3Rpb25zX2xvYWRlZFwiKTtcbiAgICAgICAgdGhpcy5maXJlQ29udGV4dENoYW5nZSgpO1xuICAgICAgICB0aGlzLmZpcmVTZWxlY3Rpb25DaGFuZ2UoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGFuIGFjdGlvbiB0byB0aGlzIG1hbmFnZXIgKGRlZmF1bHQsIGFjY2Vzc2tleSkuXG4gICAgICogQHBhcmFtIGFjdGlvbiBBY3Rpb25cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnJlZ2lzdGVyQWN0aW9uID0gZnVuY3Rpb24gcmVnaXN0ZXJBY3Rpb24oYWN0aW9uKSB7XG4gICAgICAgIHZhciBhY3Rpb25OYW1lID0gYWN0aW9uLm9wdGlvbnMubmFtZTtcbiAgICAgICAgdGhpcy5hY3Rpb25zLnNldChhY3Rpb25OYW1lLCBhY3Rpb24pO1xuICAgICAgICBpZiAoYWN0aW9uLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gYWN0aW9uLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbi5kZWZhdWx0cy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEFjdGlvbnMuc2V0KGtleSwgYWN0aW9uTmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChhY3Rpb24ub3B0aW9ucy5oYXNBY2Nlc3NLZXkpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJLZXkoYWN0aW9uLm9wdGlvbnMuYWNjZXNzS2V5LCBhY3Rpb25OYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWN0aW9uLm9wdGlvbnMuc3BlY2lhbEFjY2Vzc0tleSkge1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlcktleShcImtleV9cIiArIGFjdGlvbi5vcHRpb25zLnNwZWNpYWxBY2Nlc3NLZXksIGFjdGlvbk5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGFjdGlvbi5zZXRNYW5hZ2VyKHRoaXMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZSBhbiBYTUwgYWN0aW9uIG5vZGUgYW5kIHJlZ2lzdGVycyB0aGUgYWN0aW9uXG4gICAgICogQHBhcmFtIGRvY3VtZW50RWxlbWVudCBET01Ob2RlIFRoZSBub2RlIHRvIHBhcnNlXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5wYXJzZUFjdGlvbnMgPSBmdW5jdGlvbiBwYXJzZUFjdGlvbnMoZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgIHZhciBhY3Rpb25zID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKGRvY3VtZW50RWxlbWVudCwgXCJhY3Rpb25zL2FjdGlvblwiKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhY3Rpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1tpXS5ub2RlTmFtZSAhPSAnYWN0aW9uJykgY29udGludWU7XG4gICAgICAgICAgICBpZiAoYWN0aW9uc1tpXS5nZXRBdHRyaWJ1dGUoJ2VuYWJsZWQnKSA9PSAnZmFsc2UnKSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciBuZXdBY3Rpb24gPSBuZXcgX0FjdGlvbjJbJ2RlZmF1bHQnXSgpO1xuICAgICAgICAgICAgbmV3QWN0aW9uLnNldE1hbmFnZXIodGhpcyk7XG4gICAgICAgICAgICBuZXdBY3Rpb24uY3JlYXRlRnJvbVhNTChhY3Rpb25zW2ldKTtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJBY3Rpb24obmV3QWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIGFuIGFjdGlvbiBieSBpdHMgbmFtZVxuICAgICAqIEBwYXJhbSBhY3Rpb25OYW1lIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEFjdGlvblxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0QWN0aW9uQnlOYW1lID0gZnVuY3Rpb24gZ2V0QWN0aW9uQnlOYW1lKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aW9ucy5nZXQoYWN0aW9uTmFtZSk7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLl9zb3J0VG9vbGJhcnNBY3Rpb25zID0gZnVuY3Rpb24gX3NvcnRUb29sYmFyc0FjdGlvbnModG9vbGJhcnMpIHtcbiAgICAgICAgLy8gU29ydFxuICAgICAgICB0b29sYmFycy5mb3JFYWNoKGZ1bmN0aW9uICh2LCBrKSB7XG4gICAgICAgICAgICBpZiAoIXYuc29ydCkgcmV0dXJuO1xuICAgICAgICAgICAgdi5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHdBID0gYS53ZWlnaHQgfHwgYS5vcHRpb25zICYmIGEub3B0aW9ucy53ZWlnaHQgfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgd0IgPSBiLndlaWdodCB8fCBiLm9wdGlvbnMgJiYgYi5vcHRpb25zLndlaWdodCB8fCAwO1xuICAgICAgICAgICAgICAgIHJldHVybiB3QSA9PT0gd0IgPyAwIDogd0EgPiB3QiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRvb2xiYXJzO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ29udHJvbGxlcjtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvbnRyb2xsZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfQWp4cE5vZGUgPSByZXF1aXJlKCcuL0FqeHBOb2RlJyk7XG5cbnZhciBfQWp4cE5vZGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQWp4cE5vZGUpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL0xhbmdVdGlscycpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbExhbmdVdGlscyk7XG5cbnZhciBfdXRpbFBhdGhVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvUGF0aFV0aWxzJyk7XG5cbnZhciBfdXRpbFBhdGhVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsUGF0aFV0aWxzKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbi8qKlxuICogRnVsbCBjb250YWluZXIgb2YgdGhlIGRhdGEgdHJlZS4gQ29udGFpbnMgdGhlIFNlbGVjdGlvbk1vZGVsIGFzIHdlbGwuXG4gKi9cblxudmFyIFB5ZGlvRGF0YU1vZGVsID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuXHRfaW5oZXJpdHMoUHlkaW9EYXRhTW9kZWwsIF9PYnNlcnZhYmxlKTtcblxuXHQvKipcbiAgKiBDb25zdHJ1Y3RvclxuICAgICAqID4gV2FybmluZywgZXZlbnRzIGFyZSBub3cgTE9DQUwgYnkgZGVmYXVsdFxuICAqL1xuXG5cdGZ1bmN0aW9uIFB5ZGlvRGF0YU1vZGVsKCkge1xuXHRcdHZhciBsb2NhbEV2ZW50cyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbMF07XG5cblx0XHRfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHlkaW9EYXRhTW9kZWwpO1xuXG5cdFx0X09ic2VydmFibGUuY2FsbCh0aGlzKTtcblx0XHR0aGlzLl9jdXJyZW50UmVwID0gJy8nO1xuXHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMgPSBbXTtcblx0XHR0aGlzLl9iRW1wdHkgPSB0cnVlO1xuXHRcdHRoaXMuX2dsb2JhbEV2ZW50cyA9ICFsb2NhbEV2ZW50cztcblxuXHRcdHRoaXMuX2JGaWxlID0gZmFsc2U7XG5cdFx0dGhpcy5fYkRpciA9IGZhbHNlO1xuXHRcdHRoaXMuX2lzUmVjeWNsZSA9IGZhbHNlO1xuXG5cdFx0dGhpcy5fcGVuZGluZ1NlbGVjdGlvbiA9IG51bGw7XG5cdFx0dGhpcy5fc2VsZWN0aW9uU291cmNlID0ge307XG5cblx0XHR0aGlzLl9yb290Tm9kZSA9IG51bGw7XG5cdH1cblxuXHRQeWRpb0RhdGFNb2RlbC5SZW1vdGVEYXRhTW9kZWxGYWN0b3J5ID0gZnVuY3Rpb24gUmVtb3RlRGF0YU1vZGVsRmFjdG9yeShwcm92aWRlclByb3BlcnRpZXMpIHtcblx0XHR2YXIgcm9vdExhYmVsID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbMV07XG5cblx0XHR2YXIgZGF0YU1vZGVsID0gbmV3IFB5ZGlvRGF0YU1vZGVsKHRydWUpO1xuXHRcdHZhciByTm9kZVByb3ZpZGVyID0gbmV3IFJlbW90ZU5vZGVQcm92aWRlcihwcm92aWRlclByb3BlcnRpZXMpO1xuXHRcdGRhdGFNb2RlbC5zZXRBanhwTm9kZVByb3ZpZGVyKHJOb2RlUHJvdmlkZXIpO1xuXHRcdHZhciByb290Tm9kZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10oXCIvXCIsIGZhbHNlLCByb290TGFiZWwsICcnLCByTm9kZVByb3ZpZGVyKTtcblx0XHRkYXRhTW9kZWwuc2V0Um9vdE5vZGUocm9vdE5vZGUpO1xuXHRcdHJldHVybiBkYXRhTW9kZWw7XG5cdH07XG5cblx0LyoqXG4gICogU2V0cyB0aGUgZGF0YSBzb3VyY2UgdGhhdCB3aWxsIGZlZWQgdGhlIG5vZGVzIHdpdGggY2hpbGRyZW4uXG4gICogQHBhcmFtIGlBanhwTm9kZVByb3ZpZGVyIElBanhwTm9kZVByb3ZpZGVyXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldEFqeHBOb2RlUHJvdmlkZXIgPSBmdW5jdGlvbiBzZXRBanhwTm9kZVByb3ZpZGVyKGlBanhwTm9kZVByb3ZpZGVyKSB7XG5cdFx0dGhpcy5faUFqeHBOb2RlUHJvdmlkZXIgPSBpQWp4cE5vZGVQcm92aWRlcjtcblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm4gdGhlIGN1cnJlbnQgZGF0YSBzb3VyY2UgcHJvdmlkZXJcbiAgKiBAcmV0dXJuIElBanhwTm9kZVByb3ZpZGVyXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldEFqeHBOb2RlUHJvdmlkZXIgPSBmdW5jdGlvbiBnZXRBanhwTm9kZVByb3ZpZGVyKCkge1xuXHRcdHJldHVybiB0aGlzLl9pQWp4cE5vZGVQcm92aWRlcjtcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIHRoZSBjdXJyZW50IGNvbnRleHQgbm9kZS5cbiAgKiBAcGFyYW0gYWp4cE5vZGUgQWp4cE5vZGUgVGFyZ2V0IG5vZGUsIGVpdGhlciBhbiBleGlzdGluZyBvbmUgb3IgYSBmYWtlIG9uZSBjb250YWluaW5nIHRoZSB0YXJnZXQgcGFydC5cbiAgKiBAcGFyYW0gZm9yY2VSZWxvYWQgQm9vbGVhbiBJZiBzZXQgdG8gdHJ1ZSwgdGhlIG5vZGUgd2lsbCBiZSByZWxvYWRlZCBldmVuIGlmIGFscmVhZHkgbG9hZGVkLlxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5yZXF1aXJlQ29udGV4dENoYW5nZSA9IGZ1bmN0aW9uIHJlcXVpcmVDb250ZXh0Q2hhbmdlKGFqeHBOb2RlKSB7XG5cdFx0dmFyIF90aGlzID0gdGhpcztcblxuXHRcdHZhciBmb3JjZVJlbG9hZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0aWYgKGFqeHBOb2RlID09IG51bGwpIHJldHVybjtcblx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMoW10pO1xuXHRcdHZhciBwYXRoID0gYWp4cE5vZGUuZ2V0UGF0aCgpO1xuXHRcdGlmICgocGF0aCA9PSBcIlwiIHx8IHBhdGggPT0gXCIvXCIpICYmIGFqeHBOb2RlICE9IHRoaXMuX3Jvb3ROb2RlKSB7XG5cdFx0XHRhanhwTm9kZSA9IHRoaXMuX3Jvb3ROb2RlO1xuXHRcdH1cblx0XHR2YXIgcGFnaW5hdGlvblBhZ2UgPSBudWxsO1xuXHRcdGlmIChhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmhhcygncGFnaW5hdGlvbkRhdGEnKSAmJiBhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKS5oYXMoJ25ld19wYWdlJykgJiYgYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykuZ2V0KCduZXdfcGFnZScpICE9IGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpLmdldCgnY3VycmVudCcpKSB7XG5cdFx0XHRwYWdpbmF0aW9uUGFnZSA9IGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpLmdldCgnbmV3X3BhZ2UnKTtcblx0XHRcdGZvcmNlUmVsb2FkID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKGFqeHBOb2RlICE9IHRoaXMuX3Jvb3ROb2RlICYmICghYWp4cE5vZGUuZ2V0UGFyZW50KCkgfHwgYWp4cE5vZGUuZmFrZSkpIHtcblx0XHRcdC8vIEZpbmQgaW4gYXJibyBvciBidWlsZCBmYWtlIGFyYm9cblx0XHRcdHZhciBmYWtlTm9kZXMgPSBbXTtcblx0XHRcdGFqeHBOb2RlID0gYWp4cE5vZGUuZmluZEluQXJibyh0aGlzLl9yb290Tm9kZSwgZmFrZU5vZGVzKTtcblx0XHRcdGlmIChmYWtlTm9kZXMubGVuZ3RoKSB7XG5cdFx0XHRcdHZhciBfcmV0ID0gKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHR2YXIgZmlyc3RGYWtlID0gZmFrZU5vZGVzLnNoaWZ0KCk7XG5cdFx0XHRcdFx0Zmlyc3RGYWtlLm9ic2VydmVPbmNlKFwiZmlyc3RfbG9hZFwiLCAoZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0XHRcdHRoaXMucmVxdWlyZUNvbnRleHRDaGFuZ2UoYWp4cE5vZGUpO1xuXHRcdFx0XHRcdH0pLmJpbmQoX3RoaXMpKTtcblx0XHRcdFx0XHRmaXJzdEZha2Uub2JzZXJ2ZU9uY2UoXCJlcnJvclwiLCAoZnVuY3Rpb24gKG1lc3NhZ2UpIHtcblx0XHRcdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKG1lc3NhZ2UpO1xuXHRcdFx0XHRcdFx0Zmlyc3RGYWtlLm5vdGlmeShcIm5vZGVfcmVtb3ZlZFwiKTtcblx0XHRcdFx0XHRcdHZhciBwYXJlbnQgPSBmaXJzdEZha2UuZ2V0UGFyZW50KCk7XG5cdFx0XHRcdFx0XHRwYXJlbnQucmVtb3ZlQ2hpbGQoZmlyc3RGYWtlKTtcblx0XHRcdFx0XHRcdC8vZGVsZXRlKGZpcnN0RmFrZSk7XG5cdFx0XHRcdFx0XHR0aGlzLnJlcXVpcmVDb250ZXh0Q2hhbmdlKHBhcmVudCk7XG5cdFx0XHRcdFx0fSkuYmluZChfdGhpcykpO1xuXHRcdFx0XHRcdF90aGlzLnB1Ymxpc2goXCJjb250ZXh0X2xvYWRpbmdcIik7XG5cdFx0XHRcdFx0Zmlyc3RGYWtlLmxvYWQoX3RoaXMuX2lBanhwTm9kZVByb3ZpZGVyKTtcblx0XHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdFx0djogdW5kZWZpbmVkXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fSkoKTtcblxuXHRcdFx0XHRpZiAodHlwZW9mIF9yZXQgPT09ICdvYmplY3QnKSByZXR1cm4gX3JldC52O1xuXHRcdFx0fVxuXHRcdH1cblx0XHRhanhwTm9kZS5vYnNlcnZlT25jZShcImxvYWRlZFwiLCAoZnVuY3Rpb24gKCkge1xuXHRcdFx0dGhpcy5zZXRDb250ZXh0Tm9kZShhanhwTm9kZSwgdHJ1ZSk7XG5cdFx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2xvYWRlZFwiKTtcblx0XHRcdGlmICh0aGlzLmdldFBlbmRpbmdTZWxlY3Rpb24oKSkge1xuXHRcdFx0XHR2YXIgc2VsUGF0aCA9IGFqeHBOb2RlLmdldFBhdGgoKSArIChhanhwTm9kZS5nZXRQYXRoKCkgPT0gXCIvXCIgPyBcIlwiIDogXCIvXCIpICsgdGhpcy5nZXRQZW5kaW5nU2VsZWN0aW9uKCk7XG5cdFx0XHRcdHZhciBzZWxOb2RlID0gYWp4cE5vZGUuZmluZENoaWxkQnlQYXRoKHNlbFBhdGgpO1xuXHRcdFx0XHRpZiAoc2VsTm9kZSkge1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWROb2Rlcyhbc2VsTm9kZV0sIHRoaXMpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmIChhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInBhZ2luYXRpb25EYXRhXCIpICYmIGFyZ3VtZW50cy5sZW5ndGggPCAzKSB7XG5cdFx0XHRcdFx0XHR2YXIgbmV3UGFnZSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdHZhciBjdXJyZW50UGFnZSA9IGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicGFnaW5hdGlvbkRhdGFcIikuZ2V0KFwiY3VycmVudFwiKTtcblx0XHRcdFx0XHRcdHRoaXMubG9hZFBhdGhJbmZvU3luYyhzZWxQYXRoLCBmdW5jdGlvbiAoZm91bmROb2RlKSB7XG5cdFx0XHRcdFx0XHRcdG5ld1BhZ2UgPSBmb3VuZE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJwYWdlX3Bvc2l0aW9uXCIpO1xuXHRcdFx0XHRcdFx0fSwgeyBwYWdlX3Bvc2l0aW9uOiAndHJ1ZScgfSk7XG5cdFx0XHRcdFx0XHRpZiAobmV3UGFnZSAmJiBuZXdQYWdlICE9PSBjdXJyZW50UGFnZSkge1xuXHRcdFx0XHRcdFx0XHRhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInBhZ2luYXRpb25EYXRhXCIpLnNldChcIm5ld19wYWdlXCIsIG5ld1BhZ2UpO1xuXHRcdFx0XHRcdFx0XHR0aGlzLnJlcXVpcmVDb250ZXh0Q2hhbmdlKGFqeHBOb2RlLCB0cnVlLCB0cnVlKTtcblx0XHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLmNsZWFyUGVuZGluZ1NlbGVjdGlvbigpO1xuXHRcdFx0fVxuXHRcdH0pLmJpbmQodGhpcykpO1xuXHRcdGFqeHBOb2RlLm9ic2VydmVPbmNlKFwiZXJyb3JcIiwgKGZ1bmN0aW9uIChtZXNzYWdlKSB7XG5cdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihtZXNzYWdlKTtcblx0XHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfbG9hZGVkXCIpO1xuXHRcdH0pLmJpbmQodGhpcykpO1xuXHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfbG9hZGluZ1wiKTtcblx0XHR0cnkge1xuXHRcdFx0aWYgKGZvcmNlUmVsb2FkKSB7XG5cdFx0XHRcdGlmIChwYWdpbmF0aW9uUGFnZSkge1xuXHRcdFx0XHRcdGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpLnNldCgnY3VycmVudCcsIHBhZ2luYXRpb25QYWdlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRhanhwTm9kZS5yZWxvYWQodGhpcy5faUFqeHBOb2RlUHJvdmlkZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YWp4cE5vZGUubG9hZCh0aGlzLl9pQWp4cE5vZGVQcm92aWRlcik7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9sb2FkZWRcIik7XG5cdFx0fVxuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5yZXF1aXJlTm9kZVJlbG9hZCA9IGZ1bmN0aW9uIHJlcXVpcmVOb2RlUmVsb2FkKG5vZGVPclBhdGgsIGNvbXBsZXRlQ2FsbGJhY2spIHtcblx0XHRpZiAobm9kZU9yUGF0aCBpbnN0YW5jZW9mIFN0cmluZykge1xuXHRcdFx0bm9kZU9yUGF0aCA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10obm9kZU9yUGF0aCk7XG5cdFx0fVxuXHRcdHZhciBvbkNvbXBsZXRlID0gbnVsbDtcblx0XHRpZiAodGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGgpIHtcblx0XHRcdHZhciBmb3VuZCA9IC0xO1xuXHRcdFx0dGhpcy5fc2VsZWN0ZWROb2Rlcy5tYXAoZnVuY3Rpb24gKG5vZGUsIGtleSkge1xuXHRcdFx0XHRpZiAobm9kZS5nZXRQYXRoKCkgPT0gbm9kZU9yUGF0aC5nZXRQYXRoKCkpIGZvdW5kID0ga2V5O1xuXHRcdFx0fSk7XG5cdFx0XHRpZiAoZm91bmQgIT09IC0xKSB7XG5cdFx0XHRcdC8vIE1BS0UgU1VSRSBTRUxFQ1RJT04gSVMgT0sgQUZURVIgUkVMT0FEXG5cdFx0XHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5hcnJheVdpdGhvdXQodGhpcy5fc2VsZWN0ZWROb2RlcywgZm91bmQpO1xuXHRcdFx0XHR0aGlzLnB1Ymxpc2goXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzKTtcblx0XHRcdFx0b25Db21wbGV0ZSA9IChmdW5jdGlvbiAobmV3Tm9kZSkge1xuXHRcdFx0XHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMucHVzaChuZXdOb2RlKTtcblx0XHRcdFx0XHR0aGlzLl9zZWxlY3Rpb25Tb3VyY2UgPSB7fTtcblx0XHRcdFx0XHR0aGlzLnB1Ymxpc2goXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzKTtcblx0XHRcdFx0XHRpZiAoY29tcGxldGVDYWxsYmFjaykgY29tcGxldGVDYWxsYmFjayhuZXdOb2RlKTtcblx0XHRcdFx0fSkuYmluZCh0aGlzKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5faUFqeHBOb2RlUHJvdmlkZXIucmVmcmVzaE5vZGVBbmRSZXBsYWNlKG5vZGVPclBhdGgsIG9uQ29tcGxldGUpO1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5sb2FkUGF0aEluZm9TeW5jID0gZnVuY3Rpb24gbG9hZFBhdGhJbmZvU3luYyhwYXRoLCBjYWxsYmFjaykge1xuXHRcdHZhciBhZGRpdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzJdO1xuXG5cdFx0dGhpcy5faUFqeHBOb2RlUHJvdmlkZXIubG9hZExlYWZOb2RlU3luYyhuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKHBhdGgpLCBjYWxsYmFjaywgZmFsc2UsIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKTtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUubG9hZFBhdGhJbmZvQXN5bmMgPSBmdW5jdGlvbiBsb2FkUGF0aEluZm9Bc3luYyhwYXRoLCBjYWxsYmFjaykge1xuXHRcdHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyLmxvYWRMZWFmTm9kZVN5bmMobmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShwYXRoKSwgY2FsbGJhY2ssIHRydWUpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldHMgdGhlIHJvb3Qgb2YgdGhlIGRhdGEgc3RvcmVcbiAgKiBAcGFyYW0gYWp4cFJvb3ROb2RlIEFqeHBOb2RlIFRoZSBwYXJlbnQgbm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRSb290Tm9kZSA9IGZ1bmN0aW9uIHNldFJvb3ROb2RlKGFqeHBSb290Tm9kZSkge1xuXHRcdHRoaXMuX3Jvb3ROb2RlID0gYWp4cFJvb3ROb2RlO1xuXHRcdHRoaXMuX3Jvb3ROb2RlLnNldFJvb3QoKTtcblx0XHR0aGlzLl9yb290Tm9kZS5vYnNlcnZlKFwiY2hpbGRfYWRkZWRcIiwgZnVuY3Rpb24gKGMpIHtcblx0XHRcdC8vY29uc29sZS5sb2coYyk7XG5cdFx0fSk7XG5cdFx0dGhpcy5wdWJsaXNoKFwicm9vdF9ub2RlX2NoYW5nZWRcIiwgdGhpcy5fcm9vdE5vZGUpO1xuXHRcdHRoaXMuc2V0Q29udGV4dE5vZGUodGhpcy5fcm9vdE5vZGUpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGN1cnJlbnQgcm9vdCBub2RlXG4gICogQHJldHVybnMgQWp4cE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0Um9vdE5vZGUgPSBmdW5jdGlvbiBnZXRSb290Tm9kZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fcm9vdE5vZGU7XG5cdH07XG5cblx0LyoqXG4gICogU2V0cyB0aGUgY3VycmVudCBjb250ZXh0IG5vZGVcbiAgKiBAcGFyYW0gYWp4cERhdGFOb2RlIEFqeHBOb2RlXG4gICogQHBhcmFtIGZvcmNlRXZlbnQgQm9vbGVhbiBJZiBzZXQgdG8gdHJ1ZSwgZXZlbnQgd2lsbCBiZSB0cmlnZ2VyZWQgZXZlbiBpZiB0aGUgY3VycmVudCBub2RlIGlzIGFscmVhZHkgdGhlIHNhbWUuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldENvbnRleHROb2RlID0gZnVuY3Rpb24gc2V0Q29udGV4dE5vZGUoYWp4cERhdGFOb2RlLCBmb3JjZUV2ZW50KSB7XG5cdFx0aWYgKHRoaXMuX2NvbnRleHROb2RlICYmIHRoaXMuX2NvbnRleHROb2RlID09IGFqeHBEYXRhTm9kZSAmJiB0aGlzLl9jdXJyZW50UmVwID09IGFqeHBEYXRhTm9kZS5nZXRQYXRoKCkgJiYgIWZvcmNlRXZlbnQpIHtcblx0XHRcdHJldHVybjsgLy8gTm8gY2hhbmdlc1xuXHRcdH1cblx0XHRpZiAoIWFqeHBEYXRhTm9kZSkgcmV0dXJuO1xuXHRcdGlmICh0aGlzLl9jb250ZXh0Tm9kZVJlcGxhY2VkT2JzZXJ2ZXIgJiYgdGhpcy5fY29udGV4dE5vZGUpIHtcblx0XHRcdHRoaXMuX2NvbnRleHROb2RlLnN0b3BPYnNlcnZpbmcoXCJub2RlX3JlcGxhY2VkXCIsIHRoaXMuX2NvbnRleHROb2RlUmVwbGFjZWRPYnNlcnZlcik7XG5cdFx0fVxuXHRcdHRoaXMuX2NvbnRleHROb2RlID0gYWp4cERhdGFOb2RlO1xuXHRcdHRoaXMuX2N1cnJlbnRSZXAgPSBhanhwRGF0YU5vZGUuZ2V0UGF0aCgpO1xuXHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfY2hhbmdlZFwiLCBhanhwRGF0YU5vZGUpO1xuXHRcdGlmICghdGhpcy5fY29udGV4dE5vZGVSZXBsYWNlZE9ic2VydmVyKSB0aGlzLl9jb250ZXh0Tm9kZVJlcGxhY2VkT2JzZXJ2ZXIgPSB0aGlzLmNvbnRleHROb2RlUmVwbGFjZWQuYmluZCh0aGlzKTtcblx0XHRhanhwRGF0YU5vZGUub2JzZXJ2ZShcIm5vZGVfcmVwbGFjZWRcIiwgdGhpcy5fY29udGV4dE5vZGVSZXBsYWNlZE9ic2VydmVyKTtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuY29udGV4dE5vZGVSZXBsYWNlZCA9IGZ1bmN0aW9uIGNvbnRleHROb2RlUmVwbGFjZWQobmV3Tm9kZSkge1xuXHRcdHRoaXMuc2V0Q29udGV4dE5vZGUobmV3Tm9kZSk7XG5cdH07XG5cblx0LyoqXG4gICpcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUucHVibGlzaCA9IGZ1bmN0aW9uIHB1Ymxpc2goZXZlbnROYW1lLCBvcHRpb25hbERhdGEpIHtcblx0XHR2YXIgYXJncyA9IFtdO1xuXHRcdGlmICh0aGlzLl9nbG9iYWxFdmVudHMpIHtcblx0XHRcdGlmICh3aW5kb3cucHlkaW8pIHtcblx0XHRcdFx0YXJncy5wdXNoKGV2ZW50TmFtZSk7XG5cdFx0XHRcdGlmIChvcHRpb25hbERhdGEpIGFyZ3MucHVzaChvcHRpb25hbERhdGEpO1xuXHRcdFx0XHR3aW5kb3cucHlkaW8uZmlyZS5hcHBseSh3aW5kb3cucHlkaW8sIGFyZ3MpO1xuXHRcdFx0fSBlbHNlIGlmIChkb2N1bWVudC5maXJlKSB7XG5cdFx0XHRcdGFyZ3MucHVzaChcImFqYXhwbG9yZXI6XCIgKyBldmVudE5hbWUpO1xuXHRcdFx0XHRpZiAob3B0aW9uYWxEYXRhKSBhcmdzLnB1c2gob3B0aW9uYWxEYXRhKTtcblx0XHRcdFx0ZG9jdW1lbnQuZmlyZS5hcHBseShkb2N1bWVudCwgYXJncyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAob3B0aW9uYWxEYXRhKSB7XG5cdFx0XHRcdGFyZ3MgPSBbZXZlbnROYW1lLCB7IG1lbW86IG9wdGlvbmFsRGF0YSB9XTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFyZ3MgPSBbZXZlbnROYW1lXTtcblx0XHRcdH1cblx0XHRcdHRoaXMubm90aWZ5LmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAob3B0aW9uYWxEYXRhKSB7XG5cdFx0XHRcdGFyZ3MgPSBbZXZlbnROYW1lLCB7IG1lbW86IG9wdGlvbmFsRGF0YSB9XTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFyZ3MgPSBbZXZlbnROYW1lXTtcblx0XHRcdH1cblx0XHRcdHRoaXMubm90aWZ5LmFwcGx5KHRoaXMsIGFyZ3MpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBHZXQgdGhlIGN1cnJlbnQgY29udGV4dCBub2RlXG4gICogQHJldHVybnMgQWp4cE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0Q29udGV4dE5vZGUgPSBmdW5jdGlvbiBnZXRDb250ZXh0Tm9kZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fY29udGV4dE5vZGU7XG5cdH07XG5cblx0LyoqXG4gICogQWZ0ZXIgYSBjb3B5IG9yIG1vdmUgb3BlcmF0aW9uLCBtYW55IG5vZGVzIG1heSBoYXZlIHRvIGJlIHJlbG9hZGVkXG4gICogVGhpcyBmdW5jdGlvbiB0cmllcyB0byByZWxvYWQgdGhlbSBpbiB0aGUgcmlnaHQgb3JkZXIgYW5kIGlmIG5lY2Vzc2FyeS5cbiAgKiBAcGFyYW0gbm9kZXMgQWp4cE5vZGVzW10gQW4gYXJyYXkgb2Ygbm9kZXNcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUubXVsdGlwbGVOb2Rlc1JlbG9hZCA9IGZ1bmN0aW9uIG11bHRpcGxlTm9kZXNSZWxvYWQobm9kZXMpIHtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgbm9kZVBhdGhPck5vZGUgPSBub2Rlc1tpXTtcblx0XHRcdHZhciBub2RlO1xuXHRcdFx0aWYgKG5vZGVQYXRoT3JOb2RlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG5cdFx0XHRcdG5vZGUgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKG5vZGVQYXRoT3JOb2RlKTtcblx0XHRcdFx0aWYgKG5vZGUuZ2V0UGF0aCgpID09IHRoaXMuX3Jvb3ROb2RlLmdldFBhdGgoKSkgbm9kZSA9IHRoaXMuX3Jvb3ROb2RlO2Vsc2Ugbm9kZSA9IG5vZGUuZmluZEluQXJibyh0aGlzLl9yb290Tm9kZSwgW10pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bm9kZSA9IG5vZGVQYXRoT3JOb2RlO1xuXHRcdFx0fVxuXHRcdFx0bm9kZXNbaV0gPSBub2RlO1xuXHRcdH1cblx0XHR2YXIgY2hpbGRyZW4gPSBbXTtcblx0XHRub2Rlcy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG5cdFx0XHRpZiAoYS5pc1BhcmVudE9mKGIpKSB7XG5cdFx0XHRcdGNoaWxkcmVuLnB1c2goYik7XG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHRcdGlmIChhLmlzQ2hpbGRPZihiKSkge1xuXHRcdFx0XHRjaGlsZHJlbi5wdXNoKGEpO1xuXHRcdFx0XHRyZXR1cm4gKzE7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9KTtcblx0XHRjaGlsZHJlbi5tYXAoZnVuY3Rpb24gKGMpIHtcblx0XHRcdG5vZGVzID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10uYXJyYXlXaXRob3V0KG5vZGVzLCBjKTtcblx0XHR9KTtcblx0XHRub2Rlcy5tYXAodGhpcy5xdWV1ZU5vZGVSZWxvYWQuYmluZCh0aGlzKSk7XG5cdFx0dGhpcy5uZXh0Tm9kZVJlbG9hZGVyKCk7XG5cdH07XG5cblx0LyoqXG4gICogQWRkIGEgbm9kZSB0byB0aGUgcXVldWUgb2Ygbm9kZXMgdG8gcmVsb2FkLlxuICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnF1ZXVlTm9kZVJlbG9hZCA9IGZ1bmN0aW9uIHF1ZXVlTm9kZVJlbG9hZChub2RlKSB7XG5cdFx0aWYgKCF0aGlzLnF1ZXVlKSB0aGlzLnF1ZXVlID0gW107XG5cdFx0aWYgKG5vZGUpIHtcblx0XHRcdHRoaXMucXVldWUucHVzaChub2RlKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogUXVldWUgcHJvY2Vzc29yIGZvciB0aGUgbm9kZXMgdG8gcmVsb2FkXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLm5leHROb2RlUmVsb2FkZXIgPSBmdW5jdGlvbiBuZXh0Tm9kZVJlbG9hZGVyKCkge1xuXHRcdGlmICghdGhpcy5xdWV1ZS5sZW5ndGgpIHtcblx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfY2hhbmdlZFwiLCB0aGlzLl9jb250ZXh0Tm9kZSk7XG5cdFx0XHR9KS5iaW5kKHRoaXMpLCAyMDApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR2YXIgbmV4dCA9IHRoaXMucXVldWUuc2hpZnQoKTtcblx0XHR2YXIgb2JzZXJ2ZXIgPSB0aGlzLm5leHROb2RlUmVsb2FkZXIuYmluZCh0aGlzKTtcblx0XHRuZXh0Lm9ic2VydmVPbmNlKFwibG9hZGVkXCIsIG9ic2VydmVyKTtcblx0XHRuZXh0Lm9ic2VydmVPbmNlKFwiZXJyb3JcIiwgb2JzZXJ2ZXIpO1xuXHRcdGlmIChuZXh0ID09IHRoaXMuX2NvbnRleHROb2RlIHx8IG5leHQuaXNQYXJlbnRPZih0aGlzLl9jb250ZXh0Tm9kZSkpIHtcblx0XHRcdHRoaXMucmVxdWlyZUNvbnRleHRDaGFuZ2UobmV4dCwgdHJ1ZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG5leHQucmVsb2FkKHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogSW5zZXJ0IGEgbm9kZSBzb21ld2hlcmUgaW4gdGhlIGRhdGFtb2RlbFxuICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICogQHBhcmFtIHNldFNlbGVjdGVkQWZ0ZXJBZGQgYm9vbFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5hZGROb2RlID0gZnVuY3Rpb24gYWRkTm9kZShub2RlKSB7XG5cdFx0dmFyIHNldFNlbGVjdGVkQWZ0ZXJBZGQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdHZhciBwYXJlbnRGYWtlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSk7XG5cdFx0dmFyIHBhcmVudCA9IHBhcmVudEZha2UuZmluZEluQXJibyh0aGlzLmdldFJvb3ROb2RlKCksIHVuZGVmaW5lZCk7XG5cdFx0aWYgKCFwYXJlbnQgJiYgX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSkgPT0gXCJcIikgcGFyZW50ID0gdGhpcy5nZXRSb290Tm9kZSgpO1xuXHRcdGlmIChwYXJlbnQpIHtcblx0XHRcdHZhciBhZGRlZE5vZGUgPSBwYXJlbnQuYWRkQ2hpbGQobm9kZSk7XG5cdFx0XHRpZiAoYWRkZWROb2RlICYmIHNldFNlbGVjdGVkQWZ0ZXJBZGQgJiYgdGhpcy5nZXRDb250ZXh0Tm9kZSgpID09IHBhcmVudCkge1xuXHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMoW2FkZGVkTm9kZV0sIHt9KTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogUmVtb3ZlIGEgbm9kZSBieSBwYXRoIHNvbWV3aGVyZVxuICAqIEBwYXJhbSBwYXRoIHN0cmluZ1xuICAqIEBwYXJhbSBpbVRpbWUgaW50ZWdlcnxudWxsXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnJlbW92ZU5vZGVCeVBhdGggPSBmdW5jdGlvbiByZW1vdmVOb2RlQnlQYXRoKHBhdGgpIHtcblx0XHR2YXIgaW1UaW1lID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdHZhciBmYWtlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShwYXRoKTtcblx0XHR2YXIgbiA9IGZha2UuZmluZEluQXJibyh0aGlzLmdldFJvb3ROb2RlKCksIHVuZGVmaW5lZCk7XG5cdFx0aWYgKG4pIHtcblx0XHRcdGlmIChpbVRpbWUgJiYgbi5nZXRNZXRhZGF0YSgpICYmIG4uZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikgJiYgcGFyc2VJbnQobi5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSkgPj0gaW1UaW1lKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdG4uZ2V0UGFyZW50KCkucmVtb3ZlQ2hpbGQobik7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFVwZGF0ZSBhIG5vZGUgc29tZXdoZXJlIGluIHRoZSBkYXRhbW9kZWxcbiAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAqIEBwYXJhbSBzZXRTZWxlY3RlZEFmdGVyVXBkYXRlIGJvb2xcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUudXBkYXRlTm9kZSA9IGZ1bmN0aW9uIHVwZGF0ZU5vZGUobm9kZSkge1xuXHRcdHZhciBzZXRTZWxlY3RlZEFmdGVyVXBkYXRlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cblx0XHR2YXIgb3JpZ2luYWwgPSBub2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwib3JpZ2luYWxfcGF0aFwiKTtcblx0XHR2YXIgZmFrZSwgbjtcblx0XHRpZiAob3JpZ2luYWwgJiYgb3JpZ2luYWwgIT0gbm9kZS5nZXRQYXRoKCkgJiYgX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShvcmlnaW5hbCkgIT0gX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSkpIHtcblx0XHRcdC8vIE5vZGUgd2FzIHJlYWxseSBtb3ZlZCB0byBhbm90aGVyIGZvbGRlclxuXHRcdFx0ZmFrZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10ob3JpZ2luYWwpO1xuXHRcdFx0biA9IGZha2UuZmluZEluQXJibyh0aGlzLmdldFJvb3ROb2RlKCksIHVuZGVmaW5lZCk7XG5cdFx0XHRpZiAobikge1xuXHRcdFx0XHRuLmdldFBhcmVudCgpLnJlbW92ZUNoaWxkKG4pO1xuXHRcdFx0fVxuXHRcdFx0dmFyIHBhcmVudEZha2UgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpKTtcblx0XHRcdHZhciBwYXJlbnQgPSBwYXJlbnRGYWtlLmZpbmRJbkFyYm8odGhpcy5nZXRSb290Tm9kZSgpLCB1bmRlZmluZWQpO1xuXHRcdFx0aWYgKCFwYXJlbnQgJiYgX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSkgPT0gXCJcIikgcGFyZW50ID0gdGhpcy5nZXRSb290Tm9kZSgpO1xuXHRcdFx0aWYgKHBhcmVudCkge1xuXHRcdFx0XHRub2RlLmdldE1ldGFkYXRhKCkuc2V0KFwib3JpZ2luYWxfcGF0aFwiLCB1bmRlZmluZWQpO1xuXHRcdFx0XHRwYXJlbnQuYWRkQ2hpbGQobm9kZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmIChub2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwib3JpZ2luYWxfcGF0aFwiKSA9PT0gXCIvXCIgJiYgbm9kZS5nZXRQYXRoKCkgPT09IFwiL1wiKSB7XG5cdFx0XHRcdG4gPSB0aGlzLmdldFJvb3ROb2RlKCk7XG5cdFx0XHRcdG4ucmVwbGFjZU1ldGFkYXRhKG5vZGUuZ2V0TWV0YWRhdGEoKSk7XG5cdFx0XHRcdGlmIChzZXRTZWxlY3RlZEFmdGVyVXBkYXRlICYmIHRoaXMuZ2V0Q29udGV4dE5vZGUoKSA9PSBuKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKFtuXSwge30pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdGZha2UgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKG9yaWdpbmFsKTtcblx0XHRcdG4gPSBmYWtlLmZpbmRJbkFyYm8odGhpcy5nZXRSb290Tm9kZSgpLCB1bmRlZmluZWQpO1xuXHRcdFx0aWYgKG4gJiYgIW4uaXNNb3JlUmVjZW50VGhhbihub2RlKSkge1xuXHRcdFx0XHRub2RlLl9pc0xvYWRlZCA9IG4uX2lzTG9hZGVkO1xuXHRcdFx0XHRuLnJlcGxhY2VCeShub2RlLCBcIm92ZXJyaWRlXCIpO1xuXHRcdFx0XHRpZiAoc2V0U2VsZWN0ZWRBZnRlclVwZGF0ZSAmJiB0aGlzLmdldENvbnRleHROb2RlKCkgPT0gbi5nZXRQYXJlbnQoKSkge1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWROb2Rlcyhbbl0sIHt9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBTZXRzIGFuIGFycmF5IG9mIG5vZGVzIHRvIGJlIHNlbGVjdGVkIGFmdGVyIHRoZSBjb250ZXh0IGlzIChyZSlsb2FkZWRcbiAgKiBAcGFyYW0gc2VsZWN0aW9uIEFqeHBOb2RlW11cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0UGVuZGluZ1NlbGVjdGlvbiA9IGZ1bmN0aW9uIHNldFBlbmRpbmdTZWxlY3Rpb24oc2VsZWN0aW9uKSB7XG5cdFx0dGhpcy5fcGVuZGluZ1NlbGVjdGlvbiA9IHNlbGVjdGlvbjtcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBhcnJheSBvZiBub2RlcyB0byBiZSBzZWxlY3RlZCBhZnRlciB0aGUgY29udGV4dCBpcyAocmUpbG9hZGVkXG4gICogQHJldHVybnMgQWp4cE5vZGVbXVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRQZW5kaW5nU2VsZWN0aW9uID0gZnVuY3Rpb24gZ2V0UGVuZGluZ1NlbGVjdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5fcGVuZGluZ1NlbGVjdGlvbjtcblx0fTtcblxuXHQvKipcbiAgKiBDbGVhcnMgdGhlIG5vZGVzIHRvIGJlIHNlbGVjdGVkXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmNsZWFyUGVuZGluZ1NlbGVjdGlvbiA9IGZ1bmN0aW9uIGNsZWFyUGVuZGluZ1NlbGVjdGlvbigpIHtcblx0XHR0aGlzLl9wZW5kaW5nU2VsZWN0aW9uID0gbnVsbDtcblx0fTtcblxuXHQvKipcbiAgKiBTZXQgYW4gYXJyYXkgb2Ygbm9kZXMgYXMgdGhlIGN1cnJlbnQgc2VsZWN0aW9uXG4gICogQHBhcmFtIGFqeHBEYXRhTm9kZXMgQWp4cE5vZGVbXSBUaGUgbm9kZXMgdG8gc2VsZWN0XG4gICogQHBhcmFtIHNvdXJjZSBTdHJpbmcgVGhlIHNvdXJjZSBvZiB0aGlzIHNlbGVjdGlvbiBhY3Rpb25cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0U2VsZWN0ZWROb2RlcyA9IGZ1bmN0aW9uIHNldFNlbGVjdGVkTm9kZXMoYWp4cERhdGFOb2Rlcywgc291cmNlKSB7XG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoID09IGFqeHBEYXRhTm9kZXMubGVuZ3RoKSB7XG5cdFx0XHRpZiAoYWp4cERhdGFOb2Rlcy5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0dmFyIGVxdWFsID0gdHJ1ZTtcblx0XHRcdGZvciAodmFyIGsgPSAwOyBrIDwgYWp4cERhdGFOb2Rlcy5sZW5ndGg7IGsrKykge1xuXHRcdFx0XHRlcXVhbCA9IGVxdWFsICYmIGFqeHBEYXRhTm9kZXNba10gPT0gdGhpcy5fc2VsZWN0ZWROb2Rlc1trXTtcblx0XHRcdH1cblx0XHRcdGlmIChlcXVhbCkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghc291cmNlKSB7XG5cdFx0XHR0aGlzLl9zZWxlY3Rpb25Tb3VyY2UgPSB7fTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fc2VsZWN0aW9uU291cmNlID0gc291cmNlO1xuXHRcdH1cblx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzID0gYWp4cERhdGFOb2Rlcztcblx0XHR0aGlzLl9iRW1wdHkgPSBhanhwRGF0YU5vZGVzICYmIGFqeHBEYXRhTm9kZXMubGVuZ3RoID8gZmFsc2UgOiB0cnVlO1xuXHRcdHRoaXMuX2JGaWxlID0gdGhpcy5fYkRpciA9IHRoaXMuX2lzUmVjeWNsZSA9IGZhbHNlO1xuXHRcdGlmICghdGhpcy5fYkVtcHR5KSB7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGFqeHBEYXRhTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0dmFyIHNlbGVjdGVkTm9kZSA9IGFqeHBEYXRhTm9kZXNbaV07XG5cdFx0XHRcdGlmIChzZWxlY3RlZE5vZGUuaXNMZWFmKCkpIHRoaXMuX2JGaWxlID0gdHJ1ZTtlbHNlIHRoaXMuX2JEaXIgPSB0cnVlO1xuXHRcdFx0XHRpZiAoc2VsZWN0ZWROb2RlLmlzUmVjeWNsZSgpKSB0aGlzLl9pc1JlY3ljbGUgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR0aGlzLnB1Ymxpc2goXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzKTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgbm9kZXNcbiAgKiBAcmV0dXJucyBBanhwTm9kZVtdXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFNlbGVjdGVkTm9kZXMgPSBmdW5jdGlvbiBnZXRTZWxlY3RlZE5vZGVzKCkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIHNvdXJjZSBvZiB0aGUgbGFzdCBzZWxlY3Rpb24gYWN0aW9uXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFNlbGVjdGlvblNvdXJjZSA9IGZ1bmN0aW9uIGdldFNlbGVjdGlvblNvdXJjZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0aW9uU291cmNlO1xuXHR9O1xuXG5cdC8qKlxuICAqIE1hbnVhbGx5IHNldHMgdGhlIHNvdXJjZSBvZiB0aGUgc2VsZWN0aW9uXG4gICogQHBhcmFtIG9iamVjdFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRTZWxlY3Rpb25Tb3VyY2UgPSBmdW5jdGlvbiBzZXRTZWxlY3Rpb25Tb3VyY2Uob2JqZWN0KSB7XG5cdFx0dGhpcy5fc2VsZWN0aW9uU291cmNlID0gb2JqZWN0O1xuXHR9O1xuXG5cdC8qKlxuICAqIERFUFJFQ0FURURcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0U2VsZWN0ZWRJdGVtcyA9IGZ1bmN0aW9uIGdldFNlbGVjdGVkSXRlbXMoKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiRGVwcmVjYXRlZCA6IHVzZSBnZXRTZWxlY3RlZE5vZGVzKCkgaW5zdGVhZFwiKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZWxlY3QgYWxsIHRoZSBjaGlsZHJlbiBvZiB0aGUgY3VycmVudCBjb250ZXh0IG5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2VsZWN0QWxsID0gZnVuY3Rpb24gc2VsZWN0QWxsKCkge1xuXHRcdHZhciBub2RlcyA9IFtdO1xuXHRcdHZhciBjaGlsZHJlbk1hcCA9IHRoaXMuX2NvbnRleHROb2RlLmdldENoaWxkcmVuKCk7XG5cdFx0Y2hpbGRyZW5NYXAuZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcblx0XHRcdG5vZGVzLnB1c2goY2hpbGQpO1xuXHRcdH0pO1xuXHRcdHRoaXMuc2V0U2VsZWN0ZWROb2Rlcyhub2RlcywgXCJkYXRhTW9kZWxcIik7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGlzIGVtcHR5XG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gaXNFbXB0eSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2RlcyA/IHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoID09IDAgOiB0cnVlO1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5oYXNSZWFkT25seSA9IGZ1bmN0aW9uIGhhc1JlYWRPbmx5KCkge1xuXHRcdHZhciB0ZXN0ID0gZmFsc2U7XG5cdFx0dHJ5IHtcblx0XHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuXHRcdFx0XHRpZiAobm9kZS5oYXNNZXRhZGF0YUluQnJhbmNoKFwiYWp4cF9yZWFkb25seVwiLCBcInRydWVcIikpIHtcblx0XHRcdFx0XHR0ZXN0ID0gdHJ1ZTtcblx0XHRcdFx0XHR0aHJvdyAkYnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gY2F0Y2ggKGUpIHt9XG5cdFx0cmV0dXJuIHRlc3Q7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNlbGVjdGlvbkhhc1Jvb3ROb2RlID0gZnVuY3Rpb24gc2VsZWN0aW9uSGFzUm9vdE5vZGUoKSB7XG5cdFx0dmFyIGZvdW5kID0gZmFsc2U7XG5cdFx0dHJ5IHtcblx0XHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcblx0XHRcdFx0aWYgKGVsLmlzUm9vdCgpKSB7XG5cdFx0XHRcdFx0Zm91bmQgPSB0cnVlO1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGNhdGNoIChlKSB7fVxuXHRcdHJldHVybiBmb3VuZDtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaXMgdW5pcXVlXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5pc1VuaXF1ZSA9IGZ1bmN0aW9uIGlzVW5pcXVlKCkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzICYmIHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoID09PSAxO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBoYXMgYSBmaWxlIHNlbGVjdGVkLlxuICAqIFNob3VsZCBiZSBoYXNMZWFmXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5oYXNGaWxlID0gZnVuY3Rpb24gaGFzRmlsZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fYkZpbGU7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGhhcyBhIGRpciBzZWxlY3RlZFxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaGFzRGlyID0gZnVuY3Rpb24gaGFzRGlyKCkge1xuXHRcdHJldHVybiB0aGlzLl9iRGlyO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIGN1cnJlbnQgY29udGV4dCBpcyB0aGUgcmVjeWNsZSBiaW5cbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmlzUmVjeWNsZSA9IGZ1bmN0aW9uIGlzUmVjeWNsZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5faXNSZWN5Y2xlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBoYXMgbW9yZSB0aGFuIG9uZSBub2RlIHNlbGVjdGVkXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5pc011bHRpcGxlID0gZnVuY3Rpb24gaXNNdWx0aXBsZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2RlcyAmJiB0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCA+IDE7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGhhcyBhIGZpbGUgd2l0aCBvbmUgb2YgdGhlIG1pbWVzXG4gICogQHBhcmFtIG1pbWVUeXBlcyBBcnJheSBBcnJheSBvZiBtaW1lIHR5cGVzXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5oYXNNaW1lID0gZnVuY3Rpb24gaGFzTWltZShtaW1lVHlwZXMpIHtcblx0XHRpZiAobWltZVR5cGVzLmxlbmd0aCA9PSAxICYmIG1pbWVUeXBlc1swXSA9PSBcIipcIikgcmV0dXJuIHRydWU7XG5cdFx0dmFyIGhhcyA9IGZhbHNlO1xuXHRcdG1pbWVUeXBlcy5tYXAoKGZ1bmN0aW9uIChtaW1lKSB7XG5cdFx0XHRpZiAoaGFzKSByZXR1cm47XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0aWYgKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEFqeHBNaW1lVHlwZSh0aGlzLl9zZWxlY3RlZE5vZGVzW2ldKSA9PT0gbWltZSkge1xuXHRcdFx0XHRcdGhhcyA9IHRydWU7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KS5iaW5kKHRoaXMpKTtcblx0XHRyZXR1cm4gaGFzO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCBhbGwgc2VsZWN0ZWQgZmlsZW5hbWVzIGFzIGFuIGFycmF5LlxuICAqIEBwYXJhbSBzZXBhcmF0b3IgU3RyaW5nIElzIGEgc2VwYXJhdG9yLCB3aWxsIHJldHVybiBhIHN0cmluZyBqb2luZWRcbiAgKiBAcmV0dXJucyBBcnJheXxTdHJpbmd8Ym9vbFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRGaWxlTmFtZXMgPSBmdW5jdGlvbiBnZXRGaWxlTmFtZXMoc2VwYXJhdG9yKSB7XG5cdFx0aWYgKCF0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCkge1xuXHRcdFx0YWxlcnQoJ1BsZWFzZSBzZWxlY3QgYSBmaWxlIScpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHR2YXIgdG1wID0gbmV3IEFycmF5KHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRtcFtpXSA9IHRoaXMuX3NlbGVjdGVkTm9kZXNbaV0uZ2V0UGF0aCgpO1xuXHRcdH1cblx0XHRpZiAoc2VwYXJhdG9yKSB7XG5cdFx0XHRyZXR1cm4gdG1wLmpvaW4oc2VwYXJhdG9yKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHRtcDtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogR2V0IGFsbCB0aGUgZmlsZW5hbWVzIG9mIHRoZSBjdXJyZW50IGNvbnRleHQgbm9kZSBjaGlsZHJlblxuICAqIEBwYXJhbSBzZXBhcmF0b3IgU3RyaW5nIElmIHBhc3NlZCwgd2lsbCBqb2luIHRoZSBhcnJheSBhcyBhIHN0cmluZ1xuICAqIEByZXR1cm4gQXJyYXl8U3RyaW5nfGJvb2xcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0Q29udGV4dEZpbGVOYW1lcyA9IGZ1bmN0aW9uIGdldENvbnRleHRGaWxlTmFtZXMoc2VwYXJhdG9yKSB7XG5cdFx0dmFyIGFsbEl0ZW1zID0gdGhpcy5fY29udGV4dE5vZGUuZ2V0Q2hpbGRyZW4oKTtcblx0XHRpZiAoIWFsbEl0ZW1zLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHR2YXIgbmFtZXMgPSBbXTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGFsbEl0ZW1zLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRuYW1lcy5wdXNoKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKGFsbEl0ZW1zW2ldLmdldFBhdGgoKSkpO1xuXHRcdH1cblx0XHRpZiAoc2VwYXJhdG9yKSB7XG5cdFx0XHRyZXR1cm4gbmFtZXMuam9pbihzZXBhcmF0b3IpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gbmFtZXM7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIGNvbnRleHQgbm9kZSBoYXMgYSBjaGlsZCB3aXRoIHRoaXMgYmFzZW5hbWVcbiAgKiBAcGFyYW0gbmV3RmlsZU5hbWUgU3RyaW5nIFRoZSBuYW1lIHRvIGNoZWNrXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqIEBwYXJhbSBsb2NhbFxuICAqIEBwYXJhbSBjb250ZXh0Tm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5maWxlTmFtZUV4aXN0cyA9IGZ1bmN0aW9uIGZpbGVOYW1lRXhpc3RzKG5ld0ZpbGVOYW1lLCBsb2NhbCwgY29udGV4dE5vZGUpIHtcblx0XHRpZiAoIWNvbnRleHROb2RlKSB7XG5cdFx0XHRjb250ZXh0Tm9kZSA9IHRoaXMuX2NvbnRleHROb2RlO1xuXHRcdH1cblx0XHRpZiAobG9jYWwpIHtcblx0XHRcdHZhciB0ZXN0ID0gKGNvbnRleHROb2RlLmdldFBhdGgoKSA9PSBcIi9cIiA/IFwiXCIgOiBjb250ZXh0Tm9kZS5nZXRQYXRoKCkpICsgXCIvXCIgKyBuZXdGaWxlTmFtZTtcblx0XHRcdHZhciBmb3VuZCA9IGZhbHNlO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29udGV4dE5vZGUuZ2V0Q2hpbGRyZW4oKS5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7XG5cdFx0XHRcdFx0aWYgKGMuZ2V0UGF0aCgpID09IHRlc3QpIHtcblx0XHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcigpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7fVxuXHRcdFx0cmV0dXJuIGZvdW5kO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgbm9kZUV4aXN0cyA9IGZhbHNlO1xuXHRcdFx0dGhpcy5sb2FkUGF0aEluZm9TeW5jKGNvbnRleHROb2RlLmdldFBhdGgoKSArIFwiL1wiICsgbmV3RmlsZU5hbWUsIGZ1bmN0aW9uIChmb3VuZE5vZGUpIHtcblx0XHRcdFx0bm9kZUV4aXN0cyA9IHRydWU7XG5cdFx0XHR9KTtcblx0XHRcdHJldHVybiBub2RlRXhpc3RzO1xuXHRcdH1cblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuYXBwbHlDaGVja0hvb2sgPSBmdW5jdGlvbiBhcHBseUNoZWNrSG9vayhub2RlKSB7XG5cdFx0dmFyIGFkZGl0aW9uYWxQYXJhbXMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0dmFyIGNsaWVudCA9IF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCk7XG5cdFx0dmFyIHJlc3VsdDtcblx0XHRjbGllbnQuYXBwbHlDaGVja0hvb2sobm9kZSwgXCJiZWZvcmVfY3JlYXRlXCIsIG5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJmaWxlc2l6ZVwiKSB8fCAtMSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuXHRcdFx0cmVzdWx0ID0gY2xpZW50LnBhcnNlWG1sTWVzc2FnZSh0cmFuc3BvcnQucmVzcG9uc2VYTUwpO1xuXHRcdH0sIGFkZGl0aW9uYWxQYXJhbXMpO1xuXHRcdGlmIChyZXN1bHQgPT09IGZhbHNlKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDaGVjayBmYWlsZWRcIik7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEdldHMgdGhlIGZpcnN0IG5hbWUgb2YgdGhlIGN1cnJlbnQgc2VsZWN0aW9uXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFVuaXF1ZUZpbGVOYW1lID0gZnVuY3Rpb24gZ2V0VW5pcXVlRmlsZU5hbWUoKSB7XG5cdFx0aWYgKHRoaXMuZ2V0RmlsZU5hbWVzKCkubGVuZ3RoKSByZXR1cm4gdGhpcy5nZXRGaWxlTmFtZXMoKVswXTtcblx0XHRyZXR1cm4gbnVsbDtcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBmaXJzdCBub2RlIG9mIHRoZSBzZWxlY3Rpb24sIG9yIE51bGxcbiAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRVbmlxdWVOb2RlID0gZnVuY3Rpb24gZ2V0VW5pcXVlTm9kZSgpIHtcblx0XHRpZiAodGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGgpIHtcblx0XHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzWzBdO1xuXHRcdH1cblx0XHRyZXR1cm4gbnVsbDtcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIGEgbm9kZSBmcm9tIHRoZSBjdXJyZW50IHNlbGVjdGlvblxuICAqIEBwYXJhbSBpIEludGVnZXIgdGhlIG5vZGUgaW5kZXhcbiAgKiBAcmV0dXJucyBBanhwTm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXROb2RlID0gZnVuY3Rpb24gZ2V0Tm9kZShpKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXNbaV07XG5cdH07XG5cblx0LyoqXG4gICogV2lsbCBhZGQgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIG5vZGVzIGFzIHNlcmlhbGl6YWJsZSBkYXRhIHRvIHRoZSBlbGVtZW50IHBhc3NlZCA6XG4gICogZWl0aGVyIGFzIGhpZGRlbiBpbnB1dCBlbGVtZW50cyBpZiBpdCdzIGEgZm9ybSwgb3IgYXMgcXVlcnkgcGFyYW1ldGVycyBpZiBpdCdzIGFuIHVybFxuICAqIEBwYXJhbSBvRm9ybUVsZW1lbnQgSFRNTEZvcm0gVGhlIGZvcm1cbiAgKiBAcGFyYW0gc1VybCBTdHJpbmcgQW4gdXJsIHRvIGNvbXBsZXRlXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnVwZGF0ZUZvcm1PclVybCA9IGZ1bmN0aW9uIHVwZGF0ZUZvcm1PclVybChvRm9ybUVsZW1lbnQsIHNVcmwpIHtcblx0XHQvLyBDTEVBUiBGUk9NIFBSRVZJT1VTIEFDVElPTlMhXG5cdFx0aWYgKG9Gb3JtRWxlbWVudCkge1xuXHRcdFx0JChvRm9ybUVsZW1lbnQpLnNlbGVjdCgnaW5wdXRbdHlwZT1cImhpZGRlblwiXScpLm1hcChmdW5jdGlvbiAoZWxlbWVudCkge1xuXHRcdFx0XHRpZiAoZWxlbWVudC5uYW1lID09IFwibm9kZXNbXVwiIHx8IGVsZW1lbnQubmFtZSA9PSBcImZpbGVcIikgZWxlbWVudC5yZW1vdmUoKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0XHQvLyBVUERBVEUgVEhFICdESVInIEZJRUxEU1xuXHRcdGlmIChvRm9ybUVsZW1lbnQgJiYgb0Zvcm1FbGVtZW50WydyZXAnXSkgb0Zvcm1FbGVtZW50WydyZXAnXS52YWx1ZSA9IHRoaXMuX2N1cnJlbnRSZXA7XG5cdFx0c1VybCArPSAnJmRpcj0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMuX2N1cnJlbnRSZXApO1xuXG5cdFx0Ly8gVVBEQVRFIFRIRSAnZmlsZScgRklFTERTXG5cdFx0aWYgKHRoaXMuaXNFbXB0eSgpKSByZXR1cm4gc1VybDtcblx0XHR2YXIgZmlsZU5hbWVzID0gdGhpcy5nZXRGaWxlTmFtZXMoKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGZpbGVOYW1lcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0c1VybCArPSAnJicgKyAnbm9kZXNbXT0nICsgZW5jb2RlVVJJQ29tcG9uZW50KGZpbGVOYW1lc1tpXSk7XG5cdFx0XHRpZiAob0Zvcm1FbGVtZW50KSB0aGlzLl9hZGRIaWRkZW5GaWVsZChvRm9ybUVsZW1lbnQsICdub2Rlc1tdJywgZmlsZU5hbWVzW2ldKTtcblx0XHR9XG5cdFx0aWYgKGZpbGVOYW1lcy5sZW5ndGggPT0gMSkge1xuXHRcdFx0c1VybCArPSAnJicgKyAnZmlsZT0nICsgZW5jb2RlVVJJQ29tcG9uZW50KGZpbGVOYW1lc1swXSk7XG5cdFx0XHRpZiAob0Zvcm1FbGVtZW50KSB0aGlzLl9hZGRIaWRkZW5GaWVsZChvRm9ybUVsZW1lbnQsICdmaWxlJywgZmlsZU5hbWVzWzBdKTtcblx0XHR9XG5cdFx0cmV0dXJuIHNVcmw7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLl9hZGRIaWRkZW5GaWVsZCA9IGZ1bmN0aW9uIF9hZGRIaWRkZW5GaWVsZChvRm9ybUVsZW1lbnQsIHNGaWVsZE5hbWUsIHNGaWVsZFZhbHVlKSB7XG5cdFx0b0Zvcm1FbGVtZW50Lmluc2VydChuZXcgRWxlbWVudCgnaW5wdXQnLCB7IHR5cGU6ICdoaWRkZW4nLCBuYW1lOiBzRmllbGROYW1lLCB2YWx1ZTogc0ZpZWxkVmFsdWUgfSkpO1xuXHR9O1xuXG5cdHJldHVybiBQeWRpb0RhdGFNb2RlbDtcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFB5ZGlvRGF0YU1vZGVsO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIEVtcHR5Tm9kZVByb3ZpZGVyID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhFbXB0eU5vZGVQcm92aWRlciwgX09ic2VydmFibGUpO1xuXG4gICAgZnVuY3Rpb24gRW1wdHlOb2RlUHJvdmlkZXIoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBFbXB0eU5vZGVQcm92aWRlcik7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICB9XG5cbiAgICBFbXB0eU5vZGVQcm92aWRlci5wcm90b3R5cGUuaW5pdFByb3ZpZGVyID0gZnVuY3Rpb24gaW5pdFByb3ZpZGVyKHByb3BlcnRpZXMpIHtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSBub2RlQ2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gY2hpbGRDYWxsYmFjayBGdW5jdGlvblxuICAgICAqL1xuXG4gICAgRW1wdHlOb2RlUHJvdmlkZXIucHJvdG90eXBlLmxvYWROb2RlID0gZnVuY3Rpb24gbG9hZE5vZGUobm9kZSwgbm9kZUNhbGxiYWNrLCBjaGlsZENhbGxiYWNrKSB7fTtcblxuICAgIEVtcHR5Tm9kZVByb3ZpZGVyLnByb3RvdHlwZS5sb2FkTGVhZk5vZGVTeW5jID0gZnVuY3Rpb24gbG9hZExlYWZOb2RlU3luYyhub2RlLCBjYWxsYmFjaykge307XG5cbiAgICByZXR1cm4gRW1wdHlOb2RlUHJvdmlkZXI7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBFbXB0eU5vZGVQcm92aWRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBfdXRpbFBhdGhVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvUGF0aFV0aWxzJyk7XG5cbnZhciBfdXRpbFBhdGhVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsUGF0aFV0aWxzKTtcblxudmFyIEFqeHBOb2RlID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhBanhwTm9kZSwgX09ic2VydmFibGUpO1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGF0aCBTdHJpbmdcbiAgICAgKiBAcGFyYW0gaXNMZWFmIEJvb2xlYW5cbiAgICAgKiBAcGFyYW0gbGFiZWwgU3RyaW5nXG4gICAgICogQHBhcmFtIGljb24gU3RyaW5nXG4gICAgICogQHBhcmFtIGlOb2RlUHJvdmlkZXIgSUFqeHBOb2RlUHJvdmlkZXJcbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIEFqeHBOb2RlKHBhdGgpIHtcbiAgICAgICAgdmFyIGlzTGVhZiA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgbGFiZWwgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGljb24gPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1szXTtcbiAgICAgICAgdmFyIGlOb2RlUHJvdmlkZXIgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDQgfHwgYXJndW1lbnRzWzRdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzRdO1xuXG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBanhwTm9kZSk7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5fcGF0aCA9IHBhdGg7XG4gICAgICAgIGlmICh0aGlzLl9wYXRoICYmIHRoaXMuX3BhdGgubGVuZ3RoICYmIHRoaXMuX3BhdGgubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3BhdGhbdGhpcy5fcGF0aC5sZW5ndGggLSAxXSA9PSBcIi9cIikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3BhdGggPSB0aGlzLl9wYXRoLnN1YnN0cmluZygwLCB0aGlzLl9wYXRoLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzTGVhZiA9IGlzTGVhZjtcbiAgICAgICAgdGhpcy5fbGFiZWwgPSBsYWJlbDtcbiAgICAgICAgdGhpcy5faWNvbiA9IGljb247XG4gICAgICAgIHRoaXMuX2lzUm9vdCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuX21ldGFkYXRhID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLl9jaGlsZHJlbiA9IG5ldyBNYXAoKTtcblxuICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmZha2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faU5vZGVQcm92aWRlciA9IGlOb2RlUHJvdmlkZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIG5vZGUgaXMgbG9hZGVkIG9yIG5vdFxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc0xvYWRlZCA9IGZ1bmN0aW9uIGlzTG9hZGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNMb2FkZWQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBub2RlIGlzIGN1cnJlbnRseSBsb2FkaW5nXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzTG9hZGluZyA9IGZ1bmN0aW9uIGlzTG9hZGluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzTG9hZGluZztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyBsb2FkZWQgc3RhdHVzXG4gICAgICogQHBhcmFtIGJvb2wgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnNldExvYWRlZCA9IGZ1bmN0aW9uIHNldExvYWRlZChib29sKSB7XG4gICAgICAgIHRoaXMuX2lzTG9hZGVkID0gYm9vbDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIG5vZGUgcHJvdmlkZXJcbiAgICAgKiBAcGFyYW0gaUFqeHBOb2RlUHJvdmlkZXJcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS51cGRhdGVQcm92aWRlciA9IGZ1bmN0aW9uIHVwZGF0ZVByb3ZpZGVyKGlBanhwTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgIHRoaXMuX2lOb2RlUHJvdmlkZXIgPSBpQWp4cE5vZGVQcm92aWRlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZHMgdGhlIG5vZGUgdXNpbmcgaXRzIG93biBwcm92aWRlciBvciB0aGUgb25lIHBhc3NlZFxuICAgICAqIEBwYXJhbSBpQWp4cE5vZGVQcm92aWRlciBJQWp4cE5vZGVQcm92aWRlciBPcHRpb25uYWxcbiAgICAgKiBAcGFyYW0gYWRkaXRpb25hbFBhcmFtZXRlcnMgT2JqZWN0IG9mIG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gbG9hZChpQWp4cE5vZGVQcm92aWRlcikge1xuICAgICAgICB2YXIgYWRkaXRpb25hbFBhcmFtZXRlcnMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIGlmICh0aGlzLl9pc0xvYWRpbmcpIHJldHVybjtcbiAgICAgICAgaWYgKCFpQWp4cE5vZGVQcm92aWRlcikge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2lOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgICAgICAgICBpQWp4cE5vZGVQcm92aWRlciA9IHRoaXMuX2lOb2RlUHJvdmlkZXI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlBanhwTm9kZVByb3ZpZGVyID0gbmV3IFJlbW90ZU5vZGVQcm92aWRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzTG9hZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMubm90aWZ5KFwibG9hZGluZ1wiKTtcbiAgICAgICAgaWYgKHRoaXMuX2lzTG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KFwibG9hZGVkXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlBanhwTm9kZVByb3ZpZGVyLmxvYWROb2RlKHRoaXMsIChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgdGhpcy5faXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5faXNMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeShcImxvYWRlZFwiKTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KFwiZmlyc3RfbG9hZFwiKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSwgbnVsbCwgZmFsc2UsIC0xLCBhZGRpdGlvbmFsUGFyYW1ldGVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBjaGlsZHJlbiBhbmQgcmVsb2FkIG5vZGVcbiAgICAgKiBAcGFyYW0gaUFqeHBOb2RlUHJvdmlkZXIgSUFqeHBOb2RlUHJvdmlkZXIgT3B0aW9ubmFsXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUucmVsb2FkID0gZnVuY3Rpb24gcmVsb2FkKGlBanhwTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgIHZhciBzaWxlbnRDbGVhciA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIHRoaXMuX2lzTG9hZGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2NoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkLCBrZXkpIHtcbiAgICAgICAgICAgIGlmICghc2lsZW50Q2xlYXIpIGNoaWxkLm5vdGlmeShcIm5vZGVfcmVtb3ZlZFwiKTtcbiAgICAgICAgICAgIGNoaWxkLl9wYXJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX2NoaWxkcmVuWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgaWYgKCFzaWxlbnRDbGVhcikgdGhpcy5ub3RpZnkoXCJjaGlsZF9yZW1vdmVkXCIsIGNoaWxkKTtcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgICAgIHRoaXMubG9hZChpQWp4cE5vZGVQcm92aWRlcik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVubG9hZCBjaGlsZCBhbmQgbm90aWZ5IFwiZm9yY2VfY2xlYXJcIlxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICAgIHRoaXMuX2NoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkLCBrZXkpIHtcbiAgICAgICAgICAgIGNoaWxkLm5vdGlmeShcIm5vZGVfcmVtb3ZlZFwiKTtcbiAgICAgICAgICAgIGNoaWxkLl9wYXJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX2NoaWxkcmVuWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoXCJjaGlsZF9yZW1vdmVkXCIsIGNoaWxkKTtcbiAgICAgICAgfSwgdGhpcyk7XG4gICAgICAgIHRoaXMuX2lzTG9hZGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiZm9yY2VfY2xlYXJcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhpcyBBanhwTm9kZSBhcyBiZWluZyB0aGUgcm9vdCBwYXJlbnRcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5zZXRSb290ID0gZnVuY3Rpb24gc2V0Um9vdCgpIHtcbiAgICAgICAgdGhpcy5faXNSb290ID0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBub2RlIGNoaWxkcmVuIGFzIGEgYnVuY2hcbiAgICAgKiBAcGFyYW0gYWp4cE5vZGVzIEFqeHBOb2Rlc1tdXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuc2V0Q2hpbGRyZW4gPSBmdW5jdGlvbiBzZXRDaGlsZHJlbihhanhwTm9kZXMpIHtcbiAgICAgICAgdGhpcy5fY2hpbGRyZW4gPSBuZXcgTWFwKCk7XG4gICAgICAgIGFqeHBOb2Rlcy5mb3JFYWNoKChmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuX2NoaWxkcmVuLnNldCh2YWx1ZS5nZXRQYXRoKCksIHZhbHVlKTtcbiAgICAgICAgICAgIHZhbHVlLnNldFBhcmVudCh0aGlzKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgY2hpbGRyZW4gYXMgYSBidW5jaFxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlW11cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIGdldENoaWxkcmVuKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW47XG4gICAgfTtcblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRGaXJzdENoaWxkSWZFeGlzdHMgPSBmdW5jdGlvbiBnZXRGaXJzdENoaWxkSWZFeGlzdHMoKSB7XG4gICAgICAgIGlmICh0aGlzLl9jaGlsZHJlbi5zaXplKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW4udmFsdWVzKCkubmV4dCgpLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNNb3JlUmVjZW50VGhhbiA9IGZ1bmN0aW9uIGlzTW9yZVJlY2VudFRoYW4ob3RoZXJOb2RlKSB7XG4gICAgICAgIHJldHVybiBvdGhlck5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikgJiYgdGhpcy5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSAmJiBwYXJzZUludCh0aGlzLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpKSA+PSBwYXJzZUludChvdGhlck5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgY2hpbGQgdG8gY2hpbGRyZW5cbiAgICAgKiBAcGFyYW0gYWp4cE5vZGUgQWp4cE5vZGUgVGhlIGNoaWxkXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuYWRkQ2hpbGQgPSBmdW5jdGlvbiBhZGRDaGlsZChhanhwTm9kZSkge1xuICAgICAgICBhanhwTm9kZS5zZXRQYXJlbnQodGhpcyk7XG4gICAgICAgIGlmICh0aGlzLl9pTm9kZVByb3ZpZGVyKSBhanhwTm9kZS5faU5vZGVQcm92aWRlciA9IHRoaXMuX2lOb2RlUHJvdmlkZXI7XG4gICAgICAgIHZhciBleGlzdGluZ05vZGUgPSB0aGlzLmZpbmRDaGlsZEJ5UGF0aChhanhwTm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICBpZiAoZXhpc3RpbmdOb2RlICYmICEoZXhpc3RpbmdOb2RlIGluc3RhbmNlb2YgU3RyaW5nKSkge1xuICAgICAgICAgICAgaWYgKCFleGlzdGluZ05vZGUuaXNNb3JlUmVjZW50VGhhbihhanhwTm9kZSkpIHtcbiAgICAgICAgICAgICAgICBleGlzdGluZ05vZGUucmVwbGFjZUJ5KGFqeHBOb2RlLCBcIm92ZXJyaWRlXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBleGlzdGluZ05vZGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2NoaWxkcmVuLnNldChhanhwTm9kZS5nZXRQYXRoKCksIGFqeHBOb2RlKTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KFwiY2hpbGRfYWRkZWRcIiwgYWp4cE5vZGUuZ2V0UGF0aCgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWp4cE5vZGU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIGNoaWxkIGZyb20gdGhlIGNoaWxkcmVuXG4gICAgICogQHBhcmFtIGFqeHBOb2RlIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUucmVtb3ZlQ2hpbGQgPSBmdW5jdGlvbiByZW1vdmVDaGlsZChhanhwTm9kZSkge1xuICAgICAgICB2YXIgcmVtb3ZlUGF0aCA9IGFqeHBOb2RlLmdldFBhdGgoKTtcbiAgICAgICAgYWp4cE5vZGUubm90aWZ5KFwibm9kZV9yZW1vdmVkXCIpO1xuICAgICAgICBhanhwTm9kZS5fcGFyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMuX2NoaWxkcmVuWydkZWxldGUnXShhanhwTm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICB0aGlzLm5vdGlmeShcImNoaWxkX3JlbW92ZWRcIiwgcmVtb3ZlUGF0aCk7XG4gICAgfTtcblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5yZXBsYWNlTWV0YWRhdGEgPSBmdW5jdGlvbiByZXBsYWNlTWV0YWRhdGEobmV3TWV0YSkge1xuICAgICAgICB0aGlzLl9tZXRhZGF0YSA9IG5ld01ldGE7XG4gICAgICAgIHRoaXMubm90aWZ5KFwibWV0YV9yZXBsYWNlZFwiLCB0aGlzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgdGhlIGN1cnJlbnQgbm9kZSBieSBhIG5ldyBvbmUuIENvcHkgYWxsIHByb3BlcnRpZXMgZGVlcGx5XG4gICAgICogQHBhcmFtIGFqeHBOb2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIG1ldGFNZXJnZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnJlcGxhY2VCeSA9IGZ1bmN0aW9uIHJlcGxhY2VCeShhanhwTm9kZSwgbWV0YU1lcmdlKSB7XG4gICAgICAgIHRoaXMuX2lzTGVhZiA9IGFqeHBOb2RlLl9pc0xlYWY7XG4gICAgICAgIHZhciBwYXRoQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoYWp4cE5vZGUuZ2V0UGF0aCgpICYmIHRoaXMuX3BhdGggIT0gYWp4cE5vZGUuZ2V0UGF0aCgpKSB7XG4gICAgICAgICAgICB2YXIgb3JpZ2luYWxQYXRoID0gdGhpcy5fcGF0aDtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldFBhcmVudCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudENoaWxkcmVuSW5kZXggPSB0aGlzLmdldFBhcmVudCgpLl9jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICBwYXJlbnRDaGlsZHJlbkluZGV4LnNldChhanhwTm9kZS5nZXRQYXRoKCksIHRoaXMpO1xuICAgICAgICAgICAgICAgIHBhcmVudENoaWxkcmVuSW5kZXhbJ2RlbGV0ZSddKG9yaWdpbmFsUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9wYXRoID0gYWp4cE5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICAgICAgcGF0aENoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhanhwTm9kZS5fbGFiZWwpIHtcbiAgICAgICAgICAgIHRoaXMuX2xhYmVsID0gYWp4cE5vZGUuX2xhYmVsO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhanhwTm9kZS5faWNvbikge1xuICAgICAgICAgICAgdGhpcy5faWNvbiA9IGFqeHBOb2RlLl9pY29uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhanhwTm9kZS5faU5vZGVQcm92aWRlcikge1xuICAgICAgICAgICAgdGhpcy5faU5vZGVQcm92aWRlciA9IGFqeHBOb2RlLl9pTm9kZVByb3ZpZGVyO1xuICAgICAgICB9XG4gICAgICAgIC8vdGhpcy5faXNSb290ID0gYWp4cE5vZGUuX2lzUm9vdDtcbiAgICAgICAgdGhpcy5faXNMb2FkZWQgPSBhanhwTm9kZS5faXNMb2FkZWQ7XG4gICAgICAgIHRoaXMuZmFrZSA9IGFqeHBOb2RlLmZha2U7XG4gICAgICAgIHZhciBtZXRhID0gYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKTtcbiAgICAgICAgaWYgKG1ldGFNZXJnZSA9PSBcIm92ZXJyaWRlXCIpIHRoaXMuX21ldGFkYXRhID0gbmV3IE1hcCgpO1xuICAgICAgICBtZXRhLmZvckVhY2goKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICBpZiAobWV0YU1lcmdlID09IFwib3ZlcnJpZGVcIikge1xuICAgICAgICAgICAgICAgIHRoaXMuX21ldGFkYXRhLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX21ldGFkYXRhLmhhcyhrZXkpICYmIHZhbHVlID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5fbWV0YWRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgaWYgKHBhdGhDaGFuZ2VkICYmICF0aGlzLl9pc0xlYWYgJiYgdGhpcy5nZXRDaGlsZHJlbigpLnNpemUpIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWxvYWQodGhpcy5faU5vZGVQcm92aWRlcik7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpLCAxMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGFqeHBOb2RlLmdldENoaWxkcmVuKCkuZm9yRWFjaCgoZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICB0aGlzLmFkZENoaWxkKGNoaWxkKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMubm90aWZ5KFwibm9kZV9yZXBsYWNlZFwiLCB0aGlzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgYSBjaGlsZCBub2RlIGJ5IGl0cyBwYXRoXG4gICAgICogQHBhcmFtIHBhdGggU3RyaW5nXG4gICAgICogQHJldHVybnMgQWp4cE5vZGVcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5maW5kQ2hpbGRCeVBhdGggPSBmdW5jdGlvbiBmaW5kQ2hpbGRCeVBhdGgocGF0aCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW4uZ2V0KHBhdGgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBtZXRhZGF0YSBhcyBhIGJ1bmNoXG4gICAgICogQHBhcmFtIGRhdGEgTWFwIEEgTWFwXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuc2V0TWV0YWRhdGEgPSBmdW5jdGlvbiBzZXRNZXRhZGF0YShkYXRhKSB7XG4gICAgICAgIHRoaXMuX21ldGFkYXRhID0gZGF0YTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbWV0YWRhdFxuICAgICAqIEByZXR1cm5zIE1hcFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldE1ldGFkYXRhID0gZnVuY3Rpb24gZ2V0TWV0YWRhdGEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9tZXRhZGF0YTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSXMgdGhpcyBub2RlIGEgbGVhZlxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc0xlYWYgPSBmdW5jdGlvbiBpc0xlYWYoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0xlYWY7XG4gICAgfTtcblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc0Jyb3dzYWJsZSA9IGZ1bmN0aW9uIGlzQnJvd3NhYmxlKCkge1xuICAgICAgICByZXR1cm4gIXRoaXMuX2lzTGVhZiB8fCB0aGlzLmdldEFqeHBNaW1lKCkgPT09ICdhanhwX2Jyb3dzYWJsZV9hcmNoaXZlJztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgU3RyaW5nXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0UGF0aCA9IGZ1bmN0aW9uIGdldFBhdGgoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wYXRoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBTdHJpbmdcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRMYWJlbCA9IGZ1bmN0aW9uIGdldExhYmVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGFiZWw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldEljb24gPSBmdW5jdGlvbiBnZXRJY29uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faWNvbjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzUmVjeWNsZSA9IGZ1bmN0aW9uIGlzUmVjeWNsZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QWp4cE1pbWUoKSA9PSAnYWp4cF9yZWN5Y2xlJztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgU3RyaW5nXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0U3ZnU291cmNlID0gZnVuY3Rpb24gZ2V0U3ZnU291cmNlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRNZXRhZGF0YSgpLmdldChcImZvbnRpY29uXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZWFyY2ggdGhlIG1pbWUgdHlwZSBpbiB0aGUgcGFyZW50IGJyYW5jaFxuICAgICAqIEBwYXJhbSBhanhwTWltZSBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaGFzQWp4cE1pbWVJbkJyYW5jaCA9IGZ1bmN0aW9uIGhhc0FqeHBNaW1lSW5CcmFuY2goYWp4cE1pbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2V0QWp4cE1pbWUoKSA9PSBhanhwTWltZS50b0xvd2VyQ2FzZSgpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgdmFyIHBhcmVudCA9IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNydCA9IHRoaXM7XG4gICAgICAgIHdoaWxlIChwYXJlbnQgPSBjcnQuX3BhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIGlmIChwYXJlbnQuZ2V0QWp4cE1pbWUoKSA9PSBhanhwTWltZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjcnQgPSBwYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZWFyY2ggdGhlIG1pbWUgdHlwZSBpbiB0aGUgcGFyZW50IGJyYW5jaFxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKiBAcGFyYW0gbWV0YWRhdGFLZXlcbiAgICAgKiBAcGFyYW0gbWV0YWRhdGFWYWx1ZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmhhc01ldGFkYXRhSW5CcmFuY2ggPSBmdW5jdGlvbiBoYXNNZXRhZGF0YUluQnJhbmNoKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLmdldE1ldGFkYXRhKCkuaGFzKG1ldGFkYXRhS2V5KSkge1xuICAgICAgICAgICAgaWYgKG1ldGFkYXRhVmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRNZXRhZGF0YSgpLmdldChtZXRhZGF0YUtleSkgPT0gbWV0YWRhdGFWYWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmVudCA9IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNydCA9IHRoaXM7XG4gICAgICAgIHdoaWxlIChwYXJlbnQgPSBjcnQuX3BhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIGlmIChwYXJlbnQuZ2V0TWV0YWRhdGEoKS5oYXMobWV0YWRhdGFLZXkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1ldGFkYXRhVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudC5nZXRNZXRhZGF0YSgpLmdldChtZXRhZGF0YUtleSkgPT0gbWV0YWRhdGFWYWx1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjcnQgPSBwYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgbm9kZVxuICAgICAqIEBwYXJhbSBwYXJlbnROb2RlIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuc2V0UGFyZW50ID0gZnVuY3Rpb24gc2V0UGFyZW50KHBhcmVudE5vZGUpIHtcbiAgICAgICAgdGhpcy5fcGFyZW50Tm9kZSA9IHBhcmVudE5vZGU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHBhcmVudCBOb2RlXG4gICAgICogQHJldHVybnMgQWp4cE5vZGVcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbiBnZXRQYXJlbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9wYXJlbnROb2RlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGlzIG5vZGUgYnkgcGF0aCBpZiBpdCBhbHJlYWR5IGV4aXN0cyBpbiBhcmJvcmVzY2VuY2VcbiAgICAgKiBAcGFyYW0gcm9vdE5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gZmFrZU5vZGVzIEFqeHBOb2RlW11cbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZXx1bmRlZmluZWRcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5maW5kSW5BcmJvID0gZnVuY3Rpb24gZmluZEluQXJibyhyb290Tm9kZSwgZmFrZU5vZGVzKSB7XG4gICAgICAgIGlmICghdGhpcy5nZXRQYXRoKCkpIHJldHVybjtcbiAgICAgICAgdmFyIHBhdGhQYXJ0cyA9IHRoaXMuZ2V0UGF0aCgpLnNwbGl0KFwiL1wiKTtcbiAgICAgICAgdmFyIGNydFBhdGggPSBcIlwiLFxuICAgICAgICAgICAgY3J0Tm9kZSA9IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNydFBhcmVudE5vZGUgPSByb290Tm9kZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRoUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChwYXRoUGFydHNbaV0gPT0gXCJcIikgY29udGludWU7XG4gICAgICAgICAgICBjcnRQYXRoID0gY3J0UGF0aCArIFwiL1wiICsgcGF0aFBhcnRzW2ldO1xuICAgICAgICAgICAgdmFyIG5vZGUgPSBjcnRQYXJlbnROb2RlLmZpbmRDaGlsZEJ5UGF0aChjcnRQYXRoKTtcbiAgICAgICAgICAgIGlmIChub2RlICYmICEobm9kZSBpbnN0YW5jZW9mIFN0cmluZykpIHtcbiAgICAgICAgICAgICAgICBjcnROb2RlID0gbm9kZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGZha2VOb2RlcyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGNydE5vZGUgPSBuZXcgQWp4cE5vZGUoY3J0UGF0aCwgZmFsc2UsIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKGNydFBhdGgpKTtcbiAgICAgICAgICAgICAgICBjcnROb2RlLmZha2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGNydE5vZGUuZ2V0TWV0YWRhdGEoKS5zZXQoXCJ0ZXh0XCIsIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKGNydFBhdGgpKTtcbiAgICAgICAgICAgICAgICBmYWtlTm9kZXMucHVzaChjcnROb2RlKTtcbiAgICAgICAgICAgICAgICBjcnRQYXJlbnROb2RlLmFkZENoaWxkKGNydE5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3J0UGFyZW50Tm9kZSA9IGNydE5vZGU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNydE5vZGU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc1Jvb3QgPSBmdW5jdGlvbiBpc1Jvb3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1Jvb3Q7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGl0J3MgdGhlIHBhcmVudCBvZiB0aGUgZ2l2ZW4gbm9kZVxuICAgICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzUGFyZW50T2YgPSBmdW5jdGlvbiBpc1BhcmVudE9mKG5vZGUpIHtcbiAgICAgICAgdmFyIGNoaWxkUGF0aCA9IG5vZGUuZ2V0UGF0aCgpO1xuICAgICAgICB2YXIgcGFyZW50UGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICByZXR1cm4gY2hpbGRQYXRoLnN1YnN0cmluZygwLCBwYXJlbnRQYXRoLmxlbmd0aCkgPT09IHBhcmVudFBhdGg7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGl0J3MgYSBjaGlsZCBvZiB0aGUgZ2l2ZW4gbm9kZVxuICAgICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzQ2hpbGRPZiA9IGZ1bmN0aW9uIGlzQ2hpbGRPZihub2RlKSB7XG4gICAgICAgIHZhciBjaGlsZFBhdGggPSB0aGlzLmdldFBhdGgoKTtcbiAgICAgICAgdmFyIHBhcmVudFBhdGggPSBub2RlLmdldFBhdGgoKTtcbiAgICAgICAgcmV0dXJuIGNoaWxkUGF0aC5zdWJzdHJpbmcoMCwgcGFyZW50UGF0aC5sZW5ndGgpID09PSBwYXJlbnRQYXRoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50J3Mgbm9kZSBtaW1lIHR5cGUsIGVpdGhlciBieSBhanhwX21pbWUgb3IgYnkgZXh0ZW5zaW9uLlxuICAgICAqIEByZXR1cm5zIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldEFqeHBNaW1lID0gZnVuY3Rpb24gZ2V0QWp4cE1pbWUoKSB7XG4gICAgICAgIGlmICh0aGlzLl9tZXRhZGF0YSAmJiB0aGlzLl9tZXRhZGF0YS5oYXMoXCJhanhwX21pbWVcIikpIHJldHVybiB0aGlzLl9tZXRhZGF0YS5nZXQoXCJhanhwX21pbWVcIikudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKHRoaXMuX21ldGFkYXRhICYmIHRoaXMuaXNMZWFmKCkpIHJldHVybiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRBanhwTWltZVR5cGUodGhpcy5fbWV0YWRhdGEpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgIH07XG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuYnVpbGRSYW5kb21TZWVkID0gZnVuY3Rpb24gYnVpbGRSYW5kb21TZWVkKGFqeHBOb2RlKSB7XG4gICAgICAgIHZhciBtdGltZVN0cmluZyA9IFwiJnRpbWVfc2VlZD1cIiArIHRoaXMuX21ldGFkYXRhLmdldChcImFqeHBfbW9kaWZ0aW1lXCIpO1xuICAgICAgICBpZiAodGhpcy5nZXRQYXJlbnQoKSkge1xuICAgICAgICAgICAgdmFyIHByZXZpZXdfc2VlZCA9IHRoaXMuZ2V0UGFyZW50KCkuZ2V0TWV0YWRhdGEoKS5nZXQoJ3ByZXZpZXdfc2VlZCcpO1xuICAgICAgICAgICAgaWYgKHByZXZpZXdfc2VlZCkge1xuICAgICAgICAgICAgICAgIG10aW1lU3RyaW5nICs9IFwiJnJhbmQ9XCIgKyBwcmV2aWV3X3NlZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG10aW1lU3RyaW5nO1xuICAgIH07XG5cbiAgICByZXR1cm4gQWp4cE5vZGU7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBBanhwTm9kZTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbnZhciBfVXNlciA9IHJlcXVpcmUoJy4vVXNlcicpO1xuXG52YXIgX1VzZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfVXNlcik7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlciA9IHJlcXVpcmUoJy4uL2h0dHAvUmVzb3VyY2VzTWFuYWdlcicpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBSZXNvdXJjZXNNYW5hZ2VyKTtcblxudmFyIFJlZ2lzdHJ5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBSZWdpc3RyeShweWRpb09iamVjdCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUmVnaXN0cnkpO1xuXG4gICAgICAgIHRoaXMuX3JlZ2lzdHJ5ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5ID0geyBcImVkaXRvclwiOiBbXSwgXCJ1cGxvYWRlclwiOiBbXSB9O1xuICAgICAgICB0aGlzLl9yZXNvdXJjZXNSZWdpc3RyeSA9IHt9O1xuICAgICAgICB0aGlzLl9weWRpb09iamVjdCA9IHB5ZGlvT2JqZWN0O1xuICAgICAgICB0aGlzLl94UGF0aExvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fZ2xvYmFsTG9hZGluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhcnNlIFhNTCBTdHJpbmcgZGlyZWN0bHlcbiAgICAgKiBAcGFyYW0gc1xuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmxvYWRGcm9tU3RyaW5nID0gZnVuY3Rpb24gbG9hZEZyb21TdHJpbmcocykge1xuICAgICAgICB0aGlzLl9yZWdpc3RyeSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10ucGFyc2VYbWwocykuZG9jdW1lbnRFbGVtZW50O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIHJlZ2lzdHJ5IGZyb20gc2VydmVyXG4gICAgICogQHBhcmFtIHhQYXRoXG4gICAgICogQHBhcmFtIGNvbXBsZXRlRnVuY1xuICAgICAqIEBwYXJhbSByZXBvc2l0b3J5SWRcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gbG9hZCgpIHtcbiAgICAgICAgdmFyIHhQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1swXTtcbiAgICAgICAgdmFyIGNvbXBsZXRlRnVuYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciByZXBvc2l0b3J5SWQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzJdO1xuXG4gICAgICAgIGlmICh4UGF0aCA9PT0gbnVsbCAmJiB0aGlzLl9nbG9iYWxMb2FkaW5nIHx8IHhQYXRoICYmIHRoaXMuX3hQYXRoTG9hZGluZyA9PT0geFBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeFBhdGgpIHRoaXMuX3hQYXRoTG9hZGluZyA9IHhQYXRoO2Vsc2UgdGhpcy5fZ2xvYmFsTG9hZGluZyA9IHRydWU7XG4gICAgICAgIHZhciBvbkNvbXBsZXRlID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGlmICh4UGF0aCkgdGhpcy5feFBhdGhMb2FkaW5nID0gZmFsc2U7ZWxzZSB0aGlzLl9nbG9iYWxMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MID09IG51bGwgfHwgdHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCA9PSBudWxsKSByZXR1cm47XG4gICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PSBcImFqeHBfcmVnaXN0cnlcIikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlZ2lzdHJ5ID0gdHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbXBsZXRlRnVuYykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5maXJlKFwicmVnaXN0cnlfbG9hZGVkXCIsIHRoaXMuX3JlZ2lzdHJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgPT0gXCJhanhwX3JlZ2lzdHJ5X3BhcnRcIikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVmcmVzaFhtbFJlZ2lzdHJ5UGFydCh0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb21wbGV0ZUZ1bmMpIGNvbXBsZXRlRnVuYyh0aGlzLl9yZWdpc3RyeSk7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7IGdldF9hY3Rpb246ICdnZXRfeG1sX3JlZ2lzdHJ5JyB9O1xuICAgICAgICBpZiAoeFBhdGgpIHtcbiAgICAgICAgICAgIHBhcmFtc1sneFBhdGgnXSA9IHhQYXRoO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgICAgIHBhcmFtc1snd3NfaWQnXSA9IHJlcG9zaXRvcnlJZDsgLy8gZm9yIGNhY2hpbmcgb25seVxuICAgICAgICB9XG4gICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIG9uQ29tcGxldGUsIG51bGwsIHsgbWV0aG9kOiAnZ2V0JyB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSW5zZXJ0cyBhIGRvY3VtZW50IGZyYWdtZW50IHJldHJpZXZlZCBmcm9tIHNlcnZlciBpbnNpZGUgdGhlIGZ1bGwgdHJlZS5cbiAgICAgKiBUaGUgbm9kZSBtdXN0IGNvbnRhaW5zIHRoZSB4UGF0aCBhdHRyaWJ1dGUgdG8gbG9jYXRlIGl0IGluc2lkZSB0aGUgcmVnaXN0cnkuXG4gICAgICogRXZlbnQgYWpheHBsb3JlcjpyZWdpc3RyeV9wYXJ0X2xvYWRlZCBpcyB0cmlnZ2VyZCBvbmNlIHRoaXMgaXMgZG9uZS5cbiAgICAgKiBAcGFyYW0gZG9jdW1lbnRFbGVtZW50IERPTU5vZGVcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5yZWZyZXNoWG1sUmVnaXN0cnlQYXJ0ID0gZnVuY3Rpb24gcmVmcmVzaFhtbFJlZ2lzdHJ5UGFydChkb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHhQYXRoID0gZG9jdW1lbnRFbGVtZW50LmdldEF0dHJpYnV0ZShcInhQYXRoXCIpO1xuICAgICAgICB2YXIgZXhpc3RpbmdOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksIHhQYXRoKTtcbiAgICAgICAgdmFyIHBhcmVudE5vZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChleGlzdGluZ05vZGUgJiYgZXhpc3RpbmdOb2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHBhcmVudE5vZGUgPSBleGlzdGluZ05vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZXhpc3RpbmdOb2RlKTtcbiAgICAgICAgICAgIGlmIChkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQuY2xvbmVOb2RlKHRydWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh4UGF0aC5pbmRleE9mKFwiL1wiKSA+IC0xKSB7XG4gICAgICAgICAgICAvLyB0cnkgc2VsZWN0aW5nIHBhcmVudE5vZGVcbiAgICAgICAgICAgIHZhciBwYXJlbnRQYXRoID0geFBhdGguc3Vic3RyaW5nKDAsIHhQYXRoLmxhc3RJbmRleE9mKFwiL1wiKSk7XG4gICAgICAgICAgICBwYXJlbnROb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksIHBhcmVudFBhdGgpO1xuICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkLmNsb25lTm9kZSh0cnVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQpIHRoaXMuX3JlZ2lzdHJ5LmFwcGVuZENoaWxkKGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkLmNsb25lTm9kZSh0cnVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZmlyZShcInJlZ2lzdHJ5X3BhcnRfbG9hZGVkXCIsIHhQYXRoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVHJhbnNsYXRlIHRoZSBYTUwgYW5zd2VyIHRvIGEgbmV3IFVzZXIgb2JqZWN0XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUucGFyc2VVc2VyID0gZnVuY3Rpb24gcGFyc2VVc2VyKCkge1xuICAgICAgICB2YXIgdXNlciA9IG51bGwsXG4gICAgICAgICAgICB1c2VyTm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHRoaXMuX3JlZ2lzdHJ5KSB7XG4gICAgICAgICAgICB1c2VyTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCBcInVzZXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHVzZXJOb2RlKSB7XG4gICAgICAgICAgICB2YXIgdXNlcklkID0gdXNlck5vZGUuZ2V0QXR0cmlidXRlKCdpZCcpO1xuICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdXNlck5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgIGlmICh1c2VySWQpIHtcbiAgICAgICAgICAgICAgICB1c2VyID0gbmV3IF9Vc2VyMlsnZGVmYXVsdCddKHVzZXJJZCwgY2hpbGRyZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1c2VyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtFbGVtZW50fCp8bnVsbH1cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXRYTUwgPSBmdW5jdGlvbiBnZXRYTUwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWdpc3RyeTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCBFeHRlbnNpb24gaW5pdGlhbGlzYXRpb24gbm9kZXMgKGFjdGl2ZUNvbmRpdGlvbiwgb25Jbml0LCBldGMpLCBwYXJzZXNcbiAgICAgKiB0aGUgWE1MIGFuZCBleGVjdXRlIEpTLlxuICAgICAqIEBwYXJhbSB4bWxOb2RlIHtFbGVtZW50fSBUaGUgZXh0ZW5zaW9uIG5vZGVcbiAgICAgKiBAcGFyYW0gZXh0ZW5zaW9uRGVmaW5pdGlvbiBPYmplY3QgSW5mb3JtYXRpb24gYWxyZWFkeSBjb2xsZWN0ZWQgYWJvdXQgdGhpcyBleHRlbnNpb25cbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuaW5pdEV4dGVuc2lvbiA9IGZ1bmN0aW9uIGluaXRFeHRlbnNpb24oeG1sTm9kZSwgZXh0ZW5zaW9uRGVmaW5pdGlvbikge1xuICAgICAgICB2YXIgYWN0aXZlQ29uZGl0aW9uID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvYWN0aXZlQ29uZGl0aW9uJyk7XG4gICAgICAgIGlmIChhY3RpdmVDb25kaXRpb24gJiYgYWN0aXZlQ29uZGl0aW9uLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBuZXcgRnVuY3Rpb24oYWN0aXZlQ29uZGl0aW9uLmZpcnN0Q2hpbGQubm9kZVZhbHVlLnRyaW0oKSk7XG4gICAgICAgICAgICAgICAgaWYgKGZ1bmMoKSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHhtbE5vZGUubm9kZU5hbWUgPT0gJ2VkaXRvcicpIHtcblxuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihleHRlbnNpb25EZWZpbml0aW9uLCB7XG4gICAgICAgICAgICAgICAgb3BlbmFibGU6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwib3BlbmFibGVcIikgPT0gXCJ0cnVlXCIsXG4gICAgICAgICAgICAgICAgbW9kYWxPbmx5OiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm1vZGFsT25seVwiKSA9PSBcInRydWVcIixcbiAgICAgICAgICAgICAgICBwcmV2aWV3UHJvdmlkZXI6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwicHJldmlld1Byb3ZpZGVyXCIpID09IFwidHJ1ZVwiLFxuICAgICAgICAgICAgICAgIG9yZGVyOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm9yZGVyXCIpID8gcGFyc2VJbnQoeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJvcmRlclwiKSkgOiAwLFxuICAgICAgICAgICAgICAgIGZvcm1JZDogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJmb3JtSWRcIikgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICB0ZXh0OiB0aGlzLl9weWRpb09iamVjdC5NZXNzYWdlSGFzaFt4bWxOb2RlLmdldEF0dHJpYnV0ZShcInRleHRcIildLFxuICAgICAgICAgICAgICAgIHRpdGxlOiB0aGlzLl9weWRpb09iamVjdC5NZXNzYWdlSGFzaFt4bWxOb2RlLmdldEF0dHJpYnV0ZShcInRpdGxlXCIpXSxcbiAgICAgICAgICAgICAgICBpY29uOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImljb25cIiksXG4gICAgICAgICAgICAgICAgaWNvbl9jbGFzczogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJpY29uQ2xhc3NcIiksXG4gICAgICAgICAgICAgICAgZWRpdG9yQWN0aW9uczogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJhY3Rpb25zXCIpLFxuICAgICAgICAgICAgICAgIGVkaXRvckNsYXNzOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImNsYXNzTmFtZVwiKSxcbiAgICAgICAgICAgICAgICBtaW1lczogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJtaW1lc1wiKS5zcGxpdChcIixcIiksXG4gICAgICAgICAgICAgICAgd3JpdGU6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwid3JpdGVcIikgJiYgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJ3cml0ZVwiKSA9PSBcInRydWVcIiA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBjYW5Xcml0ZTogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJjYW5Xcml0ZVwiKSAmJiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcImNhbldyaXRlXCIpID09IFwidHJ1ZVwiID8gdHJ1ZSA6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh4bWxOb2RlLm5vZGVOYW1lID09ICd1cGxvYWRlcicpIHtcblxuICAgICAgICAgICAgdmFyIHRoID0gdGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycy5nZXQoJ3RoZW1lJyk7XG4gICAgICAgICAgICB2YXIgY2xpZW50Rm9ybSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2NsaWVudEZvcm1bQHRoZW1lPVwiJyArIHRoICsgJ1wiXScpO1xuICAgICAgICAgICAgaWYgKCFjbGllbnRGb3JtKSB7XG4gICAgICAgICAgICAgICAgY2xpZW50Rm9ybSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2NsaWVudEZvcm0nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbGllbnRGb3JtICYmIGNsaWVudEZvcm0uZ2V0QXR0cmlidXRlKCdtb2R1bGUnKSkge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24ubW9kdWxlTmFtZSA9IGNsaWVudEZvcm0uZ2V0QXR0cmlidXRlKCdtb2R1bGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm9yZGVyXCIpKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5vcmRlciA9IHBhcnNlSW50KHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwib3JkZXJcIikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLm9yZGVyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBleHRlbnNpb25PbkluaXQgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9leHRlbnNpb25PbkluaXQnKTtcbiAgICAgICAgICAgIGlmIChleHRlbnNpb25PbkluaXQgJiYgZXh0ZW5zaW9uT25Jbml0LmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAvLyBAVE9ETzogVEhJUyBXSUxMIExJS0VMWSBUUklHR0VSIFBST1RPVFlQRSBDT0RFXG4gICAgICAgICAgICAgICAgICAgIGV2YWwoZXh0ZW5zaW9uT25Jbml0LmZpcnN0Q2hpbGQubm9kZVZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKFwiSWdub3JpbmcgRXJyb3IgaW4gZXh0ZW5zaW9uT25Jbml0IGNvZGU6XCIpO1xuICAgICAgICAgICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihleHRlbnNpb25PbkluaXQuZmlyc3RDaGlsZC5ub2RlVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkaWFsb2dPbk9wZW4gPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9kaWFsb2dPbk9wZW4nKTtcbiAgICAgICAgICAgIGlmIChkaWFsb2dPbk9wZW4gJiYgZGlhbG9nT25PcGVuLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLmRpYWxvZ09uT3BlbiA9IGRpYWxvZ09uT3Blbi5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkaWFsb2dPbkNvbXBsZXRlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvZGlhbG9nT25Db21wbGV0ZScpO1xuICAgICAgICAgICAgaWYgKGRpYWxvZ09uQ29tcGxldGUgJiYgZGlhbG9nT25Db21wbGV0ZS5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5kaWFsb2dPbkNvbXBsZXRlID0gZGlhbG9nT25Db21wbGV0ZS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVmcmVzaCB0aGUgY3VycmVudGx5IGFjdGl2ZSBleHRlbnNpb25zXG4gICAgICogRXh0ZW5zaW9ucyBhcmUgZWRpdG9ycyBhbmQgdXBsb2FkZXJzIGZvciB0aGUgbW9tZW50LlxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLnJlZnJlc2hFeHRlbnNpb25zUmVnaXN0cnkgPSBmdW5jdGlvbiByZWZyZXNoRXh0ZW5zaW9uc1JlZ2lzdHJ5KCkge1xuXG4gICAgICAgIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeSA9IHsgXCJlZGl0b3JcIjogW10sIFwidXBsb2FkZXJcIjogW10gfTtcbiAgICAgICAgdmFyIGV4dGVuc2lvbnMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXModGhpcy5fcmVnaXN0cnksIFwicGx1Z2lucy9lZGl0b3J8cGx1Z2lucy91cGxvYWRlclwiKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBleHRlbnNpb25zLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIHZhciBleHRlbnNpb25EZWZpbml0aW9uID0ge1xuICAgICAgICAgICAgICAgIGlkOiBleHRlbnNpb25zW2ldLmdldEF0dHJpYnV0ZShcImlkXCIpLFxuICAgICAgICAgICAgICAgIHhtbE5vZGU6IGV4dGVuc2lvbnNbaV0sXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VzTWFuYWdlcjogbmV3IF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXSgpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5fcmVzb3VyY2VzUmVnaXN0cnlbZXh0ZW5zaW9uRGVmaW5pdGlvbi5pZF0gPSBleHRlbnNpb25EZWZpbml0aW9uLnJlc291cmNlc01hbmFnZXI7XG4gICAgICAgICAgICB2YXIgcmVzb3VyY2VOb2RlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhleHRlbnNpb25zW2ldLCBcImNsaWVudF9zZXR0aW5ncy9yZXNvdXJjZXN8ZGVwZW5kZW5jaWVzfGNsaWVudEZvcm1cIik7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlc291cmNlTm9kZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLnJlc291cmNlc01hbmFnZXIubG9hZEZyb21YbWxOb2RlKHJlc291cmNlTm9kZXNbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaW5pdEV4dGVuc2lvbihleHRlbnNpb25zW2ldLCBleHRlbnNpb25EZWZpbml0aW9uKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeVtleHRlbnNpb25zW2ldLm5vZGVOYW1lXS5wdXNoKGV4dGVuc2lvbkRlZmluaXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXS5sb2FkQXV0b0xvYWRSZXNvdXJjZXModGhpcy5fcmVnaXN0cnkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBjdXJyZW50bHkgYWN0aXZlIGV4dGVuc2lvbnMgYnkgdHlwZVxuICAgICAqIEBwYXJhbSBleHRlbnNpb25UeXBlIFN0cmluZyBcImVkaXRvclwiIG9yIFwidXBsb2FkZXJcIlxuICAgICAqIEByZXR1cm5zIHthcnJheX1cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXRBY3RpdmVFeHRlbnNpb25CeVR5cGUgPSBmdW5jdGlvbiBnZXRBY3RpdmVFeHRlbnNpb25CeVR5cGUoZXh0ZW5zaW9uVHlwZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5W2V4dGVuc2lvblR5cGVdO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIGEgZ2l2ZW4gZWRpdG9yIGJ5IGl0cyBpZFxuICAgICAqIEBwYXJhbSBlZGl0b3JJZCBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBBYnN0cmFjdEVkaXRvclxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmZpbmRFZGl0b3JCeUlkID0gZnVuY3Rpb24gZmluZEVkaXRvckJ5SWQoZWRpdG9ySWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeS5lZGl0b3IuZmluZChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBlbC5pZCA9PSBlZGl0b3JJZDtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgRWRpdG9ycyB0aGF0IGNhbiBoYW5kbGUgYSBnaXZlbiBtaW1lIHR5cGVcbiAgICAgKiBAcGFyYW0gbWltZSBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBBYnN0cmFjdEVkaXRvcltdXG4gICAgICogQHBhcmFtIHJlc3RyaWN0VG9QcmV2aWV3UHJvdmlkZXJzXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZmluZEVkaXRvcnNGb3JNaW1lID0gZnVuY3Rpb24gZmluZEVkaXRvcnNGb3JNaW1lKG1pbWUsIHJlc3RyaWN0VG9QcmV2aWV3UHJvdmlkZXJzKSB7XG5cbiAgICAgICAgdmFyIHVzZXIgPSB0aGlzLl9weWRpb09iamVjdC51c2VyO1xuICAgICAgICB2YXIgZWRpdG9ycyA9IFtdLFxuICAgICAgICAgICAgY2hlY2tXcml0ZSA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh1c2VyICE9IG51bGwgJiYgIXVzZXIuY2FuV3JpdGUoKSkge1xuICAgICAgICAgICAgY2hlY2tXcml0ZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc1JlZ2lzdHJ5LmVkaXRvci5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgaWYgKGVsLm1pbWVzLmluZGV4T2YobWltZSkgIT09IC0xIHx8IGVsLm1pbWVzLmluZGV4T2YoJyonKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdHJpY3RUb1ByZXZpZXdQcm92aWRlcnMgJiYgIWVsLnByZXZpZXdQcm92aWRlcikgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGlmICghY2hlY2tXcml0ZSB8fCAhZWwud3JpdGUpIGVkaXRvcnMucHVzaChlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZWRpdG9ycy5sZW5ndGggJiYgZWRpdG9ycy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBlZGl0b3JzID0gZWRpdG9ycy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChhLm9yZGVyIHx8IDApIC0gKGIub3JkZXIgfHwgMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWRpdG9ycztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciB0aGUgbG9hZCBtZXRob2Qgb2YgdGhlIHJlc291cmNlc01hbmFnZXIuXG4gICAgICogQHBhcmFtIHJlc291cmNlc01hbmFnZXIgUmVzb3VyY2VzTWFuYWdlclxuICAgICAqIEBwYXJhbSBjYWxsYmFjayB0cmlnZ2VyZWQgYWZ0ZXIgSlMgbG9hZGVkXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUubG9hZEVkaXRvclJlc291cmNlcyA9IGZ1bmN0aW9uIGxvYWRFZGl0b3JSZXNvdXJjZXMocmVzb3VyY2VzTWFuYWdlciwgY2FsbGJhY2spIHtcbiAgICAgICAgcmVzb3VyY2VzTWFuYWdlci5sb2FkKHRoaXMuX3Jlc291cmNlc1JlZ2lzdHJ5LCBmYWxzZSwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBwbHVnaW5RdWVyeVxuICAgICAqIEByZXR1cm5zIHtNYXB9XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZ2V0UGx1Z2luQ29uZmlncyA9IGZ1bmN0aW9uIGdldFBsdWdpbkNvbmZpZ3MocGx1Z2luUXVlcnkpIHtcblxuICAgICAgICB2YXIgeHBhdGggPSAncGx1Z2lucy8qW0BpZD1cImNvcmUuJyArIHBsdWdpblF1ZXJ5ICsgJ1wiXS9wbHVnaW5fY29uZmlncy9wcm9wZXJ0eSB8IHBsdWdpbnMvKltAaWQ9XCInICsgcGx1Z2luUXVlcnkgKyAnXCJdL3BsdWdpbl9jb25maWdzL3Byb3BlcnR5JztcbiAgICAgICAgaWYgKHBsdWdpblF1ZXJ5LmluZGV4T2YoJy4nKSA9PSAtMSkge1xuICAgICAgICAgICAgeHBhdGggPSAncGx1Z2lucy8nICsgcGx1Z2luUXVlcnkgKyAnL3BsdWdpbl9jb25maWdzL3Byb3BlcnR5IHwnICsgeHBhdGg7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByb3BlcnRpZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXModGhpcy5fcmVnaXN0cnksIHhwYXRoKTtcbiAgICAgICAgdmFyIGNvbmZpZ3MgPSBuZXcgTWFwKCk7XG4gICAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAocHJvcE5vZGUpIHtcbiAgICAgICAgICAgIGNvbmZpZ3Muc2V0KHByb3BOb2RlLmdldEF0dHJpYnV0ZShcIm5hbWVcIiksIEpTT04ucGFyc2UocHJvcE5vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb25maWdzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBwbHVnaW5JZFxuICAgICAqIEBwYXJhbSBwYXJhbU5hbWVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmdldERlZmF1bHRJbWFnZUZyb21QYXJhbWV0ZXJzID0gZnVuY3Rpb24gZ2V0RGVmYXVsdEltYWdlRnJvbVBhcmFtZXRlcnMocGx1Z2luSWQsIHBhcmFtTmFtZSkge1xuICAgICAgICB2YXIgbm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCBcInBsdWdpbnMvKltAaWQ9J1wiICsgcGx1Z2luSWQgKyBcIiddL3NlcnZlcl9zZXR0aW5ncy9nbG9iYWxfcGFyYW1bQG5hbWU9J1wiICsgcGFyYW1OYW1lICsgXCInXVwiKTtcbiAgICAgICAgaWYgKCFub2RlKSByZXR1cm4gJyc7XG4gICAgICAgIHJldHVybiBub2RlLmdldEF0dHJpYnV0ZShcImRlZmF1bHRJbWFnZVwiKSB8fCAnJztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdHlwZVxuICAgICAqIEBwYXJhbSBuYW1lXG4gICAgICogQHJldHVybnMge2Jvb2x9XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuaGFzUGx1Z2luT2ZUeXBlID0gZnVuY3Rpb24gaGFzUGx1Z2luT2ZUeXBlKHR5cGUsIG5hbWUpIHtcbiAgICAgICAgdmFyIG5vZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChuYW1lID09IG51bGwpIHtcbiAgICAgICAgICAgIG5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgJ3BsdWdpbnMvYWp4cF9wbHVnaW5bY29udGFpbnMoQGlkLCBcIicgKyB0eXBlICsgJy5cIildIHwgcGx1Z2lucy8nICsgdHlwZSArICdbQGlkXScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCAncGx1Z2lucy9hanhwX3BsdWdpbltAaWQ9XCInICsgdHlwZSArICcuJyArIG5hbWUgKyAnXCJdIHwgcGx1Z2lucy8nICsgdHlwZSArICdbQGlkPVwiJyArIHR5cGUgKyAnLicgKyBuYW1lICsgJ1wiXScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBub2RlICE9IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFJlZ2lzdHJ5O1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUmVnaXN0cnk7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2h0dHBNZXRhQ2FjaGVTZXJ2aWNlID0gcmVxdWlyZSgnLi4vaHR0cC9NZXRhQ2FjaGVTZXJ2aWNlJyk7XG5cbnZhciBfaHR0cE1ldGFDYWNoZVNlcnZpY2UyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cE1ldGFDYWNoZVNlcnZpY2UpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4uL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxudmFyIF91dGlsUGF0aFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9QYXRoVXRpbHMnKTtcblxudmFyIF91dGlsUGF0aFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxQYXRoVXRpbHMpO1xuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX0FqeHBOb2RlID0gcmVxdWlyZSgnLi9BanhwTm9kZScpO1xuXG52YXIgX0FqeHBOb2RlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0FqeHBOb2RlKTtcblxuLyoqXG4gKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgSUFqeHBOb2RlUHJvdmlkZXIgaW50ZXJmYWNlIGJhc2VkIG9uIGEgcmVtb3RlIHNlcnZlciBhY2Nlc3MuXG4gKiBEZWZhdWx0IGZvciBhbGwgcmVwb3NpdG9yaWVzLlxuICovXG5cbnZhciBSZW1vdGVOb2RlUHJvdmlkZXIgPSAoZnVuY3Rpb24gKCkge1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIFJlbW90ZU5vZGVQcm92aWRlcigpIHtcbiAgICAgICAgdmFyIHByb3BlcnRpZXMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSZW1vdGVOb2RlUHJvdmlkZXIpO1xuXG4gICAgICAgIHRoaXMuZGlzY3JldGUgPSBmYWxzZTtcbiAgICAgICAgaWYgKHByb3BlcnRpZXMpIHRoaXMuaW5pdFByb3ZpZGVyKHByb3BlcnRpZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgcHJvcGVydGllc1xuICAgICAqIEBwYXJhbSBwcm9wZXJ0aWVzIE9iamVjdFxuICAgICAqL1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5pbml0UHJvdmlkZXIgPSBmdW5jdGlvbiBpbml0UHJvdmlkZXIocHJvcGVydGllcykge1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocCkpIHRoaXMucHJvcGVydGllcy5zZXQocCwgcHJvcGVydGllc1twXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcyAmJiB0aGlzLnByb3BlcnRpZXMuaGFzKCdjb25uZXhpb25fZGlzY3JldGUnKSkge1xuICAgICAgICAgICAgdGhpcy5kaXNjcmV0ZSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnByb3BlcnRpZXNbJ2RlbGV0ZSddKCdjb25uZXhpb25fZGlzY3JldGUnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzICYmIHRoaXMucHJvcGVydGllcy5oYXMoJ2NhY2hlX3NlcnZpY2UnKSkge1xuICAgICAgICAgICAgdGhpcy5jYWNoZVNlcnZpY2UgPSB0aGlzLnByb3BlcnRpZXMuZ2V0KCdjYWNoZV9zZXJ2aWNlJyk7XG4gICAgICAgICAgICB0aGlzLnByb3BlcnRpZXNbJ2RlbGV0ZSddKCdjYWNoZV9zZXJ2aWNlJyk7XG4gICAgICAgICAgICBfaHR0cE1ldGFDYWNoZVNlcnZpY2UyWydkZWZhdWx0J10uZ2V0SW5zdGFuY2UoKS5yZWdpc3Rlck1ldGFTdHJlYW0odGhpcy5jYWNoZVNlcnZpY2VbJ21ldGFTdHJlYW1OYW1lJ10sIHRoaXMuY2FjaGVTZXJ2aWNlWydleHBpcmF0aW9uUG9saWN5J10pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBub2RlXG4gICAgICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZUNhbGxiYWNrIEZ1bmN0aW9uIE9uIG5vZGUgbG9hZGVkXG4gICAgICogQHBhcmFtIGNoaWxkQ2FsbGJhY2sgRnVuY3Rpb24gT24gY2hpbGQgYWRkZWRcbiAgICAgKiBAcGFyYW0gcmVjdXJzaXZlXG4gICAgICogQHBhcmFtIGRlcHRoXG4gICAgICogQHBhcmFtIG9wdGlvbmFsUGFyYW1ldGVyc1xuICAgICAqL1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5sb2FkTm9kZSA9IGZ1bmN0aW9uIGxvYWROb2RlKG5vZGUpIHtcbiAgICAgICAgdmFyIG5vZGVDYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBjaGlsZENhbGxiYWNrID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIHJlY3Vyc2l2ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzNdO1xuICAgICAgICB2YXIgZGVwdGggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDQgfHwgYXJndW1lbnRzWzRdID09PSB1bmRlZmluZWQgPyAtMSA6IGFyZ3VtZW50c1s0XTtcbiAgICAgICAgdmFyIG9wdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNSB8fCBhcmd1bWVudHNbNV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbNV07XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICdscycsXG4gICAgICAgICAgICBvcHRpb25zOiAnYWwnXG4gICAgICAgIH07XG4gICAgICAgIGlmIChyZWN1cnNpdmUpIHtcbiAgICAgICAgICAgIHBhcmFtc1sncmVjdXJzaXZlJ10gPSB0cnVlO1xuICAgICAgICAgICAgcGFyYW1zWydkZXB0aCddID0gZGVwdGg7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhdGggPSBub2RlLmdldFBhdGgoKTtcbiAgICAgICAgLy8gRG91YmxlIGVuY29kZSAjIGNoYXJhY3RlclxuICAgICAgICB2YXIgcGFnaW5hdGlvbkhhc2ggPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChub2RlLmdldE1ldGFkYXRhKCkuaGFzKFwicGFnaW5hdGlvbkRhdGFcIikpIHtcbiAgICAgICAgICAgIHBhZ2luYXRpb25IYXNoID0gXCIlMjNcIiArIG5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJwYWdpbmF0aW9uRGF0YVwiKS5nZXQoXCJjdXJyZW50XCIpO1xuICAgICAgICAgICAgcGF0aCArPSBwYWdpbmF0aW9uSGFzaDtcbiAgICAgICAgICAgIHBhcmFtc1sncmVtb3RlX29yZGVyJ10gPSAndHJ1ZSc7XG4gICAgICAgICAgICB2YXIgcmVtb3RlT3JkZXJEYXRhID0gbm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInJlbW90ZV9vcmRlclwiKTtcbiAgICAgICAgICAgIGlmIChyZW1vdGVPcmRlckRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVtb3RlT3JkZXJEYXRhLl9vYmplY3QpIHJlbW90ZU9yZGVyRGF0YSA9IFByb3RvQ29tcGF0Lmhhc2gybWFwKHJlbW90ZU9yZGVyRGF0YSk7XG4gICAgICAgICAgICAgICAgcmVtb3RlT3JkZXJEYXRhLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBwYXJhbXNbJ2RpciddID0gcGF0aDtcbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgICAgICBwYXJhbXNba2V5XSA9IHZhbHVlICsgKGtleSA9PSAnZGlyJyAmJiBwYWdpbmF0aW9uSGFzaCA/IHBhZ2luYXRpb25IYXNoIDogJycpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbmFsUGFyYW1ldGVycykge1xuICAgICAgICAgICAgcGFyYW1zID0gX2V4dGVuZHMoe30sIHBhcmFtcywgb3B0aW9uYWxQYXJhbWV0ZXJzKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyc2VyID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIHRoaXMucGFyc2VOb2Rlcyhub2RlLCB0cmFuc3BvcnQsIG5vZGVDYWxsYmFjaywgY2hpbGRDYWxsYmFjayk7XG4gICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuY2FjaGVTZXJ2aWNlKSB7XG4gICAgICAgICAgICB2YXIgbG9hZGVyID0gKGZ1bmN0aW9uIChhanhwTm9kZSwgY2FjaGVDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIGNhY2hlQ2FsbGJhY2ssIG51bGwsIHsgZGlzY3JldGU6IHRoaXMuZGlzY3JldGUgfSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgdmFyIGNhY2hlTG9hZGVyID0gKGZ1bmN0aW9uIChuZXdOb2RlKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5yZXBsYWNlQnkobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgbm9kZUNhbGxiYWNrKG5vZGUpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgICAgIF9odHRwTWV0YUNhY2hlU2VydmljZTJbJ2RlZmF1bHQnXS5nZXRJbnN0YW5jZSgpLm1ldGFGb3JOb2RlKHRoaXMuY2FjaGVTZXJ2aWNlWydtZXRhU3RyZWFtTmFtZSddLCBub2RlLCBsb2FkZXIsIHBhcnNlciwgY2FjaGVMb2FkZXIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgcGFyc2VyLCBudWxsLCB7IGRpc2NyZXRlOiB0aGlzLmRpc2NyZXRlIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBub2RlXG4gICAgICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZUNhbGxiYWNrIEZ1bmN0aW9uIE9uIG5vZGUgbG9hZGVkXG4gICAgICogQHBhcmFtIGFTeW5jIGJvb2xcbiAgICAgKiBAcGFyYW0gYWRkaXRpb25hbFBhcmFtZXRlcnMgb2JqZWN0XG4gICAgICovXG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLmxvYWRMZWFmTm9kZVN5bmMgPSBmdW5jdGlvbiBsb2FkTGVhZk5vZGVTeW5jKG5vZGUsIG5vZGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgYVN5bmMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IF9leHRlbmRzKHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICdscycsXG4gICAgICAgICAgICBvcHRpb25zOiAnYWwnLFxuICAgICAgICAgICAgZGlyOiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSxcbiAgICAgICAgICAgIGZpbGU6IF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKG5vZGUuZ2V0UGF0aCgpKVxuICAgICAgICB9LCBhZGRpdGlvbmFsUGFyYW1ldGVycyk7XG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHBhcmFtcyA9IF9leHRlbmRzKHt9LCBwYXJhbXMsIHRoaXMucHJvcGVydGllcyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbXBsZXRlID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuaXNSb290KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJzZU5vZGVzKG5vZGUsIHRyYW5zcG9ydCwgbm9kZUNhbGxiYWNrLCBudWxsLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnNlTm9kZXMobm9kZSwgdHJhbnNwb3J0LCBudWxsLCBub2RlQ2FsbGJhY2ssIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcignTG9hZGluZyBlcnJvciA6JyArIGUubWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlLCBudWxsLCB7IGFzeW5jOiBhU3luYyB9KTtcbiAgICB9O1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5yZWZyZXNoTm9kZUFuZFJlcGxhY2UgPSBmdW5jdGlvbiByZWZyZXNoTm9kZUFuZFJlcGxhY2Uobm9kZSwgb25Db21wbGV0ZSkge1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnbHMnLFxuICAgICAgICAgICAgb3B0aW9uczogJ2FsJyxcbiAgICAgICAgICAgIGRpcjogX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSksXG4gICAgICAgICAgICBmaWxlOiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShub2RlLmdldFBhdGgoKSlcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBfZXh0ZW5kcyh7fSwgcGFyYW1zLCB0aGlzLnByb3BlcnRpZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG5vZGVDYWxsYmFjayA9IGZ1bmN0aW9uIG5vZGVDYWxsYmFjayhuZXdOb2RlKSB7XG4gICAgICAgICAgICBub2RlLnJlcGxhY2VCeShuZXdOb2RlLCBcIm92ZXJyaWRlXCIpO1xuICAgICAgICAgICAgaWYgKG9uQ29tcGxldGUpIG9uQ29tcGxldGUobm9kZSk7XG4gICAgICAgIH07XG4gICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmlzUm9vdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFyc2VOb2Rlcyhub2RlLCB0cmFuc3BvcnQsIG5vZGVDYWxsYmFjaywgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJzZU5vZGVzKG5vZGUsIHRyYW5zcG9ydCwgbnVsbCwgbm9kZUNhbGxiYWNrLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZSB0aGUgYW5zd2VyIGFuZCBjcmVhdGUgQWp4cE5vZGVzXG4gICAgICogQHBhcmFtIG9yaWdOb2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIHRyYW5zcG9ydCBBamF4LlJlc3BvbnNlXG4gICAgICogQHBhcmFtIG5vZGVDYWxsYmFjayBGdW5jdGlvblxuICAgICAqIEBwYXJhbSBjaGlsZENhbGxiYWNrIEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNoaWxkcmVuT25seVxuICAgICAqL1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5wYXJzZU5vZGVzID0gZnVuY3Rpb24gcGFyc2VOb2RlcyhvcmlnTm9kZSwgdHJhbnNwb3J0LCBub2RlQ2FsbGJhY2ssIGNoaWxkQ2FsbGJhY2ssIGNoaWxkcmVuT25seSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdHJhbnNwb3J0LnJlc3BvbnNlWE1MIHx8ICF0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5kZWJ1ZygnTG9hZGluZyBub2RlICcgKyBvcmlnTm9kZS5nZXRQYXRoKCkgKyAnIGhhcyB3cm9uZyByZXNwb25zZTogJyArIHRyYW5zcG9ydC5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgaWYgKG5vZGVDYWxsYmFjaykgbm9kZUNhbGxiYWNrKG9yaWdOb2RlKTtcbiAgICAgICAgICAgIG9yaWdOb2RlLnNldExvYWRlZChmYWxzZSk7XG4gICAgICAgICAgICBpZiAoIXRyYW5zcG9ydC5yZXNwb25zZVRleHQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VtcHR5IHJlc3BvbnNlIScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFhNTCBEb2N1bWVudCAoc2VlIGNvbnNvbGUpJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvb3ROb2RlID0gdHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgaWYgKCFjaGlsZHJlbk9ubHkpIHtcbiAgICAgICAgICAgIHZhciBjb250ZXh0Tm9kZSA9IHRoaXMucGFyc2VBanhwTm9kZShyb290Tm9kZSk7XG4gICAgICAgICAgICBvcmlnTm9kZS5yZXBsYWNlQnkoY29udGV4dE5vZGUsIFwibWVyZ2VcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDSEVDSyBGT1IgTUVTU0FHRSBPUiBFUlJPUlNcbiAgICAgICAgdmFyIGVycm9yTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHJvb3ROb2RlLCBcImVycm9yfG1lc3NhZ2VcIik7XG4gICAgICAgIGlmIChlcnJvck5vZGUpIHtcbiAgICAgICAgICAgIHZhciB0eXBlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKGVycm9yTm9kZS5ub2RlTmFtZSA9PSBcIm1lc3NhZ2VcIikge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBlcnJvck5vZGUuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZSA9PSBcIkVSUk9SXCIpIHtcbiAgICAgICAgICAgICAgICBvcmlnTm9kZS5ub3RpZnkoXCJlcnJvclwiLCBlcnJvck5vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUgKyAnKFNvdXJjZTonICsgb3JpZ05vZGUuZ2V0UGF0aCgpICsgJyknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENIRUNLIEZPUiBBVVRIIFBST01QVCBSRVFVSVJFRFxuICAgICAgICB2YXIgYXV0aE5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShyb290Tm9kZSwgXCJwcm9tcHRcIik7XG4gICAgICAgIGlmIChhdXRoTm9kZSAmJiBweWRpbyAmJiBweWRpby5VSSAmJiBweWRpby5VSS5vcGVuUHJvbXB0RGlhbG9nKSB7XG4gICAgICAgICAgICB2YXIganNvbkRhdGEgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShhdXRoTm9kZSwgXCJkYXRhXCIpLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgcHlkaW8uVUkub3BlblByb21wdERpYWxvZyhKU09OLnBhcnNlKGpzb25EYXRhKSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDSEVDSyBGT1IgUEFHSU5BVElPTiBEQVRBXG4gICAgICAgIHZhciBwYWdpbmF0aW9uTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHJvb3ROb2RlLCBcInBhZ2luYXRpb25cIik7XG4gICAgICAgIGlmIChwYWdpbmF0aW9uTm9kZSkge1xuICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFnaW5hdGlvbkRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICAgICAgQXJyYXkuZnJvbShwYWdpbmF0aW9uTm9kZS5hdHRyaWJ1dGVzKS5mb3JFYWNoKChmdW5jdGlvbiAoYXR0KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhZ2luYXRpb25EYXRhLnNldChhdHQubm9kZU5hbWUsIGF0dC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSkuYmluZChfdGhpcykpO1xuICAgICAgICAgICAgICAgIG9yaWdOb2RlLmdldE1ldGFkYXRhKCkuc2V0KCdwYWdpbmF0aW9uRGF0YScsIHBhZ2luYXRpb25EYXRhKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3JpZ05vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykpIHtcbiAgICAgICAgICAgIG9yaWdOb2RlLmdldE1ldGFkYXRhKClbJ2RlbGV0ZSddKCdwYWdpbmF0aW9uRGF0YScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ0hFQ0sgRk9SIENPTVBPTkVOVCBDT05GSUdTIENPTlRFWFRVQUwgREFUQVxuICAgICAgICB2YXIgY29uZmlncyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHJvb3ROb2RlLCBcImNsaWVudF9jb25maWdzXCIpO1xuICAgICAgICBpZiAoY29uZmlncykge1xuICAgICAgICAgICAgb3JpZ05vZGUuZ2V0TWV0YWRhdGEoKS5zZXQoJ2NsaWVudF9jb25maWdzJywgY29uZmlncyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOT1cgUEFSU0UgQ0hJTERSRU5cbiAgICAgICAgdmFyIGNoaWxkcmVuID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHJvb3ROb2RlLCBcInRyZWVcIik7XG4gICAgICAgIGNoaWxkcmVuLmZvckVhY2goKGZ1bmN0aW9uIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgIHZhciBjaGlsZCA9IHRoaXMucGFyc2VBanhwTm9kZShjaGlsZE5vZGUpO1xuICAgICAgICAgICAgaWYgKCFjaGlsZHJlbk9ubHkpIHtcbiAgICAgICAgICAgICAgICBvcmlnTm9kZS5hZGRDaGlsZChjaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY0xvYWRlZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoY2hpbGROb2RlLCAndHJlZScpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhjaGlsZE5vZGUsICd0cmVlJykuZm9yRWFjaCgoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkID0gdGhpcy5wYXJzZUFqeHBOb2RlKGMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLmFkZENoaWxkKG5ld0NoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgICAgIGNMb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNoaWxkQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjaGlsZENhbGxiYWNrKGNoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjTG9hZGVkKSBjaGlsZC5zZXRMb2FkZWQodHJ1ZSk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuXG4gICAgICAgIGlmIChub2RlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIG5vZGVDYWxsYmFjayhvcmlnTm9kZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5wYXJzZUFqeHBOb2Rlc0RpZmZzID0gZnVuY3Rpb24gcGFyc2VBanhwTm9kZXNEaWZmcyh4bWxFbGVtZW50LCB0YXJnZXREYXRhTW9kZWwsIHRhcmdldFJlcG9zaXRvcnlJZCkge1xuICAgICAgICB2YXIgc2V0Q29udGV4dENoaWxkcmVuU2VsZWN0ZWQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICB2YXIgcmVtb3ZlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh4bWxFbGVtZW50LCBcInJlbW92ZS90cmVlXCIpO1xuICAgICAgICB2YXIgYWRkcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh4bWxFbGVtZW50LCBcImFkZC90cmVlXCIpO1xuICAgICAgICB2YXIgdXBkYXRlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh4bWxFbGVtZW50LCBcInVwZGF0ZS90cmVlXCIpO1xuICAgICAgICB2YXIgbm90aWZ5U2VydmVyQ2hhbmdlID0gW107XG4gICAgICAgIGlmIChyZW1vdmVzICYmIHJlbW92ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZW1vdmVzLmZvckVhY2goZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcCA9IHIuZ2V0QXR0cmlidXRlKFwiZmlsZW5hbWVcIik7XG4gICAgICAgICAgICAgICAgaWYgKHIuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICYmIHIuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICE9PSB0YXJnZXRSZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgaW1UaW1lID0gcGFyc2VJbnQoci5nZXRBdHRyaWJ1dGUoXCJhanhwX2ltX3RpbWVcIikpO1xuICAgICAgICAgICAgICAgIHRhcmdldERhdGFNb2RlbC5yZW1vdmVOb2RlQnlQYXRoKHAsIGltVGltZSk7XG4gICAgICAgICAgICAgICAgbm90aWZ5U2VydmVyQ2hhbmdlLnB1c2gocCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWRkcyAmJiBhZGRzLmxlbmd0aCAmJiB0YXJnZXREYXRhTW9kZWwuZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGUpIHtcbiAgICAgICAgICAgIGFkZHMuZm9yRWFjaChmdW5jdGlvbiAodHJlZSkge1xuICAgICAgICAgICAgICAgIGlmICh0cmVlLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAmJiB0cmVlLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAhPT0gdGFyZ2V0UmVwb3NpdG9yeUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSB0YXJnZXREYXRhTW9kZWwuZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGUodHJlZSk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RGF0YU1vZGVsLmFkZE5vZGUobmV3Tm9kZSwgc2V0Q29udGV4dENoaWxkcmVuU2VsZWN0ZWQpO1xuICAgICAgICAgICAgICAgIG5vdGlmeVNlcnZlckNoYW5nZS5wdXNoKG5ld05vZGUuZ2V0UGF0aCgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1cGRhdGVzICYmIHVwZGF0ZXMubGVuZ3RoICYmIHRhcmdldERhdGFNb2RlbC5nZXRBanhwTm9kZVByb3ZpZGVyKCkucGFyc2VBanhwTm9kZSkge1xuICAgICAgICAgICAgdXBkYXRlcy5mb3JFYWNoKGZ1bmN0aW9uICh0cmVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRyZWUuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICYmIHRyZWUuZ2V0QXR0cmlidXRlKFwibm9kZV9yZXBvc2l0b3J5X2lkXCIpICE9PSB0YXJnZXRSZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHRhcmdldERhdGFNb2RlbC5nZXRBanhwTm9kZVByb3ZpZGVyKCkucGFyc2VBanhwTm9kZSh0cmVlKTtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZ2luYWwgPSBuZXdOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwib3JpZ2luYWxfcGF0aFwiKTtcbiAgICAgICAgICAgICAgICB0YXJnZXREYXRhTW9kZWwudXBkYXRlTm9kZShuZXdOb2RlLCBzZXRDb250ZXh0Q2hpbGRyZW5TZWxlY3RlZCk7XG4gICAgICAgICAgICAgICAgbm90aWZ5U2VydmVyQ2hhbmdlLnB1c2gobmV3Tm9kZS5nZXRQYXRoKCkpO1xuICAgICAgICAgICAgICAgIGlmIChvcmlnaW5hbCkgbm90aWZ5U2VydmVyQ2hhbmdlLnB1c2gob3JpZ2luYWwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vdGlmeVNlcnZlckNoYW5nZS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRhcmdldERhdGFNb2RlbC5ub3RpZnkoXCJzZXJ2ZXJfdXBkYXRlXCIsIG5vdGlmeVNlcnZlckNoYW5nZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGFyc2VzIFhNTCBOb2RlIGFuZCBjcmVhdGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0geG1sTm9kZSBYTUxOb2RlXG4gICAgICogQHJldHVybnMgQWp4cE5vZGVcbiAgICAgKi9cblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUucGFyc2VBanhwTm9kZSA9IGZ1bmN0aW9uIHBhcnNlQWp4cE5vZGUoeG1sTm9kZSkge1xuICAgICAgICB2YXIgbm9kZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10oeG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ2ZpbGVuYW1lJyksIHhtbE5vZGUuZ2V0QXR0cmlidXRlKCdpc19maWxlJykgPT0gXCIxXCIgfHwgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ2lzX2ZpbGUnKSA9PSBcInRydWVcIiwgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ3RleHQnKSwgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ2ljb24nKSk7XG4gICAgICAgIHZhciBtZXRhZGF0YSA9IG5ldyBNYXAoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB4bWxOb2RlLmF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG1ldGFkYXRhLnNldCh4bWxOb2RlLmF0dHJpYnV0ZXNbaV0ubm9kZU5hbWUsIHhtbE5vZGUuYXR0cmlidXRlc1tpXS52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5zZXRNZXRhZGF0YShtZXRhZGF0YSk7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH07XG5cbiAgICByZXR1cm4gUmVtb3RlTm9kZVByb3ZpZGVyO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUmVtb3RlTm9kZVByb3ZpZGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIgPSByZXF1aXJlKCcuLi9odHRwL1Jlc291cmNlc01hbmFnZXInKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUmVzb3VyY2VzTWFuYWdlcik7XG5cbi8qKiBcbiAqIENvbnRhaW5lciBmb3IgYSBSZXBvc2l0b3J5LlxuICovXG5cbnZhciBSZXBvc2l0b3J5ID0gKGZ1bmN0aW9uICgpIHtcblxuXHQvKipcbiAgKiBDb25zdHJ1Y3RvclxuICAqIEBwYXJhbSBpZCBTdHJpbmdcbiAgKiBAcGFyYW0geG1sRGVmIFhNTE5vZGVcbiAgKi9cblxuXHRmdW5jdGlvbiBSZXBvc2l0b3J5KGlkLCB4bWxEZWYpIHtcblx0XHRfY2xhc3NDYWxsQ2hlY2sodGhpcywgUmVwb3NpdG9yeSk7XG5cblx0XHR0aGlzLmxhYmVsID0gJyc7XG5cdFx0dGhpcy5pZCA9IGlkO1xuXHRcdHRoaXMuYWNjZXNzVHlwZSA9ICcnO1xuXHRcdHRoaXMubm9kZVByb3ZpZGVyRGVmID0gdW5kZWZpbmVkO1xuXHRcdHRoaXMuYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5ID0gZmFsc2U7XG5cdFx0dGhpcy51c2VyRWRpdGFibGUgPSBmYWxzZTtcblx0XHR0aGlzLnNsdWcgPSAnJztcblx0XHR0aGlzLm93bmVyID0gJyc7XG5cdFx0dGhpcy5kZXNjcmlwdGlvbiA9ICcnO1xuXHRcdHRoaXMuX2hhc0NvbnRlbnRGaWx0ZXIgPSBmYWxzZTtcblx0XHR0aGlzLl9oYXNVc2VyU2NvcGUgPSBmYWxzZTtcblx0XHR0aGlzLl9yZXBvc2l0b3J5VHlwZSA9ICdsb2NhbCc7XG5cdFx0dGhpcy5fYWNjZXNzU3RhdHVzID0gbnVsbDtcblx0XHR0aGlzLl9sYXN0Q29ubmVjdGlvbiA9IG51bGw7XG5cdFx0dGhpcy5pY29uID0gJyc7XG5cdFx0dGhpcy5yZXNvdXJjZXNNYW5hZ2VyID0gbmV3IF9odHRwUmVzb3VyY2VzTWFuYWdlcjJbJ2RlZmF1bHQnXSgpO1xuXHRcdGlmICh4bWxEZWYpIHRoaXMubG9hZEZyb21YbWwoeG1sRGVmKTtcblx0fVxuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldElkID0gZnVuY3Rpb24gZ2V0SWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQ7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0U2hhcmVJZCA9IGZ1bmN0aW9uIGdldFNoYXJlSWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaWQucmVwbGFjZSgvb2NzX3JlbW90ZV9zaGFyZV8vLCAnJyk7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0TGFiZWwgPSBmdW5jdGlvbiBnZXRMYWJlbCgpIHtcblx0XHRyZXR1cm4gdGhpcy5sYWJlbDtcblx0fTtcblxuXHQvKipcbiAgKiBAcGFyYW0gbGFiZWwgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuc2V0TGFiZWwgPSBmdW5jdGlvbiBzZXRMYWJlbChsYWJlbCkge1xuXHRcdHRoaXMubGFiZWwgPSBsYWJlbDtcblx0fTtcblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRMZXR0ZXJzQmFkZ2UgPSBmdW5jdGlvbiBnZXRMZXR0ZXJzQmFkZ2UoKSB7XG5cdFx0aWYgKCF0aGlzLmxhYmVsKSByZXR1cm4gJyc7XG5cdFx0cmV0dXJuIHRoaXMubGFiZWwuc3BsaXQoXCIgXCIpLm1hcChmdW5jdGlvbiAod29yZCkge1xuXHRcdFx0cmV0dXJuIHdvcmQuc3Vic3RyKDAsIDEpO1xuXHRcdH0pLnNsaWNlKDAsIDIpLmpvaW4oXCJcIik7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybiBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXREZXNjcmlwdGlvbiA9IGZ1bmN0aW9uIGdldERlc2NyaXB0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmRlc2NyaXB0aW9uO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldEljb24gPSBmdW5jdGlvbiBnZXRJY29uKCkge1xuXHRcdHJldHVybiB0aGlzLmljb247XG5cdH07XG5cblx0LyoqXG4gICogQHBhcmFtIGljb24gU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuc2V0SWNvbiA9IGZ1bmN0aW9uIHNldEljb24oaWNvbikge1xuXHRcdHRoaXMuaWNvbiA9IGljb247XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybiBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRPd25lciA9IGZ1bmN0aW9uIGdldE93bmVyKCkge1xuXHRcdHJldHVybiB0aGlzLm93bmVyO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldEFjY2Vzc1R5cGUgPSBmdW5jdGlvbiBnZXRBY2Nlc3NUeXBlKCkge1xuXHRcdHJldHVybiB0aGlzLmFjY2Vzc1R5cGU7XG5cdH07XG5cblx0LyoqXG4gICogQHBhcmFtIGFjY2VzcyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5zZXRBY2Nlc3NUeXBlID0gZnVuY3Rpb24gc2V0QWNjZXNzVHlwZShhY2Nlc3MpIHtcblx0XHR0aGlzLmFjY2Vzc1R5cGUgPSBhY2Nlc3M7XG5cdH07XG5cblx0LyoqXG4gICogVHJpZ2dlcnMgUmVzb3VyY2VzTWFuYWdlci5sb2FkXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUubG9hZFJlc291cmNlcyA9IGZ1bmN0aW9uIGxvYWRSZXNvdXJjZXMoKSB7XG5cdFx0dGhpcy5yZXNvdXJjZXNNYW5hZ2VyLmxvYWQobnVsbCwgdHJ1ZSk7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgT2JqZWN0XG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0Tm9kZVByb3ZpZGVyRGVmID0gZnVuY3Rpb24gZ2V0Tm9kZVByb3ZpZGVyRGVmKCkge1xuXHRcdHJldHVybiB0aGlzLm5vZGVQcm92aWRlckRlZjtcblx0fTtcblxuXHQvKipcbiAgKiBAcGFyYW0gc2x1ZyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5zZXRTbHVnID0gZnVuY3Rpb24gc2V0U2x1ZyhzbHVnKSB7XG5cdFx0dGhpcy5zbHVnID0gc2x1Zztcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRTbHVnID0gZnVuY3Rpb24gZ2V0U2x1ZygpIHtcblx0XHRyZXR1cm4gdGhpcy5zbHVnO1xuXHR9O1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldE92ZXJsYXkgPSBmdW5jdGlvbiBnZXRPdmVybGF5KCkge1xuXHRcdHJldHVybiB0aGlzLmdldE93bmVyKCkgPyBfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10ucmVzb2x2ZUltYWdlU291cmNlKFwic2hhcmVkLnBuZ1wiLCBcIm92ZXJsYXlzL0lDT05fU0laRVwiLCA4KSA6IFwiXCI7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMge2Jvb2xlYW59XG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuaGFzQ29udGVudEZpbHRlciA9IGZ1bmN0aW9uIGhhc0NvbnRlbnRGaWx0ZXIoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2hhc0NvbnRlbnRGaWx0ZXI7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMge2Jvb2xlYW59XG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuaGFzVXNlclNjb3BlID0gZnVuY3Rpb24gaGFzVXNlclNjb3BlKCkge1xuXHRcdHJldHVybiB0aGlzLl9oYXNVc2VyU2NvcGU7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMge3N0cmluZ31cbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRSZXBvc2l0b3J5VHlwZSA9IGZ1bmN0aW9uIGdldFJlcG9zaXRvcnlUeXBlKCkge1xuXHRcdHJldHVybiB0aGlzLl9yZXBvc2l0b3J5VHlwZTtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldEFjY2Vzc1N0YXR1cyA9IGZ1bmN0aW9uIGdldEFjY2Vzc1N0YXR1cygpIHtcblx0XHRyZXR1cm4gdGhpcy5fYWNjZXNzU3RhdHVzO1xuXHR9O1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLnNldEFjY2Vzc1N0YXR1cyA9IGZ1bmN0aW9uIHNldEFjY2Vzc1N0YXR1cyhzdGF0dXMpIHtcblx0XHR0aGlzLl9hY2Nlc3NTdGF0dXMgPSBzdGF0dXM7XG5cdH07XG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0TGFzdENvbm5lY3Rpb24gPSBmdW5jdGlvbiBnZXRMYXN0Q29ubmVjdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5fbGFzdENvbm5lY3Rpb247XG5cdH07XG5cblx0LyoqXG4gICogUGFyc2VzIFhNTCBOb2RlXG4gICogQHBhcmFtIHJlcG9Ob2RlIFhNTE5vZGVcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5sb2FkRnJvbVhtbCA9IGZ1bmN0aW9uIGxvYWRGcm9tWG1sKHJlcG9Ob2RlKSB7XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5JykgJiYgcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHknKSA9PSBcInRydWVcIikge1xuXHRcdFx0dGhpcy5hbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHkgPSB0cnVlO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdoYXNDb250ZW50RmlsdGVyJykgJiYgcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdoYXNDb250ZW50RmlsdGVyJykgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdHRoaXMuX2hhc0NvbnRlbnRGaWx0ZXIgPSB0cnVlO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCd1c2VyU2NvcGUnKSAmJiByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3VzZXJTY29wZScpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHR0aGlzLl9oYXNVc2VyU2NvcGUgPSB0cnVlO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdyZXBvc2l0b3J5X3R5cGUnKSkge1xuXHRcdFx0dGhpcy5fcmVwb3NpdG9yeVR5cGUgPSByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3JlcG9zaXRvcnlfdHlwZScpO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdhY2Nlc3Nfc3RhdHVzJykpIHtcblx0XHRcdHRoaXMuX2FjY2Vzc1N0YXR1cyA9IHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWNjZXNzX3N0YXR1cycpO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdsYXN0X2Nvbm5lY3Rpb24nKSkge1xuXHRcdFx0dGhpcy5fbGFzdENvbm5lY3Rpb24gPSByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2xhc3RfY29ubmVjdGlvbicpO1xuXHRcdH1cblxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3VzZXJfZWRpdGFibGVfcmVwb3NpdG9yeScpICYmIHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgndXNlcl9lZGl0YWJsZV9yZXBvc2l0b3J5JykgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdHRoaXMudXNlckVkaXRhYmxlID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWNjZXNzX3R5cGUnKSkge1xuXHRcdFx0dGhpcy5zZXRBY2Nlc3NUeXBlKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWNjZXNzX3R5cGUnKSk7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3JlcG9zaXRvcnlTbHVnJykpIHtcblx0XHRcdHRoaXMuc2V0U2x1ZyhyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3JlcG9zaXRvcnlTbHVnJykpO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdvd25lcicpKSB7XG5cdFx0XHR0aGlzLm93bmVyID0gcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdvd25lcicpO1xuXHRcdH1cblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJlcG9Ob2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBjaGlsZE5vZGUgPSByZXBvTm9kZS5jaGlsZE5vZGVzW2ldO1xuXHRcdFx0aWYgKGNoaWxkTm9kZS5ub2RlTmFtZSA9PSBcImxhYmVsXCIpIHtcblx0XHRcdFx0dGhpcy5zZXRMYWJlbChjaGlsZE5vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUpO1xuXHRcdFx0fSBlbHNlIGlmIChjaGlsZE5vZGUubm9kZU5hbWUgPT0gXCJkZXNjcmlwdGlvblwiKSB7XG5cdFx0XHRcdHRoaXMuZGVzY3JpcHRpb24gPSBjaGlsZE5vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG5cdFx0XHR9IGVsc2UgaWYgKGNoaWxkTm9kZS5ub2RlTmFtZSA9PSBcImNsaWVudF9zZXR0aW5nc1wiKSB7XG5cdFx0XHRcdGlmIChjaGlsZE5vZGUuZ2V0QXR0cmlidXRlKCdpY29uX3RwbF9pZCcpKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRJY29uKHdpbmRvdy5weWRpby5QYXJhbWV0ZXJzLmdldCgnc2VydmVyQWNjZXNzUGF0aCcpICsgJyZnZXRfYWN0aW9uPWdldF91c2VyX3RlbXBsYXRlX2xvZ28mdGVtcGxhdGVfaWQ9JyArIGNoaWxkTm9kZS5nZXRBdHRyaWJ1dGUoJ2ljb25fdHBsX2lkJykgKyAnJmljb25fZm9ybWF0PXNtYWxsJyk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRJY29uKGNoaWxkTm9kZS5nZXRBdHRyaWJ1dGUoJ2ljb24nKSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yICh2YXIgaiA9IDA7IGogPCBjaGlsZE5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdHZhciBzdWJDaCA9IGNoaWxkTm9kZS5jaGlsZE5vZGVzW2pdO1xuXHRcdFx0XHRcdGlmIChzdWJDaC5ub2RlTmFtZSA9PSAncmVzb3VyY2VzJykge1xuXHRcdFx0XHRcdFx0dGhpcy5yZXNvdXJjZXNNYW5hZ2VyLmxvYWRGcm9tWG1sTm9kZShzdWJDaCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChzdWJDaC5ub2RlTmFtZSA9PSAnbm9kZV9wcm92aWRlcicpIHtcblx0XHRcdFx0XHRcdHZhciBub2RlUHJvdmlkZXJOYW1lID0gc3ViQ2guZ2V0QXR0cmlidXRlKFwiYWp4cENsYXNzXCIpO1xuXHRcdFx0XHRcdFx0dmFyIG5vZGVQcm92aWRlck9wdGlvbnMgPSBKU09OLnBhcnNlKHN1YkNoLmdldEF0dHJpYnV0ZShcImFqeHBPcHRpb25zXCIpKTtcblx0XHRcdFx0XHRcdHRoaXMubm9kZVByb3ZpZGVyRGVmID0geyBuYW1lOiBub2RlUHJvdmlkZXJOYW1lLCBvcHRpb25zOiBub2RlUHJvdmlkZXJPcHRpb25zIH07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiBSZXBvc2l0b3J5O1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUmVwb3NpdG9yeTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG52YXIgX1JlcG9zaXRvcnkgPSByZXF1aXJlKCcuL1JlcG9zaXRvcnknKTtcblxudmFyIF9SZXBvc2l0b3J5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX1JlcG9zaXRvcnkpO1xuXG4vKipcbiAqIEFic3RyYWN0aW9uIG9mIHRoZSBjdXJyZW50bHkgbG9nZ2VkIHVzZXIuIENhbiBiZSBhIFwiZmFrZVwiIHVzZXIgd2hlbiB1c2VycyBtYW5hZ2VtZW50XG4gKiBzeXN0ZW0gaXMgZGlzYWJsZWRcbiAqL1xuXG52YXIgVXNlciA9IChmdW5jdGlvbiAoKSB7XG5cblx0LyoqXG4gICogQ29uc3RydWN0b3JcbiAgKiBAcGFyYW0gaWQgU3RyaW5nIFRoZSB1c2VyIHVuaXF1ZSBpZFxuICAqIEBwYXJhbSB4bWxEZWYgWE1MTm9kZSBSZWdpc3RyeSBGcmFnbWVudFxuICAqL1xuXG5cdGZ1bmN0aW9uIFVzZXIoaWQsIHhtbERlZikge1xuXHRcdF9jbGFzc0NhbGxDaGVjayh0aGlzLCBVc2VyKTtcblxuXHRcdC8qKlxuICAgKiBAdmFyIFN0cmluZ1xuICAgKi9cblx0XHR0aGlzLmlkID0gaWQ7XG5cdFx0LyoqXG4gICAqIEB2YXIgU3RyaW5nXG4gICAqL1xuXHRcdHRoaXMuYWN0aXZlUmVwb3NpdG9yeSA9IHVuZGVmaW5lZDtcblx0XHQvKipcbiAgICogQHZhciBCb29sZWFuXG4gICAqL1xuXHRcdHRoaXMucmVhZCA9IGZhbHNlO1xuXHRcdC8qKlxuICAgKiBAdmFyIEJvb2xlYW5cbiAgICovXG5cdFx0dGhpcy53cml0ZSA9IGZhbHNlLFxuXHRcdC8qKlxuICAgKiBAdmFyIEJvb2xlYW5cbiAgICovXG5cdFx0dGhpcy5jcm9zc1JlcG9zaXRvcnlDb3B5ID0gZmFsc2UsXG5cdFx0LyoqXG4gICAqIEB2YXIgTWFwKClcbiAgICovXG5cdFx0dGhpcy5wcmVmZXJlbmNlcyA9IG5ldyBNYXAoKSxcblx0XHQvKipcbiAgICogQHZhciBNYXAoKVxuICAgKi9cblx0XHR0aGlzLnJlcG9zaXRvcmllcyA9IG5ldyBNYXAoKSxcblx0XHQvKipcbiAgICogQHZhciBNYXAoKVxuICAgKi9cblx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yaWVzID0gbmV3IE1hcCgpLFxuXHRcdC8qKlxuICAgKiBAdmFyIE1hcCgpXG4gICAqL1xuXHRcdHRoaXMucmVwb0ljb25zID0gbmV3IE1hcCgpLFxuXHRcdC8qKlxuICAgKiBAdmFyIE1hcCgpXG4gICAqL1xuXHRcdHRoaXMucmVwb1NlYXJjaEVuZ2luZXMgPSBuZXcgTWFwKCksXG5cdFx0LyoqXG4gICAqIEB2YXIgQm9vbGVhblxuICAgKi9cblx0XHR0aGlzLmlzQWRtaW4gPSBmYWxzZTtcblx0XHQvKipcbiAgICogQHZhciBTdHJpbmdcbiAgICovXG5cdFx0dGhpcy5sb2NrID0gZmFsc2U7XG5cdFx0LyoqXG4gICAqXG4gICAqIEB0eXBlIE1hcFxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblx0XHR0aGlzLl9wYXJzZWRKU09OQ2FjaGUgPSBuZXcgTWFwKCk7XG5cblx0XHRpZiAoeG1sRGVmKSB0aGlzLmxvYWRGcm9tWG1sKHhtbERlZik7XG5cdH1cblxuXHQvKipcbiAgKiBTZXQgY3VycmVudCByZXBvc2l0b3J5XG4gICogQHBhcmFtIGlkIFN0cmluZ1xuICAqIEBwYXJhbSByZWFkIEJvb2xlYW5cbiAgKiBAcGFyYW0gd3JpdGUgQm9vbGVhblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLnNldEFjdGl2ZVJlcG9zaXRvcnkgPSBmdW5jdGlvbiBzZXRBY3RpdmVSZXBvc2l0b3J5KGlkLCByZWFkLCB3cml0ZSkge1xuXHRcdHRoaXMuYWN0aXZlUmVwb3NpdG9yeSA9IGlkO1xuXHRcdHRoaXMucmVhZCA9IHJlYWQgPT0gXCIxXCI7XG5cdFx0dGhpcy53cml0ZSA9IHdyaXRlID09IFwiMVwiO1xuXHRcdGlmICh0aGlzLnJlcG9zaXRvcmllcy5oYXMoaWQpKSB7XG5cdFx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yeUNvcHkgPSB0aGlzLnJlcG9zaXRvcmllcy5nZXQoaWQpLmFsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weTtcblx0XHR9XG5cdFx0aWYgKHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXMuaGFzKGlkKSkge1xuXHRcdFx0dGhpcy5jcm9zc1JlcG9zaXRvcmllc1snZGVsZXRlJ10oaWQpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSByZXBvc2l0b3J5XG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0QWN0aXZlUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIGdldEFjdGl2ZVJlcG9zaXRvcnkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYWN0aXZlUmVwb3NpdG9yeTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIGN1cnJlbnQgcmVwbyBpcyBhbGxvd2VkIHRvIGJlIHJlYWRcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuY2FuUmVhZCA9IGZ1bmN0aW9uIGNhblJlYWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVhZDtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIGN1cnJlbnQgcmVwbyBpcyBhbGxvd2VkIHRvIGJlIHdyaXR0ZW5cbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuY2FuV3JpdGUgPSBmdW5jdGlvbiBjYW5Xcml0ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy53cml0ZTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIGN1cnJlbnQgcmVwbyBpcyBhbGxvd2VkIHRvIGJlIGNyb3NzLWNvcGllZFxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5jYW5Dcm9zc1JlcG9zaXRvcnlDb3B5ID0gZnVuY3Rpb24gY2FuQ3Jvc3NSZXBvc2l0b3J5Q29weSgpIHtcblx0XHRyZXR1cm4gdGhpcy5jcm9zc1JlcG9zaXRvcnlDb3B5O1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCBhIHVzZXIgcHJlZmVyZW5jZSBieSBpdHMgbmFtZVxuICAqIEByZXR1cm5zIE1peGVkXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0UHJlZmVyZW5jZSA9IGZ1bmN0aW9uIGdldFByZWZlcmVuY2UocHJlZk5hbWUsIGZyb21KU09OKSB7XG5cdFx0aWYgKGZyb21KU09OKSB7XG5cdFx0XHR2YXIgdGVzdCA9IHRoaXMuX3BhcnNlZEpTT05DYWNoZS5nZXQocHJlZk5hbWUpO1xuXHRcdFx0aWYgKHRlc3QpIHJldHVybiB0ZXN0O1xuXHRcdH1cblx0XHR2YXIgdmFsdWUgPSB0aGlzLnByZWZlcmVuY2VzLmdldChwcmVmTmFtZSk7XG5cdFx0aWYgKGZyb21KU09OKSB7XG5cdFx0XHRpZiAodmFsdWUpIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRpZiAodHlwZW9mIHZhbHVlID09IFwib2JqZWN0XCIpIHJldHVybiB2YWx1ZTtcblx0XHRcdFx0XHR2YXIgcGFyc2VkID0gSlNPTi5wYXJzZSh2YWx1ZSk7XG5cdFx0XHRcdFx0dGhpcy5fcGFyc2VkSlNPTkNhY2hlLnNldChwcmVmTmFtZSwgcGFyc2VkKTtcblx0XHRcdFx0XHRpZiAoIXBhcnNlZCkgcmV0dXJuIHt9O1xuXHRcdFx0XHRcdHJldHVybiBwYXJzZWQ7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRpZiAod2luZG93LmNvbnNvbGUpIHtcblx0XHRcdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmxvZyhcIkVycm9yIHBhcnNpbmcgSlNPTiBpbiBwcmVmZXJlbmNlcyAoXCIgKyBwcmVmTmFtZSArIFwiKS4gWW91IHNob3VsZCBjb250YWN0IHN5c3RlbSBhZG1pbiBhbmQgY2xlYXIgdXNlciBwcmVmZXJlbmNlcy5cIik7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGFsZXJ0KFwiRXJyb3IgcGFyc2luZyBKU09OIGluIHByZWZlcmVuY2VzLiBZb3Ugc2hvdWxkIGNvbnRhY3Qgc3lzdGVtIGFkbWluIGFuZCBjbGVhciB1c2VyIHByZWZlcmVuY2VzLlwiKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB7fTtcblx0XHR9XG5cdFx0cmV0dXJuIHZhbHVlO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCBhbGwgcmVwb3NpdG9yaWVzIFxuICAqIEByZXR1cm5zIE1hcFxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldFJlcG9zaXRvcmllc0xpc3QgPSBmdW5jdGlvbiBnZXRSZXBvc2l0b3JpZXNMaXN0KCkge1xuXHRcdHJldHVybiB0aGlzLnJlcG9zaXRvcmllcztcblx0fTtcblxuXHQvKipcbiAgKiBTZXQgYSBwcmVmZXJlbmNlIHZhbHVlXG4gICogQHBhcmFtIHByZWZOYW1lIFN0cmluZ1xuICAqIEBwYXJhbSBwcmVmVmFsdWUgTWl4ZWRcbiAgKiBAcGFyYW0gdG9KU09OIEJvb2xlYW4gV2hldGhlciB0byBjb252ZXJ0IHRoZSB2YWx1ZSB0byBKU09OIHJlcHJlc2VudGF0aW9uXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuc2V0UHJlZmVyZW5jZSA9IGZ1bmN0aW9uIHNldFByZWZlcmVuY2UocHJlZk5hbWUsIHByZWZWYWx1ZSkge1xuXHRcdHZhciB0b0pTT04gPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1syXTtcblxuXHRcdGlmICh0b0pTT04pIHtcblx0XHRcdHRoaXMuX3BhcnNlZEpTT05DYWNoZVsnZGVsZXRlJ10ocHJlZk5hbWUpO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0cHJlZlZhbHVlID0gSlNPTi5zdHJpbmdpZnkocHJlZlZhbHVlKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0aWYgKGNvbnNvbGUpIHtcblx0XHRcdFx0XHR2YXIgaXNDeWNsaWMgPSBmdW5jdGlvbiBpc0N5Y2xpYyhvYmopIHtcblx0XHRcdFx0XHRcdHZhciBzZWVuT2JqZWN0cyA9IFtdO1xuXG5cdFx0XHRcdFx0XHRmdW5jdGlvbiBkZXRlY3Qob2JqKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChvYmogJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoc2Vlbk9iamVjdHMuaW5kZXhPZihvYmopICE9PSAtMSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHNlZW5PYmplY3RzLnB1c2gob2JqKTtcblx0XHRcdFx0XHRcdFx0XHRmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkgJiYgZGV0ZWN0KG9ialtrZXldKSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRjb25zb2xlLmxvZyhvYmosICdjeWNsZSBhdCAnICsga2V5KTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHJldHVybiBkZXRlY3Qob2JqKTtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0Y29uc29sZS5sb2coXCJDYXVnaHQgdG9KU09OIGVycm9yIFwiICsgZS5tZXNzYWdlLCBwcmVmVmFsdWUsIGlzQ3ljbGljKHByZWZWYWx1ZSkpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5wcmVmZXJlbmNlcy5zZXQocHJlZk5hbWUsIHByZWZWYWx1ZSk7XG5cdH07XG5cblx0LyoqXG4gICogU2V0IHRoZSByZXBvc2l0b3JpZXMgYXMgYSBidW5jaFxuICAqIEBwYXJhbSByZXBvSGFzaCBNYXBcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5zZXRSZXBvc2l0b3JpZXNMaXN0ID0gZnVuY3Rpb24gc2V0UmVwb3NpdG9yaWVzTGlzdChyZXBvSGFzaCkge1xuXHRcdHRoaXMucmVwb3NpdG9yaWVzID0gcmVwb0hhc2g7XG5cdFx0Ly8gZmlsdGVyIHJlcG9zaXRvcmllcyBvbmNlIGZvciBhbGxcblx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yaWVzID0gbmV3IE1hcCgpO1xuXHRcdHRoaXMucmVwb3NpdG9yaWVzLmZvckVhY2goKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG5cdFx0XHRpZiAodmFsdWUuYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5ICYmIHZhbHVlLmFjY2Vzc1R5cGUgIT0gJ2luYm94Jykge1xuXHRcdFx0XHR0aGlzLmNyb3NzUmVwb3NpdG9yaWVzLnNldChrZXksIHZhbHVlKTtcblx0XHRcdH1cblx0XHR9KS5iaW5kKHRoaXMpKTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZXJlIGFyZSBhbnkgcmVwb3NpdG9yaWVzIGFsbG93aW5nIGNyb3NzQ29weVxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5oYXNDcm9zc1JlcG9zaXRvcmllcyA9IGZ1bmN0aW9uIGhhc0Nyb3NzUmVwb3NpdG9yaWVzKCkge1xuXHRcdHJldHVybiB0aGlzLmNyb3NzUmVwb3NpdG9yaWVzLnNpemU7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IHJlcG9zaXRvcmllcyBhbGxvd2luZyBjcm9zcyBjb3B5XG4gICogQHJldHVybnMge01hcH1cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRDcm9zc1JlcG9zaXRvcmllcyA9IGZ1bmN0aW9uIGdldENyb3NzUmVwb3NpdG9yaWVzKCkge1xuXHRcdHJldHVybiB0aGlzLmNyb3NzUmVwb3NpdG9yaWVzO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCB0aGUgY3VycmVudCByZXBvc2l0b3J5IEljb25cbiAgKiBAcGFyYW0gcmVwb0lkIFN0cmluZ1xuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldFJlcG9zaXRvcnlJY29uID0gZnVuY3Rpb24gZ2V0UmVwb3NpdG9yeUljb24ocmVwb0lkKSB7XG5cdFx0cmV0dXJuIHRoaXMucmVwb0ljb24uZ2V0KHJlcG9JZCk7XG5cdH07XG5cblx0LyoqXG4gICogR2V0IHRoZSByZXBvc2l0b3J5IHNlYXJjaCBlbmdpbmVcbiAgKiBAcGFyYW0gcmVwb0lkIFN0cmluZ1xuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldFJlcG9TZWFyY2hFbmdpbmUgPSBmdW5jdGlvbiBnZXRSZXBvU2VhcmNoRW5naW5lKHJlcG9JZCkge1xuXHRcdHJldHVybiB0aGlzLnJlcG9TZWFyY2hFbmdpbmVzLmdldChyZXBvSWQpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNlbmQgdGhlIHByZWZlcmVuY2UgdG8gdGhlIHNlcnZlciBmb3Igc2F2aW5nXG4gICogQHBhcmFtIHByZWZOYW1lIFN0cmluZ1xuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLnNhdmVQcmVmZXJlbmNlID0gZnVuY3Rpb24gc2F2ZVByZWZlcmVuY2UocHJlZk5hbWUpIHtcblx0XHRpZiAoIXRoaXMucHJlZmVyZW5jZXMuaGFzKHByZWZOYW1lKSkgcmV0dXJuO1xuXHRcdHZhciBwcmVmVmFsdWUgPSB0aGlzLnByZWZlcmVuY2VzLmdldChwcmVmTmFtZSk7XG5cdFx0d2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0X2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS51c2VyU2F2ZVByZWZlcmVuY2UocHJlZk5hbWUsIHByZWZWYWx1ZSk7XG5cdFx0fSwgMjUwKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZW5kIGFsbCBwcmVmZXJlbmNlcyB0byB0aGUgc2VydmVyLiBJZiBvbGRQYXNzLCBuZXdQYXNzIGFuZCBzZWVkIGFyZSBzZXQsIGFsc28gc2F2ZSBwYXNzLlxuICAqIEBwYXJhbSBvbGRQYXNzIFN0cmluZ1xuICAqIEBwYXJhbSBuZXdQYXNzIFN0cmluZ1xuICAqIEBwYXJhbSBzZWVkIFN0cmluZ1xuICAqIEBwYXJhbSBvbkNvbXBsZXRlRnVuYyBGdW5jdGlvblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLnNhdmVQcmVmZXJlbmNlcyA9IGZ1bmN0aW9uIHNhdmVQcmVmZXJlbmNlcyhvbGRQYXNzLCBuZXdQYXNzLCBzZWVkLCBvbkNvbXBsZXRlRnVuYykge1xuXHRcdGlmIChvbGRQYXNzICYmIG5ld1Bhc3MpIHtcblx0XHRcdF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkudXNlclNhdmVQYXNzd29yZChvbGRQYXNzLCBuZXdQYXNzLCBzZWVkLCBvbkNvbXBsZXRlRnVuYyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkudXNlclNhdmVQcmVmZXJlbmNlcyh0aGlzLnByZWZlcmVuY2VzLCBvbkNvbXBsZXRlRnVuYyk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFBhcnNlIHRoZSByZWdpc3RyeSBmcmFnbWVudCB0byBsb2FkIHRoaXMgdXNlclxuICAqIEBwYXJhbSB1c2VyTm9kZXMgRE9NTm9kZVxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmxvYWRGcm9tWG1sID0gZnVuY3Rpb24gbG9hZEZyb21YbWwodXNlck5vZGVzKSB7XG5cblx0XHR2YXIgcmVwb3NpdG9yaWVzID0gbmV3IE1hcCgpLFxuXHRcdCAgICBhY3RpdmVOb2RlID0gdW5kZWZpbmVkO1xuXHRcdHZhciBpID0gdW5kZWZpbmVkLFxuXHRcdCAgICBqID0gdW5kZWZpbmVkO1xuXHRcdGZvciAoaSA9IDA7IGkgPCB1c2VyTm9kZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICh1c2VyTm9kZXNbaV0ubm9kZU5hbWUgPT0gXCJhY3RpdmVfcmVwb1wiKSB7XG5cdFx0XHRcdGFjdGl2ZU5vZGUgPSB1c2VyTm9kZXNbaV07XG5cdFx0XHR9IGVsc2UgaWYgKHVzZXJOb2Rlc1tpXS5ub2RlTmFtZSA9PSBcInJlcG9zaXRvcmllc1wiKSB7XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCB1c2VyTm9kZXNbaV0uY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdHZhciByZXBvQ2hpbGQgPSB1c2VyTm9kZXNbaV0uY2hpbGROb2Rlc1tqXTtcblx0XHRcdFx0XHRpZiAocmVwb0NoaWxkLm5vZGVOYW1lID09IFwicmVwb1wiKSB7XG5cdFx0XHRcdFx0XHR2YXIgcmVwb3NpdG9yeSA9IG5ldyBfUmVwb3NpdG9yeTJbJ2RlZmF1bHQnXShyZXBvQ2hpbGQuZ2V0QXR0cmlidXRlKFwiaWRcIiksIHJlcG9DaGlsZCk7XG5cdFx0XHRcdFx0XHRyZXBvc2l0b3JpZXMuc2V0KHJlcG9DaGlsZC5nZXRBdHRyaWJ1dGUoXCJpZFwiKSwgcmVwb3NpdG9yeSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuc2V0UmVwb3NpdG9yaWVzTGlzdChyZXBvc2l0b3JpZXMpO1xuXHRcdFx0fSBlbHNlIGlmICh1c2VyTm9kZXNbaV0ubm9kZU5hbWUgPT0gXCJwcmVmZXJlbmNlc1wiKSB7XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCB1c2VyTm9kZXNbaV0uY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdHZhciBwcmVmQ2hpbGQgPSB1c2VyTm9kZXNbaV0uY2hpbGROb2Rlc1tqXTtcblx0XHRcdFx0XHRpZiAocHJlZkNoaWxkLm5vZGVOYW1lID09IFwicHJlZlwiKSB7XG5cdFx0XHRcdFx0XHR2YXIgdmFsdWUgPSBwcmVmQ2hpbGQuZ2V0QXR0cmlidXRlKFwidmFsdWVcIik7XG5cdFx0XHRcdFx0XHRpZiAoIXZhbHVlICYmIHByZWZDaGlsZC5maXJzdENoaWxkKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFJldHJpZXZlIHZhbHVlIGZyb20gQ0RBVEFcblx0XHRcdFx0XHRcdFx0dmFsdWUgPSBwcmVmQ2hpbGQuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR0aGlzLnNldFByZWZlcmVuY2UocHJlZkNoaWxkLmdldEF0dHJpYnV0ZShcIm5hbWVcIiksIHZhbHVlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAodXNlck5vZGVzW2ldLm5vZGVOYW1lID09IFwic3BlY2lhbF9yaWdodHNcIikge1xuXHRcdFx0XHR2YXIgYXR0ciA9IHVzZXJOb2Rlc1tpXS5nZXRBdHRyaWJ1dGUoXCJpc19hZG1pblwiKTtcblx0XHRcdFx0aWYgKGF0dHIgJiYgYXR0ciA9PT0gXCIxXCIpIHRoaXMuaXNBZG1pbiA9IHRydWU7XG5cdFx0XHRcdGlmICh1c2VyTm9kZXNbaV0uZ2V0QXR0cmlidXRlKFwibG9ja1wiKSkge1xuXHRcdFx0XHRcdHRoaXMubG9jayA9IHVzZXJOb2Rlc1tpXS5nZXRBdHRyaWJ1dGUoXCJsb2NrXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdC8vIE1ha2Ugc3VyZSBpdCBoYXBwZW5zIGF0IHRoZSBlbmRcblx0XHRpZiAoYWN0aXZlTm9kZSkge1xuXHRcdFx0dGhpcy5zZXRBY3RpdmVSZXBvc2l0b3J5KGFjdGl2ZU5vZGUuZ2V0QXR0cmlidXRlKCdpZCcpLCBhY3RpdmVOb2RlLmdldEF0dHJpYnV0ZSgncmVhZCcpLCBhY3RpdmVOb2RlLmdldEF0dHJpYnV0ZSgnd3JpdGUnKSk7XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiBVc2VyO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gVXNlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbi8qKlxuICogQSBtb25pdG9yIGZvciB1c2VyIFwiaWRsZVwiIHN0YXRlIHRvIHByZXZlbnQgc2Vzc2lvbiB0aW1pbmcgb3V0LlxuICovXG5cbnZhciBBY3Rpdml0eU1vbml0b3IgPSAoZnVuY3Rpb24gKF9PYnNlcnZhYmxlKSB7XG4gICAgX2luaGVyaXRzKEFjdGl2aXR5TW9uaXRvciwgX09ic2VydmFibGUpO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gcHlkaW8gUHlkaW9cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIEFjdGl2aXR5TW9uaXRvcihweWRpbykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBY3Rpdml0eU1vbml0b3IpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG5cbiAgICAgICAgdmFyIHNlcnZlclNlc3Npb25UaW1lID0gcHlkaW8uUGFyYW1ldGVycy5nZXQoJ3Nlc3Npb25fdGltZW91dCcpO1xuICAgICAgICB2YXIgY2xpZW50U2Vzc2lvblRpbWUgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnY2xpZW50X3RpbWVvdXQnKTtcbiAgICAgICAgdmFyIHdhcm5pbmdNaW51dGVzID0gcHlkaW8uUGFyYW1ldGVycy5nZXQoJ2NsaWVudF90aW1lb3V0X3dhcm5pbmcnKTtcblxuICAgICAgICB0aGlzLl9weWRpbyA9IHB5ZGlvO1xuICAgICAgICB0aGlzLl93YXJuaW5nTWludXRlcyA9IDM7XG4gICAgICAgIHRoaXMuX3JlbmV3TWludXRlcyA9IDEwO1xuICAgICAgICB0aGlzLl9sb2dvdXRNaW51dGVzID0gMDtcblxuICAgICAgICB0aGlzLl9sYXN0QWN0aXZlID0gMDtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSAnYWN0aXZlJztcbiAgICAgICAgdGhpcy5fbG9uZ1Rhc2tSdW5uaW5nID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFzZXJ2ZXJTZXNzaW9uVGltZSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChzZXJ2ZXJTZXNzaW9uVGltZSA8PSA2MCAqIHRoaXMuX3JlbmV3TWludXRlcykge1xuICAgICAgICAgICAgdGhpcy5fcmVuZXdNaW51dGVzID0gMjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2xpZW50U2Vzc2lvblRpbWUgPT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5ld1RpbWUgPSBzZXJ2ZXJTZXNzaW9uVGltZSAtIHRoaXMuX3JlbmV3TWludXRlcyAqIDYwO1xuICAgICAgICAgICAgaWYgKHRoaXMuX3B5ZGlvLnVzZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0U2VydmVyTG9uZ1BvbGxlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgndXNlcl9sb2dnZWQnLCBmdW5jdGlvbiAodSkge1xuICAgICAgICAgICAgICAgIGlmICh1KSBfdGhpcy5zdGFydFNlcnZlckxvbmdQb2xsZXIoKTtlbHNlIF90aGlzLnN0b3BTZXJ2ZXJMb25nUG9sbGVyKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3NlcnZlclNlc3Npb25UaW1lID0gc2VydmVyU2Vzc2lvblRpbWU7XG4gICAgICAgIGlmICh3YXJuaW5nTWludXRlcykge1xuICAgICAgICAgICAgdGhpcy5fd2FybmluZ01pbnV0ZXMgPSB3YXJuaW5nTWludXRlcztcbiAgICAgICAgICAgIHRoaXMuX3dhcm5pbmdUaW1lID0gY2xpZW50U2Vzc2lvblRpbWUgLSB0aGlzLl93YXJuaW5nTWludXRlcyAqIDYwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fd2FybmluZ1RpbWUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9sb2dvdXRUaW1lID0gY2xpZW50U2Vzc2lvblRpbWUgLSB0aGlzLl9sb2dvdXRNaW51dGVzICogNjA7XG4gICAgICAgIHRoaXMuX3JlbmV3VGltZSA9IHNlcnZlclNlc3Npb25UaW1lIC0gdGhpcy5fcmVuZXdNaW51dGVzICogNjA7XG4gICAgICAgIHRoaXMuX2xhc3RBY3RpdmUgPSB0aGlzLmdldE5vdygpO1xuXG4gICAgICAgIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIgPSBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLl9weWRpby51c2VyKSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgndXNlcl9sb2dnZWQnLCBmdW5jdGlvbiAodSkge1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlTGFzdEFjdGl2ZSgpO1xuICAgICAgICAgICAgaWYgKHUpIF90aGlzLnJlZ2lzdGVyKCk7ZWxzZSBfdGhpcy51bnJlZ2lzdGVyKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8qXG4gICAgICAgIGRvY3VtZW50Lm9ic2VydmUoXCJhamF4cGxvcmVyOnVzZXJfbG9nZ2VkXCIsIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAvLyBCZSBzdXJlIG5vdCB0byBtdWx0aXBseSB0aGUgc2V0SW50ZXJ2YWxcbiAgICAgICAgICAgIHRoaXMuX2xhc3RBY3RpdmUgPSB0aGlzLmdldE5vdygpO1xuICAgICAgICAgICAgaWYodGhpcy5pbnRlcnZhbCkgY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsKTtcbiAgICAgICAgICAgIGlmKHRoaXMuc2VydmVySW50ZXJ2YWwpIGNsZWFySW50ZXJ2YWwodGhpcy5zZXJ2ZXJJbnRlcnZhbCk7XG4gICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLnN0b3BPYnNlcnZpbmcoXCJrZXlwcmVzc1wiLCBhY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkuc3RvcE9ic2VydmluZyhcIm1vdXNlb3ZlclwiLCBhY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkuc3RvcE9ic2VydmluZyhcIm1vdXNlbW92ZVwiLCBhY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgICAgIGRvY3VtZW50LnN0b3BPYnNlcnZpbmcoXCJhamF4cGxvcmVyOnNlcnZlcl9hbnN3ZXJcIiwgYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICBpZihhamF4cGxvcmVyLnVzZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkub2JzZXJ2ZShcImtleXByZXNzXCIsIGFjdGl2aXR5T2JzZXJ2ZXIgKTtcbiAgICAgICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLm9ic2VydmUoXCJtb3VzZW92ZXJcIiwgYWN0aXZpdHlPYnNlcnZlciApO1xuICAgICAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkub2JzZXJ2ZShcIm1vdXNlbW92ZVwiLCBhY3Rpdml0eU9ic2VydmVyICk7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQub2JzZXJ2ZShcImFqYXhwbG9yZXI6c2VydmVyX2Fuc3dlclwiLCBhY3Rpdml0eU9ic2VydmVyICk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnRlcnZhbCA9IHNldEludGVydmFsKHRoaXMuaWRsZU9ic2VydmVyLmJpbmQodGhpcyksIDUwMDApO1xuICAgICAgICAgICAgICAgIHRoaXMuc2VydmVySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLnNlcnZlck9ic2VydmVyLmJpbmQodGhpcyksIE1hdGgubWluKChNYXRoLnBvdygyLDMxKS0xKSwgdGhpcy5fcmVuZXdUaW1lKjEwMDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgZG9jdW1lbnQub2JzZXJ2ZShcImFqYXhwbG9yZXI6bG9uZ3Rhc2tfc3RhcnRpbmdcIiwgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdUYXNrUnVubmluZyA9IHRydWU7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIGRvY3VtZW50Lm9ic2VydmUoXCJhamF4cGxvcmVyOmxvbmd0YXNrX2ZpbmlzaGVkXCIsIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICB0aGlzLl9sb25nVGFza1J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgKi9cbiAgICB9XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnN0YXJ0U2VydmVyTG9uZ1BvbGxlciA9IGZ1bmN0aW9uIHN0YXJ0U2VydmVyTG9uZ1BvbGxlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuX3NlcnZlckludGVydmFsKSByZXR1cm47XG4gICAgICAgIHRoaXMuX3NlcnZlckludGVydmFsID0gc2V0SW50ZXJ2YWwodGhpcy5zZXJ2ZXJQb2xsZXIuYmluZCh0aGlzKSwgTWF0aC5taW4oTWF0aC5wb3coMiwgMzEpIC0gMSwgdGhpcy5fcmVuZXdUaW1lICogMTAwMCkpO1xuICAgIH07XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnN0b3BTZXJ2ZXJMb25nUG9sbGVyID0gZnVuY3Rpb24gc3RvcFNlcnZlckxvbmdQb2xsZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLl9zZXJ2ZXJJbnRlcnZhbCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLl9zZXJ2ZXJJbnRlcnZhbCk7XG4gICAgICAgICAgICB0aGlzLl9zZXJ2ZXJJbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zdGFydElkbGVQb2xsZXIgPSBmdW5jdGlvbiBzdGFydElkbGVQb2xsZXIoKSB7XG4gICAgICAgIHZhciByZXN0YXJ0QXQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICAgIGlmIChyZXN0YXJ0QXQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pZGxlSW50ZXJ2YWwpIGNsZWFySW50ZXJ2YWwodGhpcy5faWRsZUludGVydmFsKTtcbiAgICAgICAgICAgIHRoaXMuX2lkbGVJbnRlcnZhbCA9IHNldEludGVydmFsKHRoaXMuaWRsZU9ic2VydmVyLmJpbmQodGhpcyksIHJlc3RhcnRBdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faWRsZUludGVydmFsKSByZXR1cm47XG4gICAgICAgICAgICB0aGlzLl9pZGxlSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLmlkbGVPYnNlcnZlci5iaW5kKHRoaXMpLCA1MDAwKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnN0b3BJZGxlUG9sbGVyID0gZnVuY3Rpb24gc3RvcElkbGVQb2xsZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLl9pZGxlSW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5faWRsZUludGVydmFsKTtcbiAgICAgICAgICAgIHRoaXMuX2lkbGVJbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5yZWdpc3RlciA9IGZ1bmN0aW9uIHJlZ2lzdGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5fYWN0aXZpdHlPYnNlcnZlciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gQWxyZWFkeSByZWdpc3RlcmVkXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RhdGUgPSAnYWN0aXZlJztcbiAgICAgICAgdGhpcy5fYWN0aXZpdHlPYnNlcnZlciA9IHRoaXMuYWN0aXZpdHlPYnNlcnZlci5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCd1c2VyX2FjdGl2aXR5JywgdGhpcy5fYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ3NlcnZlcl9hbnN3ZXInLCB0aGlzLl9hY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgnbG9uZ3Rhc2tfc3RhcnRpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpczIuX2xvbmdUYXNrUnVubmluZyA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCdsb25ndGFza19maW5pc2hlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzMi5fbG9uZ1Rhc2tSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnN0YXJ0SWRsZVBvbGxlcigpO1xuICAgICAgICB0aGlzLnN0YXJ0U2VydmVyTG9uZ1BvbGxlcigpO1xuICAgIH07XG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnVucmVnaXN0ZXIgPSBmdW5jdGlvbiB1bnJlZ2lzdGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5fYWN0aXZpdHlPYnNlcnZlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gQWxyZWFkeSBpbmFjdGl2ZVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RvcElkbGVQb2xsZXIoKTtcbiAgICAgICAgdGhpcy5zdG9wU2VydmVyTG9uZ1BvbGxlcigpO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9ICdpbmFjdGl2ZSc7XG4gICAgICAgIHRoaXMuX3B5ZGlvLnN0b3BPYnNlcnZpbmcoJ3VzZXJfYWN0aXZpdHknLCB0aGlzLl9hY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgdGhpcy5fcHlkaW8uc3RvcE9ic2VydmluZygnc2VydmVyX2Fuc3dlcicsIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLl9weWRpby5zdG9wT2JzZXJ2aW5nKCdsb25ndGFza19zdGFydGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzMy5fbG9uZ1Rhc2tSdW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX3B5ZGlvLnN0b3BPYnNlcnZpbmcoJ2xvbmd0YXNrX2ZpbmlzaGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMzLl9sb25nVGFza1J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIgPSBudWxsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW5lciB0byBjbGVhciB0aGUgdGltZXJcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuYWN0aXZpdHlPYnNlcnZlciA9IGZ1bmN0aW9uIGFjdGl2aXR5T2JzZXJ2ZXIoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50ICYmIChldmVudC5tZW1vICYmIGV2ZW50Lm1lbW8uZGlzY3JldGUgfHwgZXZlbnQuZGlzY3JldGUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3N0YXRlID09PSAnd2FybmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuZXhpdElkbGVTdGF0ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnRlcm5hbFRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy5faW50ZXJuYWxUaW1lcik7XG4gICAgICAgIHRoaXMuX2ludGVybmFsVGltZXIgPSBzZXRUaW1lb3V0KHRoaXMudXBkYXRlTGFzdEFjdGl2ZS5iaW5kKHRoaXMpLCAxMDAwKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0IGxhc3QgYWN0aXZpdHkgdGltZVxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS51cGRhdGVMYXN0QWN0aXZlID0gZnVuY3Rpb24gdXBkYXRlTGFzdEFjdGl2ZSgpIHtcbiAgICAgICAgdGhpcy5fbGFzdEFjdGl2ZSA9IHRoaXMuZ2V0Tm93KCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBpbmdzIHRoZSBzZXJ2ZXJcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc2VydmVyUG9sbGVyID0gZnVuY3Rpb24gc2VydmVyUG9sbGVyKCkge1xuICAgICAgICBQeWRpb0FwaS5nZXRDbGllbnQoKS5yZXF1ZXN0KHsgZ2V0X2FjdGlvbjogJ3BpbmcnIH0sIG51bGwsIG51bGwsIHsgbWV0aG9kOiAnZ2V0JywgZGlzY3JldGU6IHRydWUgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExpc3RlbmVyIGZvciBcImlkbGVcIiBzdGF0ZSBvZiB0aGUgdXNlclxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5pZGxlT2JzZXJ2ZXIgPSBmdW5jdGlvbiBpZGxlT2JzZXJ2ZXIoKSB7XG4gICAgICAgIHZhciBfdGhpczQgPSB0aGlzO1xuXG4gICAgICAgIHZhciBpZGxlVGltZSA9IHRoaXMuZ2V0Tm93KCkgLSB0aGlzLl9sYXN0QWN0aXZlO1xuICAgICAgICBpZiAodGhpcy5fc3RhdGUgPT09ICdpbmFjdGl2ZScpIHJldHVybjtcbiAgICAgICAgaWYgKHRoaXMuX2xvbmdUYXNrUnVubmluZykge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMYXN0QWN0aXZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy9jb25zb2xlLmxvZyhpZGxlVGltZSwgdGhpcy5fbG9nb3V0VGltZSk7XG4gICAgICAgIGlmIChpZGxlVGltZSA+PSB0aGlzLl9sb2dvdXRUaW1lKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVdhcm5pbmdTdGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSAnYWN0aXZlJztcbiAgICAgICAgICAgIHRoaXMuc3RvcElkbGVQb2xsZXIoKTtcbiAgICAgICAgICAgIHRoaXMuc3RvcFNlcnZlckxvbmdQb2xsZXIoKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzNC5fcHlkaW8uZ2V0Q29udHJvbGxlcigpLmZpcmVEZWZhdWx0QWN0aW9uKFwiZXhwaXJlXCIpO1xuICAgICAgICAgICAgfSwgMTAwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3dhcm5pbmdUaW1lICYmIGlkbGVUaW1lID49IHRoaXMuX3dhcm5pbmdUaW1lKSB7XG4gICAgICAgICAgICB2YXIgdGltZXJTdHJpbmcgPSB0aGlzLmdldFdhcm5pbmdUaW1lcih0aGlzLl9sb2dvdXRUaW1lIC0gaWRsZVRpbWUpO1xuICAgICAgICAgICAgdGhpcy5zZXRXYXJuaW5nU3RhdGUodGltZXJTdHJpbmcpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlYWN0aXZhdGUgd2luZG93XG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLmV4aXRJZGxlU3RhdGUgPSBmdW5jdGlvbiBleGl0SWRsZVN0YXRlKCkge1xuICAgICAgICB0aGlzLnJlbW92ZVdhcm5pbmdTdGF0ZSgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxhc3RBY3RpdmUoKTtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSAnYWN0aXZlJztcbiAgICAgICAgdGhpcy5zdGFydElkbGVQb2xsZXIoNTAwMCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFB1dCB0aGUgd2luZG93IGluIFwid2FybmluZ1wiIHN0YXRlIDogb3ZlcmxheSwgc2hha2luZyB0aW1lciwgY2hyb25vbWV0ZXIuXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnNldFdhcm5pbmdTdGF0ZSA9IGZ1bmN0aW9uIHNldFdhcm5pbmdTdGF0ZSh3YXJuaW5nVGltZXJTdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSAnd2FybmluZyc7XG4gICAgICAgIHRoaXMuc3RhcnRJZGxlUG9sbGVyKDEwMDApO1xuXG4gICAgICAgIHRoaXMuX3B5ZGlvLm5vdGlmeSgnYWN0aXZpdHlfc3RhdGVfY2hhbmdlJywge1xuICAgICAgICAgICAgYWN0aXZlU3RhdGU6ICd3YXJuaW5nJyxcbiAgICAgICAgICAgIGxhc3RBY3RpdmVTaW5jZTogdGhpcy5fd2FybmluZ1RpbWUgLyA2MCxcbiAgICAgICAgICAgIHRpbWVyU3RyaW5nOiB3YXJuaW5nVGltZXJTdHJpbmdcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENocm9ub21ldGVyIGZvciB3YXJuaW5nIGJlZm9yZSB0aW1lb3V0XG4gICAgICogQHBhcmFtIHRpbWUgSW50ZWdlclxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5nZXRXYXJuaW5nVGltZXIgPSBmdW5jdGlvbiBnZXRXYXJuaW5nVGltZXIodGltZSkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aW1lIC8gNjApICsgJ21uJyArIHRpbWUgJSA2MCArICdzJztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgb3ZlcmxheSBvZiB3YXJuaW5nIHN0YXRlXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnJlbW92ZVdhcm5pbmdTdGF0ZSA9IGZ1bmN0aW9uIHJlbW92ZVdhcm5pbmdTdGF0ZSgpIHtcbiAgICAgICAgdGhpcy5fcHlkaW8ubm90aWZ5KCdhY3Rpdml0eV9zdGF0ZV9jaGFuZ2UnLCB7XG4gICAgICAgICAgICBhY3RpdmVTdGF0ZTogJ2FjdGl2ZSdcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFV0aWxpdHkgdG8gZ2V0IHRoZSB0aW1lXG4gICAgICogQHJldHVybnMgSW50ZWdlclxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5nZXROb3cgPSBmdW5jdGlvbiBnZXROb3coKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gICAgfTtcblxuICAgIHJldHVybiBBY3Rpdml0eU1vbml0b3I7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBBY3Rpdml0eU1vbml0b3I7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqIFB1cmUgSmF2YXNjcmlwdCAoRVM2KSBDb29raWUgTWFuYWdlciBpbnNwaXJlZCBieSBDb29raWVKYXIgdGhhdCB3YXMgcmVseWluZyBvbiBQcm90b3R5cGVKUy5cbiAqXG4gKiAtLS0tXG4gKiBDb29raWVKQVIgT3JpZ2luYWwgSGVhZGVyXG4gKlxuICogSmF2YXNjcmlwdCBjb2RlIHRvIHN0b3JlIGRhdGEgYXMgSlNPTiBzdHJpbmdzIGluIGNvb2tpZXMuIFxuICogSXQgdXNlcyBwcm90b3R5cGUuanMgMS41LjEgKGh0dHA6Ly93d3cucHJvdG90eXBlanMub3JnKVxuICogXG4gKiBBdXRob3IgOiBMYWxpdCBQYXRlbFxuICogV2Vic2l0ZTogaHR0cDovL3d3dy5sYWxpdC5vcmcvbGFiL2pzb25jb29raWVzXG4gKiBMaWNlbnNlOiBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgMi41XG4gKiAgICAgICAgICBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8yLjUvXG4gKiBWZXJzaW9uOiAwLjRcbiAqIFVwZGF0ZWQ6IEF1ZyAxMSwgMjAwNyAxMDowOWFtXG4gKiBcbiAqIENobmFnZSBMb2c6XG4gKiAgIHYgMC40XG4gKiAgIC0gIFJlbW92ZWQgYSBleHRyYSBjb21tYSBpbiBvcHRpb25zICh3YXMgYnJlYWtpbmcgaW4gSUUgYW5kIE9wZXJhKS4gKFRoYW5rcyBKYXNvbilcbiAqICAgLSAgUmVtb3ZlZCB0aGUgcGFyYW1ldGVyIG5hbWUgZnJvbSB0aGUgaW5pdGlhbGl6ZSBmdW5jdGlvblxuICogICAtICBDaGFuZ2VkIHRoZSB3YXkgZXhwaXJlcyBkYXRlIHdhcyBiZWluZyBjYWxjdWxhdGVkLiAoVGhhbmtzIERhdmlkKVxuICogICB2IDAuM1xuICogICAtICBSZW1vdmVkIGRlcGVuZGFuY3kgb24ganNvbi5qcyAoaHR0cDovL3d3dy5qc29uLm9yZy9qc29uLmpzKVxuICogICAtICBlbXB0eSgpIGZ1bmN0aW9uIG9ubHkgZGVsZXRlcyB0aGUgY29va2llcyBzZXQgYnkgQ29va2llSmFyXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIENvb2tpZXNNYW5hZ2VyID0gKGZ1bmN0aW9uICgpIHtcblx0Q29va2llc01hbmFnZXIuc3VwcG9ydGVkID0gZnVuY3Rpb24gc3VwcG9ydGVkKCkge1xuXHRcdHJldHVybiBkb2N1bWVudCAmJiBkb2N1bWVudC5jb29raWUgIT09IHVuZGVmaW5lZDtcblx0fTtcblxuXHQvKipcbiAgKiBJbml0aWFsaXplcyB0aGUgY29va2llIGphciB3aXRoIHRoZSBvcHRpb25zLlxuICAqL1xuXG5cdGZ1bmN0aW9uIENvb2tpZXNNYW5hZ2VyKG9wdGlvbnMpIHtcblx0XHRfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29va2llc01hbmFnZXIpO1xuXG5cdFx0LyoqXG4gICAqIEFwcGVuZCBiZWZvcmUgYWxsIGNvb2tpZSBuYW1lcyB0byBkaWZmZXJudGlhdGUgdGhlbS5cbiAgICovXG5cdFx0dGhpcy5fYXBwZW5kU3RyaW5nID0gXCJfX1BZRElPX19cIjtcblxuXHRcdHRoaXMub3B0aW9ucyA9IHtcblx0XHRcdGV4cGlyZXM6IDM2MDAsIC8vIHNlY29uZHMgKDEgaHIpXG5cdFx0XHRwYXRoOiAnJywgLy8gY29va2llIHBhdGhcblx0XHRcdGRvbWFpbjogJycsIC8vIGNvb2tpZSBkb21haW5cblx0XHRcdHNlY3VyZTogJycgLy8gc2VjdXJlID9cblx0XHR9O1xuXHRcdHRoaXMub3B0aW9ucyA9IExhbmdVdGlscy5vYmplY3RNZXJnZSh0aGlzLm9wdGlvbnMsIG9wdGlvbnMgfHwge30pO1xuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5leHBpcmVzICE9ICcnKSB7XG5cdFx0XHR2YXIgZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0XHRkYXRlID0gbmV3IERhdGUoZGF0ZS5nZXRUaW1lKCkgKyB0aGlzLm9wdGlvbnMuZXhwaXJlcyAqIDEwMDApO1xuXHRcdFx0dGhpcy5vcHRpb25zLmV4cGlyZXMgPSAnOyBleHBpcmVzPScgKyBkYXRlLnRvR01UU3RyaW5nKCk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMucGF0aCAhPSAnJykge1xuXHRcdFx0dGhpcy5vcHRpb25zLnBhdGggPSAnOyBwYXRoPScgKyBlbmNvZGVVUkkodGhpcy5vcHRpb25zLnBhdGgpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLmRvbWFpbiAhPSAnJykge1xuXHRcdFx0dGhpcy5vcHRpb25zLmRvbWFpbiA9ICc7IGRvbWFpbj0nICsgZW5jb2RlVVJJKHRoaXMub3B0aW9ucy5kb21haW4pO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLnNlY3VyZSA9PSAnc2VjdXJlJykge1xuXHRcdFx0dGhpcy5vcHRpb25zLnNlY3VyZSA9ICc7IHNlY3VyZSc7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zZWN1cmUgPSAnJztcblx0XHR9XG5cdH1cblxuXHQvKipcbiAgKiBBZGRzIGEgbmFtZSB2YWx1ZXMgcGFpci5cbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUucHV0Q29va2llID0gZnVuY3Rpb24gcHV0Q29va2llKG5hbWUsIHZhbHVlKSB7XG5cdFx0bmFtZSA9IHRoaXMuX2FwcGVuZFN0cmluZyArIG5hbWU7XG5cdFx0dmFyIGNvb2tpZSA9IHRoaXMub3B0aW9ucztcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblx0XHRzd2l0Y2ggKHR5cGUpIHtcblx0XHRcdGNhc2UgJ3VuZGVmaW5lZCc6XG5cdFx0XHRjYXNlICdmdW5jdGlvbic6XG5cdFx0XHRjYXNlICd1bmtub3duJzpcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0Y2FzZSAnYm9vbGVhbic6XG5cdFx0XHRjYXNlICdzdHJpbmcnOlxuXHRcdFx0Y2FzZSAnbnVtYmVyJzpcblx0XHRcdFx0dmFsdWUgPSBTdHJpbmcodmFsdWUudG9TdHJpbmcoKSk7XG5cdFx0fVxuXHRcdHZhciBjb29raWVfc3RyID0gbmFtZSArIFwiPVwiICsgZW5jb2RlVVJJKEpTT04uc3RyaW5naWZ5KHZhbHVlKSk7XG5cdFx0dHJ5IHtcblx0XHRcdGRvY3VtZW50LmNvb2tpZSA9IGNvb2tpZV9zdHIgKyBjb29raWUuZXhwaXJlcyArIGNvb2tpZS5wYXRoICsgY29va2llLmRvbWFpbiArIGNvb2tpZS5zZWN1cmU7XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcblxuXHQvKipcbiAgKiBSZW1vdmVzIGEgcGFydGljdWxhciBjb29raWUgKG5hbWUgdmFsdWUgcGFpcikgZm9ybSB0aGUgQ29va2llIEphci5cbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUucmVtb3ZlQ29va2llID0gZnVuY3Rpb24gcmVtb3ZlQ29va2llKG5hbWUpIHtcblx0XHRuYW1lID0gdGhpcy5fYXBwZW5kU3RyaW5nICsgbmFtZTtcblx0XHR2YXIgY29va2llID0gdGhpcy5vcHRpb25zO1xuXHRcdHRyeSB7XG5cdFx0XHR2YXIgZGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0XHRkYXRlLnNldFRpbWUoZGF0ZS5nZXRUaW1lKCkgLSAzNjAwICogMTAwMCk7XG5cdFx0XHR2YXIgZXhwaXJlcyA9ICc7IGV4cGlyZXM9JyArIGRhdGUudG9HTVRTdHJpbmcoKTtcblx0XHRcdGRvY3VtZW50LmNvb2tpZSA9IG5hbWUgKyBcIj1cIiArIGV4cGlyZXMgKyBjb29raWUucGF0aCArIGNvb2tpZS5kb21haW4gKyBjb29raWUuc2VjdXJlO1xuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJuIGEgcGFydGljdWxhciBjb29raWUgYnkgbmFtZTtcbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUuZ2V0Q29va2llID0gZnVuY3Rpb24gZ2V0Q29va2llKG5hbWUpIHtcblx0XHRuYW1lID0gdGhpcy5fYXBwZW5kU3RyaW5nICsgbmFtZTtcblx0XHR2YXIgY29va2llcyA9IGRvY3VtZW50LmNvb2tpZS5tYXRjaChuYW1lICsgJz0oLio/KSg7fCQpJyk7XG5cdFx0aWYgKGNvb2tpZXMpIHtcblx0XHRcdHJldHVybiBKU09OLnBhcnNlKGRlY29kZVVSSShjb29raWVzWzFdKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBFbXB0aWVzIHRoZSBDb29raWUgSmFyLiBEZWxldGVzIGFsbCB0aGUgY29va2llcy5cbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUuZW1wdHlBbGwgPSBmdW5jdGlvbiBlbXB0eUFsbCgpIHtcblx0XHR2YXIga2V5cyA9IHRoaXMuZ2V0S2V5cygpO1xuXHRcdHZhciBzaXplID0ga2V5cy5zaXplKCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcblx0XHRcdHRoaXMucmVtb3ZlQ29va2llKGtleXNbaV0pO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm5zIGFsbCBjb29raWVzIGFzIGEgc2luZ2xlIG9iamVjdFxuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5nZXRQYWNrID0gZnVuY3Rpb24gZ2V0UGFjaygpIHtcblx0XHR2YXIgcGFjayA9IHt9O1xuXHRcdHZhciBrZXlzID0gdGhpcy5nZXRLZXlzKCk7XG5cblx0XHR2YXIgc2l6ZSA9IGtleXMuc2l6ZSgpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG5cdFx0XHRwYWNrW2tleXNbaV1dID0gdGhpcy5nZXQoa2V5c1tpXSk7XG5cdFx0fVxuXHRcdHJldHVybiBwYWNrO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybnMgYWxsIGtleXMuXG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLmdldEtleXMgPSBmdW5jdGlvbiBnZXRLZXlzKCkge1xuXHRcdHZhciBrZXlzID0gW107XG5cdFx0dmFyIGtleVJlID0gL1tePTsgXSsoPz1cXD0pL2c7XG5cdFx0dmFyIHN0ciA9IGRvY3VtZW50LmNvb2tpZTtcblx0XHR2YXIgQ0pSZSA9IG5ldyBSZWdFeHAoXCJeXCIgKyB0aGlzLl9hcHBlbmRTdHJpbmcpO1xuXHRcdHZhciBtYXRjaDtcblx0XHR3aGlsZSAoKG1hdGNoID0ga2V5UmUuZXhlYyhzdHIpKSAhPSB1bmRlZmluZWQpIHtcblx0XHRcdGlmIChDSlJlLnRlc3QobWF0Y2hbMF0uc3RyaXAoKSkpIHtcblx0XHRcdFx0a2V5cy5wdXNoKG1hdGNoWzBdLnN0cmlwKCkuZ3N1YihcIl5cIiArIHRoaXMuX2FwcGVuZFN0cmluZywgXCJcIikpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4ga2V5cztcblx0fTtcblxuXHRyZXR1cm4gQ29va2llc01hbmFnZXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBDb29raWVzTWFuYWdlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgbGFuZ3VhZ2Ugc3BlY2lmaWMgbWV0aG9kc1xuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgRE9NVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERPTVV0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRE9NVXRpbHMpO1xuICAgIH1cblxuICAgIERPTVV0aWxzLmdldEJlemllcnNUcmFuc2l0aW9uID0gZnVuY3Rpb24gZ2V0QmV6aWVyc1RyYW5zaXRpb24oKSB7XG4gICAgICAgIHJldHVybiAnYWxsIDU1MG1zIGN1YmljLWJlemllcigwLjIzLCAxLCAwLjMyLCAxKSAwbXMnO1xuICAgIH07XG5cbiAgICBET01VdGlscy5nZXRCb3hTaGFkb3dEZXB0aCA9IGZ1bmN0aW9uIGdldEJveFNoYWRvd0RlcHRoKCkge1xuICAgICAgICB2YXIgZGVwdGggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyAxIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICAgIHJldHVybiAnMCAzcHggNnB4IHJnYmEoMCwgMCwgMCwgMC4xNiksIDAgM3B4IDZweCByZ2JhKDAsIDAsIDAsIDAuMjMpJztcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuZ2V0VXJsRnJvbUJhc2UgPSBmdW5jdGlvbiBnZXRVcmxGcm9tQmFzZSgpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdiYXNlJykubGVuZ3RoID8gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2Jhc2UnKVswXS5ocmVmIDogJyc7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLmdldFZpZXdwb3J0V2lkdGggPSBmdW5jdGlvbiBnZXRWaWV3cG9ydFdpZHRoKCkge1xuICAgICAgICByZXR1cm4gd2luZG93LmlubmVyV2lkdGggfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoIHx8IGRvY3VtZW50LmJvZHkuY2xpZW50V2lkdGg7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLmdldFZpZXdwb3J0SGVpZ2h0ID0gZnVuY3Rpb24gZ2V0Vmlld3BvcnRIZWlnaHQoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCB8fCBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDtcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuaW1hZ2VMb2FkZXIgPSBmdW5jdGlvbiBpbWFnZUxvYWRlcihpbWFnZVVybCwgb25Mb2FkLCBvbkVycm9yKSB7XG4gICAgICAgIHZhciBsb2FkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICAgICAgbG9hZGVyLm9ubG9hZCA9IG9uTG9hZC5iaW5kKGxvYWRlcik7XG4gICAgICAgIGxvYWRlci5vbmVycm9yID0gb25FcnJvci5iaW5kKGxvYWRlcik7XG4gICAgICAgIGxvYWRlci5zcmMgPSBpbWFnZVVybDtcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMub2JzZXJ2ZVdpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uIG9ic2VydmVXaW5kb3dSZXNpemUoY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmF0dGFjaEV2ZW50KCdvbnJlc2l6ZScsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBET01VdGlscy5zdG9wT2JzZXJ2aW5nV2luZG93UmVzaXplID0gZnVuY3Rpb24gc3RvcE9ic2VydmluZ1dpbmRvd1Jlc2l6ZShjYWxsYmFjaykge1xuICAgICAgICBpZiAod2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCBjYWxsYmFjayk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aW5kb3cuZGV0YWNoRXZlbnQoJ29ucmVzaXplJywgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBET01VdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IERPTVV0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBsYW5ndWFnZSBzcGVjaWZpYyBtZXRob2RzXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgRnVuY1V0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBGdW5jVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGdW5jVXRpbHMpO1xuICAgIH1cblxuICAgIEZ1bmNVdGlscy5FbXB0eSA9IGZ1bmN0aW9uIEVtcHR5KCkge307XG5cbiAgICBGdW5jVXRpbHMuSWRlbnRpdHkgPSBmdW5jdGlvbiBJZGVudGl0eShvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9O1xuXG4gICAgRnVuY1V0aWxzLmV4ZWN1dGVGdW5jdGlvbkJ5TmFtZSA9IGZ1bmN0aW9uIGV4ZWN1dGVGdW5jdGlvbkJ5TmFtZShmdW5jdGlvbk5hbWUsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICB2YXIgbmFtZXNwYWNlcyA9IGZ1bmN0aW9uTmFtZS5zcGxpdChcIi5cIik7XG4gICAgICAgIHZhciBmdW5jID0gbmFtZXNwYWNlcy5wb3AoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lc3BhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb250ZXh0ID0gY29udGV4dFtuYW1lc3BhY2VzW2ldXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29udGV4dFtmdW5jXS5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgRnVuY1V0aWxzLmdldEZ1bmN0aW9uQnlOYW1lID0gZnVuY3Rpb24gZ2V0RnVuY3Rpb25CeU5hbWUoZnVuY3Rpb25OYW1lLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICAgICAgdmFyIG5hbWVzcGFjZXMgPSBmdW5jdGlvbk5hbWUuc3BsaXQoXCIuXCIpO1xuICAgICAgICB2YXIgZnVuYyA9IG5hbWVzcGFjZXMucG9wKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXNwYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKCFjb250ZXh0W25hbWVzcGFjZXNbaV1dKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250ZXh0ID0gY29udGV4dFtuYW1lc3BhY2VzW2ldXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29udGV4dFtmdW5jXTtcbiAgICB9O1xuXG4gICAgRnVuY1V0aWxzLmJ1ZmZlckNhbGxiYWNrID0gZnVuY3Rpb24gYnVmZmVyQ2FsbGJhY2sobmFtZSwgdGltZSwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHdpbmRvd1tuYW1lXSkge1xuICAgICAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh3aW5kb3dbbmFtZV0pO1xuICAgICAgICB9XG4gICAgICAgIHdpbmRvd1tuYW1lXSA9IHdpbmRvdy5zZXRUaW1lb3V0KGNhbGxiYWNrLCB0aW1lKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIEZ1bmNVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gRnVuY1V0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzW1wiZGVmYXVsdFwiXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIGhhc2hpbmcgbWV0aG9kc1xuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgSGFzaGVyVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuXG4gICAgLypcbiAgICAgKiBBIEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgdGhlIFJTQSBEYXRhIFNlY3VyaXR5LCBJbmMuIE1ENSBNZXNzYWdlXG4gICAgICogRGlnZXN0IEFsZ29yaXRobSwgYXMgZGVmaW5lZCBpbiBSRkMgMTMyMS5cbiAgICAgKiBWZXJzaW9uIDIuMSBDb3B5cmlnaHQgKEMpIFBhdWwgSm9obnN0b24gMTk5OSAtIDIwMDIuXG4gICAgICogT3RoZXIgY29udHJpYnV0b3JzOiBHcmVnIEhvbHQsIEFuZHJldyBLZXBlcnQsIFlkbmFyLCBMb3N0aW5ldFxuICAgICAqIERpc3RyaWJ1dGVkIHVuZGVyIHRoZSBCU0QgTGljZW5zZVxuICAgICAqIFNlZSBodHRwOi8vcGFqaG9tZS5vcmcudWsvY3J5cHQvbWQ1IGZvciBtb3JlIGluZm8uXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBIYXNoZXJVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEhhc2hlclV0aWxzKTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIENvbmZpZ3VyYWJsZSB2YXJpYWJsZXMuIFlvdSBtYXkgbmVlZCB0byB0d2VhayB0aGVzZSB0byBiZSBjb21wYXRpYmxlIHdpdGhcbiAgICAgKiB0aGUgc2VydmVyLXNpZGUsIGJ1dCB0aGUgZGVmYXVsdHMgd29yayBpbiBtb3N0IGNhc2VzLlxuICAgICAqL1xuXG4gICAgLypcbiAgICAgKiBUaGVzZSBhcmUgdGhlIGZ1bmN0aW9ucyB5b3UnbGwgdXN1YWxseSB3YW50IHRvIGNhbGxcbiAgICAgKiBUaGV5IHRha2Ugc3RyaW5nIGFyZ3VtZW50cyBhbmQgcmV0dXJuIGVpdGhlciBoZXggb3IgYmFzZS02NCBlbmNvZGVkIHN0cmluZ3NcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmhleF9tZDUgPSBmdW5jdGlvbiBoZXhfbWQ1KHMpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyaGV4KEhhc2hlclV0aWxzLmNvcmVfbWQ1KEhhc2hlclV0aWxzLnN0cjJiaW5sKHMpLCBzLmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6KSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLmI2NF9tZDUgPSBmdW5jdGlvbiBiNjRfbWQ1KHMpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyYjY0KEhhc2hlclV0aWxzLmNvcmVfbWQ1KEhhc2hlclV0aWxzLnN0cjJiaW5sKHMpLCBzLmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6KSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLnN0cl9tZDUgPSBmdW5jdGlvbiBzdHJfbWQ1KHMpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyc3RyKEhhc2hlclV0aWxzLmNvcmVfbWQ1KEhhc2hlclV0aWxzLnN0cjJiaW5sKHMpLCBzLmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6KSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLmhleF9obWFjX21kNSA9IGZ1bmN0aW9uIGhleF9obWFjX21kNShrZXksIGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyaGV4KEhhc2hlclV0aWxzLmNvcmVfaG1hY19tZDUoa2V5LCBkYXRhKSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLmI2NF9obWFjX21kNSA9IGZ1bmN0aW9uIGI2NF9obWFjX21kNShrZXksIGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyYjY0KEhhc2hlclV0aWxzLmNvcmVfaG1hY19tZDUoa2V5LCBkYXRhKSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLnN0cl9obWFjX21kNSA9IGZ1bmN0aW9uIHN0cl9obWFjX21kNShrZXksIGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmJpbmwyc3RyKEhhc2hlclV0aWxzLmNvcmVfaG1hY19tZDUoa2V5LCBkYXRhKSk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLmJhc2U2NF9lbmNvZGUgPSBmdW5jdGlvbiBiYXNlNjRfZW5jb2RlKGRhdGEpIHtcbiAgICAgICAgLy8gaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXRcbiAgICAgICAgLy8gKyAgIG9yaWdpbmFsIGJ5OiBUeWxlciBBa2lucyAoaHR0cDovL3J1bWtpbi5jb20pXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogQmF5cm9uIEd1ZXZhcmFcbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBUaHVuZGVyLm1cbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBLZXZpbiB2YW4gWm9ubmV2ZWxkIChodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldClcbiAgICAgICAgLy8gKyAgIGJ1Z2ZpeGVkIGJ5OiBQZWxsZW50ZXNxdWUgTWFsZXN1YWRhXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogS2V2aW4gdmFuIFpvbm5ldmVsZCAoaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXQpXG4gICAgICAgIC8vIC0gICAgZGVwZW5kcyBvbjogdXRmOF9lbmNvZGVcbiAgICAgICAgLy8gKiAgICAgZXhhbXBsZSAxOiBiYXNlNjRfZW5jb2RlKCdLZXZpbiB2YW4gWm9ubmV2ZWxkJyk7XG4gICAgICAgIC8vICogICAgIHJldHVybnMgMTogJ1MyVjJhVzRnZG1GdUlGcHZibTVsZG1Wc1pBPT0nXG5cbiAgICAgICAgLy8gbW96aWxsYSBoYXMgdGhpcyBuYXRpdmVcbiAgICAgICAgLy8gLSBidXQgYnJlYWtzIGluIDIuMC4wLjEyIVxuICAgICAgICAvL2lmICh0eXBlb2Ygd2luZG93WydhdG9iJ10gPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyAgICByZXR1cm4gYXRvYihkYXRhKTtcbiAgICAgICAgLy99XG5cbiAgICAgICAgdmFyIGI2NCA9IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLz1cIjtcbiAgICAgICAgdmFyIG8xLFxuICAgICAgICAgICAgbzIsXG4gICAgICAgICAgICBvMyxcbiAgICAgICAgICAgIGgxLFxuICAgICAgICAgICAgaDIsXG4gICAgICAgICAgICBoMyxcbiAgICAgICAgICAgIGg0LFxuICAgICAgICAgICAgYml0cyxcbiAgICAgICAgICAgIGkgPSAwLFxuICAgICAgICAgICAgYWMgPSAwLFxuICAgICAgICAgICAgZW5jLFxuICAgICAgICAgICAgdG1wX2FyciA9IFtdO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRhID0gSGFzaGVyVXRpbHMudXRmOF9lbmNvZGUoZGF0YSArICcnKTtcblxuICAgICAgICBkbyB7XG4gICAgICAgICAgICAvLyBwYWNrIHRocmVlIG9jdGV0cyBpbnRvIGZvdXIgaGV4ZXRzXG4gICAgICAgICAgICBvMSA9IGRhdGEuY2hhckNvZGVBdChpKyspO1xuICAgICAgICAgICAgbzIgPSBkYXRhLmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgICAgICAgIG8zID0gZGF0YS5jaGFyQ29kZUF0KGkrKyk7XG5cbiAgICAgICAgICAgIGJpdHMgPSBvMSA8PCAxNiB8IG8yIDw8IDggfCBvMztcblxuICAgICAgICAgICAgaDEgPSBiaXRzID4+IDE4ICYgMHgzZjtcbiAgICAgICAgICAgIGgyID0gYml0cyA+PiAxMiAmIDB4M2Y7XG4gICAgICAgICAgICBoMyA9IGJpdHMgPj4gNiAmIDB4M2Y7XG4gICAgICAgICAgICBoNCA9IGJpdHMgJiAweDNmO1xuXG4gICAgICAgICAgICAvLyB1c2UgaGV4ZXRzIHRvIGluZGV4IGludG8gYjY0LCBhbmQgYXBwZW5kIHJlc3VsdCB0byBlbmNvZGVkIHN0cmluZ1xuICAgICAgICAgICAgdG1wX2FyclthYysrXSA9IGI2NC5jaGFyQXQoaDEpICsgYjY0LmNoYXJBdChoMikgKyBiNjQuY2hhckF0KGgzKSArIGI2NC5jaGFyQXQoaDQpO1xuICAgICAgICB9IHdoaWxlIChpIDwgZGF0YS5sZW5ndGgpO1xuXG4gICAgICAgIGVuYyA9IHRtcF9hcnIuam9pbignJyk7XG5cbiAgICAgICAgc3dpdGNoIChkYXRhLmxlbmd0aCAlIDMpIHtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBlbmMgPSBlbmMuc2xpY2UoMCwgLTIpICsgJz09JztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBlbmMgPSBlbmMuc2xpY2UoMCwgLTEpICsgJz0nO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVuYztcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMudXRmOF9lbmNvZGUgPSBmdW5jdGlvbiB1dGY4X2VuY29kZShzdHJpbmcpIHtcbiAgICAgICAgLy8gaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXRcbiAgICAgICAgLy8gKyAgIG9yaWdpbmFsIGJ5OiBXZWJ0b29sa2l0LmluZm8gKGh0dHA6Ly93d3cud2VidG9vbGtpdC5pbmZvLylcbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBLZXZpbiB2YW4gWm9ubmV2ZWxkIChodHRwOi8va2V2aW4udmFuem9ubmV2ZWxkLm5ldClcbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBzb3diZXJyeVxuICAgICAgICAvLyArICAgIHR3ZWFrZWQgYnk6IEphY2tcbiAgICAgICAgLy8gKyAgIGJ1Z2ZpeGVkIGJ5OiBPbm5vIE1hcnNtYW5cbiAgICAgICAgLy8gKyAgIGltcHJvdmVkIGJ5OiBZdmVzIFN1Y2FldFxuICAgICAgICAvLyArICAgYnVnZml4ZWQgYnk6IE9ubm8gTWFyc21hblxuICAgICAgICAvLyAqICAgICBleGFtcGxlIDE6IHV0ZjhfZW5jb2RlKCdLZXZpbiB2YW4gWm9ubmV2ZWxkJyk7XG4gICAgICAgIC8vICogICAgIHJldHVybnMgMTogJ0tldmluIHZhbiBab25uZXZlbGQnXG5cbiAgICAgICAgc3RyaW5nID0gKHN0cmluZyArICcnKS5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxyL2csIFwiXFxuXCIpO1xuXG4gICAgICAgIHZhciB1dGZ0ZXh0ID0gXCJcIjtcbiAgICAgICAgdmFyIHN0YXJ0LCBlbmQ7XG4gICAgICAgIHZhciBzdHJpbmdsO1xuXG4gICAgICAgIHN0YXJ0ID0gZW5kID0gMDtcbiAgICAgICAgc3RyaW5nbCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIG4gPSAwOyBuIDwgc3RyaW5nbDsgbisrKSB7XG4gICAgICAgICAgICB2YXIgYzEgPSBzdHJpbmcuY2hhckNvZGVBdChuKTtcbiAgICAgICAgICAgIHZhciBlbmMgPSBudWxsO1xuXG4gICAgICAgICAgICBpZiAoYzEgPCAxMjgpIHtcbiAgICAgICAgICAgICAgICBlbmQrKztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYzEgPiAxMjcgJiYgYzEgPCAyMDQ4KSB7XG4gICAgICAgICAgICAgICAgZW5jID0gU3RyaW5nLmZyb21DaGFyQ29kZShjMSA+PiA2IHwgMTkyKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYzEgJiA2MyB8IDEyOCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuYyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYzEgPj4gMTIgfCAyMjQpICsgU3RyaW5nLmZyb21DaGFyQ29kZShjMSA+PiA2ICYgNjMgfCAxMjgpICsgU3RyaW5nLmZyb21DaGFyQ29kZShjMSAmIDYzIHwgMTI4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbmMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmIChlbmQgPiBzdGFydCkge1xuICAgICAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IHN0cmluZy5zdWJzdHJpbmcoc3RhcnQsIGVuZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHV0ZnRleHQgKz0gZW5jO1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gZW5kID0gbiArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZW5kID4gc3RhcnQpIHtcbiAgICAgICAgICAgIHV0ZnRleHQgKz0gc3RyaW5nLnN1YnN0cmluZyhzdGFydCwgc3RyaW5nLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdXRmdGV4dDtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBQZXJmb3JtIGEgc2ltcGxlIHNlbGYtdGVzdCB0byBzZWUgaWYgdGhlIFZNIGlzIHdvcmtpbmdcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLm1kNV92bV90ZXN0ID0gZnVuY3Rpb24gbWQ1X3ZtX3Rlc3QoKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5oZXhfbWQ1KFwiYWJjXCIpID09IFwiOTAwMTUwOTgzY2QyNGZiMGQ2OTYzZjdkMjhlMTdmNzJcIjtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDYWxjdWxhdGUgdGhlIE1ENSBvZiBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzLCBhbmQgYSBiaXQgbGVuZ3RoXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5jb3JlX21kNSA9IGZ1bmN0aW9uIGNvcmVfbWQ1KHgsIGxlbikge1xuICAgICAgICAvKiBhcHBlbmQgcGFkZGluZyAqL1xuICAgICAgICB4W2xlbiA+PiA1XSB8PSAweDgwIDw8IGxlbiAlIDMyO1xuICAgICAgICB4WyhsZW4gKyA2NCA+Pj4gOSA8PCA0KSArIDE0XSA9IGxlbjtcblxuICAgICAgICB2YXIgYSA9IDE3MzI1ODQxOTM7XG4gICAgICAgIHZhciBiID0gLTI3MTczMzg3OTtcbiAgICAgICAgdmFyIGMgPSAtMTczMjU4NDE5NDtcbiAgICAgICAgdmFyIGQgPSAyNzE3MzM4Nzg7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSArPSAxNikge1xuICAgICAgICAgICAgdmFyIG9sZGEgPSBhO1xuICAgICAgICAgICAgdmFyIG9sZGIgPSBiO1xuICAgICAgICAgICAgdmFyIG9sZGMgPSBjO1xuICAgICAgICAgICAgdmFyIG9sZGQgPSBkO1xuXG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGEsIGIsIGMsIGQsIHhbaSArIDBdLCA3LCAtNjgwODc2OTM2KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZmYoZCwgYSwgYiwgYywgeFtpICsgMV0sIDEyLCAtMzg5NTY0NTg2KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZmYoYywgZCwgYSwgYiwgeFtpICsgMl0sIDE3LCA2MDYxMDU4MTkpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9mZihiLCBjLCBkLCBhLCB4W2kgKyAzXSwgMjIsIC0xMDQ0NTI1MzMwKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZmYoYSwgYiwgYywgZCwgeFtpICsgNF0sIDcsIC0xNzY0MTg4OTcpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9mZihkLCBhLCBiLCBjLCB4W2kgKyA1XSwgMTIsIDEyMDAwODA0MjYpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9mZihjLCBkLCBhLCBiLCB4W2kgKyA2XSwgMTcsIC0xNDczMjMxMzQxKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZmYoYiwgYywgZCwgYSwgeFtpICsgN10sIDIyLCAtNDU3MDU5ODMpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9mZihhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNywgMTc3MDAzNTQxNik7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGQsIGEsIGIsIGMsIHhbaSArIDldLCAxMiwgLTE5NTg0MTQ0MTcpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9mZihjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE3LCAtNDIwNjMpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9mZihiLCBjLCBkLCBhLCB4W2kgKyAxMV0sIDIyLCAtMTk5MDQwNDE2Mik7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNywgMTgwNDYwMzY4Mik7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGQsIGEsIGIsIGMsIHhbaSArIDEzXSwgMTIsIC00MDM0MTEwMSk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGMsIGQsIGEsIGIsIHhbaSArIDE0XSwgMTcsIC0xNTAyMDAyMjkwKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZmYoYiwgYywgZCwgYSwgeFtpICsgMTVdLCAyMiwgMTIzNjUzNTMyOSk7XG5cbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZ2coYSwgYiwgYywgZCwgeFtpICsgMV0sIDUsIC0xNjU3OTY1MTApO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9nZyhkLCBhLCBiLCBjLCB4W2kgKyA2XSwgOSwgLTEwNjk1MDE2MzIpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9nZyhjLCBkLCBhLCBiLCB4W2kgKyAxMV0sIDE0LCA2NDM3MTc3MTMpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9nZyhiLCBjLCBkLCBhLCB4W2kgKyAwXSwgMjAsIC0zNzM4OTczMDIpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9nZyhhLCBiLCBjLCBkLCB4W2kgKyA1XSwgNSwgLTcwMTU1ODY5MSk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2dnKGQsIGEsIGIsIGMsIHhbaSArIDEwXSwgOSwgMzgwMTYwODMpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9nZyhjLCBkLCBhLCBiLCB4W2kgKyAxNV0sIDE0LCAtNjYwNDc4MzM1KTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZ2coYiwgYywgZCwgYSwgeFtpICsgNF0sIDIwLCAtNDA1NTM3ODQ4KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZ2coYSwgYiwgYywgZCwgeFtpICsgOV0sIDUsIDU2ODQ0NjQzOCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2dnKGQsIGEsIGIsIGMsIHhbaSArIDE0XSwgOSwgLTEwMTk4MDM2OTApO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9nZyhjLCBkLCBhLCBiLCB4W2kgKyAzXSwgMTQsIC0xODczNjM5NjEpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9nZyhiLCBjLCBkLCBhLCB4W2kgKyA4XSwgMjAsIDExNjM1MzE1MDEpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9nZyhhLCBiLCBjLCBkLCB4W2kgKyAxM10sIDUsIC0xNDQ0NjgxNDY3KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZ2coZCwgYSwgYiwgYywgeFtpICsgMl0sIDksIC01MTQwMzc4NCk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2dnKGMsIGQsIGEsIGIsIHhbaSArIDddLCAxNCwgMTczNTMyODQ3Myk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2dnKGIsIGMsIGQsIGEsIHhbaSArIDEyXSwgMjAsIC0xOTI2NjA3NzM0KTtcblxuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9oaChhLCBiLCBjLCBkLCB4W2kgKyA1XSwgNCwgLTM3ODU1OCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2hoKGQsIGEsIGIsIGMsIHhbaSArIDhdLCAxMSwgLTIwMjI1NzQ0NjMpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9oaChjLCBkLCBhLCBiLCB4W2kgKyAxMV0sIDE2LCAxODM5MDMwNTYyKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaGgoYiwgYywgZCwgYSwgeFtpICsgMTRdLCAyMywgLTM1MzA5NTU2KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaGgoYSwgYiwgYywgZCwgeFtpICsgMV0sIDQsIC0xNTMwOTkyMDYwKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaGgoZCwgYSwgYiwgYywgeFtpICsgNF0sIDExLCAxMjcyODkzMzUzKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaGgoYywgZCwgYSwgYiwgeFtpICsgN10sIDE2LCAtMTU1NDk3NjMyKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaGgoYiwgYywgZCwgYSwgeFtpICsgMTBdLCAyMywgLTEwOTQ3MzA2NDApO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9oaChhLCBiLCBjLCBkLCB4W2kgKyAxM10sIDQsIDY4MTI3OTE3NCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2hoKGQsIGEsIGIsIGMsIHhbaSArIDBdLCAxMSwgLTM1ODUzNzIyMik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2hoKGMsIGQsIGEsIGIsIHhbaSArIDNdLCAxNiwgLTcyMjUyMTk3OSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2hoKGIsIGMsIGQsIGEsIHhbaSArIDZdLCAyMywgNzYwMjkxODkpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9oaChhLCBiLCBjLCBkLCB4W2kgKyA5XSwgNCwgLTY0MDM2NDQ4Nyk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2hoKGQsIGEsIGIsIGMsIHhbaSArIDEyXSwgMTEsIC00MjE4MTU4MzUpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9oaChjLCBkLCBhLCBiLCB4W2kgKyAxNV0sIDE2LCA1MzA3NDI1MjApO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9oaChiLCBjLCBkLCBhLCB4W2kgKyAyXSwgMjMsIC05OTUzMzg2NTEpO1xuXG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2lpKGEsIGIsIGMsIGQsIHhbaSArIDBdLCA2LCAtMTk4NjMwODQ0KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaWkoZCwgYSwgYiwgYywgeFtpICsgN10sIDEwLCAxMTI2ODkxNDE1KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaWkoYywgZCwgYSwgYiwgeFtpICsgMTRdLCAxNSwgLTE0MTYzNTQ5MDUpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9paShiLCBjLCBkLCBhLCB4W2kgKyA1XSwgMjEsIC01NzQzNDA1NSk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2lpKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNiwgMTcwMDQ4NTU3MSk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2lpKGQsIGEsIGIsIGMsIHhbaSArIDNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9paShjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE1LCAtMTA1MTUyMyk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2lpKGIsIGMsIGQsIGEsIHhbaSArIDFdLCAyMSwgLTIwNTQ5MjI3OTkpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9paShhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNiwgMTg3MzMxMzM1OSk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2lpKGQsIGEsIGIsIGMsIHhbaSArIDE1XSwgMTAsIC0zMDYxMTc0NCk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2lpKGMsIGQsIGEsIGIsIHhbaSArIDZdLCAxNSwgLTE1NjAxOTgzODApO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9paShiLCBjLCBkLCBhLCB4W2kgKyAxM10sIDIxLCAxMzA5MTUxNjQ5KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaWkoYSwgYiwgYywgZCwgeFtpICsgNF0sIDYsIC0xNDU1MjMwNzApO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9paShkLCBhLCBiLCBjLCB4W2kgKyAxMV0sIDEwLCAtMTEyMDIxMDM3OSk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2lpKGMsIGQsIGEsIGIsIHhbaSArIDJdLCAxNSwgNzE4Nzg3MjU5KTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaWkoYiwgYywgZCwgYSwgeFtpICsgOV0sIDIxLCAtMzQzNDg1NTUxKTtcblxuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLnNhZmVfYWRkKGEsIG9sZGEpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLnNhZmVfYWRkKGIsIG9sZGIpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLnNhZmVfYWRkKGMsIG9sZGMpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLnNhZmVfYWRkKGQsIG9sZGQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbYSwgYiwgYywgZF07XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogVGhlc2UgZnVuY3Rpb25zIGltcGxlbWVudCB0aGUgZm91ciBiYXNpYyBvcGVyYXRpb25zIHRoZSBhbGdvcml0aG0gdXNlcy5cbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLm1kNV9jbW4gPSBmdW5jdGlvbiBtZDVfY21uKHEsIGEsIGIsIHgsIHMsIHQpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLnNhZmVfYWRkKEhhc2hlclV0aWxzLmJpdF9yb2woSGFzaGVyVXRpbHMuc2FmZV9hZGQoSGFzaGVyVXRpbHMuc2FmZV9hZGQoYSwgcSksIEhhc2hlclV0aWxzLnNhZmVfYWRkKHgsIHQpKSwgcyksIGIpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5tZDVfZmYgPSBmdW5jdGlvbiBtZDVfZmYoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMubWQ1X2NtbihiICYgYyB8IH5iICYgZCwgYSwgYiwgeCwgcywgdCk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLm1kNV9nZyA9IGZ1bmN0aW9uIG1kNV9nZyhhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5tZDVfY21uKGIgJiBkIHwgYyAmIH5kLCBhLCBiLCB4LCBzLCB0KTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X2hoID0gZnVuY3Rpb24gbWQ1X2hoKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLm1kNV9jbW4oYiBeIGMgXiBkLCBhLCBiLCB4LCBzLCB0KTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X2lpID0gZnVuY3Rpb24gbWQ1X2lpKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLm1kNV9jbW4oYyBeIChiIHwgfmQpLCBhLCBiLCB4LCBzLCB0KTtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDYWxjdWxhdGUgdGhlIEhNQUMtTUQ1LCBvZiBhIGtleSBhbmQgc29tZSBkYXRhXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5jb3JlX2htYWNfbWQ1ID0gZnVuY3Rpb24gY29yZV9obWFjX21kNShrZXksIGRhdGEpIHtcbiAgICAgICAgdmFyIGJrZXkgPSBIYXNoZXJVdGlscy5zdHIyYmlubChrZXkpO1xuICAgICAgICBpZiAoYmtleS5sZW5ndGggPiAxNikgYmtleSA9IEhhc2hlclV0aWxzLmNvcmVfbWQ1KGJrZXksIGtleS5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzeik7XG5cbiAgICAgICAgdmFyIGlwYWQgPSBuZXcgQXJyYXkoMTYpLFxuICAgICAgICAgICAgb3BhZCA9IG5ldyBBcnJheSgxNik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICAgICAgaXBhZFtpXSA9IGJrZXlbaV0gXiAweDM2MzYzNjM2O1xuICAgICAgICAgICAgb3BhZFtpXSA9IGJrZXlbaV0gXiAweDVDNUM1QzVDO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGhhc2ggPSBIYXNoZXJVdGlscy5jb3JlX21kNShpcGFkLmNvbmNhdChIYXNoZXJVdGlscy5zdHIyYmlubChkYXRhKSksIDUxMiArIGRhdGEubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3opO1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuY29yZV9tZDUob3BhZC5jb25jYXQoaGFzaCksIDUxMiArIDEyOCk7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQWRkIGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjMyLiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnMgaW50ZXJuYWxseVxuICAgICAqIHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5zYWZlX2FkZCA9IGZ1bmN0aW9uIHNhZmVfYWRkKHgsIHkpIHtcbiAgICAgICAgdmFyIGxzdyA9ICh4ICYgMHhGRkZGKSArICh5ICYgMHhGRkZGKTtcbiAgICAgICAgdmFyIG1zdyA9ICh4ID4+IDE2KSArICh5ID4+IDE2KSArIChsc3cgPj4gMTYpO1xuICAgICAgICByZXR1cm4gbXN3IDw8IDE2IHwgbHN3ICYgMHhGRkZGO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIEJpdHdpc2Ugcm90YXRlIGEgMzItYml0IG51bWJlciB0byB0aGUgbGVmdC5cbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmJpdF9yb2wgPSBmdW5jdGlvbiBiaXRfcm9sKG51bSwgY250KSB7XG4gICAgICAgIHJldHVybiBudW0gPDwgY250IHwgbnVtID4+PiAzMiAtIGNudDtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHNcbiAgICAgKiBJZiBIYXNoZXJVdGlscy5jaHJzeiBpcyBBU0NJSSwgY2hhcmFjdGVycyA+MjU1IGhhdmUgdGhlaXIgaGktYnl0ZSBzaWxlbnRseSBpZ25vcmVkLlxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuc3RyMmJpbmwgPSBmdW5jdGlvbiBzdHIyYmlubChzdHIpIHtcbiAgICAgICAgdmFyIGJpbiA9IFtdO1xuICAgICAgICB2YXIgbWFzayA9ICgxIDw8IEhhc2hlclV0aWxzLmNocnN6KSAtIDE7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6OyBpICs9IEhhc2hlclV0aWxzLmNocnN6KSBiaW5baSA+PiA1XSB8PSAoc3RyLmNoYXJDb2RlQXQoaSAvIEhhc2hlclV0aWxzLmNocnN6KSAmIG1hc2spIDw8IGkgJSAzMjtcbiAgICAgICAgcmV0dXJuIGJpbjtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMgdG8gYSBzdHJpbmdcbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmJpbmwyc3RyID0gZnVuY3Rpb24gYmlubDJzdHIoYmluKSB7XG4gICAgICAgIHZhciBzdHIgPSBcIlwiO1xuICAgICAgICB2YXIgbWFzayA9ICgxIDw8IEhhc2hlclV0aWxzLmNocnN6KSAtIDE7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmluLmxlbmd0aCAqIDMyOyBpICs9IEhhc2hlclV0aWxzLmNocnN6KSBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShiaW5baSA+PiA1XSA+Pj4gaSAlIDMyICYgbWFzayk7XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzIHRvIGEgaGV4IHN0cmluZy5cbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLmJpbmwyaGV4ID0gZnVuY3Rpb24gYmlubDJoZXgoYmluYXJyYXkpIHtcbiAgICAgICAgdmFyIGhleF90YWIgPSBIYXNoZXJVdGlscy5oZXhjYXNlID8gXCIwMTIzNDU2Nzg5QUJDREVGXCIgOiBcIjAxMjM0NTY3ODlhYmNkZWZcIjtcbiAgICAgICAgdmFyIHN0ciA9IFwiXCI7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmluYXJyYXkubGVuZ3RoICogNDsgaSsrKSB7XG4gICAgICAgICAgICBzdHIgKz0gaGV4X3RhYi5jaGFyQXQoYmluYXJyYXlbaSA+PiAyXSA+PiBpICUgNCAqIDggKyA0ICYgMHhGKSArIGhleF90YWIuY2hhckF0KGJpbmFycmF5W2kgPj4gMl0gPj4gaSAlIDQgKiA4ICYgMHhGKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3JkcyB0byBhIGJhc2UtNjQgc3RyaW5nXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5iaW5sMmI2NCA9IGZ1bmN0aW9uIGJpbmwyYjY0KGJpbmFycmF5KSB7XG4gICAgICAgIHZhciB0YWIgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky9cIjtcbiAgICAgICAgdmFyIHN0ciA9IFwiXCI7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmluYXJyYXkubGVuZ3RoICogNDsgaSArPSAzKSB7XG4gICAgICAgICAgICB2YXIgdHJpcGxldCA9IChiaW5hcnJheVtpID4+IDJdID4+IDggKiAoaSAlIDQpICYgMHhGRikgPDwgMTYgfCAoYmluYXJyYXlbaSArIDEgPj4gMl0gPj4gOCAqICgoaSArIDEpICUgNCkgJiAweEZGKSA8PCA4IHwgYmluYXJyYXlbaSArIDIgPj4gMl0gPj4gOCAqICgoaSArIDIpICUgNCkgJiAweEZGO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCA0OyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSAqIDggKyBqICogNiA+IGJpbmFycmF5Lmxlbmd0aCAqIDMyKSBzdHIgKz0gSGFzaGVyVXRpbHMuYjY0cGFkO2Vsc2Ugc3RyICs9IHRhYi5jaGFyQXQodHJpcGxldCA+PiA2ICogKDMgLSBqKSAmIDB4M0YpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfTtcblxuICAgIHJldHVybiBIYXNoZXJVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEhhc2hlclV0aWxzO1xuSGFzaGVyVXRpbHMuaGV4Y2FzZSA9IDA7IC8qIGhleCBvdXRwdXQgZm9ybWF0LiAwIC0gbG93ZXJjYXNlOyAxIC0gdXBwZXJjYXNlICAgICAgICAqL1xuSGFzaGVyVXRpbHMuYjY0cGFkID0gXCJcIjsgLyogYmFzZS02NCBwYWQgY2hhcmFjdGVyLiBcIj1cIiBmb3Igc3RyaWN0IFJGQyBjb21wbGlhbmNlICAgKi9cbkhhc2hlclV0aWxzLmNocnN6ID0gODsgLyogYml0cyBwZXIgaW5wdXQgY2hhcmFjdGVyLiA4IC0gQVNDSUk7IDE2IC0gVW5pY29kZSAgICAgICovXG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIGxhbmd1YWdlIHNwZWNpZmljIG1ldGhvZHNcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTsgZm9yICh2YXIga2V5IGluIHNvdXJjZSkgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkgeyB0YXJnZXRba2V5XSA9IHNvdXJjZVtrZXldOyB9IH0gfSByZXR1cm4gdGFyZ2V0OyB9O1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIExhbmdVdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTGFuZ1V0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTGFuZ1V0aWxzKTtcbiAgICB9XG5cbiAgICBMYW5nVXRpbHMuYXJyYXlXaXRob3V0ID0gZnVuY3Rpb24gYXJyYXlXaXRob3V0KGFycmF5LCBrZXkpIHtcbiAgICAgICAgaWYgKCFhcnJheS5sZW5ndGgpIHJldHVybiBhcnJheTtcbiAgICAgICAgaWYgKGtleSA+PSBhcnJheS5sZW5ndGgpIHJldHVybiBhcnJheTtcbiAgICAgICAgdmFyIG5ld0FycmF5O1xuICAgICAgICBpZiAoa2V5ID09IDApIG5ld0FycmF5ID0gYXJyYXkuc2xpY2UoMSk7ZWxzZSBpZiAoa2V5ID09IGFycmF5Lmxlbmd0aCAtIDEpIG5ld0FycmF5ID0gYXJyYXkuc2xpY2UoMCwgLTEpO2Vsc2UgbmV3QXJyYXkgPSBhcnJheS5zbGljZSgwLCBrZXkpLmNvbmNhdChhcnJheS5zbGljZShrZXkgKyAxKSk7XG4gICAgICAgIHJldHVybiBuZXdBcnJheTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLm9iamVjdE1lcmdlID0gZnVuY3Rpb24gb2JqZWN0TWVyZ2Uob2JqMSwgb2JqMikge1xuICAgICAgICByZXR1cm4gX2V4dGVuZHMoe30sIG9iajEsIG9iajIpO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMucGFyc2VVcmwgPSBmdW5jdGlvbiBwYXJzZVVybChkYXRhKSB7XG4gICAgICAgIHZhciBtYXRjaGVzID0gW107XG4gICAgICAgIC8vdmFyIGU9LygoaHR0cHxmdHApOlxcLyk/XFwvPyhbXjpcXC9cXHNdKykoKFxcL1xcdyspKlxcLykoW1xcd1xcLVxcLl0rXFwuW14jP1xcc10rKSgjW1xcd1xcLV0rKT8vO1xuICAgICAgICB2YXIgZGV0ZWN0ID0gLyhweWRpbzpcXC8pP1xcLz8oW146XFwvXFxzXSspKChcXC9cXHcrKSpcXC8pKC4qKSgjW1xcd1xcLV0rKT8vZztcbiAgICAgICAgdmFyIHJlc3VsdHMgPSBkYXRhLm1hdGNoKGRldGVjdCk7XG4gICAgICAgIGlmIChyZXN1bHRzICYmIHJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgZSA9IC9eKChweWRpbyk6XFwvKT9cXC8/KFteOlxcL1xcc10rKSgoXFwvXFx3KykqXFwvKSguKikoI1tcXHdcXC1dKyk/JC87XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlc3VsdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0c1tpXS5tYXRjaChlKSkge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLnB1c2goeyB1cmw6IFJlZ0V4cFsnJCYnXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3RvY29sOiBSZWdFeHAuJDIsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiBSZWdFeHAuJDMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBSZWdFeHAuJDQsXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlOiBSZWdFeHAuJDYsXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNoOiBSZWdFeHAuJDcgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXRjaGVzO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMuY29tcHV0ZVN0cmluZ1NsdWcgPSBmdW5jdGlvbiBjb21wdXRlU3RyaW5nU2x1Zyh2YWx1ZSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gTGFuZ1V0aWxzLnNsdWdUYWJsZS5sZW5ndGg7IGkgPCBsZW47IGkrKykgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKExhbmdVdGlscy5zbHVnVGFibGVbaV0ucmUsIExhbmdVdGlscy5zbHVnVGFibGVbaV0uY2gpO1xuXG4gICAgICAgIC8vIDEpIG1ldCBlbiBiYXMgZGUgY2Fzc2VcbiAgICAgICAgLy8gMikgcmVtcGxhY2UgbGVzIGVzcGFjZSBwYXIgZGVzIHRpcmV0c1xuICAgICAgICAvLyAzKSBlbmxldmUgdG91dCBsZXMgY2FyYXTDqHJlcyBub24gYWxwaGFudW1lcmlxdWVzXG4gICAgICAgIC8vIDQpIGVubMOodmUgbGVzIGRvdWJsZXMgdGlyZXRzXG4gICAgICAgIHJldHVybiB2YWx1ZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccysvZywgJy0nKS5yZXBsYWNlKC9bXmEtejAtOS1dL2csICcnKS5yZXBsYWNlKC9cXC17Mix9L2csICctJyk7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5mb3JjZUpTT05BcnJheVRvT2JqZWN0ID0gZnVuY3Rpb24gZm9yY2VKU09OQXJyYXlUb09iamVjdChjb250YWluZXIsIHZhbHVlKSB7XG4gICAgICAgIGlmIChjb250YWluZXJbdmFsdWVdIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIENsb25lXG4gICAgICAgICAgICB2YXIgY29weSA9IGNvbnRhaW5lclt2YWx1ZV0uc2xpY2UoMCk7XG4gICAgICAgICAgICBjb250YWluZXJbdmFsdWVdID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvcHkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXJbdmFsdWVdW2ldID0gY29weVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBMYW5nVXRpbHMuZGVlcENvcHkgPSBmdW5jdGlvbiBkZWVwQ29weShzb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIExhbmdVdGlscy5tZXJnZU9iamVjdHNSZWN1cnNpdmUoe30sIHNvdXJjZSk7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5zaW1wbGVDb3B5ID0gZnVuY3Rpb24gc2ltcGxlQ29weShzb3VyY2UpIHtcbiAgICAgICAgdmFyIGNvcHkgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgcHJvcGVydHkgaW4gc291cmNlKSB7XG4gICAgICAgICAgICBpZiAoc291cmNlLmhhc093blByb3BlcnR5KHByb3BlcnR5KSkge1xuICAgICAgICAgICAgICAgIGNvcHlbcHJvcGVydHldID0gc291cmNlW3Byb3BlcnR5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29weTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLm1lcmdlT2JqZWN0c1JlY3Vyc2l2ZSA9IGZ1bmN0aW9uIG1lcmdlT2JqZWN0c1JlY3Vyc2l2ZShzb3VyY2UsIGRlc3RpbmF0aW9uKSB7XG4gICAgICAgIHZhciBuZXdPYmplY3QgPSB7fSxcbiAgICAgICAgICAgIHByb3BlcnR5O1xuICAgICAgICBmb3IgKHByb3BlcnR5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgICAgICAvL2lmIChzb3VyY2VbcHJvcGVydHldID09PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBpZiAoZGVzdGluYXRpb24uaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VbcHJvcGVydHldIGluc3RhbmNlb2YgT2JqZWN0ICYmIGRlc3RpbmF0aW9uIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gTGFuZ1V0aWxzLm1lcmdlT2JqZWN0c1JlY3Vyc2l2ZShzb3VyY2VbcHJvcGVydHldLCBkZXN0aW5hdGlvbltwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IGRlc3RpbmF0aW9uW3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VbcHJvcGVydHldIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gTGFuZ1V0aWxzLm1lcmdlT2JqZWN0c1JlY3Vyc2l2ZShzb3VyY2VbcHJvcGVydHldLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gc291cmNlW3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHByb3BlcnR5IGluIGRlc3RpbmF0aW9uKSB7XG4gICAgICAgICAgICBpZiAoZGVzdGluYXRpb24uaGFzT3duUHJvcGVydHkocHJvcGVydHkpICYmICFuZXdPYmplY3QuaGFzT3duUHJvcGVydHkocHJvcGVydHkpIC8qJiYgZGVzdGluYXRpb25bcHJvcGVydHldICE9PSBudWxsKi8pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlc3RpbmF0aW9uW3Byb3BlcnR5XSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IExhbmdVdGlscy5tZXJnZU9iamVjdHNSZWN1cnNpdmUoZGVzdGluYXRpb25bcHJvcGVydHldLCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdPYmplY3RbcHJvcGVydHldID0gZGVzdGluYXRpb25bcHJvcGVydHldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXdPYmplY3Q7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5vYmplY3RWYWx1ZXMgPSBmdW5jdGlvbiBvYmplY3RWYWx1ZXMob2JqZWN0KSB7XG4gICAgICAgIHZhciByZXN1bHRzID0gW107XG4gICAgICAgIGZvciAodmFyIHByb3BlcnR5IGluIG9iamVjdCkgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaChvYmplY3RbcHJvcGVydHldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLnRyaW1MZWZ0ID0gZnVuY3Rpb24gdHJpbUxlZnQoc3RyaW5nLCBjaGFybGlzdCkge1xuICAgICAgICBpZiAoY2hhcmxpc3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY2hhcmxpc3QgPSBcIlxcc1wiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZShuZXcgUmVnRXhwKFwiXltcIiArIGNoYXJsaXN0ICsgXCJdK1wiKSwgXCJcIik7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy50cmltUmlnaHQgPSBmdW5jdGlvbiB0cmltUmlnaHQoc3RyaW5nLCBjaGFybGlzdCkge1xuICAgICAgICBpZiAoY2hhcmxpc3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY2hhcmxpc3QgPSBcIlxcc1wiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZShuZXcgUmVnRXhwKFwiW1wiICsgY2hhcmxpc3QgKyBcIl0rJFwiKSwgXCJcIik7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy50cmltID0gZnVuY3Rpb24gdHJpbShzdHJpbmcsIGNoYXJsaXN0KSB7XG4gICAgICAgIHJldHVybiBMYW5nVXRpbHMudHJpbUxlZnQoTGFuZ1V0aWxzLnRyaW1SaWdodChzdHJpbmcsIGNoYXJsaXN0KSwgY2hhcmxpc3QpO1xuICAgIH07XG5cbiAgICByZXR1cm4gTGFuZ1V0aWxzO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gTGFuZ1V0aWxzO1xuXG5MYW5nVXRpbHMuc2x1Z1RhYmxlID0gW3sgcmU6IC9bXFx4QzAtXFx4QzZdL2csIGNoOiAnQScgfSwgeyByZTogL1tcXHhFMC1cXHhFNl0vZywgY2g6ICdhJyB9LCB7IHJlOiAvW1xceEM4LVxceENCXS9nLCBjaDogJ0UnIH0sIHsgcmU6IC9bXFx4RTgtXFx4RUJdL2csIGNoOiAnZScgfSwgeyByZTogL1tcXHhDQy1cXHhDRl0vZywgY2g6ICdJJyB9LCB7IHJlOiAvW1xceEVDLVxceEVGXS9nLCBjaDogJ2knIH0sIHsgcmU6IC9bXFx4RDItXFx4RDZdL2csIGNoOiAnTycgfSwgeyByZTogL1tcXHhGMi1cXHhGNl0vZywgY2g6ICdvJyB9LCB7IHJlOiAvW1xceEQ5LVxceERDXS9nLCBjaDogJ1UnIH0sIHsgcmU6IC9bXFx4RjktXFx4RkNdL2csIGNoOiAndScgfSwgeyByZTogL1tcXHhDNy1cXHhFN10vZywgY2g6ICdjJyB9LCB7IHJlOiAvW1xceEQxXS9nLCBjaDogJ04nIH0sIHsgcmU6IC9bXFx4RjFdL2csIGNoOiAnbicgfV07XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi4vaHR0cC9SZXNvdXJjZXNNYW5hZ2VyJyk7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFJlc291cmNlc01hbmFnZXIpO1xuXG4vKipcbiAqXG4gKiBVdGlscyB0byBjb21wdXRlIHBhc3N3b3JkIHN0cmVuZ3RoXG4gKlxuICovXG5cbnZhciBQYXNzVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBhc3NVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFBhc3NVdGlscyk7XG4gICAgfVxuXG4gICAgUGFzc1V0aWxzLmdldFN0YXRlID0gZnVuY3Rpb24gZ2V0U3RhdGUoKSB7XG4gICAgICAgIHZhciBwYXNzVmFsdWUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1swXTtcbiAgICAgICAgdmFyIGNvbmZpcm1WYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY3J0U3RhdGUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyB7IHZhbGlkOiBmYWxzZSB9IDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgb25DaGFuZ2UgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBmdW5jdGlvbiAoc3RhdHVzKSB7fSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICB2YXIgc3RhdGUgPSB7XG4gICAgICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICAgICAgICAgIHBhc3NFcnJvclRleHQ6IG51bGwsXG4gICAgICAgICAgICBwYXNzSGludFRleHQ6IG51bGwsXG4gICAgICAgICAgICBjb25maXJtRXJyb3JUZXh0OiBudWxsXG4gICAgICAgIH07XG4gICAgICAgIGlmICghcGFzc1ZhbHVlICYmICFjb25maXJtVmFsdWUpIHtcbiAgICAgICAgICAgIHN0YXRlLnZhbGlkID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBQYXNzVXRpbHMuY2hlY2tQYXNzd29yZFN0cmVuZ3RoKHBhc3NWYWx1ZSwgZnVuY3Rpb24gKHZhbGlkLCBtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgc3RhdGUudmFsaWQgPSB2YWxpZDtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLnBhc3NFcnJvclRleHQgPSBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLnBhc3NIaW50VGV4dCA9IG1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWNvbmZpcm1WYWx1ZSkge1xuICAgICAgICAgICAgICAgIHN0YXRlLnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhdGUuY29uZmlybUVycm9yVGV4dCA9IGdsb2JhbC5weWRpby5NZXNzYWdlSGFzaFs2MjFdO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb25maXJtVmFsdWUgIT09IHBhc3NWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHN0YXRlLnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RhdGUuY29uZmlybUVycm9yVGV4dCA9IGdsb2JhbC5weWRpby5NZXNzYWdlSGFzaFsyMzhdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChjcnRTdGF0ZS52YWxpZCAhPT0gc3RhdGUudmFsaWQpIHtcbiAgICAgICAgICAgIG9uQ2hhbmdlKHN0YXRlLnZhbGlkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgfTtcblxuICAgIFBhc3NVdGlscy5nZXRPcHRpb25zID0gZnVuY3Rpb24gZ2V0T3B0aW9ucygpIHtcbiAgICAgICAgaWYgKFBhc3NVdGlscy5PcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gUGFzc1V0aWxzLk9wdGlvbnM7XG4gICAgICAgIH1cbiAgICAgICAgUGFzc1V0aWxzLk9wdGlvbnMgPSB7XG4gICAgICAgICAgICBweWRpb01lc3NhZ2VzOiBbMzc5LCAzODAsIDM4MSwgMzgyLCAzODMsIDM4NCwgMzg1XSxcbiAgICAgICAgICAgIG1lc3NhZ2VzOiBbXCJVbnNhZmUgcGFzc3dvcmQgd29yZCFcIiwgXCJUb28gc2hvcnRcIiwgXCJWZXJ5IHdlYWtcIiwgXCJXZWFrXCIsIFwiTWVkaXVtXCIsIFwiU3Ryb25nXCIsIFwiVmVyeSBzdHJvbmdcIl0sXG4gICAgICAgICAgICBjb2xvcnM6IFtcIiNmMDBcIiwgXCIjOTk5XCIsIFwiI0M3MEYwRlwiLCBcIiNDNzBGMEZcIiwgXCIjRkY4NDMyXCIsIFwiIzI3OUQwMFwiLCBcIiMyNzlEMDBcIl0sXG4gICAgICAgICAgICBzY29yZXM6IFsxMCwgMTUsIDMwLCA0MF0sXG4gICAgICAgICAgICBjb21tb246IFtcInBhc3N3b3JkXCIsIFwiMTIzNDU2XCIsIFwiMTIzXCIsIFwiMTIzNFwiLCBcIm15cGFzc1wiLCBcInBhc3NcIiwgXCJsZXRtZWluXCIsIFwicXdlcnR5XCIsIFwibW9ua2V5XCIsIFwiYXNkZmdoXCIsIFwienhjdmJuXCIsIFwicGFzc1wiXSxcbiAgICAgICAgICAgIG1pbmNoYXI6IDhcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHB5ZGlvTWluID0gcGFyc2VJbnQoZ2xvYmFsLnB5ZGlvLmdldFBsdWdpbkNvbmZpZ3MoXCJjb3JlLmF1dGhcIikuZ2V0KFwiUEFTU1dPUkRfTUlOTEVOR1RIXCIpKTtcbiAgICAgICAgaWYgKHB5ZGlvTWluKSB7XG4gICAgICAgICAgICBQYXNzVXRpbHMuT3B0aW9ucy5taW5jaGFyID0gcHlkaW9NaW47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFBhc3NVdGlscy5PcHRpb25zO1xuICAgIH07XG5cbiAgICBQYXNzVXRpbHMuY2hlY2tQYXNzd29yZFN0cmVuZ3RoID0gZnVuY3Rpb24gY2hlY2tQYXNzd29yZFN0cmVuZ3RoKHZhbHVlLCBjYWxsYmFjaykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIFBhc3NQb2xpY3lMaWIgPSBfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10ucmVxdWlyZUxpYihcIlBhc3N3b3JkUG9saWN5XCIsIGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChQYXNzUG9saWN5TGliICYmIFBhc3NQb2xpY3lMaWIuQ2hlY2tlcikge1xuICAgICAgICAgICAgICAgIHZhciBDaGVja2VyID0gUGFzc1BvbGljeUxpYi5DaGVja2VyO1xuXG4gICAgICAgICAgICAgICAgaWYgKENoZWNrZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgQ2hlY2tlci5jaGVja1Bhc3N3b3JkU3RyZW5ndGgodmFsdWUsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgLy8gVXBkYXRlIHdpdGggUHlkaW8gb3B0aW9uc1xuICAgICAgICB2YXIgb3B0aW9ucyA9IFBhc3NVdGlscy5nZXRPcHRpb25zKCk7XG4gICAgICAgIGlmIChvcHRpb25zLm1pbmNoYXIgJiYgdmFsdWUubGVuZ3RoIDwgb3B0aW9ucy5taW5jaGFyKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhmYWxzZSwgZ2xvYmFsLnB5ZGlvLk1lc3NhZ2VIYXNoWzM4MF0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB3cmFwcGVkQ2FsbGJhY2sgPSBmdW5jdGlvbiB3cmFwcGVkQ2FsbGJhY2sobXNnSWQsIHBlcmNlbnQpIHtcbiAgICAgICAgICAgIHZhciBzID0gb3B0aW9ucy5tZXNzYWdlc1ttc2dJZF07XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHMgPSBnbG9iYWwucHlkaW8uTWVzc2FnZUhhc2hbb3B0aW9ucy5weWRpb01lc3NhZ2VzW21zZ0lkXV07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgY2FsbGJhY2socGVyY2VudCA+IDEsIHMpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgc3RyZW5ndGggPSBQYXNzVXRpbHMuZ2V0UGFzc3dvcmRTY29yZSh2YWx1ZSwgb3B0aW9ucy5taW5jaGFyKTtcbiAgICAgICAgaWYgKHN0cmVuZ3RoID09IC0yMDApIHtcbiAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjaygwLCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChzdHJlbmd0aCA8IDAgJiYgc3RyZW5ndGggPiAtMTk5KSB7XG4gICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDEsIDEwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0cmVuZ3RoIDw9IG9wdGlvbnMuc2NvcmVzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjaygyLCAxMCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmVuZ3RoID4gb3B0aW9ucy5zY29yZXNbMF0gJiYgc3RyZW5ndGggPD0gb3B0aW9ucy5zY29yZXNbMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjaygzLCAyNSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RyZW5ndGggPiBvcHRpb25zLnNjb3Jlc1sxXSAmJiBzdHJlbmd0aCA8PSBvcHRpb25zLnNjb3Jlc1syXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDQsIDU1KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJlbmd0aCA+IG9wdGlvbnMuc2NvcmVzWzJdICYmIHN0cmVuZ3RoIDw9IG9wdGlvbnMuc2NvcmVzWzNdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soNSwgODApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDYsIDk4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQYXNzVXRpbHMuZ2V0UGFzc3dvcmRTY29yZSA9IGZ1bmN0aW9uIGdldFBhc3N3b3JkU2NvcmUodmFsdWUsIG1pbmNoYXIpIHtcblxuICAgICAgICB2YXIgc3RyZW5ndGggPSAwO1xuICAgICAgICBpZiAodmFsdWUubGVuZ3RoIDwgbWluY2hhcikge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCAtIDEwMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPj0gbWluY2hhciAmJiB2YWx1ZS5sZW5ndGggPD0gbWluY2hhciArIDIpIHtcbiAgICAgICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+PSBtaW5jaGFyICsgMyAmJiB2YWx1ZS5sZW5ndGggPD0gbWluY2hhciArIDQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDEyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPj0gbWluY2hhciArIDUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAxODtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goL1thLXpdLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAxO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvW0EtWl0vKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC9cXGQrLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA1O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvKC4qWzAtOV0uKlswLTldLipbMC05XSkvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8uWyEsQCMkJV4mKj9ffl0vKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8oLipbISxAIyQlXiYqP19+XS4qWyEsQCMkJV4mKj9ffl0pLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA3O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvKFthLXpdLipbQS1aXSl8KFtBLVpdLipbYS16XSkvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8oW2EtekEtWl0pLykgJiYgdmFsdWUubWF0Y2goLyhbMC05XSkvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC8oW2EtekEtWjAtOV0uKlshLEAjJCVeJio/X35dKXwoWyEsQCMkJV4mKj9ffl0uKlthLXpBLVowLTldKS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMztcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tbW9uID0gW1wicGFzc3dvcmRcIiwgXCIxMjM0NTZcIiwgXCIxMjNcIiwgXCIxMjM0XCIsIFwibXlwYXNzXCIsIFwicGFzc1wiLCBcImxldG1laW5cIiwgXCJxd2VydHlcIiwgXCJtb25rZXlcIiwgXCJhc2RmZ2hcIiwgXCJ6eGN2Ym5cIiwgXCJwYXNzXCJdO1xuICAgICAgICBpZiAoY29tbW9uLmluZGV4T2YodmFsdWUudG9Mb3dlckNhc2UoKSkgIT09IC0xKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IC0yMDA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cmVuZ3RoO1xuICAgIH07XG5cbiAgICByZXR1cm4gUGFzc1V0aWxzO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUGFzc1V0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBtYW5pcHVsYXRpbmcgZmlsZS9mb2xkZXJzIHBhdGhlc1xuICovXG5cInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFBhdGhVdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGF0aFV0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUGF0aFV0aWxzKTtcbiAgICB9XG5cbiAgICBQYXRoVXRpbHMuZ2V0QmFzZW5hbWUgPSBmdW5jdGlvbiBnZXRCYXNlbmFtZShmaWxlTmFtZSkge1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgICAgIHZhciBzZXBhcmF0b3IgPSBcIi9cIjtcbiAgICAgICAgaWYgKGZpbGVOYW1lLmluZGV4T2YoXCJcXFxcXCIpICE9IC0xKSBzZXBhcmF0b3IgPSBcIlxcXFxcIjtcbiAgICAgICAgcmV0dXJuIGZpbGVOYW1lLnN1YnN0cihmaWxlTmFtZS5sYXN0SW5kZXhPZihzZXBhcmF0b3IpICsgMSwgZmlsZU5hbWUubGVuZ3RoKTtcbiAgICB9O1xuXG4gICAgUGF0aFV0aWxzLmdldERpcm5hbWUgPSBmdW5jdGlvbiBnZXREaXJuYW1lKGZpbGVOYW1lKSB7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZS5zdWJzdHIoMCwgZmlsZU5hbWUubGFzdEluZGV4T2YoXCIvXCIpKTtcbiAgICB9O1xuXG4gICAgUGF0aFV0aWxzLmdldEFqeHBNaW1lVHlwZSA9IGZ1bmN0aW9uIGdldEFqeHBNaW1lVHlwZShpdGVtKSB7XG4gICAgICAgIGlmICghaXRlbSkgcmV0dXJuIFwiXCI7XG4gICAgICAgIGlmIChpdGVtIGluc3RhbmNlb2YgTWFwKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbS5nZXQoJ2FqeHBfbWltZScpIHx8IFBhdGhVdGlscy5nZXRGaWxlRXh0ZW5zaW9uKGl0ZW0uZ2V0KCdmaWxlbmFtZScpKTtcbiAgICAgICAgfSBlbHNlIGlmIChpdGVtLmdldE1ldGFkYXRhKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbS5nZXRNZXRhZGF0YSgpLmdldCgnYWp4cF9taW1lJykgfHwgUGF0aFV0aWxzLmdldEZpbGVFeHRlbnNpb24oaXRlbS5nZXRQYXRoKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0QXR0cmlidXRlKCdhanhwX21pbWUnKSB8fCBQYXRoVXRpbHMuZ2V0RmlsZUV4dGVuc2lvbihpdGVtLmdldEF0dHJpYnV0ZSgnZmlsZW5hbWUnKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUGF0aFV0aWxzLmdldEZpbGVFeHRlbnNpb24gPSBmdW5jdGlvbiBnZXRGaWxlRXh0ZW5zaW9uKGZpbGVOYW1lKSB7XG4gICAgICAgIGlmICghZmlsZU5hbWUgfHwgZmlsZU5hbWUgPT0gXCJcIikgcmV0dXJuIFwiXCI7XG4gICAgICAgIHZhciBzcGxpdCA9IFBhdGhVdGlscy5nZXRCYXNlbmFtZShmaWxlTmFtZSkuc3BsaXQoJy4nKTtcbiAgICAgICAgaWYgKHNwbGl0Lmxlbmd0aCA+IDEpIHJldHVybiBzcGxpdFtzcGxpdC5sZW5ndGggLSAxXS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfTtcblxuICAgIFBhdGhVdGlscy5yb3VuZEZpbGVTaXplID0gZnVuY3Rpb24gcm91bmRGaWxlU2l6ZShmaWxlc2l6ZSkge1xuICAgICAgICB2YXIgc2l6ZV91bml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gXCJvXCIgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgaWYgKGZpbGVzaXplID49IDEwNzM3NDE4MjQpIHtcbiAgICAgICAgICAgIGZpbGVzaXplID0gTWF0aC5yb3VuZChmaWxlc2l6ZSAvIDEwNzM3NDE4MjQgKiAxMDApIC8gMTAwICsgXCIgR1wiICsgc2l6ZV91bml0O1xuICAgICAgICB9IGVsc2UgaWYgKGZpbGVzaXplID49IDEwNDg1NzYpIHtcbiAgICAgICAgICAgIGZpbGVzaXplID0gTWF0aC5yb3VuZChmaWxlc2l6ZSAvIDEwNDg1NzYgKiAxMDApIC8gMTAwICsgXCIgTVwiICsgc2l6ZV91bml0O1xuICAgICAgICB9IGVsc2UgaWYgKGZpbGVzaXplID49IDEwMjQpIHtcbiAgICAgICAgICAgIGZpbGVzaXplID0gTWF0aC5yb3VuZChmaWxlc2l6ZSAvIDEwMjQgKiAxMDApIC8gMTAwICsgXCIgS1wiICsgc2l6ZV91bml0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmlsZXNpemUgPSBmaWxlc2l6ZSArIFwiIFwiICsgc2l6ZV91bml0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWxlc2l6ZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZGF0ZU9iamVjdCBEYXRlXG4gICAgICogQHBhcmFtIGZvcm1hdCBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cblxuICAgIFBhdGhVdGlscy5mb3JtYXRNb2RpZkRhdGUgPSBmdW5jdGlvbiBmb3JtYXRNb2RpZkRhdGUoZGF0ZU9iamVjdCwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghZm9ybWF0ICYmIHdpbmRvdyAmJiB3aW5kb3cucHlkaW8gJiYgcHlkaW8uTWVzc2FnZUhhc2gpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IHB5ZGlvLk1lc3NhZ2VIYXNoW1wiZGF0ZV9mb3JtYXRcIl07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFmb3JtYXQpIHJldHVybiAnbm8gZm9ybWF0JztcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJkXCIsIGRhdGVPYmplY3QuZ2V0RGF0ZSgpIDwgMTAgPyAnMCcgKyBkYXRlT2JqZWN0LmdldERhdGUoKSA6IGRhdGVPYmplY3QuZ2V0RGF0ZSgpKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJEXCIsIGRhdGVPYmplY3QuZ2V0RGF5KCkpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcIllcIiwgZGF0ZU9iamVjdC5nZXRGdWxsWWVhcigpKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJ5XCIsIGRhdGVPYmplY3QuZ2V0WWVhcigpKTtcbiAgICAgICAgdmFyIG1vbnRoID0gZGF0ZU9iamVjdC5nZXRNb250aCgpICsgMTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJtXCIsIG1vbnRoIDwgMTAgPyAnMCcgKyBtb250aCA6IG1vbnRoKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJIXCIsIChkYXRlT2JqZWN0LmdldEhvdXJzKCkgPCAxMCA/ICcwJyA6ICcnKSArIGRhdGVPYmplY3QuZ2V0SG91cnMoKSk7XG4gICAgICAgIC8vIFN1cHBvcnQgMTIgaG91ciBmb3JtYXQgY29tcGF0aWJpbGl0eVxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcImhcIiwgZGF0ZU9iamVjdC5nZXRIb3VycygpICUgMTIgfHwgMTIpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcInBcIiwgZGF0ZU9iamVjdC5nZXRIb3VycygpIDwgMTIgPyBcImFtXCIgOiBcInBtXCIpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcIlBcIiwgZGF0ZU9iamVjdC5nZXRIb3VycygpIDwgMTIgPyBcIkFNXCIgOiBcIlBNXCIpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcImlcIiwgKGRhdGVPYmplY3QuZ2V0TWludXRlcygpIDwgMTAgPyAnMCcgOiAnJykgKyBkYXRlT2JqZWN0LmdldE1pbnV0ZXMoKSk7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwic1wiLCAoZGF0ZU9iamVjdC5nZXRTZWNvbmRzKCkgPCAxMCA/ICcwJyA6ICcnKSArIGRhdGVPYmplY3QuZ2V0U2Vjb25kcygpKTtcbiAgICAgICAgcmV0dXJuIGZvcm1hdDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFBhdGhVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gUGF0aFV0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzW1wiZGVmYXVsdFwiXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBQZXJpb2RpY2FsRXhlY3V0ZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBlcmlvZGljYWxFeGVjdXRlcihjYWxsYmFjaywgZnJlcXVlbmN5KSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQZXJpb2RpY2FsRXhlY3V0ZXIpO1xuXG4gICAgICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICAgICAgdGhpcy5mcmVxdWVuY3kgPSBmcmVxdWVuY3k7XG4gICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5yZWdpc3RlckNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgUGVyaW9kaWNhbEV4ZWN1dGVyLnByb3RvdHlwZS5yZWdpc3RlckNhbGxiYWNrID0gZnVuY3Rpb24gcmVnaXN0ZXJDYWxsYmFjaygpIHtcbiAgICAgICAgdGhpcy50aW1lciA9IHNldEludGVydmFsKHRoaXMub25UaW1lckV2ZW50LmJpbmQodGhpcyksIHRoaXMuZnJlcXVlbmN5ICogMTAwMCk7XG4gICAgfTtcblxuICAgIFBlcmlvZGljYWxFeGVjdXRlci5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uIGV4ZWN1dGUoKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2sodGhpcyk7XG4gICAgfTtcblxuICAgIFBlcmlvZGljYWxFeGVjdXRlci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uIHN0b3AoKSB7XG4gICAgICAgIGlmICghdGhpcy50aW1lcikgcmV0dXJuO1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMudGltZXIpO1xuICAgICAgICB0aGlzLnRpbWVyID0gbnVsbDtcbiAgICB9O1xuXG4gICAgUGVyaW9kaWNhbEV4ZWN1dGVyLnByb3RvdHlwZS5vblRpbWVyRXZlbnQgPSBmdW5jdGlvbiBvblRpbWVyRXZlbnQoKSB7XG4gICAgICAgIGlmICghdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhlY3V0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBQZXJpb2RpY2FsRXhlY3V0ZXI7XG59KSgpO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IFBlcmlvZGljYWxFeGVjdXRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1tcImRlZmF1bHRcIl07XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF93aWNrZWRHb29kWHBhdGggPSByZXF1aXJlKCd3aWNrZWQtZ29vZC14cGF0aCcpO1xuXG52YXIgX3dpY2tlZEdvb2RYcGF0aDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF93aWNrZWRHb29kWHBhdGgpO1xuXG5fd2lja2VkR29vZFhwYXRoMlsnZGVmYXVsdCddLmluc3RhbGwoKTtcbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBtYW5pcHVsYXRpbmcgWE1MXG4gKi9cblxudmFyIFhNTFV0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBYTUxVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFhNTFV0aWxzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIHRoZSBmaXJzdCBYbWxOb2RlIHRoYXQgbWF0Y2hlcyB0aGUgWFBhdGggZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IHtFbGVtZW50IHwgRG9jdW1lbnR9IHJvb3QgZWxlbWVudCBmb3IgdGhlIHNlYXJjaFxuICAgICAqIEBwYXJhbSBxdWVyeSB7U3RyaW5nfSBYUGF0aCBxdWVyeVxuICAgICAqIEByZXR1cm4ge0VsZW1lbnR9IGZpcnN0IG1hdGNoaW5nIGVsZW1lbnRcbiAgICAgKiBAc2lnbmF0dXJlIGZ1bmN0aW9uKGVsZW1lbnQsIHF1ZXJ5KVxuICAgICAqL1xuXG4gICAgWE1MVXRpbHMuWFBhdGhTZWxlY3RTaW5nbGVOb2RlID0gZnVuY3Rpb24gWFBhdGhTZWxlY3RTaW5nbGVOb2RlKGVsZW1lbnQsIHF1ZXJ5KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoZWxlbWVudFsnc2VsZWN0U2luZ2xlTm9kZSddICYmIHR5cGVvZiBlbGVtZW50LnNlbGVjdFNpbmdsZU5vZGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHZhciByZXMgPSBlbGVtZW50LnNlbGVjdFNpbmdsZU5vZGUocXVlcnkpO1xuICAgICAgICAgICAgICAgIGlmIChyZXMpIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgICAgaWYgKCFYTUxVdGlscy5fX3hwZSAmJiB3aW5kb3cuWFBhdGhFdmFsdWF0b3IpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgWE1MVXRpbHMuX194cGUgPSBuZXcgWFBhdGhFdmFsdWF0b3IoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVhNTFV0aWxzLl9feHBlKSB7XG4gICAgICAgICAgICBxdWVyeSA9IGRvY3VtZW50LmNyZWF0ZUV4cHJlc3Npb24ocXVlcnksIG51bGwpO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHF1ZXJ5LmV2YWx1YXRlKGVsZW1lbnQsIDcsIG51bGwpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5zbmFwc2hvdExlbmd0aCA/IHJlc3VsdC5zbmFwc2hvdEl0ZW0oMCkgOiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHhwZSA9IFhNTFV0aWxzLl9feHBlO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4geHBlLmV2YWx1YXRlKHF1ZXJ5LCBlbGVtZW50LCB4cGUuY3JlYXRlTlNSZXNvbHZlcihlbGVtZW50KSwgWFBhdGhSZXN1bHQuRklSU1RfT1JERVJFRF9OT0RFX1RZUEUsIG51bGwpLnNpbmdsZU5vZGVWYWx1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZWxlY3RTaW5nbGVOb2RlOiBxdWVyeTogXCIgKyBxdWVyeSArIFwiLCBlbGVtZW50OiBcIiArIGVsZW1lbnQgKyBcIiwgZXJyb3I6IFwiICsgZXJyKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIGEgbGlzdCBvZiBub2RlcyBtYXRjaGluZyB0aGUgWFBhdGggZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IHtFbGVtZW50IHwgRG9jdW1lbnR9IHJvb3QgZWxlbWVudCBmb3IgdGhlIHNlYXJjaFxuICAgICAqIEBwYXJhbSBxdWVyeSB7U3RyaW5nfSBYUGF0aCBxdWVyeVxuICAgICAqIEByZXR1cm4ge0VsZW1lbnRbXX0gTGlzdCBvZiBtYXRjaGluZyBlbGVtZW50c1xuICAgICAqIEBzaWduYXR1cmUgZnVuY3Rpb24oZWxlbWVudCwgcXVlcnkpXG4gICAgICovXG5cbiAgICBYTUxVdGlscy5YUGF0aFNlbGVjdE5vZGVzID0gZnVuY3Rpb24gWFBhdGhTZWxlY3ROb2RlcyhlbGVtZW50LCBxdWVyeSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBlbGVtZW50LnNlbGVjdE5vZGVzID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5vd25lckRvY3VtZW50ICYmIGVsZW1lbnQub3duZXJEb2N1bWVudC5zZXRQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5vd25lckRvY3VtZW50LnNldFByb3BlcnR5KFwiU2VsZWN0aW9uTGFuZ3VhZ2VcIiwgXCJYUGF0aFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlbGVtZW50LnNldFByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldFByb3BlcnR5KFwiU2VsZWN0aW9uTGFuZ3VhZ2VcIiwgXCJYUGF0aFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IEFycmF5LmZyb20oZWxlbWVudC5zZWxlY3ROb2RlcyhxdWVyeSkpO1xuICAgICAgICAgICAgICAgIGlmIChyZXMpIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgICAgdmFyIHhwZSA9IFhNTFV0aWxzLl9feHBlO1xuXG4gICAgICAgIGlmICgheHBlICYmIHdpbmRvdy5YUGF0aEV2YWx1YXRvcikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBYTUxVdGlscy5fX3hwZSA9IHhwZSA9IG5ldyBYUGF0aEV2YWx1YXRvcigpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0LFxuICAgICAgICAgICAgbm9kZXMgPSBbXSxcbiAgICAgICAgICAgIGk7XG4gICAgICAgIGlmICghWE1MVXRpbHMuX194cGUpIHtcbiAgICAgICAgICAgIHF1ZXJ5ID0gZG9jdW1lbnQuY3JlYXRlRXhwcmVzc2lvbihxdWVyeSwgbnVsbCk7XG4gICAgICAgICAgICByZXN1bHQgPSBxdWVyeS5ldmFsdWF0ZShlbGVtZW50LCA3LCBudWxsKTtcbiAgICAgICAgICAgIG5vZGVzID0gW107XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVzdWx0LnNuYXBzaG90TGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoRWxlbWVudC5leHRlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZXNbaV0gPSBFbGVtZW50LmV4dGVuZChyZXN1bHQuc25hcHNob3RJdGVtKGkpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBub2Rlc1tpXSA9IHJlc3VsdC5zbmFwc2hvdEl0ZW0oaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHhwZS5ldmFsdWF0ZShxdWVyeSwgZWxlbWVudCwgeHBlLmNyZWF0ZU5TUmVzb2x2ZXIoZWxlbWVudCksIFhQYXRoUmVzdWx0Lk9SREVSRURfTk9ERV9TTkFQU0hPVF9UWVBFLCBudWxsKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZWxlY3ROb2RlczogcXVlcnk6IFwiICsgcXVlcnkgKyBcIiwgZWxlbWVudDogXCIgKyBlbGVtZW50ICsgXCIsIGVycm9yOiBcIiArIGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmVzdWx0LnNuYXBzaG90TGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5vZGVzW2ldID0gcmVzdWx0LnNuYXBzaG90SXRlbShpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBub2RlcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgZmlyc3QgWG1sTm9kZSB0aGF0IG1hdGNoZXMgdGhlIFhQYXRoIGV4cHJlc3Npb24gYW5kIHJldHVybnMgdGhlIHRleHQgY29udGVudCBvZiB0aGUgZWxlbWVudFxuICAgICAqXG4gICAgICogQHBhcmFtIGVsZW1lbnQge0VsZW1lbnR8RG9jdW1lbnR9IHJvb3QgZWxlbWVudCBmb3IgdGhlIHNlYXJjaFxuICAgICAqIEBwYXJhbSBxdWVyeSB7U3RyaW5nfSAgWFBhdGggcXVlcnlcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IHRoZSBqb2luZWQgdGV4dCBjb250ZW50IG9mIHRoZSBmb3VuZCBlbGVtZW50IG9yIG51bGwgaWYgbm90IGFwcHJvcHJpYXRlLlxuICAgICAqIEBzaWduYXR1cmUgZnVuY3Rpb24oZWxlbWVudCwgcXVlcnkpXG4gICAgICovXG5cbiAgICBYTUxVdGlscy5YUGF0aEdldFNpbmdsZU5vZGVUZXh0ID0gZnVuY3Rpb24gWFBhdGhHZXRTaW5nbGVOb2RlVGV4dChlbGVtZW50LCBxdWVyeSkge1xuICAgICAgICB2YXIgbm9kZSA9IFhNTFV0aWxzLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShlbGVtZW50LCBxdWVyeSk7XG4gICAgICAgIHJldHVybiBYTUxVdGlscy5nZXREb21Ob2RlVGV4dChub2RlKTtcbiAgICB9O1xuXG4gICAgWE1MVXRpbHMuZ2V0RG9tTm9kZVRleHQgPSBmdW5jdGlvbiBnZXREb21Ob2RlVGV4dChub2RlKSB7XG4gICAgICAgIHZhciBpbmNsdWRlQ0RhdGEgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAoIW5vZGUgfHwgIW5vZGUubm9kZVR5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChub2RlLm5vZGVUeXBlKSB7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgLy8gTk9ERV9FTEVNRU5UXG4gICAgICAgICAgICAgICAgdmFyIGksXG4gICAgICAgICAgICAgICAgICAgIGEgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlLmNoaWxkTm9kZXMsXG4gICAgICAgICAgICAgICAgICAgIGxlbmd0aCA9IG5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYVtpXSA9IFhNTFV0aWxzLmdldERvbU5vZGVUZXh0KG5vZGVzW2ldLCBpbmNsdWRlQ0RhdGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhLmpvaW4oXCJcIik7XG5cbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAvLyBOT0RFX0FUVFJJQlVURVxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlLnZhbHVlO1xuXG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgLy8gTk9ERV9URVhUXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGUubm9kZVZhbHVlO1xuXG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgLy8gQ0RBVEFcbiAgICAgICAgICAgICAgICBpZiAoaW5jbHVkZUNEYXRhKSByZXR1cm4gbm9kZS5ub2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHhtbFN0clxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuXG4gICAgWE1MVXRpbHMucGFyc2VYbWwgPSBmdW5jdGlvbiBwYXJzZVhtbCh4bWxTdHIpIHtcblxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5ET01QYXJzZXIgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyB3aW5kb3cuRE9NUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKHhtbFN0ciwgXCJ0ZXh0L3htbFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5BY3RpdmVYT2JqZWN0ICE9IFwidW5kZWZpbmVkXCIgJiYgbmV3IHdpbmRvdy5BY3RpdmVYT2JqZWN0KFwiTVNYTUwyLkRPTURvY3VtZW50LjYuMFwiKSkge1xuICAgICAgICAgICAgdmFyIHhtbERvYyA9IG5ldyB3aW5kb3cuQWN0aXZlWE9iamVjdChcIk1TWE1MMi5ET01Eb2N1bWVudC42LjBcIik7XG4gICAgICAgICAgICB4bWxEb2MudmFsaWRhdGVPblBhcnNlID0gZmFsc2U7XG4gICAgICAgICAgICB4bWxEb2MuYXN5bmMgPSBmYWxzZTtcbiAgICAgICAgICAgIHhtbERvYy5sb2FkWE1MKHhtbFN0cik7XG4gICAgICAgICAgICB4bWxEb2Muc2V0UHJvcGVydHkoJ1NlbGVjdGlvbkxhbmd1YWdlJywgJ1hQYXRoJyk7XG4gICAgICAgICAgICByZXR1cm4geG1sRG9jO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHBhcnNlIFhNTCBzdHJpbmcnKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFhNTFV0aWxzO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gWE1MVXRpbHM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG52YXIgX21vZGVsUmVnaXN0cnkgPSByZXF1aXJlKCcuL21vZGVsL1JlZ2lzdHJ5Jyk7XG5cbnZhciBfbW9kZWxSZWdpc3RyeTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbFJlZ2lzdHJ5KTtcblxudmFyIF9tb2RlbEFqeHBOb2RlID0gcmVxdWlyZSgnLi9tb2RlbC9BanhwTm9kZScpO1xuXG52YXIgX21vZGVsQWp4cE5vZGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxBanhwTm9kZSk7XG5cbnZhciBfbW9kZWxQeWRpb0RhdGFNb2RlbCA9IHJlcXVpcmUoJy4vbW9kZWwvUHlkaW9EYXRhTW9kZWwnKTtcblxudmFyIF9tb2RlbFB5ZGlvRGF0YU1vZGVsMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsUHlkaW9EYXRhTW9kZWwpO1xuXG52YXIgX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyID0gcmVxdWlyZSgnLi9tb2RlbC9SZW1vdGVOb2RlUHJvdmlkZXInKTtcblxudmFyIF9tb2RlbFJlbW90ZU5vZGVQcm92aWRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbFJlbW90ZU5vZGVQcm92aWRlcik7XG5cbnZhciBfbW9kZWxSZXBvc2l0b3J5ID0gcmVxdWlyZSgnLi9tb2RlbC9SZXBvc2l0b3J5Jyk7XG5cbnZhciBfbW9kZWxSZXBvc2l0b3J5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsUmVwb3NpdG9yeSk7XG5cbnZhciBfbW9kZWxDb250cm9sbGVyID0gcmVxdWlyZSgnLi9tb2RlbC9Db250cm9sbGVyJyk7XG5cbnZhciBfbW9kZWxDb250cm9sbGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsQ29udHJvbGxlcik7XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBfdXRpbFBhdGhVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9QYXRoVXRpbHMnKTtcblxudmFyIF91dGlsUGF0aFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxQYXRoVXRpbHMpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvTGFuZ1V0aWxzJyk7XG5cbnZhciBfdXRpbExhbmdVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsTGFuZ1V0aWxzKTtcblxudmFyIF91dGlsQWN0aXZpdHlNb25pdG9yID0gcmVxdWlyZSgnLi91dGlsL0FjdGl2aXR5TW9uaXRvcicpO1xuXG52YXIgX3V0aWxBY3Rpdml0eU1vbml0b3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbEFjdGl2aXR5TW9uaXRvcik7XG5cbi8qKlxuICogVGhpcyBpcyB0aGUgbWFpbiBjbGFzcyBmb3IgbGF1bmNoaW5nIHRoZSB3aG9sZSBmcmFtZXdvcmssXG4gKiB3aXRoIG9yIHdpdGhvdXQgYSBVSS5cbiAqIEl0IGNhbiBiZSBsYXVuY2hlZCBieSBQeWRpb0Jvb3RzdHJhcCBvciBkaXJlY3RseSBieSBnaXZpbmcgdGhlIHJpZ2h0IHBhcmFtZXRlcnMuXG4gKi9cblxudmFyIFB5ZGlvID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhQeWRpbywgX09ic2VydmFibGUpO1xuXG4gICAgLyoqXG4gICAgICogUHlkaW8gQ29uc3RydWN0b3IgdGFrZXMgYSBNYXAgb2Ygc3RhcnQgcGFyYW1ldGVycy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYXJhbWV0ZXJzIHtNYXB9XG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBQeWRpbyhwYXJhbWV0ZXJzKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQeWRpbyk7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5QYXJhbWV0ZXJzID0gcGFyYW1ldGVycztcbiAgICAgICAgdGhpcy5faW5pdExvYWRSZXAgPSBwYXJhbWV0ZXJzLmdldCgnaW5pdExvYWRSZXAnKSB8fCBudWxsO1xuICAgICAgICB0aGlzLnVzZXJzRW5hYmxlZCA9IHBhcmFtZXRlcnMuZ2V0KCd1c2Vyc0VuYWJsZWQnKSB8fCBudWxsO1xuICAgICAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZSA9IHBhcmFtZXRlcnMuZ2V0KCdjdXJyZW50TGFuZ3VhZ2UnKSB8fCBudWxsO1xuICAgICAgICB0aGlzLmFwcFRpdGxlID0gXCJQeWRpb1wiO1xuICAgICAgICBpZiAodGhpcy5QYXJhbWV0ZXJzLmhhcyhcImN1c3RvbVdvcmRpbmdcIikpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwVGl0bGUgPSB0aGlzLlBhcmFtZXRlcnMuZ2V0KFwiY3VzdG9tV29yZGluZ1wiKS50aXRsZSB8fCBcIlB5ZGlvXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51c2VyID0gbnVsbDtcbiAgICAgICAgdGhpcy5NZXNzYWdlSGFzaCA9IHt9O1xuICAgICAgICBpZiAod2luZG93Lk1lc3NhZ2VIYXNoKSB0aGlzLk1lc3NhZ2VIYXNoID0gd2luZG93Lk1lc3NhZ2VIYXNoO1xuICAgICAgICB0aGlzLkFwaUNsaWVudCA9IF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCk7XG4gICAgICAgIHRoaXMuQXBpQ2xpZW50LnNldFB5ZGlvT2JqZWN0KHRoaXMpO1xuICAgICAgICB0aGlzLkFjdGl2aXR5TW9uaXRvciA9IG5ldyBfdXRpbEFjdGl2aXR5TW9uaXRvcjJbJ2RlZmF1bHQnXSh0aGlzKTtcbiAgICAgICAgdGhpcy5SZWdpc3RyeSA9IG5ldyBfbW9kZWxSZWdpc3RyeTJbJ2RlZmF1bHQnXSh0aGlzKTtcbiAgICAgICAgdGhpcy5fcm9vdE5vZGUgPSBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10oXCIvXCIsIFwiUm9vdFwiKTtcbiAgICAgICAgdGhpcy5fZGF0YU1vZGVsID0gdGhpcy5fY29udGV4dEhvbGRlciA9IG5ldyBfbW9kZWxQeWRpb0RhdGFNb2RlbDJbJ2RlZmF1bHQnXShmYWxzZSk7XG4gICAgICAgIHRoaXMuX2RhdGFNb2RlbC5zZXRBanhwTm9kZVByb3ZpZGVyKG5ldyBfbW9kZWxSZW1vdGVOb2RlUHJvdmlkZXIyWydkZWZhdWx0J10oKSk7XG4gICAgICAgIHRoaXMuX2RhdGFNb2RlbC5zZXRSb290Tm9kZSh0aGlzLl9yb290Tm9kZSk7XG4gICAgICAgIC8vIE11c3QgaGFwcGVuIEFGVEVSIGRhdGFtb2RlbCBpbml0aXphdGlvbi5cbiAgICAgICAgdGhpcy5Db250cm9sbGVyID0gbmV3IF9tb2RlbENvbnRyb2xsZXIyWydkZWZhdWx0J10odGhpcyk7XG4gICAgfVxuXG4gICAgUHlkaW8ucHJvdG90eXBlLmZpcmUgPSBmdW5jdGlvbiBmaXJlKGV2ZW50TmFtZSwgZGF0YSkge1xuICAgICAgICB0aGlzLm5vdGlmeShldmVudE5hbWUsIGRhdGEpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7VXNlcnxudWxsfSB1c2VyT2JqZWN0XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUudXBkYXRlVXNlciA9IGZ1bmN0aW9uIHVwZGF0ZVVzZXIodXNlck9iamVjdCkge1xuICAgICAgICB2YXIgc2tpcEV2ZW50ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdGhpcy51c2VyID0gdXNlck9iamVjdDtcbiAgICAgICAgaWYgKCFza2lwRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KCd1c2VyX2xvZ2dlZCcsIHVzZXJPYmplY3QpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHJldHVybnMge251bGx8VXNlcn1cbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRVc2VyID0gZnVuY3Rpb24gZ2V0VXNlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudXNlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVmcmVzaCB1c2VyL3ByZWZlcmVuY2VzIHJlZ2lzdHJ5IHBhcnRcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5yZWZyZXNoVXNlckRhdGEgPSBmdW5jdGlvbiByZWZyZXNoVXNlckRhdGEoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy5vYnNlcnZlT25jZShcInJlZ2lzdHJ5X3BhcnRfbG9hZGVkXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50ICE9PSBcInVzZXIvcHJlZmVyZW5jZXNcIikgcmV0dXJuO1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlVXNlcihfdGhpcy5SZWdpc3RyeS5wYXJzZVVzZXIoKSwgZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5SZWdpc3RyeS5sb2FkKFwidXNlci9wcmVmZXJlbmNlc1wiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVhbCBpbml0aWFsaXNhdGlvbiBzZXF1ZW5jZS4gV2lsbCBUcmlnZ2VyIHRoZSB3aG9sZSBHVUkgYnVpbGRpbmcuXG4gICAgICogRXZlbnQgYWpheHBsb3Jlcjpsb2FkZWQgaXMgZmlyZWQgYXQgdGhlIGVuZC5cbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCF0aGlzLlBhcmFtZXRlcnMuaGFzKCdTRUNVUkVfVE9LRU4nKSkge1xuICAgICAgICAgICAgX2h0dHBQeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5nZXRCb290Q29uZigoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdCgpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9ic2VydmUoXCJyZWdpc3RyeV9sb2FkZWRcIiwgZnVuY3Rpb24gKCkge1xuXG4gICAgICAgICAgICBfdGhpczIuUmVnaXN0cnkucmVmcmVzaEV4dGVuc2lvbnNSZWdpc3RyeSgpO1xuICAgICAgICAgICAgX3RoaXMyLnVwZGF0ZVVzZXIoX3RoaXMyLlJlZ2lzdHJ5LnBhcnNlVXNlcigpLCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAoX3RoaXMyLnVzZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwSWQgPSBfdGhpczIudXNlci5nZXRBY3RpdmVSZXBvc2l0b3J5KCk7XG4gICAgICAgICAgICAgICAgdmFyIHJlcExpc3QgPSBfdGhpczIudXNlci5nZXRSZXBvc2l0b3JpZXNMaXN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHJlcG9zaXRvcnlPYmplY3QgPSByZXBMaXN0LmdldChyZXBJZCk7XG4gICAgICAgICAgICAgICAgaWYgKHJlcG9zaXRvcnlPYmplY3QpIHJlcG9zaXRvcnlPYmplY3QubG9hZFJlc291cmNlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzMi5VSS5ndWlMb2FkZWQpIHtcbiAgICAgICAgICAgICAgICBfdGhpczIuVUkucmVmcmVzaFRlbXBsYXRlUGFydHMoKTtcbiAgICAgICAgICAgICAgICBfdGhpczIuUmVnaXN0cnkucmVmcmVzaEV4dGVuc2lvbnNSZWdpc3RyeSgpO1xuICAgICAgICAgICAgICAgIF90aGlzMi5Db250cm9sbGVyLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KF90aGlzMi5nZXRYbWxSZWdpc3RyeSgpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgX3RoaXMyLm9ic2VydmUoXCJndWlfbG9hZGVkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLlVJLnJlZnJlc2hUZW1wbGF0ZVBhcnRzKCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5SZWdpc3RyeS5yZWZyZXNoRXh0ZW5zaW9uc1JlZ2lzdHJ5KCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5Db250cm9sbGVyLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KF90aGlzMi5nZXRYbWxSZWdpc3RyeSgpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzMi5sb2FkQWN0aXZlUmVwb3NpdG9yeSgpO1xuICAgICAgICAgICAgaWYgKF90aGlzMi5QYXJhbWV0ZXJzLmhhcyhcIlVTRVJfR1VJX0FDVElPTlwiKSkge1xuICAgICAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gX3RoaXMyLlBhcmFtZXRlcnMuZ2V0KFwiVVNFUl9HVUlfQUNUSU9OXCIpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIuUGFyYW1ldGVyc1snZGVsZXRlJ10oXCJVU0VSX0dVSV9BQ1RJT05cIik7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMyLkNvbnRyb2xsZXIuZmlyZUFjdGlvbihhKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMTAwMCk7XG4gICAgICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIHN0YXJ0ZXJGdW5jID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRDbGFzc2VzQW5kQXBwbHkoW1wiUmVhY3RcIiwgXCJQeWRpb1JlYWN0VUlcIl0sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpczMuVUkgPSBuZXcgd2luZG93LlB5ZGlvUmVhY3RVSS5CdWlsZGVyKF90aGlzMyk7XG4gICAgICAgICAgICAgICAgX3RoaXMzLlVJLmluaXRUZW1wbGF0ZXMoKTtcbiAgICAgICAgICAgICAgICBfdGhpczMuZmlyZShcInJlZ2lzdHJ5X2xvYWRlZFwiLCBfdGhpczMuUmVnaXN0cnkuZ2V0WE1MKCkpO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpczMuZmlyZSgnbG9hZGVkJyk7XG4gICAgICAgICAgICAgICAgfSwgMjAwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIGlmICh0aGlzLlBhcmFtZXRlcnMuZ2V0KFwiUFJFTE9BREVEX1JFR0lTVFJZXCIpKSB7XG5cbiAgICAgICAgICAgIHRoaXMuUmVnaXN0cnkubG9hZEZyb21TdHJpbmcodGhpcy5QYXJhbWV0ZXJzLmdldChcIlBSRUxPQURFRF9SRUdJU1RSWVwiKSk7XG4gICAgICAgICAgICB0aGlzLlBhcmFtZXRlcnNbJ2RlbGV0ZSddKFwiUFJFTE9BREVEX1JFR0lTVFJZXCIpO1xuICAgICAgICAgICAgc3RhcnRlckZ1bmMoKTtcbiAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgdGhpcy5sb2FkWG1sUmVnaXN0cnkoZmFsc2UsIG51bGwsIHN0YXJ0ZXJGdW5jKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub2JzZXJ2ZShcInNlcnZlcl9tZXNzYWdlXCIsIGZ1bmN0aW9uICh4bWwpIHtcbiAgICAgICAgICAgIHZhciByZWxvYWQgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWwsIFwidHJlZS9yZXF1aXJlX3JlZ2lzdHJ5X3JlbG9hZFwiKTtcbiAgICAgICAgICAgIGlmIChyZWxvYWQpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVsb2FkLmdldEF0dHJpYnV0ZShcInJlcG9zaXRvcnlJZFwiKSAhPT0gX3RoaXMyLnJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBudWxsLCBudWxsLCByZWxvYWQuZ2V0QXR0cmlidXRlKFwicmVwb3NpdG9yeUlkXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLnJlcG9zaXRvcnlJZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZHMgdGhlIFhNTCBSZWdpc3RyeSwgYW4gaW1hZ2Ugb2YgdGhlIGFwcGxpY2F0aW9uIGluIGl0cyBjdXJyZW50IHN0YXRlXG4gICAgICogc2VudCBieSB0aGUgc2VydmVyLlxuICAgICAqIEBwYXJhbSBzeW5jIEJvb2xlYW4gV2hldGhlciB0byBzZW5kIHN5bmNocm9ub3VzbHkgb3Igbm90LlxuICAgICAqIEBwYXJhbSB4UGF0aCBTdHJpbmcgQW4gWFBhdGggdG8gbG9hZCBvbmx5IGEgc3VicGFydCBvZiB0aGUgcmVnaXN0cnlcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkWG1sUmVnaXN0cnkgPSBmdW5jdGlvbiBsb2FkWG1sUmVnaXN0cnkoc3luYykge1xuICAgICAgICB2YXIgeFBhdGggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY29tcGxldGVGdW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIHRhcmdldFJlcG9zaXRvcnlJZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdGhpcy5SZWdpc3RyeS5sb2FkKHhQYXRoLCBjb21wbGV0ZUZ1bmMsIHRhcmdldFJlcG9zaXRvcnlJZCA9PT0gbnVsbCA/IE1hdGgucmFuZG9tKCkgOiB0YXJnZXRSZXBvc2l0b3J5SWQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIFhNTCBSZWdpc3RyeVxuICAgICAqIEByZXR1cm5zIERvY3VtZW50XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0WG1sUmVnaXN0cnkgPSBmdW5jdGlvbiBnZXRYbWxSZWdpc3RyeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuUmVnaXN0cnkuZ2V0WE1MKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgdGhlIGN1cnJlbnQgcmVwb3NpdG9yeSAoZnJvbSB0aGUgY3VycmVudCB1c2VyKSBhbmQgbG9hZCBpdC5cbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkQWN0aXZlUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIGxvYWRBY3RpdmVSZXBvc2l0b3J5KCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICB2YXIgcmVwb3NpdG9yeU9iamVjdCA9IG5ldyBfbW9kZWxSZXBvc2l0b3J5MlsnZGVmYXVsdCddKG51bGwpO1xuICAgICAgICBpZiAodGhpcy51c2VyID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmxvYWRSZXBvc2l0b3J5KHJlcG9zaXRvcnlPYmplY3QpO1xuICAgICAgICAgICAgdGhpcy5maXJlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCB7IGxpc3Q6IGZhbHNlLCBhY3RpdmU6IGZhbHNlIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlcElkID0gdGhpcy51c2VyLmdldEFjdGl2ZVJlcG9zaXRvcnkoKTtcbiAgICAgICAgdmFyIHJlcExpc3QgPSB0aGlzLnVzZXIuZ2V0UmVwb3NpdG9yaWVzTGlzdCgpO1xuICAgICAgICByZXBvc2l0b3J5T2JqZWN0ID0gcmVwTGlzdC5nZXQocmVwSWQpO1xuXG4gICAgICAgIGlmICghcmVwb3NpdG9yeU9iamVjdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudXNlci5sb2NrKSB7XG4gICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXM0LkNvbnRyb2xsZXIubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoX3RoaXM0LmdldFhtbFJlZ2lzdHJ5KCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbG9jayA9IF90aGlzNC51c2VyLmxvY2suc3BsaXQoXCIsXCIpLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzNC5Db250cm9sbGVyLmZpcmVBY3Rpb24obG9jayk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDUwKTtcbiAgICAgICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbGVydChcIk5vIGFjdGl2ZSByZXBvc2l0b3J5IGZvdW5kIGZvciB1c2VyIVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVzZXIuZ2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIpICYmIHRoaXMudXNlci5nZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIikgIT0gXCItMVwiKSB7XG5cbiAgICAgICAgICAgIHRoaXMuX2luaXRMb2FkUmVwID0gdGhpcy51c2VyLmdldFByZWZlcmVuY2UoXCJwZW5kaW5nX2ZvbGRlclwiKTtcbiAgICAgICAgICAgIHRoaXMudXNlci5zZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIiwgXCItMVwiKTtcbiAgICAgICAgICAgIHRoaXMudXNlci5zYXZlUHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2FkUmVwb3NpdG9yeShyZXBvc2l0b3J5T2JqZWN0KTtcbiAgICAgICAgdGhpcy5maXJlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCB7IGxpc3Q6IHJlcExpc3QsIGFjdGl2ZTogcmVwSWQgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZnJlc2ggdGhlIHJlcG9zaXRvcmllcyBsaXN0IGZvciB0aGUgY3VycmVudCB1c2VyXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUucmVsb2FkUmVwb3NpdG9yaWVzTGlzdCA9IGZ1bmN0aW9uIHJlbG9hZFJlcG9zaXRvcmllc0xpc3QoKSB7XG4gICAgICAgIHZhciBfdGhpczUgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdGhpcy51c2VyKSByZXR1cm47XG4gICAgICAgIHRoaXMub2JzZXJ2ZU9uY2UoXCJyZWdpc3RyeV9wYXJ0X2xvYWRlZFwiLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgaWYgKGRhdGEgIT0gXCJ1c2VyL3JlcG9zaXRvcmllc1wiKSByZXR1cm47XG4gICAgICAgICAgICBfdGhpczUudXBkYXRlVXNlcihfdGhpczUuUmVnaXN0cnkucGFyc2VVc2VyKCkpO1xuICAgICAgICAgICAgX3RoaXM1LmZpcmUoXCJyZXBvc2l0b3J5X2xpc3RfcmVmcmVzaGVkXCIsIHtcbiAgICAgICAgICAgICAgICBsaXN0OiBfdGhpczUudXNlci5nZXRSZXBvc2l0b3JpZXNMaXN0KCksXG4gICAgICAgICAgICAgICAgYWN0aXZlOiBfdGhpczUudXNlci5nZXRBY3RpdmVSZXBvc2l0b3J5KClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sb2FkWG1sUmVnaXN0cnkoZmFsc2UsIFwidXNlci9yZXBvc2l0b3JpZXNcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBSZXBvc2l0b3J5IGluc3RhbmNlXG4gICAgICogQHBhcmFtIHJlcG9zaXRvcnkgUmVwb3NpdG9yeVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmxvYWRSZXBvc2l0b3J5ID0gZnVuY3Rpb24gbG9hZFJlcG9zaXRvcnkocmVwb3NpdG9yeSkge1xuICAgICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5yZXBvc2l0b3J5SWQgIT0gbnVsbCAmJiB0aGlzLnJlcG9zaXRvcnlJZCA9PSByZXBvc2l0b3J5LmdldElkKCkpIHtcbiAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmRlYnVnKCdSZXBvc2l0b3J5IGFscmVhZHkgbG9hZGVkLCBkbyBub3RoaW5nJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRTZWxlY3RlZE5vZGVzKFtdKTtcbiAgICAgICAgaWYgKHJlcG9zaXRvcnkgPT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgICAgIHJlcG9zaXRvcnkubG9hZFJlc291cmNlcygpO1xuICAgICAgICB2YXIgcmVwb3NpdG9yeUlkID0gcmVwb3NpdG9yeS5nZXRJZCgpO1xuICAgICAgICB2YXIgbmV3SWNvbiA9IHJlcG9zaXRvcnkuZ2V0SWNvbigpO1xuXG4gICAgICAgIHZhciBwcm92aWRlckRlZiA9IHJlcG9zaXRvcnkuZ2V0Tm9kZVByb3ZpZGVyRGVmKCk7XG4gICAgICAgIHZhciByb290Tm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHByb3ZpZGVyRGVmICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBwcm92aWRlciA9IGV2YWwoJ25ldyAnICsgcHJvdmlkZXJEZWYubmFtZSArICcoKScpO1xuICAgICAgICAgICAgaWYgKHByb3ZpZGVyRGVmLm9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm92aWRlci5pbml0UHJvdmlkZXIocHJvdmlkZXJEZWYub3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnNldEFqeHBOb2RlUHJvdmlkZXIocHJvdmlkZXIpO1xuICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10oXCIvXCIsIGZhbHNlLCByZXBvc2l0b3J5LmdldExhYmVsKCksIG5ld0ljb24sIHByb3ZpZGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKFwiL1wiLCBmYWxzZSwgcmVwb3NpdG9yeS5nZXRMYWJlbCgpLCBuZXdJY29uKTtcbiAgICAgICAgICAgIC8vIERlZmF1bHRcbiAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0QWp4cE5vZGVQcm92aWRlcihuZXcgX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyMlsnZGVmYXVsdCddKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluaXRMb2FkUmVwID0gdGhpcy5faW5pdExvYWRSZXAgJiYgdGhpcy5faW5pdExvYWRSZXAgIT09ICcvJyA/IHRoaXMuX2luaXRMb2FkUmVwLnZhbHVlT2YoKSA6IG51bGw7XG4gICAgICAgIHZhciBmaXJzdExvYWRPYnMgPSBmdW5jdGlvbiBmaXJzdExvYWRPYnMoKSB7fTtcbiAgICAgICAgaWYgKGluaXRMb2FkUmVwKSB7XG4gICAgICAgICAgICBmaXJzdExvYWRPYnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXM2LmdvVG8oaW5pdExvYWRSZXApO1xuICAgICAgICAgICAgICAgIF90aGlzNi5faW5pdExvYWRSZXAgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0Um9vdE5vZGUocm9vdE5vZGUpO1xuICAgICAgICByb290Tm9kZS5vYnNlcnZlT25jZSgnZmlyc3RfbG9hZCcsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLm5vdGlmeSgnY29udGV4dF9jaGFuZ2VkJywgcm9vdE5vZGUpO1xuICAgICAgICAgICAgZmlyc3RMb2FkT2JzKCk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLnJlcG9zaXRvcnlJZCA9IHJlcG9zaXRvcnlJZDtcbiAgICAgICAgcm9vdE5vZGUubG9hZCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXF1aXJlIGEgY29udGV4dCBjaGFuZ2UgdG8gdGhlIGdpdmVuIHBhdGhcbiAgICAgKiBAcGFyYW0gbm9kZU9yUGF0aCBBanhwTm9kZXxTdHJpbmcgQSBub2RlIG9yIGEgcGF0aFxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdvVG8gPSBmdW5jdGlvbiBnb1RvKG5vZGVPclBhdGgpIHtcbiAgICAgICAgdmFyIGdvdG9Ob2RlID0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgcGF0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHR5cGVvZiBub2RlT3JQYXRoID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHBhdGggPSBub2RlT3JQYXRoO1xuICAgICAgICAgICAgZ290b05vZGUgPSBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10obm9kZU9yUGF0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnb3RvTm9kZSA9IG5vZGVPclBhdGg7XG4gICAgICAgICAgICBwYXRoID0gZ290b05vZGUuZ2V0UGF0aCgpO1xuICAgICAgICAgICAgaWYgKG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5oYXMoXCJyZXBvc2l0b3J5X2lkXCIpICYmIG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5nZXQoXCJyZXBvc2l0b3J5X2lkXCIpICE9IHRoaXMucmVwb3NpdG9yeUlkICYmIG5vZGVPclBhdGguZ2V0QWp4cE1pbWUoKSAhPSBcInJlcG9zaXRvcnlcIiAmJiBub2RlT3JQYXRoLmdldEFqeHBNaW1lKCkgIT0gXCJyZXBvc2l0b3J5X2VkaXRhYmxlXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXNlci5zZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIiwgbm9kZU9yUGF0aC5nZXRQYXRoKCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IG5vZGVPclBhdGguZ2V0UGF0aCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXJSZXBvc2l0b3J5Q2hhbmdlKG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5nZXQoXCJyZXBvc2l0b3J5X2lkXCIpKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3JlcG9zaXRvcnlDdXJyZW50bHlTd2l0Y2hpbmcgJiYgdGhpcy51c2VyKSB7XG4gICAgICAgICAgICB0aGlzLnVzZXIuc2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIsIGdvdG9Ob2RlLmdldFBhdGgoKSk7XG4gICAgICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IGdvdG9Ob2RlLmdldFBhdGgoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Q29udGV4dE5vZGUoKTtcbiAgICAgICAgaWYgKGN1cnJlbnQgJiYgY3VycmVudC5nZXRQYXRoKCkgPT0gcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoID09PSBcIlwiIHx8IHBhdGggPT09IFwiL1wiKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnJlcXVpcmVDb250ZXh0Q2hhbmdlKHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Um9vdE5vZGUoKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnb3RvTm9kZSA9IGdvdG9Ob2RlLmZpbmRJbkFyYm8odGhpcy5fY29udGV4dEhvbGRlci5nZXRSb290Tm9kZSgpKTtcbiAgICAgICAgICAgIGlmIChnb3RvTm9kZSkge1xuICAgICAgICAgICAgICAgIC8vIE5vZGUgaXMgYWxyZWFkeSBoZXJlXG4gICAgICAgICAgICAgICAgaWYgKCFnb3RvTm9kZS5pc0Jyb3dzYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0UGVuZGluZ1NlbGVjdGlvbihfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShwYXRoKSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoZ290b05vZGUuZ2V0UGFyZW50KCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoZ290b05vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgb24gc2VydmVyIGlmIGl0IGRvZXMgZXhpc3QsIHRoZW4gbG9hZFxuICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIubG9hZFBhdGhJbmZvQXN5bmMocGF0aCwgKGZ1bmN0aW9uIChmb3VuZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmb3VuZE5vZGUuaXNCcm93c2FibGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRQZW5kaW5nU2VsZWN0aW9uKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKHBhdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdvdG9Ob2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUocGF0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ290b05vZGUgPSBmb3VuZE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5yZXF1aXJlQ29udGV4dENoYW5nZShnb3RvTm9kZSk7XG4gICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlIHRoZSByZXBvc2l0b3J5IG9mIHRoZSBjdXJyZW50IHVzZXIgYW5kIHJlbG9hZCBsaXN0IGFuZCBjdXJyZW50LlxuICAgICAqIEBwYXJhbSByZXBvc2l0b3J5SWQgU3RyaW5nIElkIG9mIHRoZSBuZXcgcmVwb3NpdG9yeVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnRyaWdnZXJSZXBvc2l0b3J5Q2hhbmdlID0gZnVuY3Rpb24gdHJpZ2dlclJlcG9zaXRvcnlDaGFuZ2UocmVwb3NpdG9yeUlkLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgICB0aGlzLmZpcmUoXCJ0cmlnZ2VyX3JlcG9zaXRvcnlfc3dpdGNoXCIpO1xuICAgICAgICB0aGlzLl9yZXBvc2l0b3J5Q3VycmVudGx5U3dpdGNoaW5nID0gdHJ1ZTtcbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSBmdW5jdGlvbiBvbkNvbXBsZXRlKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTCkge1xuICAgICAgICAgICAgICAgIF90aGlzNy5BcGlDbGllbnQucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpczcubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBudWxsLCBudWxsLCByZXBvc2l0b3J5SWQpO1xuICAgICAgICAgICAgX3RoaXM3LnJlcG9zaXRvcnlJZCA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT0gXCJmdW5jdGlvblwiKSBjYWxsYmFjaygpO1xuICAgICAgICAgICAgX3RoaXM3Ll9yZXBvc2l0b3J5Q3VycmVudGx5U3dpdGNoaW5nID0gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHJvb3QgPSB0aGlzLl9jb250ZXh0SG9sZGVyLmdldFJvb3ROb2RlKCk7XG4gICAgICAgIGlmIChyb290KSB7XG4gICAgICAgICAgICByb290LmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5BcGlDbGllbnQuc3dpdGNoUmVwb3NpdG9yeShyZXBvc2l0b3J5SWQsIG9uQ29tcGxldGUpO1xuICAgIH07XG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0UGx1Z2luQ29uZmlncyA9IGZ1bmN0aW9uIGdldFBsdWdpbkNvbmZpZ3MocGx1Z2luUXVlcnkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuUmVnaXN0cnkuZ2V0UGx1Z2luQ29uZmlncyhwbHVnaW5RdWVyeSk7XG4gICAgfTtcblxuICAgIFB5ZGlvLnByb3RvdHlwZS5saXN0TGFuZ3VhZ2VzV2l0aENhbGxiYWNrID0gZnVuY3Rpb24gbGlzdExhbmd1YWdlc1dpdGhDYWxsYmFjayhjYWxsYmFjaykge1xuICAgICAgICB2YXIgbGFuZ3MgPSB0aGlzLlBhcmFtZXRlcnMuZ2V0KFwiYXZhaWxhYmxlTGFuZ3VhZ2VzXCIpIHx8IHsgXCJlblwiOiBcIkRlZmF1bHRcIiB9O1xuICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudExhbmd1YWdlO1xuICAgICAgICBPYmplY3Qua2V5cyhsYW5ncykuc29ydCgpLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBjYWxsYmFjayhrZXksIGxhbmdzW2tleV0sIGN1cnJlbnQgPT09IGtleSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWxvYWQgYWxsIG1lc3NhZ2VzIGZyb20gc2VydmVyIGFuZCB0cmlnZ2VyIHVwZGF0ZUkxOG5UYWdzXG4gICAgICogQHBhcmFtIG5ld0xhbmd1YWdlIFN0cmluZ1xuICAgICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvblxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmxvYWRJMThOTWVzc2FnZXMgPSBmdW5jdGlvbiBsb2FkSTE4Tk1lc3NhZ2VzKG5ld0xhbmd1YWdlKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdGhpcy5BcGlDbGllbnQuc3dpdGNoTGFuZ3VhZ2UobmV3TGFuZ3VhZ2UsIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlSlNPTikge1xuICAgICAgICAgICAgICAgIHRoaXMuTWVzc2FnZUhhc2ggPSB0cmFuc3BvcnQucmVzcG9uc2VKU09OO1xuICAgICAgICAgICAgICAgIGlmICh3aW5kb3cgJiYgd2luZG93Lk1lc3NhZ2VIYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5NZXNzYWdlSGFzaCA9IHRoaXMuTWVzc2FnZUhhc2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLk1lc3NhZ2VIYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLk1lc3NhZ2VIYXNoLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuTWVzc2FnZUhhc2hba2V5XSA9IHRoaXMuTWVzc2FnZUhhc2hba2V5XS5yZXBsYWNlKFwiXFxcXG5cIiwgXCJcXG5cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5Db250cm9sbGVyLnJlZnJlc2hHdWlBY3Rpb25zSTE4bigpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZFhtbFJlZ2lzdHJ5KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ29udGV4dFJlZnJlc2goKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZSA9IG5ld0xhbmd1YWdlO1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgbWFpbiBjb250cm9sbGVyXG4gICAgICogQHJldHVybnMgQWN0aW9uTWFuYWdlclxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldENvbnRyb2xsZXIgPSBmdW5jdGlvbiBnZXRDb250cm9sbGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5Db250cm9sbGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBEaXNwbGF5IGFuIGluZm9ybWF0aW9uIG9yIGVycm9yIG1lc3NhZ2UgdG8gdGhlIHVzZXJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZVR5cGUgU3RyaW5nIEVSUk9SIG9yIFNVQ0NFU1NcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBTdHJpbmcgdGhlIG1lc3NhZ2VcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5kaXNwbGF5TWVzc2FnZSA9IGZ1bmN0aW9uIGRpc3BsYXlNZXNzYWdlKG1lc3NhZ2VUeXBlLCBtZXNzYWdlKSB7XG4gICAgICAgIHZhciB1cmxzID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ucGFyc2VVcmwobWVzc2FnZSk7XG4gICAgICAgIGlmICh1cmxzLmxlbmd0aCAmJiB0aGlzLnVzZXIgJiYgdGhpcy51c2VyLnJlcG9zaXRvcmllcykge1xuICAgICAgICAgICAgdXJscy5mb3JFYWNoKChmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwbyA9IHRoaXMudXNlci5yZXBvc2l0b3JpZXMuZ2V0KG1hdGNoLmhvc3QpO1xuICAgICAgICAgICAgICAgIGlmICghcmVwbykgcmV0dXJuO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBtZXNzYWdlLnJlcGxhY2UobWF0Y2gudXJsLCByZXBvLmxhYmVsICsgXCI6XCIgKyBtYXRjaC5wYXRoICsgbWF0Y2guZmlsZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVzc2FnZVR5cGUgPT0gJ0VSUk9SJykgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IobWVzc2FnZSk7ZWxzZSBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5sb2cobWVzc2FnZSk7XG4gICAgICAgIGlmICh0aGlzLlVJKSB7XG4gICAgICAgICAgICB0aGlzLlVJLmRpc3BsYXlNZXNzYWdlKG1lc3NhZ2VUeXBlLCBtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAqXG4gICAgICogICAgICAgICAgUFJPWFkgTUVUSE9EUyBGT1IgREFUQU1PREVMXG4gICAgICpcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIHVwZGF0aW5nIHRoZSBkYXRhbW9kZWwgY29udGV4dFxuICAgICAqIEBwYXJhbSBhanhwQ29udGV4dE5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gYWp4cFNlbGVjdGVkTm9kZXMgQWp4cE5vZGVbXVxuICAgICAqIEBwYXJhbSBzZWxlY3Rpb25Tb3VyY2UgU3RyaW5nXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUudXBkYXRlQ29udGV4dERhdGEgPSBmdW5jdGlvbiB1cGRhdGVDb250ZXh0RGF0YShhanhwQ29udGV4dE5vZGUsIGFqeHBTZWxlY3RlZE5vZGVzLCBzZWxlY3Rpb25Tb3VyY2UpIHtcbiAgICAgICAgaWYgKGFqeHBDb250ZXh0Tm9kZSkge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5yZXF1aXJlQ29udGV4dENoYW5nZShhanhwQ29udGV4dE5vZGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhanhwU2VsZWN0ZWROb2Rlcykge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRTZWxlY3RlZE5vZGVzKGFqeHBTZWxlY3RlZE5vZGVzLCBzZWxlY3Rpb25Tb3VyY2UpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBEYXRhTW9kZWxcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRDb250ZXh0SG9sZGVyID0gZnVuY3Rpb24gZ2V0Q29udGV4dEhvbGRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0Q29udGV4dE5vZGUgPSBmdW5jdGlvbiBnZXRDb250ZXh0Tm9kZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Q29udGV4dE5vZGUoKSB8fCBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10oXCJcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBEYXRhTW9kZWxcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRVc2VyU2VsZWN0aW9uID0gZnVuY3Rpb24gZ2V0VXNlclNlbGVjdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFjY2Vzc29yIGZvciBkYXRhbW9kZWwucmVxdWlyZUNvbnRleHRDaGFuZ2UoKVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmZpcmVDb250ZXh0UmVmcmVzaCA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0UmVmcmVzaCgpIHtcbiAgICAgICAgdGhpcy5nZXRDb250ZXh0SG9sZGVyKCkucmVxdWlyZUNvbnRleHRDaGFuZ2UodGhpcy5nZXRDb250ZXh0Tm9kZSgpLCB0cnVlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIGRhdGFtb2RlbC5yZXF1aXJlQ29udGV4dENoYW5nZSgpXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZmlyZU5vZGVSZWZyZXNoID0gZnVuY3Rpb24gZmlyZU5vZGVSZWZyZXNoKG5vZGVQYXRoT3JOb2RlLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2V0Q29udGV4dEhvbGRlcigpLnJlcXVpcmVOb2RlUmVsb2FkKG5vZGVQYXRoT3JOb2RlLCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIGRhdGFtb2RlbC5yZXF1aXJlQ29udGV4dENoYW5nZSgpXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZmlyZUNvbnRleHRVcCA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0VXAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdldENvbnRleHROb2RlKCkuaXNSb290KCkpIHJldHVybjtcbiAgICAgICAgdGhpcy51cGRhdGVDb250ZXh0RGF0YSh0aGlzLmdldENvbnRleHROb2RlKCkuZ2V0UGFyZW50KCkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQcm94eSB0byBSZXNvdXJjZXNNYW5hZ2VyLnJlcXVpcmVMaWIgZm9yIGVhc2Ugb2Ygd3JpdGluZ1xuICAgICAqIEBwYXJhbSBtb2R1bGVcbiAgICAgKiBAcGFyYW0gcHJvbWlzZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuXG4gICAgUHlkaW8ucmVxdWlyZUxpYiA9IGZ1bmN0aW9uIHJlcXVpcmVMaWIobW9kdWxlKSB7XG4gICAgICAgIHZhciBwcm9taXNlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgcmV0dXJuIHJlcXVpcmUoJ3B5ZGlvL2h0dHAvcmVzb3VyY2VzLW1hbmFnZXInKS5yZXF1aXJlTGliKG1vZHVsZSwgcHJvbWlzZSk7XG4gICAgfTtcblxuICAgIHJldHVybiBQeWRpbztcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFB5ZGlvO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iXX0=