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":5,"isarray":6}],5:[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 } },{}],6:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; },{}],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() rawHeaders.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 = 'status' in options ? options.status : 200 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 } 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 = {}; 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9saWIvX2VtcHR5LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvaWVlZTc1NC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pc2FycmF5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3N5c3RlbWpzL2Rpc3Qvc3lzdGVtLnNyYy5qcyIsIm5vZGVfbW9kdWxlcy93aGF0d2ctZmV0Y2gvZmV0Y2guanMiLCJub2RlX21vZHVsZXMvd2lja2VkLWdvb2QteHBhdGgvZGlzdC93Z3hwYXRoLmluc3RhbGwtbm9kZS5qcyIsInJlcy9idWlsZC9jb3JlL2luZGV4LmpzIiwicmVzL2J1aWxkL2NvcmUvaHR0cC9QeWRpb0FwaS5qcyIsInJlcy9idWlsZC9jb3JlL2h0dHAvQ29ubmV4aW9uLmpzIiwicmVzL2J1aWxkL2NvcmUvaHR0cC9NZXRhQ2FjaGVTZXJ2aWNlLmpzIiwicmVzL2J1aWxkL2NvcmUvaHR0cC9SZXNvdXJjZXNNYW5hZ2VyLmpzIiwicmVzL2J1aWxkL2NvcmUvaHR0cC9QeWRpb1VzZXJzQXBpLmpzIiwicmVzL2J1aWxkL2NvcmUvbGFuZy9Mb2dnZXIuanMiLCJyZXMvYnVpbGQvY29yZS9sYW5nL09ic2VydmFibGUuanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9BY3Rpb24uanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9Db250ZXh0TWVudSIsInJlcy9idWlsZC9jb3JlL21vZGVsL0NvbnRyb2xsZXIuanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9QeWRpb0RhdGFNb2RlbC5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL0VtcHR5Tm9kZVByb3ZpZGVyLmpzIiwicmVzL2J1aWxkL2NvcmUvbW9kZWwvQWp4cE5vZGUuanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9SZWdpc3RyeS5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL1JlbW90ZU5vZGVQcm92aWRlci5qcyIsInJlcy9idWlsZC9jb3JlL21vZGVsL1JlcG9zaXRvcnkuanMiLCJyZXMvYnVpbGQvY29yZS9tb2RlbC9Vc2VyLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9BY3Rpdml0eU1vbml0b3IuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL0Nvb2tpZXNNYW5hZ2VyLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9ET01VdGlscy5qcyIsInJlcy9idWlsZC9jb3JlL3V0aWwvRnVuY1V0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9IYXNoZXJVdGlscy5qcyIsInJlcy9idWlsZC9jb3JlL3V0aWwvTGFuZ1V0aWxzLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9QYXNzVXRpbHMuanMiLCJyZXMvYnVpbGQvY29yZS91dGlsL1BhdGhVdGlscy5qcyIsInJlcy9idWlsZC9jb3JlL3V0aWwvUGVyaW9kaWNhbEV4ZWN1dGVyLmpzIiwicmVzL2J1aWxkL2NvcmUvdXRpbC9YTUxVdGlscy5qcyIsInJlcy9idWlsZC9jb3JlL1B5ZGlvIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDeExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDNWdEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDaDZIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzdjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3JjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNuT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzeUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25uQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdDJCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM2lCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4U0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2WUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdlVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcGFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDMUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBsb29rdXAgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyc7XG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0J3VzZSBzdHJpY3QnO1xuXG4gIHZhciBBcnIgPSAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKVxuICAgID8gVWludDhBcnJheVxuICAgIDogQXJyYXlcblxuXHR2YXIgUExVUyAgID0gJysnLmNoYXJDb2RlQXQoMClcblx0dmFyIFNMQVNIICA9ICcvJy5jaGFyQ29kZUF0KDApXG5cdHZhciBOVU1CRVIgPSAnMCcuY2hhckNvZGVBdCgwKVxuXHR2YXIgTE9XRVIgID0gJ2EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFVQUEVSICA9ICdBJy5jaGFyQ29kZUF0KDApXG5cdHZhciBQTFVTX1VSTF9TQUZFID0gJy0nLmNoYXJDb2RlQXQoMClcblx0dmFyIFNMQVNIX1VSTF9TQUZFID0gJ18nLmNoYXJDb2RlQXQoMClcblxuXHRmdW5jdGlvbiBkZWNvZGUgKGVsdCkge1xuXHRcdHZhciBjb2RlID0gZWx0LmNoYXJDb2RlQXQoMClcblx0XHRpZiAoY29kZSA9PT0gUExVUyB8fFxuXHRcdCAgICBjb2RlID09PSBQTFVTX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYyIC8vICcrJ1xuXHRcdGlmIChjb2RlID09PSBTTEFTSCB8fFxuXHRcdCAgICBjb2RlID09PSBTTEFTSF9VUkxfU0FGRSlcblx0XHRcdHJldHVybiA2MyAvLyAnLydcblx0XHRpZiAoY29kZSA8IE5VTUJFUilcblx0XHRcdHJldHVybiAtMSAvL25vIG1hdGNoXG5cdFx0aWYgKGNvZGUgPCBOVU1CRVIgKyAxMClcblx0XHRcdHJldHVybiBjb2RlIC0gTlVNQkVSICsgMjYgKyAyNlxuXHRcdGlmIChjb2RlIDwgVVBQRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gVVBQRVJcblx0XHRpZiAoY29kZSA8IExPV0VSICsgMjYpXG5cdFx0XHRyZXR1cm4gY29kZSAtIExPV0VSICsgMjZcblx0fVxuXG5cdGZ1bmN0aW9uIGI2NFRvQnl0ZUFycmF5IChiNjQpIHtcblx0XHR2YXIgaSwgaiwgbCwgdG1wLCBwbGFjZUhvbGRlcnMsIGFyclxuXG5cdFx0aWYgKGI2NC5sZW5ndGggJSA0ID4gMCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0Jylcblx0XHR9XG5cblx0XHQvLyB0aGUgbnVtYmVyIG9mIGVxdWFsIHNpZ25zIChwbGFjZSBob2xkZXJzKVxuXHRcdC8vIGlmIHRoZXJlIGFyZSB0d28gcGxhY2Vob2xkZXJzLCB0aGFuIHRoZSB0d28gY2hhcmFjdGVycyBiZWZvcmUgaXRcblx0XHQvLyByZXByZXNlbnQgb25lIGJ5dGVcblx0XHQvLyBpZiB0aGVyZSBpcyBvbmx5IG9uZSwgdGhlbiB0aGUgdGhyZWUgY2hhcmFjdGVycyBiZWZvcmUgaXQgcmVwcmVzZW50IDIgYnl0ZXNcblx0XHQvLyB0aGlzIGlzIGp1c3QgYSBjaGVhcCBoYWNrIHRvIG5vdCBkbyBpbmRleE9mIHR3aWNlXG5cdFx0dmFyIGxlbiA9IGI2NC5sZW5ndGhcblx0XHRwbGFjZUhvbGRlcnMgPSAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMikgPyAyIDogJz0nID09PSBiNjQuY2hhckF0KGxlbiAtIDEpID8gMSA6IDBcblxuXHRcdC8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuXHRcdGFyciA9IG5ldyBBcnIoYjY0Lmxlbmd0aCAqIDMgLyA0IC0gcGxhY2VIb2xkZXJzKVxuXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuXHRcdGwgPSBwbGFjZUhvbGRlcnMgPiAwID8gYjY0Lmxlbmd0aCAtIDQgOiBiNjQubGVuZ3RoXG5cblx0XHR2YXIgTCA9IDBcblxuXHRcdGZ1bmN0aW9uIHB1c2ggKHYpIHtcblx0XHRcdGFycltMKytdID0gdlxuXHRcdH1cblxuXHRcdGZvciAoaSA9IDAsIGogPSAwOyBpIDwgbDsgaSArPSA0LCBqICs9IDMpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTgpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgMTIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAyKSkgPDwgNikgfCBkZWNvZGUoYjY0LmNoYXJBdChpICsgMykpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDAwMCkgPj4gMTYpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDApID4+IDgpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlSG9sZGVycyA9PT0gMikge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAyKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpID4+IDQpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fSBlbHNlIGlmIChwbGFjZUhvbGRlcnMgPT09IDEpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTApIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgNCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA+PiAyKVxuXHRcdFx0cHVzaCgodG1wID4+IDgpICYgMHhGRilcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRyZXR1cm4gYXJyXG5cdH1cblxuXHRmdW5jdGlvbiB1aW50OFRvQmFzZTY0ICh1aW50OCkge1xuXHRcdHZhciBpLFxuXHRcdFx0ZXh0cmFCeXRlcyA9IHVpbnQ4Lmxlbmd0aCAlIDMsIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG5cdFx0XHRvdXRwdXQgPSBcIlwiLFxuXHRcdFx0dGVtcCwgbGVuZ3RoXG5cblx0XHRmdW5jdGlvbiBlbmNvZGUgKG51bSkge1xuXHRcdFx0cmV0dXJuIGxvb2t1cC5jaGFyQXQobnVtKVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG5cdFx0XHRyZXR1cm4gZW5jb2RlKG51bSA+PiAxOCAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiAxMiAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiA2ICYgMHgzRikgKyBlbmNvZGUobnVtICYgMHgzRilcblx0XHR9XG5cblx0XHQvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG5cdFx0Zm9yIChpID0gMCwgbGVuZ3RoID0gdWludDgubGVuZ3RoIC0gZXh0cmFCeXRlczsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG5cdFx0XHR0ZW1wID0gKHVpbnQ4W2ldIDw8IDE2KSArICh1aW50OFtpICsgMV0gPDwgOCkgKyAodWludDhbaSArIDJdKVxuXHRcdFx0b3V0cHV0ICs9IHRyaXBsZXRUb0Jhc2U2NCh0ZW1wKVxuXHRcdH1cblxuXHRcdC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcblx0XHRzd2l0Y2ggKGV4dHJhQnl0ZXMpIHtcblx0XHRcdGNhc2UgMTpcblx0XHRcdFx0dGVtcCA9IHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUodGVtcCA+PiAyKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9PSdcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0dGVtcCA9ICh1aW50OFt1aW50OC5sZW5ndGggLSAyXSA8PCA4KSArICh1aW50OFt1aW50OC5sZW5ndGggLSAxXSlcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDEwKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wID4+IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA8PCAyKSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSAnPSdcblx0XHRcdFx0YnJlYWtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0cHV0XG5cdH1cblxuXHRleHBvcnRzLnRvQnl0ZUFycmF5ID0gYjY0VG9CeXRlQXJyYXlcblx0ZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gdWludDhUb0Jhc2U2NFxufSh0eXBlb2YgZXhwb3J0cyA9PT0gJ3VuZGVmaW5lZCcgPyAodGhpcy5iYXNlNjRqcyA9IHt9KSA6IGV4cG9ydHMpKVxuIixudWxsLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cblxuJ3VzZSBzdHJpY3QnXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXNhcnJheScpXG5cbmV4cG9ydHMuQnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLlNsb3dCdWZmZXIgPSBTbG93QnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcbkJ1ZmZlci5wb29sU2l6ZSA9IDgxOTIgLy8gbm90IHVzZWQgYnkgdGhpcyBpbXBsZW1lbnRhdGlvblxuXG52YXIgcm9vdFBhcmVudCA9IHt9XG5cbi8qKlxuICogSWYgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYDpcbiAqICAgPT09IHRydWUgICAgVXNlIFVpbnQ4QXJyYXkgaW1wbGVtZW50YXRpb24gKGZhc3Rlc3QpXG4gKiAgID09PSBmYWxzZSAgIFVzZSBPYmplY3QgaW1wbGVtZW50YXRpb24gKG1vc3QgY29tcGF0aWJsZSwgZXZlbiBJRTYpXG4gKlxuICogQnJvd3NlcnMgdGhhdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBhcmUgSUUgMTArLCBGaXJlZm94IDQrLCBDaHJvbWUgNyssIFNhZmFyaSA1LjErLFxuICogT3BlcmEgMTEuNissIGlPUyA0LjIrLlxuICpcbiAqIER1ZSB0byB2YXJpb3VzIGJyb3dzZXIgYnVncywgc29tZXRpbWVzIHRoZSBPYmplY3QgaW1wbGVtZW50YXRpb24gd2lsbCBiZSB1c2VkIGV2ZW5cbiAqIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgdHlwZWQgYXJyYXlzLlxuICpcbiAqIE5vdGU6XG4gKlxuICogICAtIEZpcmVmb3ggNC0yOSBsYWNrcyBzdXBwb3J0IGZvciBhZGRpbmcgbmV3IHByb3BlcnRpZXMgdG8gYFVpbnQ4QXJyYXlgIGluc3RhbmNlcyxcbiAqICAgICBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOC5cbiAqXG4gKiAgIC0gU2FmYXJpIDUtNyBsYWNrcyBzdXBwb3J0IGZvciBjaGFuZ2luZyB0aGUgYE9iamVjdC5wcm90b3R5cGUuY29uc3RydWN0b3JgIHByb3BlcnR5XG4gKiAgICAgb24gb2JqZWN0cy5cbiAqXG4gKiAgIC0gQ2hyb21lIDktMTAgaXMgbWlzc2luZyB0aGUgYFR5cGVkQXJyYXkucHJvdG90eXBlLnN1YmFycmF5YCBmdW5jdGlvbi5cbiAqXG4gKiAgIC0gSUUxMCBoYXMgYSBicm9rZW4gYFR5cGVkQXJyYXkucHJvdG90eXBlLnN1YmFycmF5YCBmdW5jdGlvbiB3aGljaCByZXR1cm5zIGFycmF5cyBvZlxuICogICAgIGluY29ycmVjdCBsZW5ndGggaW4gc29tZSBzaXR1YXRpb25zLlxuXG4gKiBXZSBkZXRlY3QgdGhlc2UgYnVnZ3kgYnJvd3NlcnMgYW5kIHNldCBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgIHRvIGBmYWxzZWAgc28gdGhleVxuICogZ2V0IHRoZSBPYmplY3QgaW1wbGVtZW50YXRpb24sIHdoaWNoIGlzIHNsb3dlciBidXQgYmVoYXZlcyBjb3JyZWN0bHkuXG4gKi9cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gZ2xvYmFsLlRZUEVEX0FSUkFZX1NVUFBPUlQgIT09IHVuZGVmaW5lZFxuICA/IGdsb2JhbC5UWVBFRF9BUlJBWV9TVVBQT1JUXG4gIDogdHlwZWRBcnJheVN1cHBvcnQoKVxuXG5mdW5jdGlvbiB0eXBlZEFycmF5U3VwcG9ydCAoKSB7XG4gIGZ1bmN0aW9uIEJhciAoKSB7fVxuICB0cnkge1xuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGFyci5mb28gPSBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9XG4gICAgYXJyLmNvbnN0cnVjdG9yID0gQmFyXG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDIgJiYgLy8gdHlwZWQgYXJyYXkgaW5zdGFuY2VzIGNhbiBiZSBhdWdtZW50ZWRcbiAgICAgICAgYXJyLmNvbnN0cnVjdG9yID09PSBCYXIgJiYgLy8gY29uc3RydWN0b3IgY2FuIGJlIHNldFxuICAgICAgICB0eXBlb2YgYXJyLnN1YmFycmF5ID09PSAnZnVuY3Rpb24nICYmIC8vIGNocm9tZSA5LTEwIGxhY2sgYHN1YmFycmF5YFxuICAgICAgICBhcnIuc3ViYXJyYXkoMSwgMSkuYnl0ZUxlbmd0aCA9PT0gMCAvLyBpZTEwIGhhcyBicm9rZW4gYHN1YmFycmF5YFxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuZnVuY3Rpb24ga01heExlbmd0aCAoKSB7XG4gIHJldHVybiBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVFxuICAgID8gMHg3ZmZmZmZmZlxuICAgIDogMHgzZmZmZmZmZlxufVxuXG4vKipcbiAqIENsYXNzOiBCdWZmZXJcbiAqID09PT09PT09PT09PT1cbiAqXG4gKiBUaGUgQnVmZmVyIGNvbnN0cnVjdG9yIHJldHVybnMgaW5zdGFuY2VzIG9mIGBVaW50OEFycmF5YCB0aGF0IGFyZSBhdWdtZW50ZWRcbiAqIHdpdGggZnVuY3Rpb24gcHJvcGVydGllcyBmb3IgYWxsIHRoZSBub2RlIGBCdWZmZXJgIEFQSSBmdW5jdGlvbnMuIFdlIHVzZVxuICogYFVpbnQ4QXJyYXlgIHNvIHRoYXQgc3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXQgcmV0dXJuc1xuICogYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogQnkgYXVnbWVudGluZyB0aGUgaW5zdGFuY2VzLCB3ZSBjYW4gYXZvaWQgbW9kaWZ5aW5nIHRoZSBgVWludDhBcnJheWBcbiAqIHByb3RvdHlwZS5cbiAqL1xuZnVuY3Rpb24gQnVmZmVyIChhcmcpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpIHtcbiAgICAvLyBBdm9pZCBnb2luZyB0aHJvdWdoIGFuIEFyZ3VtZW50c0FkYXB0b3JUcmFtcG9saW5lIGluIHRoZSBjb21tb24gY2FzZS5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHJldHVybiBuZXcgQnVmZmVyKGFyZywgYXJndW1lbnRzWzFdKVxuICAgIHJldHVybiBuZXcgQnVmZmVyKGFyZylcbiAgfVxuXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzLmxlbmd0aCA9IDBcbiAgICB0aGlzLnBhcmVudCA9IHVuZGVmaW5lZFxuICB9XG5cbiAgLy8gQ29tbW9uIGNhc2UuXG4gIGlmICh0eXBlb2YgYXJnID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBmcm9tTnVtYmVyKHRoaXMsIGFyZylcbiAgfVxuXG4gIC8vIFNsaWdodGx5IGxlc3MgY29tbW9uIGNhc2UuXG4gIGlmICh0eXBlb2YgYXJnID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmcm9tU3RyaW5nKHRoaXMsIGFyZywgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiAndXRmOCcpXG4gIH1cblxuICAvLyBVbnVzdWFsLlxuICByZXR1cm4gZnJvbU9iamVjdCh0aGlzLCBhcmcpXG59XG5cbmZ1bmN0aW9uIGZyb21OdW1iZXIgKHRoYXQsIGxlbmd0aCkge1xuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoIDwgMCA/IDAgOiBjaGVja2VkKGxlbmd0aCkgfCAwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdGhhdFtpXSA9IDBcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAodGhhdCwgc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgLy8gQXNzdW1wdGlvbjogYnl0ZUxlbmd0aCgpIHJldHVybiB2YWx1ZSBpcyBhbHdheXMgPCBrTWF4TGVuZ3RoLlxuICB2YXIgbGVuZ3RoID0gYnl0ZUxlbmd0aChzdHJpbmcsIGVuY29kaW5nKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcblxuICB0aGF0LndyaXRlKHN0cmluZywgZW5jb2RpbmcpXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21PYmplY3QgKHRoYXQsIG9iamVjdCkge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKG9iamVjdCkpIHJldHVybiBmcm9tQnVmZmVyKHRoYXQsIG9iamVjdClcblxuICBpZiAoaXNBcnJheShvYmplY3QpKSByZXR1cm4gZnJvbUFycmF5KHRoYXQsIG9iamVjdClcblxuICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdXN0IHN0YXJ0IHdpdGggbnVtYmVyLCBidWZmZXIsIGFycmF5IG9yIHN0cmluZycpXG4gIH1cblxuICBpZiAodHlwZW9mIEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmIChvYmplY3QuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgIHJldHVybiBmcm9tVHlwZWRBcnJheSh0aGF0LCBvYmplY3QpXG4gICAgfVxuICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih0aGF0LCBvYmplY3QpXG4gICAgfVxuICB9XG5cbiAgaWYgKG9iamVjdC5sZW5ndGgpIHJldHVybiBmcm9tQXJyYXlMaWtlKHRoYXQsIG9iamVjdClcblxuICByZXR1cm4gZnJvbUpzb25PYmplY3QodGhhdCwgb2JqZWN0KVxufVxuXG5mdW5jdGlvbiBmcm9tQnVmZmVyICh0aGF0LCBidWZmZXIpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYnVmZmVyLmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGJ1ZmZlci5jb3B5KHRoYXQsIDAsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5ICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuLy8gRHVwbGljYXRlIG9mIGZyb21BcnJheSgpIHRvIGtlZXAgZnJvbUFycmF5KCkgbW9ub21vcnBoaWMuXG5mdW5jdGlvbiBmcm9tVHlwZWRBcnJheSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgLy8gVHJ1bmNhdGluZyB0aGUgZWxlbWVudHMgaXMgcHJvYmFibHkgbm90IHdoYXQgcGVvcGxlIGV4cGVjdCBmcm9tIHR5cGVkXG4gIC8vIGFycmF5cyB3aXRoIEJZVEVTX1BFUl9FTEVNRU5UID4gMSBidXQgaXQncyBjb21wYXRpYmxlIHdpdGggdGhlIGJlaGF2aW9yXG4gIC8vIG9mIHRoZSBvbGQgQnVmZmVyIGNvbnN0cnVjdG9yLlxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5QnVmZmVyICh0aGF0LCBhcnJheSkge1xuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSwgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICBhcnJheS5ieXRlTGVuZ3RoXG4gICAgdGhhdCA9IEJ1ZmZlci5fYXVnbWVudChuZXcgVWludDhBcnJheShhcnJheSkpXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBhbiBvYmplY3QgaW5zdGFuY2Ugb2YgdGhlIEJ1ZmZlciBjbGFzc1xuICAgIHRoYXQgPSBmcm9tVHlwZWRBcnJheSh0aGF0LCBuZXcgVWludDhBcnJheShhcnJheSkpXG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5TGlrZSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbi8vIERlc2VyaWFsaXplIHsgdHlwZTogJ0J1ZmZlcicsIGRhdGE6IFsxLDIsMywuLi5dIH0gaW50byBhIEJ1ZmZlciBvYmplY3QuXG4vLyBSZXR1cm5zIGEgemVyby1sZW5ndGggYnVmZmVyIGZvciBpbnB1dHMgdGhhdCBkb24ndCBjb25mb3JtIHRvIHRoZSBzcGVjLlxuZnVuY3Rpb24gZnJvbUpzb25PYmplY3QgKHRoYXQsIG9iamVjdCkge1xuICB2YXIgYXJyYXlcbiAgdmFyIGxlbmd0aCA9IDBcblxuICBpZiAob2JqZWN0LnR5cGUgPT09ICdCdWZmZXInICYmIGlzQXJyYXkob2JqZWN0LmRhdGEpKSB7XG4gICAgYXJyYXkgPSBvYmplY3QuZGF0YVxuICAgIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgfVxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5pZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgQnVmZmVyLnByb3RvdHlwZS5fX3Byb3RvX18gPSBVaW50OEFycmF5LnByb3RvdHlwZVxuICBCdWZmZXIuX19wcm90b19fID0gVWludDhBcnJheVxufSBlbHNlIHtcbiAgLy8gcHJlLXNldCBmb3IgdmFsdWVzIHRoYXQgbWF5IGV4aXN0IGluIHRoZSBmdXR1cmVcbiAgQnVmZmVyLnByb3RvdHlwZS5sZW5ndGggPSB1bmRlZmluZWRcbiAgQnVmZmVyLnByb3RvdHlwZS5wYXJlbnQgPSB1bmRlZmluZWRcbn1cblxuZnVuY3Rpb24gYWxsb2NhdGUgKHRoYXQsIGxlbmd0aCkge1xuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSwgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICB0aGF0ID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGxlbmd0aCkpXG4gICAgdGhhdC5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBhbiBvYmplY3QgaW5zdGFuY2Ugb2YgdGhlIEJ1ZmZlciBjbGFzc1xuICAgIHRoYXQubGVuZ3RoID0gbGVuZ3RoXG4gICAgdGhhdC5faXNCdWZmZXIgPSB0cnVlXG4gIH1cblxuICB2YXIgZnJvbVBvb2wgPSBsZW5ndGggIT09IDAgJiYgbGVuZ3RoIDw9IEJ1ZmZlci5wb29sU2l6ZSA+Pj4gMVxuICBpZiAoZnJvbVBvb2wpIHRoYXQucGFyZW50ID0gcm9vdFBhcmVudFxuXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGNoZWNrZWQgKGxlbmd0aCkge1xuICAvLyBOb3RlOiBjYW5ub3QgdXNlIGBsZW5ndGggPCBrTWF4TGVuZ3RoYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IGtNYXhMZW5ndGgoKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBrTWF4TGVuZ3RoKCkudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlciAoc3ViamVjdCwgZW5jb2RpbmcpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNsb3dCdWZmZXIpKSByZXR1cm4gbmV3IFNsb3dCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcpXG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcpXG4gIGRlbGV0ZSBidWYucGFyZW50XG4gIHJldHVybiBidWZcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gaXNCdWZmZXIgKGIpIHtcbiAgcmV0dXJuICEhKGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlcilcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGEpIHx8ICFCdWZmZXIuaXNCdWZmZXIoYikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudHMgbXVzdCBiZSBCdWZmZXJzJylcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIHZhciB4ID0gYS5sZW5ndGhcbiAgdmFyIHkgPSBiLmxlbmd0aFxuXG4gIHZhciBpID0gMFxuICB2YXIgbGVuID0gTWF0aC5taW4oeCwgeSlcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkgYnJlYWtcblxuICAgICsraVxuICB9XG5cbiAgaWYgKGkgIT09IGxlbikge1xuICAgIHggPSBhW2ldXG4gICAgeSA9IGJbaV1cbiAgfVxuXG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiBpc0VuY29kaW5nIChlbmNvZGluZykge1xuICBzd2l0Y2ggKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSkge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAncmF3JzpcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0dXJuIHRydWVcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuQnVmZmVyLmNvbmNhdCA9IGZ1bmN0aW9uIGNvbmNhdCAobGlzdCwgbGVuZ3RoKSB7XG4gIGlmICghaXNBcnJheShsaXN0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdCBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMuJylcblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcigwKVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihsZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldXG4gICAgaXRlbS5jb3B5KGJ1ZiwgcG9zKVxuICAgIHBvcyArPSBpdGVtLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHN0cmluZyA9ICcnICsgc3RyaW5nXG5cbiAgdmFyIGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKGxlbiA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBVc2UgYSBmb3IgbG9vcCB0byBhdm9pZCByZWN1cnNpb25cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAvLyBEZXByZWNhdGVkXG4gICAgICBjYXNlICdyYXcnOlxuICAgICAgY2FzZSAncmF3cyc6XG4gICAgICAgIHJldHVybiBsZW5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuXG5mdW5jdGlvbiBzbG93VG9TdHJpbmcgKGVuY29kaW5nLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG5cbiAgc3RhcnQgPSBzdGFydCB8IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgfHwgZW5kID09PSBJbmZpbml0eSA/IHRoaXMubGVuZ3RoIDogZW5kIHwgMFxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG4gIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmIChlbmQgPD0gc3RhcnQpIHJldHVybiAnJ1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGJpbmFyeVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdXRmMTZsZVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9IChlbmNvZGluZyArICcnKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfCAwXG4gIGlmIChsZW5ndGggPT09IDApIHJldHVybiAnJ1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCAwLCBsZW5ndGgpXG4gIHJldHVybiBzbG93VG9TdHJpbmcuYXBwbHkodGhpcywgYXJndW1lbnRzKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIGVxdWFscyAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYikgPT09IDBcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gIHZhciBzdHIgPSAnJ1xuICB2YXIgbWF4ID0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFU1xuICBpZiAodGhpcy5sZW5ndGggPiAwKSB7XG4gICAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5tYXRjaCgvLnsyfS9nKS5qb2luKCcgJylcbiAgICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIH1cbiAgcmV0dXJuICc8QnVmZmVyICcgKyBzdHIgKyAnPidcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gMFxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYilcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZiAodmFsLCBieXRlT2Zmc2V0KSB7XG4gIGlmIChieXRlT2Zmc2V0ID4gMHg3ZmZmZmZmZikgYnl0ZU9mZnNldCA9IDB4N2ZmZmZmZmZcbiAgZWxzZSBpZiAoYnl0ZU9mZnNldCA8IC0weDgwMDAwMDAwKSBieXRlT2Zmc2V0ID0gLTB4ODAwMDAwMDBcbiAgYnl0ZU9mZnNldCA+Pj0gMFxuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xXG4gIGlmIChieXRlT2Zmc2V0ID49IHRoaXMubGVuZ3RoKSByZXR1cm4gLTFcblxuICAvLyBOZWdhdGl2ZSBvZmZzZXRzIHN0YXJ0IGZyb20gdGhlIGVuZCBvZiB0aGUgYnVmZmVyXG4gIGlmIChieXRlT2Zmc2V0IDwgMCkgYnl0ZU9mZnNldCA9IE1hdGgubWF4KHRoaXMubGVuZ3RoICsgYnl0ZU9mZnNldCwgMClcblxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xIC8vIHNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nIGFsd2F5cyBmYWlsc1xuICAgIHJldHVybiBTdHJpbmcucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLCB2YWwsIGJ5dGVPZmZzZXQpXG4gIH1cbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcih2YWwpKSB7XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQpXG4gIH1cbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUICYmIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwodGhpcywgdmFsLCBieXRlT2Zmc2V0KVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKHRoaXMsIFsgdmFsIF0sIGJ5dGVPZmZzZXQpXG4gIH1cblxuICBmdW5jdGlvbiBhcnJheUluZGV4T2YgKGFyciwgdmFsLCBieXRlT2Zmc2V0KSB7XG4gICAgdmFyIGZvdW5kSW5kZXggPSAtMVxuICAgIGZvciAodmFyIGkgPSAwOyBieXRlT2Zmc2V0ICsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFycltieXRlT2Zmc2V0ICsgaV0gPT09IHZhbFtmb3VuZEluZGV4ID09PSAtMSA/IDAgOiBpIC0gZm91bmRJbmRleF0pIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggPT09IC0xKSBmb3VuZEluZGV4ID0gaVxuICAgICAgICBpZiAoaSAtIGZvdW5kSW5kZXggKyAxID09PSB2YWwubGVuZ3RoKSByZXR1cm4gYnl0ZU9mZnNldCArIGZvdW5kSW5kZXhcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvdW5kSW5kZXggPSAtMVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTFcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlcicpXG59XG5cbi8vIGBnZXRgIGlzIGRlcHJlY2F0ZWRcbkJ1ZmZlci5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gZ2V0IChvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5nZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLnJlYWRVSW50OChvZmZzZXQpXG59XG5cbi8vIGBzZXRgIGlzIGRlcHJlY2F0ZWRcbkJ1ZmZlci5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gc2V0ICh2LCBvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5zZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLndyaXRlVUludDgodiwgb2Zmc2V0KVxufVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIC8vIG11c3QgYmUgYW4gZXZlbiBudW1iZXIgb2YgZGlnaXRzXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChzdHJMZW4gJSAyICE9PSAwKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGV4IHN0cmluZycpXG5cbiAgaWYgKGxlbmd0aCA+IHN0ckxlbiAvIDIpIHtcbiAgICBsZW5ndGggPSBzdHJMZW4gLyAyXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJzZWQgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgaWYgKGlzTmFOKHBhcnNlZCkpIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSBwYXJzZWRcbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiB1dGY4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGY4VG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBhc2NpaVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYXNjaWlUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJpbmFyeVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGFzY2lpV3JpdGUoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gdWNzMldyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmMTZsZVRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nKVxuICBpZiAob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIG9mZnNldFssIGxlbmd0aF1bLCBlbmNvZGluZ10pXG4gIH0gZWxzZSBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgICBpZiAoaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoIHwgMFxuICAgICAgaWYgKGVuY29kaW5nID09PSB1bmRlZmluZWQpIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIC8vIGxlZ2FjeSB3cml0ZShzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXQsIGxlbmd0aCkgLSByZW1vdmUgaW4gdjAuMTNcbiAgfSBlbHNlIHtcbiAgICB2YXIgc3dhcCA9IGVuY29kaW5nXG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBvZmZzZXQgPSBsZW5ndGggfCAwXG4gICAgbGVuZ3RoID0gc3dhcFxuICB9XG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCB8fCBsZW5ndGggPiByZW1haW5pbmcpIGxlbmd0aCA9IHJlbWFpbmluZ1xuXG4gIGlmICgoc3RyaW5nLmxlbmd0aCA+IDAgJiYgKGxlbmd0aCA8IDAgfHwgb2Zmc2V0IDwgMCkpIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBiaW5hcnlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICAvLyBXYXJuaW5nOiBtYXhMZW5ndGggbm90IHRha2VuIGludG8gYWNjb3VudCBpbiBiYXNlNjRXcml0ZVxuICAgICAgICByZXR1cm4gYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHVjczJXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04gKCkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6ICdCdWZmZXInLFxuICAgIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKVxuICB9XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gYnVmLmxlbmd0aCkge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1Zi5zbGljZShzdGFydCwgZW5kKSlcbiAgfVxufVxuXG5mdW5jdGlvbiB1dGY4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG4gIHZhciByZXMgPSBbXVxuXG4gIHZhciBpID0gc3RhcnRcbiAgd2hpbGUgKGkgPCBlbmQpIHtcbiAgICB2YXIgZmlyc3RCeXRlID0gYnVmW2ldXG4gICAgdmFyIGNvZGVQb2ludCA9IG51bGxcbiAgICB2YXIgYnl0ZXNQZXJTZXF1ZW5jZSA9IChmaXJzdEJ5dGUgPiAweEVGKSA/IDRcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4REYpID8gM1xuICAgICAgOiAoZmlyc3RCeXRlID4gMHhCRikgPyAyXG4gICAgICA6IDFcblxuICAgIGlmIChpICsgYnl0ZXNQZXJTZXF1ZW5jZSA8PSBlbmQpIHtcbiAgICAgIHZhciBzZWNvbmRCeXRlLCB0aGlyZEJ5dGUsIGZvdXJ0aEJ5dGUsIHRlbXBDb2RlUG9pbnRcblxuICAgICAgc3dpdGNoIChieXRlc1BlclNlcXVlbmNlKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICBpZiAoZmlyc3RCeXRlIDwgMHg4MCkge1xuICAgICAgICAgICAgY29kZVBvaW50ID0gZmlyc3RCeXRlXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4MUYpIDw8IDB4NiB8IChzZWNvbmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3Rikge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweEMgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4NiB8ICh0aGlyZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGRiAmJiAodGVtcENvZGVQb2ludCA8IDB4RDgwMCB8fCB0ZW1wQ29kZVBvaW50ID4gMHhERkZGKSkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBmb3VydGhCeXRlID0gYnVmW2kgKyAzXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAoZm91cnRoQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHgxMiB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHhDIHwgKHRoaXJkQnl0ZSAmIDB4M0YpIDw8IDB4NiB8IChmb3VydGhCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHhGRkZGICYmIHRlbXBDb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb2RlUG9pbnQgPT09IG51bGwpIHtcbiAgICAgIC8vIHdlIGRpZCBub3QgZ2VuZXJhdGUgYSB2YWxpZCBjb2RlUG9pbnQgc28gaW5zZXJ0IGFcbiAgICAgIC8vIHJlcGxhY2VtZW50IGNoYXIgKFUrRkZGRCkgYW5kIGFkdmFuY2Ugb25seSAxIGJ5dGVcbiAgICAgIGNvZGVQb2ludCA9IDB4RkZGRFxuICAgICAgYnl0ZXNQZXJTZXF1ZW5jZSA9IDFcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA+IDB4RkZGRikge1xuICAgICAgLy8gZW5jb2RlIHRvIHV0ZjE2IChzdXJyb2dhdGUgcGFpciBkYW5jZSlcbiAgICAgIGNvZGVQb2ludCAtPSAweDEwMDAwXG4gICAgICByZXMucHVzaChjb2RlUG9pbnQgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApXG4gICAgICBjb2RlUG9pbnQgPSAweERDMDAgfCBjb2RlUG9pbnQgJiAweDNGRlxuICAgIH1cblxuICAgIHJlcy5wdXNoKGNvZGVQb2ludClcbiAgICBpICs9IGJ5dGVzUGVyU2VxdWVuY2VcbiAgfVxuXG4gIHJldHVybiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkocmVzKVxufVxuXG4vLyBCYXNlZCBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjc0NzI3Mi82ODA3NDIsIHRoZSBicm93c2VyIHdpdGhcbi8vIHRoZSBsb3dlc3QgbGltaXQgaXMgQ2hyb21lLCB3aXRoIDB4MTAwMDAgYXJncy5cbi8vIFdlIGdvIDEgbWFnbml0dWRlIGxlc3MsIGZvciBzYWZldHlcbnZhciBNQVhfQVJHVU1FTlRTX0xFTkdUSCA9IDB4MTAwMFxuXG5mdW5jdGlvbiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkgKGNvZGVQb2ludHMpIHtcbiAgdmFyIGxlbiA9IGNvZGVQb2ludHMubGVuZ3RoXG4gIGlmIChsZW4gPD0gTUFYX0FSR1VNRU5UU19MRU5HVEgpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNvZGVQb2ludHMpIC8vIGF2b2lkIGV4dHJhIHNsaWNlKClcbiAgfVxuXG4gIC8vIERlY29kZSBpbiBjaHVua3MgdG8gYXZvaWQgXCJjYWxsIHN0YWNrIHNpemUgZXhjZWVkZWRcIi5cbiAgdmFyIHJlcyA9ICcnXG4gIHZhciBpID0gMFxuICB3aGlsZSAoaSA8IGxlbikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFxuICAgICAgU3RyaW5nLFxuICAgICAgY29kZVBvaW50cy5zbGljZShpLCBpICs9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKVxuICAgIClcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldICYgMHg3RilcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGJpbmFyeVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGhleFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICB2YXIgb3V0ID0gJydcbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICBvdXQgKz0gdG9IZXgoYnVmW2ldKVxuICB9XG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGJ5dGVzID0gYnVmLnNsaWNlKHN0YXJ0LCBlbmQpXG4gIHZhciByZXMgPSAnJ1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0gKyBieXRlc1tpICsgMV0gKiAyNTYpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gc2xpY2UgKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIHN0YXJ0ID0gfn5zdGFydFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbiA6IH5+ZW5kXG5cbiAgaWYgKHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ICs9IGxlblxuICAgIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMFxuICB9IGVsc2UgaWYgKHN0YXJ0ID4gbGVuKSB7XG4gICAgc3RhcnQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCAwKSB7XG4gICAgZW5kICs9IGxlblxuICAgIGlmIChlbmQgPCAwKSBlbmQgPSAwXG4gIH0gZWxzZSBpZiAoZW5kID4gbGVuKSB7XG4gICAgZW5kID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgdmFyIG5ld0J1ZlxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBuZXdCdWYgPSBCdWZmZXIuX2F1Z21lbnQodGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSlcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIG5ld0J1ZiA9IG5ldyBCdWZmZXIoc2xpY2VMZW4sIHVuZGVmaW5lZClcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNsaWNlTGVuOyBpKyspIHtcbiAgICAgIG5ld0J1ZltpXSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfVxuXG4gIGlmIChuZXdCdWYubGVuZ3RoKSBuZXdCdWYucGFyZW50ID0gdGhpcy5wYXJlbnQgfHwgdGhpc1xuXG4gIHJldHVybiBuZXdCdWZcbn1cblxuLypcbiAqIE5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgYnVmZmVyIGlzbid0IHRyeWluZyB0byB3cml0ZSBvdXQgb2YgYm91bmRzLlxuICovXG5mdW5jdGlvbiBjaGVja09mZnNldCAob2Zmc2V0LCBleHQsIGxlbmd0aCkge1xuICBpZiAoKG9mZnNldCAlIDEpICE9PSAwIHx8IG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdvZmZzZXQgaXMgbm90IHVpbnQnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gbGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRCRSA9IGZ1bmN0aW9uIHJlYWRVSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG4gIH1cblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdXG4gIHZhciBtdWwgPSAxXG4gIHdoaWxlIChieXRlTGVuZ3RoID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDggPSBmdW5jdGlvbiByZWFkVUludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiByZWFkVUludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgOCkgfCB0aGlzW29mZnNldCArIDFdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdICogMHgxMDAwMDAwKSArXG4gICAgKCh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgIHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gcmVhZEludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludEJFID0gZnVuY3Rpb24gcmVhZEludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoXG4gIHZhciBtdWwgPSAxXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0taV1cbiAgd2hpbGUgKGkgPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1pXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiByZWFkSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSkgcmV0dXJuICh0aGlzW29mZnNldF0pXG4gIHJldHVybiAoKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gcmVhZEludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdKSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10gPDwgMjQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiByZWFkSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDI0KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiByZWFkRmxvYXRMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiByZWFkRmxvYXRCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gcmVhZERvdWJsZUJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgNTIsIDgpXG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignYnVmZmVyIG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKVxuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludExFID0gZnVuY3Rpb24gd3JpdGVVSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSwgMClcblxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFID0gZnVuY3Rpb24gd3JpdGVVSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSwgMClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiB3cml0ZVVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4ZmYsIDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuZnVuY3Rpb24gb2JqZWN0V3JpdGVVSW50MTYgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuKSB7XG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgMik7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgJiAoMHhmZiA8PCAoOCAqIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpKSkpID4+PlxuICAgICAgKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkgKiA4XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuZnVuY3Rpb24gb2JqZWN0V3JpdGVVSW50MzIgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuKSB7XG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmZmZmZiArIHZhbHVlICsgMVxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGJ1Zi5sZW5ndGggLSBvZmZzZXQsIDQpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID0gKHZhbHVlID4+PiAobGl0dGxlRW5kaWFuID8gaSA6IDMgLSBpKSAqIDgpICYgMHhmZlxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludExFID0gZnVuY3Rpb24gd3JpdGVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IDBcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IHZhbHVlIDwgMCA/IDEgOiAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBsaW1pdCA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uIHdyaXRlSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweDdmLCAtMHg4MClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmZmZmZiArIHZhbHVlICsgMVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuZnVuY3Rpb24gY2hlY2tJRUVFNzU0IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcigndmFsdWUgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5mdW5jdGlvbiB3cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDQsIDMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gd3JpdGVGbG9hdEJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRG91YmxlIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDgsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG4gIHJldHVybiBvZmZzZXQgKyA4XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUJFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gY29weSAodGFyZ2V0LCB0YXJnZXRTdGFydCwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0U3RhcnQgPj0gdGFyZ2V0Lmxlbmd0aCkgdGFyZ2V0U3RhcnQgPSB0YXJnZXQubGVuZ3RoXG4gIGlmICghdGFyZ2V0U3RhcnQpIHRhcmdldFN0YXJ0ID0gMFxuICBpZiAoZW5kID4gMCAmJiBlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVybiAwXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldFN0YXJ0IDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgfVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlU3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChlbmQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCA8IGVuZCAtIHN0YXJ0KSB7XG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0ICsgc3RhcnRcbiAgfVxuXG4gIHZhciBsZW4gPSBlbmQgLSBzdGFydFxuICB2YXIgaVxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgc3RhcnQgPCB0YXJnZXRTdGFydCAmJiB0YXJnZXRTdGFydCA8IGVuZCkge1xuICAgIC8vIGRlc2NlbmRpbmcgY29weSBmcm9tIGVuZFxuICAgIGZvciAoaSA9IGxlbiAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIGlmIChsZW4gPCAxMDAwIHx8ICFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIGFzY2VuZGluZyBjb3B5IGZyb20gc3RhcnRcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRhcmdldC5fc2V0KHRoaXMuc3ViYXJyYXkoc3RhcnQsIHN0YXJ0ICsgbGVuKSwgdGFyZ2V0U3RhcnQpXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbi8vIGZpbGwodmFsdWUsIHN0YXJ0PTAsIGVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gZmlsbCAodmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCF2YWx1ZSkgdmFsdWUgPSAwXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCkgZW5kID0gdGhpcy5sZW5ndGhcblxuICBpZiAoZW5kIDwgc3RhcnQpIHRocm93IG5ldyBSYW5nZUVycm9yKCdlbmQgPCBzdGFydCcpXG5cbiAgLy8gRmlsbCAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm5cbiAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChlbmQgPCAwIHx8IGVuZCA+IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignZW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIHZhciBpXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IHZhbHVlXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBieXRlcyA9IHV0ZjhUb0J5dGVzKHZhbHVlLnRvU3RyaW5nKCkpXG4gICAgdmFyIGxlbiA9IGJ5dGVzLmxlbmd0aFxuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIHRoaXNbaV0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBgQXJyYXlCdWZmZXJgIHdpdGggdGhlICpjb3BpZWQqIG1lbW9yeSBvZiB0aGUgYnVmZmVyIGluc3RhbmNlLlxuICogQWRkZWQgaW4gTm9kZSAwLjEyLiBPbmx5IGF2YWlsYWJsZSBpbiBicm93c2VycyB0aGF0IHN1cHBvcnQgQXJyYXlCdWZmZXIuXG4gKi9cbkJ1ZmZlci5wcm90b3R5cGUudG9BcnJheUJ1ZmZlciA9IGZ1bmN0aW9uIHRvQXJyYXlCdWZmZXIgKCkge1xuICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgICByZXR1cm4gKG5ldyBCdWZmZXIodGhpcykpLmJ1ZmZlclxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYnVmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgpXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gYnVmLmxlbmd0aDsgaSA8IGxlbjsgaSArPSAxKSB7XG4gICAgICAgIGJ1ZltpXSA9IHRoaXNbaV1cbiAgICAgIH1cbiAgICAgIHJldHVybiBidWYuYnVmZmVyXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0J1ZmZlci50b0FycmF5QnVmZmVyIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBicm93c2VyJylcbiAgfVxufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbnZhciBCUCA9IEJ1ZmZlci5wcm90b3R5cGVcblxuLyoqXG4gKiBBdWdtZW50IGEgVWludDhBcnJheSAqaW5zdGFuY2UqIChub3QgdGhlIFVpbnQ4QXJyYXkgY2xhc3MhKSB3aXRoIEJ1ZmZlciBtZXRob2RzXG4gKi9cbkJ1ZmZlci5fYXVnbWVudCA9IGZ1bmN0aW9uIF9hdWdtZW50IChhcnIpIHtcbiAgYXJyLmNvbnN0cnVjdG9yID0gQnVmZmVyXG4gIGFyci5faXNCdWZmZXIgPSB0cnVlXG5cbiAgLy8gc2F2ZSByZWZlcmVuY2UgdG8gb3JpZ2luYWwgVWludDhBcnJheSBzZXQgbWV0aG9kIGJlZm9yZSBvdmVyd3JpdGluZ1xuICBhcnIuX3NldCA9IGFyci5zZXRcblxuICAvLyBkZXByZWNhdGVkXG4gIGFyci5nZXQgPSBCUC5nZXRcbiAgYXJyLnNldCA9IEJQLnNldFxuXG4gIGFyci53cml0ZSA9IEJQLndyaXRlXG4gIGFyci50b1N0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0xvY2FsZVN0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0pTT04gPSBCUC50b0pTT05cbiAgYXJyLmVxdWFscyA9IEJQLmVxdWFsc1xuICBhcnIuY29tcGFyZSA9IEJQLmNvbXBhcmVcbiAgYXJyLmluZGV4T2YgPSBCUC5pbmRleE9mXG4gIGFyci5jb3B5ID0gQlAuY29weVxuICBhcnIuc2xpY2UgPSBCUC5zbGljZVxuICBhcnIucmVhZFVJbnRMRSA9IEJQLnJlYWRVSW50TEVcbiAgYXJyLnJlYWRVSW50QkUgPSBCUC5yZWFkVUludEJFXG4gIGFyci5yZWFkVUludDggPSBCUC5yZWFkVUludDhcbiAgYXJyLnJlYWRVSW50MTZMRSA9IEJQLnJlYWRVSW50MTZMRVxuICBhcnIucmVhZFVJbnQxNkJFID0gQlAucmVhZFVJbnQxNkJFXG4gIGFyci5yZWFkVUludDMyTEUgPSBCUC5yZWFkVUludDMyTEVcbiAgYXJyLnJlYWRVSW50MzJCRSA9IEJQLnJlYWRVSW50MzJCRVxuICBhcnIucmVhZEludExFID0gQlAucmVhZEludExFXG4gIGFyci5yZWFkSW50QkUgPSBCUC5yZWFkSW50QkVcbiAgYXJyLnJlYWRJbnQ4ID0gQlAucmVhZEludDhcbiAgYXJyLnJlYWRJbnQxNkxFID0gQlAucmVhZEludDE2TEVcbiAgYXJyLnJlYWRJbnQxNkJFID0gQlAucmVhZEludDE2QkVcbiAgYXJyLnJlYWRJbnQzMkxFID0gQlAucmVhZEludDMyTEVcbiAgYXJyLnJlYWRJbnQzMkJFID0gQlAucmVhZEludDMyQkVcbiAgYXJyLnJlYWRGbG9hdExFID0gQlAucmVhZEZsb2F0TEVcbiAgYXJyLnJlYWRGbG9hdEJFID0gQlAucmVhZEZsb2F0QkVcbiAgYXJyLnJlYWREb3VibGVMRSA9IEJQLnJlYWREb3VibGVMRVxuICBhcnIucmVhZERvdWJsZUJFID0gQlAucmVhZERvdWJsZUJFXG4gIGFyci53cml0ZVVJbnQ4ID0gQlAud3JpdGVVSW50OFxuICBhcnIud3JpdGVVSW50TEUgPSBCUC53cml0ZVVJbnRMRVxuICBhcnIud3JpdGVVSW50QkUgPSBCUC53cml0ZVVJbnRCRVxuICBhcnIud3JpdGVVSW50MTZMRSA9IEJQLndyaXRlVUludDE2TEVcbiAgYXJyLndyaXRlVUludDE2QkUgPSBCUC53cml0ZVVJbnQxNkJFXG4gIGFyci53cml0ZVVJbnQzMkxFID0gQlAud3JpdGVVSW50MzJMRVxuICBhcnIud3JpdGVVSW50MzJCRSA9IEJQLndyaXRlVUludDMyQkVcbiAgYXJyLndyaXRlSW50TEUgPSBCUC53cml0ZUludExFXG4gIGFyci53cml0ZUludEJFID0gQlAud3JpdGVJbnRCRVxuICBhcnIud3JpdGVJbnQ4ID0gQlAud3JpdGVJbnQ4XG4gIGFyci53cml0ZUludDE2TEUgPSBCUC53cml0ZUludDE2TEVcbiAgYXJyLndyaXRlSW50MTZCRSA9IEJQLndyaXRlSW50MTZCRVxuICBhcnIud3JpdGVJbnQzMkxFID0gQlAud3JpdGVJbnQzMkxFXG4gIGFyci53cml0ZUludDMyQkUgPSBCUC53cml0ZUludDMyQkVcbiAgYXJyLndyaXRlRmxvYXRMRSA9IEJQLndyaXRlRmxvYXRMRVxuICBhcnIud3JpdGVGbG9hdEJFID0gQlAud3JpdGVGbG9hdEJFXG4gIGFyci53cml0ZURvdWJsZUxFID0gQlAud3JpdGVEb3VibGVMRVxuICBhcnIud3JpdGVEb3VibGVCRSA9IEJQLndyaXRlRG91YmxlQkVcbiAgYXJyLmZpbGwgPSBCUC5maWxsXG4gIGFyci5pbnNwZWN0ID0gQlAuaW5zcGVjdFxuICBhcnIudG9BcnJheUJ1ZmZlciA9IEJQLnRvQXJyYXlCdWZmZXJcblxuICByZXR1cm4gYXJyXG59XG5cbnZhciBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXitcXC8wLTlBLVphLXotX10vZ1xuXG5mdW5jdGlvbiBiYXNlNjRjbGVhbiAoc3RyKSB7XG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHJpbmd0cmltKHN0cikucmVwbGFjZShJTlZBTElEX0JBU0U2NF9SRSwgJycpXG4gIC8vIE5vZGUgY29udmVydHMgc3RyaW5ncyB3aXRoIGxlbmd0aCA8IDIgdG8gJydcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSByZXR1cm4gJydcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gc3RyaW5ndHJpbSAoc3RyKSB7XG4gIGlmIChzdHIudHJpbSkgcmV0dXJuIHN0ci50cmltKClcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJylcbn1cblxuZnVuY3Rpb24gdG9IZXggKG4pIHtcbiAgaWYgKG4gPCAxNikgcmV0dXJuICcwJyArIG4udG9TdHJpbmcoMTYpXG4gIHJldHVybiBuLnRvU3RyaW5nKDE2KVxufVxuXG5mdW5jdGlvbiB1dGY4VG9CeXRlcyAoc3RyaW5nLCB1bml0cykge1xuICB1bml0cyA9IHVuaXRzIHx8IEluZmluaXR5XG4gIHZhciBjb2RlUG9pbnRcbiAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGhcbiAgdmFyIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gIHZhciBieXRlcyA9IFtdXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcbiAgICAgIC8vIGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoIWxlYWRTdXJyb2dhdGUpIHtcbiAgICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHZhbGlkIGxlYWRcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgIGlmIChjb2RlUG9pbnQgPCAweERDMDApIHtcbiAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWQgc3Vycm9nYXRlIHBhaXJcbiAgICAgIGNvZGVQb2ludCA9IChsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwKSArIDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIsIHVuaXRzKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG5cbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShiYXNlNjRjbGVhbihzdHIpKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuIiwiZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24gKGJ1ZmZlciwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG1cbiAgdmFyIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjXG4gIHZhciBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAodmFsdWUgKiBjIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IGUgKyBlQmlhc1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSAwXG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cblxuICBlID0gKGUgPDwgbUxlbikgfCBtXG4gIGVMZW4gKz0gbUxlblxuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpIHt9XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4XG59XG4iLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChhcnIpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJyKSA9PSAnW29iamVjdCBBcnJheV0nO1xufTtcbiIsIi8qXG4gKiBTeXN0ZW1KUyB2MC4yMC4xOSBEZXZcbiAqL1xuKGZ1bmN0aW9uICgpIHtcbid1c2Ugc3RyaWN0JztcblxuLypcbiAqIEVudmlyb25tZW50XG4gKi9cbnZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xudmFyIGlzTm9kZSA9IHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiBwcm9jZXNzLnZlcnNpb25zICYmIHByb2Nlc3MudmVyc2lvbnMubm9kZTtcbnZhciBpc1dpbmRvd3MgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHByb2Nlc3MucGxhdGZvcm0gPT09ICdzdHJpbmcnICYmIHByb2Nlc3MucGxhdGZvcm0ubWF0Y2goL153aW4vKTtcblxudmFyIGVudkdsb2JhbCA9IHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/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/IHRoaXMubWFwW25hbWVdIDogbnVsbFxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHJldHVybiB0aGlzLm1hcC5oYXNPd25Qcm9wZXJ0eShub3JtYWxpemVOYW1lKG5hbWUpKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgZm9yICh2YXIgbmFtZSBpbiB0aGlzLm1hcCkge1xuICAgICAgaWYgKHRoaXMubWFwLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdGhpcy5tYXBbbmFtZV0sIG5hbWUsIHRoaXMpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgSGVhZGVycy5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpdGVtcyA9IFtdXG4gICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7IGl0ZW1zLnB1c2gobmFtZSkgfSlcbiAgICByZXR1cm4gaXRlcmF0b3JGb3IoaXRlbXMpXG4gIH1cblxuICBIZWFkZXJzLnByb3RvdHlwZS52YWx1ZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaXRlbXMgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkgeyBpdGVtcy5wdXNoKHZhbHVlKSB9KVxuICAgIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbiAgfVxuXG4gIEhlYWRlcnMucHJvdG90eXBlLmVudHJpZXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaXRlbXMgPSBbXVxuICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkgeyBpdGVtcy5wdXNoKFtuYW1lLCB2YWx1ZV0pIH0pXG4gICAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxuICB9XG5cbiAgaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgICBIZWFkZXJzLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gSGVhZGVycy5wcm90b3R5cGUuZW50cmllc1xuICB9XG5cbiAgZnVuY3Rpb24gY29uc3VtZWQoYm9keSkge1xuICAgIGlmIChib2R5LmJvZHlVc2VkKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcignQWxyZWFkeSByZWFkJykpXG4gICAgfVxuICAgIGJvZHkuYm9keVVzZWQgPSB0cnVlXG4gIH1cblxuICBmdW5jdGlvbiBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXNvbHZlKHJlYWRlci5yZXN1bHQpXG4gICAgICB9XG4gICAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QocmVhZGVyLmVycm9yKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQmxvYkFzQXJyYXlCdWZmZXIoYmxvYikge1xuICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpXG4gICAgdmFyIHByb21pc2UgPSBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKVxuICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcihibG9iKVxuICAgIHJldHVybiBwcm9taXNlXG4gIH1cblxuICBmdW5jdGlvbiByZWFkQmxvYkFzVGV4dChibG9iKSB7XG4gICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgICB2YXIgcHJvbWlzZSA9IGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpXG4gICAgcmVhZGVyLnJlYWRBc1RleHQoYmxvYilcbiAgICByZXR1cm4gcHJvbWlzZVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZEFycmF5QnVmZmVyQXNUZXh0KGJ1Zikge1xuICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmKVxuICAgIHZhciBjaGFycyA9IG5ldyBBcnJheSh2aWV3Lmxlbmd0aClcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgICAgY2hhcnNbaV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHZpZXdbaV0pXG4gICAgfVxuICAgIHJldHVybiBjaGFycy5qb2luKCcnKVxuICB9XG5cbiAgZnVuY3Rpb24gYnVmZmVyQ2xvbmUoYnVmKSB7XG4gICAgaWYgKGJ1Zi5zbGljZSkge1xuICAgICAgcmV0dXJuIGJ1Zi5zbGljZSgwKVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdmlldyA9IG5ldyBVaW50OEFycmF5KGJ1Zi5ieXRlTGVuZ3RoKVxuICAgICAgdmlldy5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmKSlcbiAgICAgIHJldHVybiB2aWV3LmJ1ZmZlclxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIEJvZHkoKSB7XG4gICAgdGhpcy5ib2R5VXNlZCA9IGZhbHNlXG5cbiAgICB0aGlzLl9pbml0Qm9keSA9IGZ1bmN0aW9uKGJvZHkpIHtcbiAgICAgIHRoaXMuX2JvZHlJbml0ID0gYm9keVxuICAgICAgaWYgKCFib2R5KSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gJydcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmJsb2IgJiYgQmxvYi5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5QmxvYiA9IGJvZHlcbiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5mb3JtRGF0YSAmJiBGb3JtRGF0YS5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5Rm9ybURhdGEgPSBib2R5XG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLl9ib2R5VGV4dCA9IGJvZHkudG9TdHJpbmcoKVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIHN1cHBvcnQuYmxvYiAmJiBpc0RhdGFWaWV3KGJvZHkpKSB7XG4gICAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlciA9IGJ1ZmZlckNsb25lKGJvZHkuYnVmZmVyKVxuICAgICAgICAvLyBJRSAxMC0xMSBjYW4ndCBoYW5kbGUgYSBEYXRhVmlldyBib2R5LlxuICAgICAgICB0aGlzLl9ib2R5SW5pdCA9IG5ldyBCbG9iKFt0aGlzLl9ib2R5QXJyYXlCdWZmZXJdKVxuICAgICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIChBcnJheUJ1ZmZlci5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSB8fCBpc0FycmF5QnVmZmVyVmlldyhib2R5KSkpIHtcbiAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyID0gYnVmZmVyQ2xvbmUoYm9keSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgQm9keUluaXQgdHlwZScpXG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJykpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICd0ZXh0L3BsYWluO2NoYXJzZXQ9VVRGLTgnKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlCbG9iICYmIHRoaXMuX2JvZHlCbG9iLnR5cGUpIHtcbiAgICAgICAgICB0aGlzLmhlYWRlcnMuc2V0KCdjb250ZW50LXR5cGUnLCB0aGlzLl9ib2R5QmxvYi50eXBlKVxuICAgICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7Y2hhcnNldD1VVEYtOCcpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3VwcG9ydC5ibG9iKSB7XG4gICAgICB0aGlzLmJsb2IgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICAgICAgaWYgKHJlamVjdGVkKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdGVkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5fYm9keUJsb2IpIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlCbG9iKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEJsb2IoW3RoaXMuX2JvZHlBcnJheUJ1ZmZlcl0pKVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgRm9ybURhdGEgYm9keSBhcyBibG9iJylcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBCbG9iKFt0aGlzLl9ib2R5VGV4dF0pKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXJyYXlCdWZmZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgICAgIHJldHVybiBjb25zdW1lZCh0aGlzKSB8fCBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUFycmF5QnVmZmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLmJsb2IoKS50aGVuKHJlYWRCbG9iQXNBcnJheUJ1ZmZlcilcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudGV4dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICAgIGlmIChyZWplY3RlZCkge1xuICAgICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2JvZHlCbG9iKSB7XG4gICAgICAgIHJldHVybiByZWFkQmxvYkFzVGV4dCh0aGlzLl9ib2R5QmxvYilcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVhZEFycmF5QnVmZmVyQXNUZXh0KHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCByZWFkIEZvcm1EYXRhIGJvZHkgYXMgdGV4dCcpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlUZXh0KVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdXBwb3J0LmZvcm1EYXRhKSB7XG4gICAgICB0aGlzLmZvcm1EYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRleHQoKS50aGVuKGRlY29kZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmpzb24gPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnRleHQoKS50aGVuKEpTT04ucGFyc2UpXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIC8vIEhUVFAgbWV0aG9kcyB3aG9zZSBjYXBpdGFsaXphdGlvbiBzaG91bGQgYmUgbm9ybWFsaXplZFxuICB2YXIgbWV0aG9kcyA9IFsnREVMRVRFJywgJ0dFVCcsICdIRUFEJywgJ09QVElPTlMnLCAnUE9TVCcsICdQVVQnXVxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZU1ldGhvZChtZXRob2QpIHtcbiAgICB2YXIgdXBjYXNlZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gICAgcmV0dXJuIChtZXRob2RzLmluZGV4T2YodXBjYXNlZCkgPiAtMSkgPyB1cGNhc2VkIDogbWV0aG9kXG4gIH1cblxuICBmdW5jdGlvbiBSZXF1ZXN0KGlucHV0LCBvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICB2YXIgYm9keSA9IG9wdGlvbnMuYm9keVxuXG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgUmVxdWVzdCkge1xuICAgICAgaWYgKGlucHV0LmJvZHlVc2VkKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FscmVhZHkgcmVhZCcpXG4gICAgICB9XG4gICAgICB0aGlzLnVybCA9IGlucHV0LnVybFxuICAgICAgdGhpcy5jcmVkZW50aWFscyA9IGlucHV0LmNyZWRlbnRpYWxzXG4gICAgICBpZiAoIW9wdGlvbnMuaGVhZGVycykge1xuICAgICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhpbnB1dC5oZWFkZXJzKVxuICAgICAgfVxuICAgICAgdGhpcy5tZXRob2QgPSBpbnB1dC5tZXRob2RcbiAgICAgIHRoaXMubW9kZSA9IGlucHV0Lm1vZGVcbiAgICAgIGlmICghYm9keSAmJiBpbnB1dC5fYm9keUluaXQgIT0gbnVsbCkge1xuICAgICAgICBib2R5ID0gaW5wdXQuX2JvZHlJbml0XG4gICAgICAgIGlucHV0LmJvZHlVc2VkID0gdHJ1ZVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVybCA9IFN0cmluZyhpbnB1dClcbiAgICB9XG5cbiAgICB0aGlzLmNyZWRlbnRpYWxzID0gb3B0aW9ucy5jcmVkZW50aWFscyB8fCB0aGlzLmNyZWRlbnRpYWxzIHx8ICdvbWl0J1xuICAgIGlmIChvcHRpb25zLmhlYWRlcnMgfHwgIXRoaXMuaGVhZGVycykge1xuICAgICAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICAgIH1cbiAgICB0aGlzLm1ldGhvZCA9IG5vcm1hbGl6ZU1ldGhvZChvcHRpb25zLm1ldGhvZCB8fCB0aGlzLm1ldGhvZCB8fCAnR0VUJylcbiAgICB0aGlzLm1vZGUgPSBvcHRpb25zLm1vZGUgfHwgdGhpcy5tb2RlIHx8IG51bGxcbiAgICB0aGlzLnJlZmVycmVyID0gbnVsbFxuXG4gICAgaWYgKCh0aGlzLm1ldGhvZCA9PT0gJ0dFVCcgfHwgdGhpcy5tZXRob2QgPT09ICdIRUFEJykgJiYgYm9keSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQm9keSBub3QgYWxsb3dlZCBmb3IgR0VUIG9yIEhFQUQgcmVxdWVzdHMnKVxuICAgIH1cbiAgICB0aGlzLl9pbml0Qm9keShib2R5KVxuICB9XG5cbiAgUmVxdWVzdC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3IFJlcXVlc3QodGhpcywgeyBib2R5OiB0aGlzLl9ib2R5SW5pdCB9KVxuICB9XG5cbiAgZnVuY3Rpb24gZGVjb2RlKGJvZHkpIHtcbiAgICB2YXIgZm9ybSA9IG5ldyBGb3JtRGF0YSgpXG4gICAgYm9keS50cmltKCkuc3BsaXQoJyYnKS5mb3JFYWNoKGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBpZiAoYnl0ZXMpIHtcbiAgICAgICAgdmFyIHNwbGl0ID0gYnl0ZXMuc3BsaXQoJz0nKVxuICAgICAgICB2YXIgbmFtZSA9IHNwbGl0LnNoaWZ0KCkucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgdmFyIHZhbHVlID0gc3BsaXQuam9pbignPScpLnJlcGxhY2UoL1xcKy9nLCAnICcpXG4gICAgICAgIGZvcm0uYXBwZW5kKGRlY29kZVVSSUNvbXBvbmVudChuYW1lKSwgZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSlcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiBmb3JtXG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUhlYWRlcnMocmF3SGVhZGVycykge1xuICAgIHZhciBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKVxuICAgIHJhd0hlYWRlcnMuc3BsaXQoL1xccj9cXG4vKS5mb3JFYWNoKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3BsaXQoJzonKVxuICAgICAgdmFyIGtleSA9IHBhcnRzLnNoaWZ0KCkudHJpbSgpXG4gICAgICBpZiAoa2V5KSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHBhcnRzLmpvaW4oJzonKS50cmltKClcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoa2V5LCB2YWx1ZSlcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiBoZWFkZXJzXG4gIH1cblxuICBCb2R5LmNhbGwoUmVxdWVzdC5wcm90b3R5cGUpXG5cbiAgZnVuY3Rpb24gUmVzcG9uc2UoYm9keUluaXQsIG9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIG9wdGlvbnMgPSB7fVxuICAgIH1cblxuICAgIHRoaXMudHlwZSA9ICdkZWZhdWx0J1xuICAgIHRoaXMuc3RhdHVzID0gJ3N0YXR1cycgaW4gb3B0aW9ucyA/IG9wdGlvbnMuc3RhdHVzIDogMjAwXG4gICAgdGhpcy5vayA9IHRoaXMuc3RhdHVzID49IDIwMCAmJiB0aGlzLnN0YXR1cyA8IDMwMFxuICAgIHRoaXMuc3RhdHVzVGV4dCA9ICdzdGF0dXNUZXh0JyBpbiBvcHRpb25zID8gb3B0aW9ucy5zdGF0dXNUZXh0IDogJ09LJ1xuICAgIHRoaXMuaGVhZGVycyA9IG5ldyBIZWFkZXJzKG9wdGlvbnMuaGVhZGVycylcbiAgICB0aGlzLnVybCA9IG9wdGlvbnMudXJsIHx8ICcnXG4gICAgdGhpcy5faW5pdEJvZHkoYm9keUluaXQpXG4gIH1cblxuICBCb2R5LmNhbGwoUmVzcG9uc2UucHJvdG90eXBlKVxuXG4gIFJlc3BvbnNlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgUmVzcG9uc2UodGhpcy5fYm9keUluaXQsIHtcbiAgICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgICBzdGF0dXNUZXh0OiB0aGlzLnN0YXR1c1RleHQsXG4gICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh0aGlzLmhlYWRlcnMpLFxuICAgICAgdXJsOiB0aGlzLnVybFxuICAgIH0pXG4gIH1cblxuICBSZXNwb25zZS5lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZXNwb25zZSA9IG5ldyBSZXNwb25zZShudWxsLCB7c3RhdHVzOiAwLCBzdGF0dXNUZXh0OiAnJ30pXG4gICAgcmVzcG9uc2UudHlwZSA9ICdlcnJvcidcbiAgICByZXR1cm4gcmVzcG9uc2VcbiAgfVxuXG4gIHZhciByZWRpcmVjdFN0YXR1c2VzID0gWzMwMSwgMzAyLCAzMDMsIDMwNywgMzA4XVxuXG4gIFJlc3BvbnNlLnJlZGlyZWN0ID0gZnVuY3Rpb24odXJsLCBzdGF0dXMpIHtcbiAgICBpZiAocmVkaXJlY3RTdGF0dXNlcy5pbmRleE9mKHN0YXR1cykgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW52YWxpZCBzdGF0dXMgY29kZScpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBSZXNwb25zZShudWxsLCB7c3RhdHVzOiBzdGF0dXMsIGhlYWRlcnM6IHtsb2NhdGlvbjogdXJsfX0pXG4gIH1cblxuICBzZWxmLkhlYWRlcnMgPSBIZWFkZXJzXG4gIHNlbGYuUmVxdWVzdCA9IFJlcXVlc3RcbiAgc2VsZi5SZXNwb25zZSA9IFJlc3BvbnNlXG5cbiAgc2VsZi5mZXRjaCA9IGZ1bmN0aW9uKGlucHV0LCBpbml0KSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHJlcXVlc3QgPSBuZXcgUmVxdWVzdChpbnB1dCwgaW5pdClcbiAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKVxuXG4gICAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICAgIHN0YXR1czogeGhyLnN0YXR1cyxcbiAgICAgICAgICBzdGF0dXNUZXh0OiB4aHIuc3RhdHVzVGV4dCxcbiAgICAgICAgICBoZWFkZXJzOiBwYXJzZUhlYWRlcnMoeGhyLmdldEFsbFJlc3BvbnNlSGVhZGVycygpIHx8ICcnKVxuICAgICAgICB9XG4gICAgICAgIG9wdGlvbnMudXJsID0gJ3Jlc3BvbnNlVVJMJyBpbiB4aHIgPyB4aHIucmVzcG9uc2VVUkwgOiBvcHRpb25zLmhlYWRlcnMuZ2V0KCdYLVJlcXVlc3QtVVJMJylcbiAgICAgICAgdmFyIGJvZHkgPSAncmVzcG9uc2UnIGluIHhociA/IHhoci5yZXNwb25zZSA6IHhoci5yZXNwb25zZVRleHRcbiAgICAgICAgcmVzb2x2ZShuZXcgUmVzcG9uc2UoYm9keSwgb3B0aW9ucykpXG4gICAgICB9XG5cbiAgICAgIHhoci5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChuZXcgVHlwZUVycm9yKCdOZXR3b3JrIHJlcXVlc3QgZmFpbGVkJykpXG4gICAgICB9XG5cbiAgICAgIHhoci5vbnRpbWVvdXQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSlcbiAgICAgIH1cblxuICAgICAgeGhyLm9wZW4ocmVxdWVzdC5tZXRob2QsIHJlcXVlc3QudXJsLCB0cnVlKVxuXG4gICAgICBpZiAocmVxdWVzdC5jcmVkZW50aWFscyA9PT0gJ2luY2x1ZGUnKSB7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlXG4gICAgICB9XG5cbiAgICAgIGlmICgncmVzcG9uc2VUeXBlJyBpbiB4aHIgJiYgc3VwcG9ydC5ibG9iKSB7XG4gICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYmxvYidcbiAgICAgIH1cblxuICAgICAgcmVxdWVzdC5oZWFkZXJzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIobmFtZSwgdmFsdWUpXG4gICAgICB9KVxuXG4gICAgICB4aHIuc2VuZCh0eXBlb2YgcmVxdWVzdC5fYm9keUluaXQgPT09ICd1bmRlZmluZWQnID8gbnVsbCA6IHJlcXVlc3QuX2JvZHlJbml0KVxuICAgIH0pXG4gIH1cbiAgc2VsZi5mZXRjaC5wb2x5ZmlsbCA9IHRydWVcbn0pKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/IHNlbGYgOiB0aGlzKTtcbiIsIihmdW5jdGlvbigpeyd1c2Ugc3RyaWN0Jzt2YXIgaz10aGlzO1xuZnVuY3Rpb24gYWEoYSl7dmFyIGI9dHlwZW9mIGE7aWYoXCJvYmplY3RcIj09YilpZihhKXtpZihhIGluc3RhbmNlb2YgQXJyYXkpcmV0dXJuXCJhcnJheVwiO2lmKGEgaW5zdGFuY2VvZiBPYmplY3QpcmV0dXJuIGI7dmFyIGM9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGEpO2lmKFwiW29iamVjdCBXaW5kb3ddXCI9PWMpcmV0dXJuXCJvYmplY3RcIjtpZihcIltvYmplY3QgQXJyYXldXCI9PWN8fFwibnVtYmVyXCI9PXR5cGVvZiBhLmxlbmd0aCYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEuc3BsaWNlJiZcInVuZGVmaW5lZFwiIT10eXBlb2YgYS5wcm9wZXJ0eUlzRW51bWVyYWJsZSYmIWEucHJvcGVydHlJc0VudW1lcmFibGUoXCJzcGxpY2VcIikpcmV0dXJuXCJhcnJheVwiO2lmKFwiW29iamVjdCBGdW5jdGlvbl1cIj09Y3x8XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEuY2FsbCYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGEucHJvcGVydHlJc0VudW1lcmFibGUmJiFhLnByb3BlcnR5SXNFbnVtZXJhYmxlKFwiY2FsbFwiKSlyZXR1cm5cImZ1bmN0aW9uXCJ9ZWxzZSByZXR1cm5cIm51bGxcIjtlbHNlIGlmKFwiZnVuY3Rpb25cIj09XG5iJiZcInVuZGVmaW5lZFwiPT10eXBlb2YgYS5jYWxsKXJldHVyblwib2JqZWN0XCI7cmV0dXJuIGJ9ZnVuY3Rpb24gbChhKXtyZXR1cm5cInN0cmluZ1wiPT10eXBlb2YgYX1mdW5jdGlvbiBiYShhLGIsYyl7cmV0dXJuIGEuY2FsbC5hcHBseShhLmJpbmQsYXJndW1lbnRzKX1mdW5jdGlvbiBjYShhLGIsYyl7aWYoIWEpdGhyb3cgRXJyb3IoKTtpZigyPGFyZ3VtZW50cy5sZW5ndGgpe3ZhciBkPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywyKTtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgYz1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO0FycmF5LnByb3RvdHlwZS51bnNoaWZ0LmFwcGx5KGMsZCk7cmV0dXJuIGEuYXBwbHkoYixjKX19cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGEuYXBwbHkoYixhcmd1bWVudHMpfX1cbmZ1bmN0aW9uIGRhKGEsYixjKXtkYT1GdW5jdGlvbi5wcm90b3R5cGUuYmluZCYmLTEhPUZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kLnRvU3RyaW5nKCkuaW5kZXhPZihcIm5hdGl2ZSBjb2RlXCIpP2JhOmNhO3JldHVybiBkYS5hcHBseShudWxsLGFyZ3VtZW50cyl9ZnVuY3Rpb24gZWEoYSxiKXt2YXIgYz1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsMSk7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIGI9Yy5zbGljZSgpO2IucHVzaC5hcHBseShiLGFyZ3VtZW50cyk7cmV0dXJuIGEuYXBwbHkodGhpcyxiKX19XG5mdW5jdGlvbiBtKGEpe3ZhciBiPW47ZnVuY3Rpb24gYygpe31jLnByb3RvdHlwZT1iLnByb3RvdHlwZTthLkc9Yi5wcm90b3R5cGU7YS5wcm90b3R5cGU9bmV3IGM7YS5wcm90b3R5cGUuY29uc3RydWN0b3I9YTthLkY9ZnVuY3Rpb24oYSxjLGYpe2Zvcih2YXIgZz1BcnJheShhcmd1bWVudHMubGVuZ3RoLTIpLGg9MjtoPGFyZ3VtZW50cy5sZW5ndGg7aCsrKWdbaC0yXT1hcmd1bWVudHNbaF07cmV0dXJuIGIucHJvdG90eXBlW2NdLmFwcGx5KGEsZyl9fTsvKlxuXG4gVGhlIE1JVCBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMDcgQ3lib3p1IExhYnMsIEluYy5cbiBDb3B5cmlnaHQgKGMpIDIwMTIgR29vZ2xlIEluYy5cblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4gc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuXG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTXG4gSU4gVEhFIFNPRlRXQVJFLlxuKi9cbnZhciBmYT1TdHJpbmcucHJvdG90eXBlLnRyaW0/ZnVuY3Rpb24oYSl7cmV0dXJuIGEudHJpbSgpfTpmdW5jdGlvbihhKXtyZXR1cm4gYS5yZXBsYWNlKC9eW1xcc1xceGEwXSt8W1xcc1xceGEwXSskL2csXCJcIil9O2Z1bmN0aW9uIHEoYSxiKXtyZXR1cm4tMSE9YS5pbmRleE9mKGIpfWZ1bmN0aW9uIGdhKGEsYil7cmV0dXJuIGE8Yj8tMTphPmI/MTowfTt2YXIgaGE9QXJyYXkucHJvdG90eXBlLmluZGV4T2Y/ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2M9bnVsbD09Yz8wOjA+Yz9NYXRoLm1heCgwLGEubGVuZ3RoK2MpOmM7aWYobChhKSlyZXR1cm4gbChiKSYmMT09Yi5sZW5ndGg/YS5pbmRleE9mKGIsYyk6LTE7Zm9yKDtjPGEubGVuZ3RoO2MrKylpZihjIGluIGEmJmFbY109PT1iKXJldHVybiBjO3JldHVybi0xfSxyPUFycmF5LnByb3RvdHlwZS5mb3JFYWNoP2Z1bmN0aW9uKGEsYixjKXtBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD1hLmxlbmd0aCxlPWwoYSk/YS5zcGxpdChcIlwiKTphLGY9MDtmPGQ7ZisrKWYgaW4gZSYmYi5jYWxsKGMsZVtmXSxmLGEpfSxpYT1BcnJheS5wcm90b3R5cGUuZmlsdGVyP2Z1bmN0aW9uKGEsYixjKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmZpbHRlci5jYWxsKGEsXG5iLGMpfTpmdW5jdGlvbihhLGIsYyl7Zm9yKHZhciBkPWEubGVuZ3RoLGU9W10sZj0wLGc9bChhKT9hLnNwbGl0KFwiXCIpOmEsaD0wO2g8ZDtoKyspaWYoaCBpbiBnKXt2YXIgcD1nW2hdO2IuY2FsbChjLHAsaCxhKSYmKGVbZisrXT1wKX1yZXR1cm4gZX0sdD1BcnJheS5wcm90b3R5cGUucmVkdWNlP2Z1bmN0aW9uKGEsYixjLGQpe2QmJihiPWRhKGIsZCkpO3JldHVybiBBcnJheS5wcm90b3R5cGUucmVkdWNlLmNhbGwoYSxiLGMpfTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgZT1jO3IoYSxmdW5jdGlvbihjLGcpe2U9Yi5jYWxsKGQsZSxjLGcsYSl9KTtyZXR1cm4gZX0samE9QXJyYXkucHJvdG90eXBlLnNvbWU/ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBBcnJheS5wcm90b3R5cGUuc29tZS5jYWxsKGEsYixjKX06ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD1hLmxlbmd0aCxlPWwoYSk/YS5zcGxpdChcIlwiKTphLGY9MDtmPGQ7ZisrKWlmKGYgaW4gZSYmYi5jYWxsKGMsZVtmXSxmLGEpKXJldHVybiEwO1xucmV0dXJuITF9O2Z1bmN0aW9uIGthKGEsYil7dmFyIGM7YTp7Yz1hLmxlbmd0aDtmb3IodmFyIGQ9bChhKT9hLnNwbGl0KFwiXCIpOmEsZT0wO2U8YztlKyspaWYoZSBpbiBkJiZiLmNhbGwodm9pZCAwLGRbZV0sZSxhKSl7Yz1lO2JyZWFrIGF9Yz0tMX1yZXR1cm4gMD5jP251bGw6bChhKT9hLmNoYXJBdChjKTphW2NdfWZ1bmN0aW9uIGxhKGEpe3JldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KEFycmF5LnByb3RvdHlwZSxhcmd1bWVudHMpfWZ1bmN0aW9uIG1hKGEsYixjKXtyZXR1cm4gMj49YXJndW1lbnRzLmxlbmd0aD9BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhLGIpOkFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGEsYixjKX07dmFyIHU7YTp7dmFyIG5hPWsubmF2aWdhdG9yO2lmKG5hKXt2YXIgb2E9bmEudXNlckFnZW50O2lmKG9hKXt1PW9hO2JyZWFrIGF9fXU9XCJcIn07dmFyIHBhPXEodSxcIk9wZXJhXCIpfHxxKHUsXCJPUFJcIiksdj1xKHUsXCJUcmlkZW50XCIpfHxxKHUsXCJNU0lFXCIpLHFhPXEodSxcIkVkZ2VcIikscmE9cSh1LFwiR2Vja29cIikmJiEocSh1LnRvTG93ZXJDYXNlKCksXCJ3ZWJraXRcIikmJiFxKHUsXCJFZGdlXCIpKSYmIShxKHUsXCJUcmlkZW50XCIpfHxxKHUsXCJNU0lFXCIpKSYmIXEodSxcIkVkZ2VcIiksc2E9cSh1LnRvTG93ZXJDYXNlKCksXCJ3ZWJraXRcIikmJiFxKHUsXCJFZGdlXCIpO2Z1bmN0aW9uIHRhKCl7dmFyIGE9ay5kb2N1bWVudDtyZXR1cm4gYT9hLmRvY3VtZW50TW9kZTp2b2lkIDB9dmFyIHVhO1xuYTp7dmFyIHZhPVwiXCIsd2E9ZnVuY3Rpb24oKXt2YXIgYT11O2lmKHJhKXJldHVybi9ydlxcOihbXlxcKTtdKykoXFwpfDspLy5leGVjKGEpO2lmKHFhKXJldHVybi9FZGdlXFwvKFtcXGRcXC5dKykvLmV4ZWMoYSk7aWYodilyZXR1cm4vXFxiKD86TVNJRXxydilbOiBdKFteXFwpO10rKShcXCl8OykvLmV4ZWMoYSk7aWYoc2EpcmV0dXJuL1dlYktpdFxcLyhcXFMrKS8uZXhlYyhhKTtpZihwYSlyZXR1cm4vKD86VmVyc2lvbilbIFxcL10/KFxcUyspLy5leGVjKGEpfSgpO3dhJiYodmE9d2E/d2FbMV06XCJcIik7aWYodil7dmFyIHhhPXRhKCk7aWYobnVsbCE9eGEmJnhhPnBhcnNlRmxvYXQodmEpKXt1YT1TdHJpbmcoeGEpO2JyZWFrIGF9fXVhPXZhfXZhciB5YT17fTtcbmZ1bmN0aW9uIHphKGEpe2lmKCF5YVthXSl7Zm9yKHZhciBiPTAsYz1mYShTdHJpbmcodWEpKS5zcGxpdChcIi5cIiksZD1mYShTdHJpbmcoYSkpLnNwbGl0KFwiLlwiKSxlPU1hdGgubWF4KGMubGVuZ3RoLGQubGVuZ3RoKSxmPTA7MD09YiYmZjxlO2YrKyl7dmFyIGc9Y1tmXXx8XCJcIixoPWRbZl18fFwiXCIscD0vKFxcZCopKFxcRCopL2cseT0vKFxcZCopKFxcRCopL2c7ZG97dmFyIEQ9cC5leGVjKGcpfHxbXCJcIixcIlwiLFwiXCJdLFg9eS5leGVjKGgpfHxbXCJcIixcIlwiLFwiXCJdO2lmKDA9PURbMF0ubGVuZ3RoJiYwPT1YWzBdLmxlbmd0aClicmVhaztiPWdhKDA9PURbMV0ubGVuZ3RoPzA6cGFyc2VJbnQoRFsxXSwxMCksMD09WFsxXS5sZW5ndGg/MDpwYXJzZUludChYWzFdLDEwKSl8fGdhKDA9PURbMl0ubGVuZ3RoLDA9PVhbMl0ubGVuZ3RoKXx8Z2EoRFsyXSxYWzJdKX13aGlsZSgwPT1iKX15YVthXT0wPD1ifX1cbnZhciBBYT1rLmRvY3VtZW50LEJhPUFhJiZ2P3RhKCl8fChcIkNTUzFDb21wYXRcIj09QWEuY29tcGF0TW9kZT9wYXJzZUludCh1YSwxMCk6NSk6dm9pZCAwO3ZhciB3PXYmJiEoOTw9TnVtYmVyKEJhKSksQ2E9diYmISg4PD1OdW1iZXIoQmEpKTtmdW5jdGlvbiB4KGEsYixjLGQpe3RoaXMuYT1hO3RoaXMubm9kZU5hbWU9Yzt0aGlzLm5vZGVWYWx1ZT1kO3RoaXMubm9kZVR5cGU9Mjt0aGlzLnBhcmVudE5vZGU9dGhpcy5vd25lckVsZW1lbnQ9Yn1mdW5jdGlvbiBEYShhLGIpe3ZhciBjPUNhJiZcImhyZWZcIj09Yi5ub2RlTmFtZT9hLmdldEF0dHJpYnV0ZShiLm5vZGVOYW1lLDIpOmIubm9kZVZhbHVlO3JldHVybiBuZXcgeChiLGEsYi5ub2RlTmFtZSxjKX07ZnVuY3Rpb24geihhKXt2YXIgYj1udWxsLGM9YS5ub2RlVHlwZTsxPT1jJiYoYj1hLnRleHRDb250ZW50LGI9dm9pZCAwPT1ifHxudWxsPT1iP2EuaW5uZXJUZXh0OmIsYj12b2lkIDA9PWJ8fG51bGw9PWI/XCJcIjpiKTtpZihcInN0cmluZ1wiIT10eXBlb2YgYilpZih3JiZcInRpdGxlXCI9PWEubm9kZU5hbWUudG9Mb3dlckNhc2UoKSYmMT09YyliPWEudGV4dDtlbHNlIGlmKDk9PWN8fDE9PWMpe2E9OT09Yz9hLmRvY3VtZW50RWxlbWVudDphLmZpcnN0Q2hpbGQ7Zm9yKHZhciBjPTAsZD1bXSxiPVwiXCI7YTspe2RvIDEhPWEubm9kZVR5cGUmJihiKz1hLm5vZGVWYWx1ZSksdyYmXCJ0aXRsZVwiPT1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkmJihiKz1hLnRleHQpLGRbYysrXT1hO3doaWxlKGE9YS5maXJzdENoaWxkKTtmb3IoO2MmJiEoYT1kWy0tY10ubmV4dFNpYmxpbmcpOyk7fX1lbHNlIGI9YS5ub2RlVmFsdWU7cmV0dXJuXCJcIitifVxuZnVuY3Rpb24gQShhLGIsYyl7aWYobnVsbD09PWIpcmV0dXJuITA7dHJ5e2lmKCFhLmdldEF0dHJpYnV0ZSlyZXR1cm4hMX1jYXRjaChkKXtyZXR1cm4hMX1DYSYmXCJjbGFzc1wiPT1iJiYoYj1cImNsYXNzTmFtZVwiKTtyZXR1cm4gbnVsbD09Yz8hIWEuZ2V0QXR0cmlidXRlKGIpOmEuZ2V0QXR0cmlidXRlKGIsMik9PWN9ZnVuY3Rpb24gQihhLGIsYyxkLGUpe3JldHVybih3P0VhOkZhKS5jYWxsKG51bGwsYSxiLGwoYyk/YzpudWxsLGwoZCk/ZDpudWxsLGV8fG5ldyBDKX1cbmZ1bmN0aW9uIEVhKGEsYixjLGQsZSl7aWYoYSBpbnN0YW5jZW9mIEV8fDg9PWEuYnx8YyYmbnVsbD09PWEuYil7dmFyIGY9Yi5hbGw7aWYoIWYpcmV0dXJuIGU7YT1HYShhKTtpZihcIipcIiE9YSYmKGY9Yi5nZXRFbGVtZW50c0J5VGFnTmFtZShhKSwhZikpcmV0dXJuIGU7aWYoYyl7Zm9yKHZhciBnPVtdLGg9MDtiPWZbaCsrXTspQShiLGMsZCkmJmcucHVzaChiKTtmPWd9Zm9yKGg9MDtiPWZbaCsrXTspXCIqXCI9PWEmJlwiIVwiPT1iLnRhZ05hbWV8fEYoZSxiKTtyZXR1cm4gZX1IYShhLGIsYyxkLGUpO3JldHVybiBlfVxuZnVuY3Rpb24gRmEoYSxiLGMsZCxlKXtiLmdldEVsZW1lbnRzQnlOYW1lJiZkJiZcIm5hbWVcIj09YyYmIXY/KGI9Yi5nZXRFbGVtZW50c0J5TmFtZShkKSxyKGIsZnVuY3Rpb24oYil7YS5hKGIpJiZGKGUsYil9KSk6Yi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lJiZkJiZcImNsYXNzXCI9PWM/KGI9Yi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGQpLHIoYixmdW5jdGlvbihiKXtiLmNsYXNzTmFtZT09ZCYmYS5hKGIpJiZGKGUsYil9KSk6YSBpbnN0YW5jZW9mIEc/SGEoYSxiLGMsZCxlKTpiLmdldEVsZW1lbnRzQnlUYWdOYW1lJiYoYj1iLmdldEVsZW1lbnRzQnlUYWdOYW1lKGEuZigpKSxyKGIsZnVuY3Rpb24oYSl7QShhLGMsZCkmJkYoZSxhKX0pKTtyZXR1cm4gZX1cbmZ1bmN0aW9uIElhKGEsYixjLGQsZSl7dmFyIGY7aWYoKGEgaW5zdGFuY2VvZiBFfHw4PT1hLmJ8fGMmJm51bGw9PT1hLmIpJiYoZj1iLmNoaWxkTm9kZXMpKXt2YXIgZz1HYShhKTtpZihcIipcIiE9ZyYmKGY9aWEoZixmdW5jdGlvbihhKXtyZXR1cm4gYS50YWdOYW1lJiZhLnRhZ05hbWUudG9Mb3dlckNhc2UoKT09Z30pLCFmKSlyZXR1cm4gZTtjJiYoZj1pYShmLGZ1bmN0aW9uKGEpe3JldHVybiBBKGEsYyxkKX0pKTtyKGYsZnVuY3Rpb24oYSl7XCIqXCI9PWcmJihcIiFcIj09YS50YWdOYW1lfHxcIipcIj09ZyYmMSE9YS5ub2RlVHlwZSl8fEYoZSxhKX0pO3JldHVybiBlfXJldHVybiBKYShhLGIsYyxkLGUpfWZ1bmN0aW9uIEphKGEsYixjLGQsZSl7Zm9yKGI9Yi5maXJzdENoaWxkO2I7Yj1iLm5leHRTaWJsaW5nKUEoYixjLGQpJiZhLmEoYikmJkYoZSxiKTtyZXR1cm4gZX1cbmZ1bmN0aW9uIEhhKGEsYixjLGQsZSl7Zm9yKGI9Yi5maXJzdENoaWxkO2I7Yj1iLm5leHRTaWJsaW5nKUEoYixjLGQpJiZhLmEoYikmJkYoZSxiKSxIYShhLGIsYyxkLGUpfWZ1bmN0aW9uIEdhKGEpe2lmKGEgaW5zdGFuY2VvZiBHKXtpZig4PT1hLmIpcmV0dXJuXCIhXCI7aWYobnVsbD09PWEuYilyZXR1cm5cIipcIn1yZXR1cm4gYS5mKCl9OyFyYSYmIXZ8fHYmJjk8PU51bWJlcihCYSl8fHJhJiZ6YShcIjEuOS4xXCIpO3YmJnphKFwiOVwiKTtmdW5jdGlvbiBLYShhLGIpe2lmKCFhfHwhYilyZXR1cm4hMTtpZihhLmNvbnRhaW5zJiYxPT1iLm5vZGVUeXBlKXJldHVybiBhPT1ifHxhLmNvbnRhaW5zKGIpO2lmKFwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKXJldHVybiBhPT1ifHwhIShhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGIpJjE2KTtmb3IoO2ImJmEhPWI7KWI9Yi5wYXJlbnROb2RlO3JldHVybiBiPT1hfVxuZnVuY3Rpb24gTGEoYSxiKXtpZihhPT1iKXJldHVybiAwO2lmKGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24pcmV0dXJuIGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oYikmMj8xOi0xO2lmKHYmJiEoOTw9TnVtYmVyKEJhKSkpe2lmKDk9PWEubm9kZVR5cGUpcmV0dXJuLTE7aWYoOT09Yi5ub2RlVHlwZSlyZXR1cm4gMX1pZihcInNvdXJjZUluZGV4XCJpbiBhfHxhLnBhcmVudE5vZGUmJlwic291cmNlSW5kZXhcImluIGEucGFyZW50Tm9kZSl7dmFyIGM9MT09YS5ub2RlVHlwZSxkPTE9PWIubm9kZVR5cGU7aWYoYyYmZClyZXR1cm4gYS5zb3VyY2VJbmRleC1iLnNvdXJjZUluZGV4O3ZhciBlPWEucGFyZW50Tm9kZSxmPWIucGFyZW50Tm9kZTtyZXR1cm4gZT09Zj9NYShhLGIpOiFjJiZLYShlLGIpPy0xKk5hKGEsYik6IWQmJkthKGYsYSk/TmEoYixhKTooYz9hLnNvdXJjZUluZGV4OmUuc291cmNlSW5kZXgpLShkP2Iuc291cmNlSW5kZXg6Zi5zb3VyY2VJbmRleCl9ZD05PT1hLm5vZGVUeXBlP1xuYTphLm93bmVyRG9jdW1lbnR8fGEuZG9jdW1lbnQ7Yz1kLmNyZWF0ZVJhbmdlKCk7Yy5zZWxlY3ROb2RlKGEpO2MuY29sbGFwc2UoITApO2Q9ZC5jcmVhdGVSYW5nZSgpO2Quc2VsZWN0Tm9kZShiKTtkLmNvbGxhcHNlKCEwKTtyZXR1cm4gYy5jb21wYXJlQm91bmRhcnlQb2ludHMoay5SYW5nZS5TVEFSVF9UT19FTkQsZCl9ZnVuY3Rpb24gTmEoYSxiKXt2YXIgYz1hLnBhcmVudE5vZGU7aWYoYz09YilyZXR1cm4tMTtmb3IodmFyIGQ9YjtkLnBhcmVudE5vZGUhPWM7KWQ9ZC5wYXJlbnROb2RlO3JldHVybiBNYShkLGEpfWZ1bmN0aW9uIE1hKGEsYil7Zm9yKHZhciBjPWI7Yz1jLnByZXZpb3VzU2libGluZzspaWYoYz09YSlyZXR1cm4tMTtyZXR1cm4gMX07ZnVuY3Rpb24gQygpe3RoaXMuYj10aGlzLmE9bnVsbDt0aGlzLmw9MH1mdW5jdGlvbiBPYShhKXt0aGlzLm5vZGU9YTt0aGlzLmE9dGhpcy5iPW51bGx9ZnVuY3Rpb24gUGEoYSxiKXtpZighYS5hKXJldHVybiBiO2lmKCFiLmEpcmV0dXJuIGE7Zm9yKHZhciBjPWEuYSxkPWIuYSxlPW51bGwsZj1udWxsLGc9MDtjJiZkOyl7dmFyIGY9Yy5ub2RlLGg9ZC5ub2RlO2Y9PWh8fGYgaW5zdGFuY2VvZiB4JiZoIGluc3RhbmNlb2YgeCYmZi5hPT1oLmE/KGY9YyxjPWMuYSxkPWQuYSk6MDxMYShjLm5vZGUsZC5ub2RlKT8oZj1kLGQ9ZC5hKTooZj1jLGM9Yy5hKTsoZi5iPWUpP2UuYT1mOmEuYT1mO2U9ZjtnKyt9Zm9yKGY9Y3x8ZDtmOylmLmI9ZSxlPWUuYT1mLGcrKyxmPWYuYTthLmI9ZTthLmw9ZztyZXR1cm4gYX1mdW5jdGlvbiBRYShhLGIpe3ZhciBjPW5ldyBPYShiKTtjLmE9YS5hO2EuYj9hLmEuYj1jOmEuYT1hLmI9YzthLmE9YzthLmwrK31cbmZ1bmN0aW9uIEYoYSxiKXt2YXIgYz1uZXcgT2EoYik7Yy5iPWEuYjthLmE/YS5iLmE9YzphLmE9YS5iPWM7YS5iPWM7YS5sKyt9ZnVuY3Rpb24gUmEoYSl7cmV0dXJuKGE9YS5hKT9hLm5vZGU6bnVsbH1mdW5jdGlvbiBTYShhKXtyZXR1cm4oYT1SYShhKSk/eihhKTpcIlwifWZ1bmN0aW9uIEgoYSxiKXtyZXR1cm4gbmV3IFRhKGEsISFiKX1mdW5jdGlvbiBUYShhLGIpe3RoaXMuZj1hO3RoaXMuYj0odGhpcy5jPWIpP2EuYjphLmE7dGhpcy5hPW51bGx9ZnVuY3Rpb24gSShhKXt2YXIgYj1hLmI7aWYobnVsbD09YilyZXR1cm4gbnVsbDt2YXIgYz1hLmE9YjthLmI9YS5jP2IuYjpiLmE7cmV0dXJuIGMubm9kZX07ZnVuY3Rpb24gbihhKXt0aGlzLmk9YTt0aGlzLmI9dGhpcy5nPSExO3RoaXMuZj1udWxsfWZ1bmN0aW9uIEooYSl7cmV0dXJuXCJcXG4gIFwiK2EudG9TdHJpbmcoKS5zcGxpdChcIlxcblwiKS5qb2luKFwiXFxuICBcIil9ZnVuY3Rpb24gVWEoYSxiKXthLmc9Yn1mdW5jdGlvbiBWYShhLGIpe2EuYj1ifWZ1bmN0aW9uIEsoYSxiKXt2YXIgYz1hLmEoYik7cmV0dXJuIGMgaW5zdGFuY2VvZiBDPytTYShjKTorY31mdW5jdGlvbiBMKGEsYil7dmFyIGM9YS5hKGIpO3JldHVybiBjIGluc3RhbmNlb2YgQz9TYShjKTpcIlwiK2N9ZnVuY3Rpb24gTShhLGIpe3ZhciBjPWEuYShiKTtyZXR1cm4gYyBpbnN0YW5jZW9mIEM/ISFjLmw6ISFjfTtmdW5jdGlvbiBOKGEsYixjKXtuLmNhbGwodGhpcyxhLmkpO3RoaXMuYz1hO3RoaXMuaD1iO3RoaXMubz1jO3RoaXMuZz1iLmd8fGMuZzt0aGlzLmI9Yi5ifHxjLmI7dGhpcy5jPT1XYSYmKGMuYnx8Yy5nfHw0PT1jLml8fDA9PWMuaXx8IWIuZj9iLmJ8fGIuZ3x8ND09Yi5pfHwwPT1iLml8fCFjLmZ8fCh0aGlzLmY9e25hbWU6Yy5mLm5hbWUsczpifSk6dGhpcy5mPXtuYW1lOmIuZi5uYW1lLHM6Y30pfW0oTik7XG5mdW5jdGlvbiBPKGEsYixjLGQsZSl7Yj1iLmEoZCk7Yz1jLmEoZCk7dmFyIGY7aWYoYiBpbnN0YW5jZW9mIEMmJmMgaW5zdGFuY2VvZiBDKXtiPUgoYik7Zm9yKGQ9SShiKTtkO2Q9SShiKSlmb3IoZT1IKGMpLGY9SShlKTtmO2Y9SShlKSlpZihhKHooZCkseihmKSkpcmV0dXJuITA7cmV0dXJuITF9aWYoYiBpbnN0YW5jZW9mIEN8fGMgaW5zdGFuY2VvZiBDKXtiIGluc3RhbmNlb2YgQz8oZT1iLGQ9Yyk6KGU9YyxkPWIpO2Y9SChlKTtmb3IodmFyIGc9dHlwZW9mIGQsaD1JKGYpO2g7aD1JKGYpKXtzd2l0Y2goZyl7Y2FzZSBcIm51bWJlclwiOmg9K3ooaCk7YnJlYWs7Y2FzZSBcImJvb2xlYW5cIjpoPSEheihoKTticmVhaztjYXNlIFwic3RyaW5nXCI6aD16KGgpO2JyZWFrO2RlZmF1bHQ6dGhyb3cgRXJyb3IoXCJJbGxlZ2FsIHByaW1pdGl2ZSB0eXBlIGZvciBjb21wYXJpc29uLlwiKTt9aWYoZT09YiYmYShoLGQpfHxlPT1jJiZhKGQsaCkpcmV0dXJuITB9cmV0dXJuITF9cmV0dXJuIGU/XCJib29sZWFuXCI9PVxudHlwZW9mIGJ8fFwiYm9vbGVhblwiPT10eXBlb2YgYz9hKCEhYiwhIWMpOlwibnVtYmVyXCI9PXR5cGVvZiBifHxcIm51bWJlclwiPT10eXBlb2YgYz9hKCtiLCtjKTphKGIsYyk6YSgrYiwrYyl9Ti5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5jLm0odGhpcy5oLHRoaXMubyxhKX07Ti5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYT1cIkJpbmFyeSBFeHByZXNzaW9uOiBcIit0aGlzLmMsYT1hK0oodGhpcy5oKTtyZXR1cm4gYSs9Sih0aGlzLm8pfTtmdW5jdGlvbiBYYShhLGIsYyxkKXt0aGlzLmE9YTt0aGlzLnc9Yjt0aGlzLmk9Yzt0aGlzLm09ZH1YYS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfTt2YXIgWWE9e307XG5mdW5jdGlvbiBQKGEsYixjLGQpe2lmKFlhLmhhc093blByb3BlcnR5KGEpKXRocm93IEVycm9yKFwiQmluYXJ5IG9wZXJhdG9yIGFscmVhZHkgY3JlYXRlZDogXCIrYSk7YT1uZXcgWGEoYSxiLGMsZCk7cmV0dXJuIFlhW2EudG9TdHJpbmcoKV09YX1QKFwiZGl2XCIsNiwxLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSyhhLGMpL0soYixjKX0pO1AoXCJtb2RcIiw2LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYyklSyhiLGMpfSk7UChcIipcIiw2LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYykqSyhiLGMpfSk7UChcIitcIiw1LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYykrSyhiLGMpfSk7UChcIi1cIiw1LDEsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBLKGEsYyktSyhiLGMpfSk7UChcIjxcIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE8Yn0sYSxiLGMpfSk7XG5QKFwiPlwiLDQsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE8oZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT5ifSxhLGIsYyl9KTtQKFwiPD1cIiw0LDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGE8PWJ9LGEsYixjKX0pO1AoXCI+PVwiLDQsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE8oZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT49Yn0sYSxiLGMpfSk7dmFyIFdhPVAoXCI9XCIsMywyLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTyhmdW5jdGlvbihhLGIpe3JldHVybiBhPT1ifSxhLGIsYywhMCl9KTtQKFwiIT1cIiwzLDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBPKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGEhPWJ9LGEsYixjLCEwKX0pO1AoXCJhbmRcIiwyLDIsZnVuY3Rpb24oYSxiLGMpe3JldHVybiBNKGEsYykmJk0oYixjKX0pO1AoXCJvclwiLDEsMixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIE0oYSxjKXx8TShiLGMpfSk7ZnVuY3Rpb24gUShhLGIsYyl7dGhpcy5hPWE7dGhpcy5iPWJ8fDE7dGhpcy5mPWN8fDF9O2Z1bmN0aW9uIFphKGEsYil7aWYoYi5hLmxlbmd0aCYmNCE9YS5pKXRocm93IEVycm9yKFwiUHJpbWFyeSBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gbm9kZXNldCBpZiBmaWx0ZXIgaGFzIHByZWRpY2F0ZShzKS5cIik7bi5jYWxsKHRoaXMsYS5pKTt0aGlzLmM9YTt0aGlzLmg9Yjt0aGlzLmc9YS5nO3RoaXMuYj1hLmJ9bShaYSk7WmEucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7YT10aGlzLmMuYShhKTtyZXR1cm4gJGEodGhpcy5oLGEpfTtaYS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYTthPVwiRmlsdGVyOlwiK0oodGhpcy5jKTtyZXR1cm4gYSs9Sih0aGlzLmgpfTtmdW5jdGlvbiBhYihhLGIpe2lmKGIubGVuZ3RoPGEuQSl0aHJvdyBFcnJvcihcIkZ1bmN0aW9uIFwiK2EuaitcIiBleHBlY3RzIGF0IGxlYXN0XCIrYS5BK1wiIGFyZ3VtZW50cywgXCIrYi5sZW5ndGgrXCIgZ2l2ZW5cIik7aWYobnVsbCE9PWEudiYmYi5sZW5ndGg+YS52KXRocm93IEVycm9yKFwiRnVuY3Rpb24gXCIrYS5qK1wiIGV4cGVjdHMgYXQgbW9zdCBcIithLnYrXCIgYXJndW1lbnRzLCBcIitiLmxlbmd0aCtcIiBnaXZlblwiKTthLkImJnIoYixmdW5jdGlvbihiLGQpe2lmKDQhPWIuaSl0aHJvdyBFcnJvcihcIkFyZ3VtZW50IFwiK2QrXCIgdG8gZnVuY3Rpb24gXCIrYS5qK1wiIGlzIG5vdCBvZiB0eXBlIE5vZGVzZXQ6IFwiK2IpO30pO24uY2FsbCh0aGlzLGEuaSk7dGhpcy5oPWE7dGhpcy5jPWI7VWEodGhpcyxhLmd8fGphKGIsZnVuY3Rpb24oYSl7cmV0dXJuIGEuZ30pKTtWYSh0aGlzLGEuRCYmIWIubGVuZ3RofHxhLkMmJiEhYi5sZW5ndGh8fGphKGIsZnVuY3Rpb24oYSl7cmV0dXJuIGEuYn0pKX1tKGFiKTtcbmFiLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmgubS5hcHBseShudWxsLGxhKGEsdGhpcy5jKSl9O2FiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhPVwiRnVuY3Rpb246IFwiK3RoaXMuaDtpZih0aGlzLmMubGVuZ3RoKXZhciBiPXQodGhpcy5jLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGErSihiKX0sXCJBcmd1bWVudHM6XCIpLGE9YStKKGIpO3JldHVybiBhfTtmdW5jdGlvbiBiYihhLGIsYyxkLGUsZixnLGgscCl7dGhpcy5qPWE7dGhpcy5pPWI7dGhpcy5nPWM7dGhpcy5EPWQ7dGhpcy5DPWU7dGhpcy5tPWY7dGhpcy5BPWc7dGhpcy52PXZvaWQgMCE9PWg/aDpnO3RoaXMuQj0hIXB9YmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07dmFyIGNiPXt9O1xuZnVuY3Rpb24gUihhLGIsYyxkLGUsZixnLGgpe2lmKGNiLmhhc093blByb3BlcnR5KGEpKXRocm93IEVycm9yKFwiRnVuY3Rpb24gYWxyZWFkeSBjcmVhdGVkOiBcIithK1wiLlwiKTtjYlthXT1uZXcgYmIoYSxiLGMsZCwhMSxlLGYsZyxoKX1SKFwiYm9vbGVhblwiLDIsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTShiLGEpfSwxKTtSKFwiY2VpbGluZ1wiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTWF0aC5jZWlsKEsoYixhKSl9LDEpO1IoXCJjb25jYXRcIiwzLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIHQobWEoYXJndW1lbnRzLDEpLGZ1bmN0aW9uKGIsZCl7cmV0dXJuIGIrTChkLGEpfSxcIlwiKX0sMixudWxsKTtSKFwiY29udGFpbnNcIiwyLCExLCExLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gcShMKGIsYSksTChjLGEpKX0sMik7UihcImNvdW50XCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiBiLmEoYSkubH0sMSwxLCEwKTtcblIoXCJmYWxzZVwiLDIsITEsITEsZnVuY3Rpb24oKXtyZXR1cm4hMX0sMCk7UihcImZsb29yXCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe3JldHVybiBNYXRoLmZsb29yKEsoYixhKSl9LDEpO1IoXCJpZFwiLDQsITEsITEsZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEpe2lmKHcpe3ZhciBiPWUuYWxsW2FdO2lmKGIpe2lmKGIubm9kZVR5cGUmJmE9PWIuaWQpcmV0dXJuIGI7aWYoYi5sZW5ndGgpcmV0dXJuIGthKGIsZnVuY3Rpb24oYil7cmV0dXJuIGE9PWIuaWR9KX1yZXR1cm4gbnVsbH1yZXR1cm4gZS5nZXRFbGVtZW50QnlJZChhKX12YXIgZD1hLmEsZT05PT1kLm5vZGVUeXBlP2Q6ZC5vd25lckRvY3VtZW50LGQ9TChiLGEpLnNwbGl0KC9cXHMrLyksZj1bXTtyKGQsZnVuY3Rpb24oYSl7YT1jKGEpOyFhfHwwPD1oYShmLGEpfHxmLnB1c2goYSl9KTtmLnNvcnQoTGEpO3ZhciBnPW5ldyBDO3IoZixmdW5jdGlvbihhKXtGKGcsYSl9KTtyZXR1cm4gZ30sMSk7XG5SKFwibGFuZ1wiLDIsITEsITEsZnVuY3Rpb24oKXtyZXR1cm4hMX0sMSk7UihcImxhc3RcIiwxLCEwLCExLGZ1bmN0aW9uKGEpe2lmKDEhPWFyZ3VtZW50cy5sZW5ndGgpdGhyb3cgRXJyb3IoXCJGdW5jdGlvbiBsYXN0IGV4cGVjdHMgKClcIik7cmV0dXJuIGEuZn0sMCk7UihcImxvY2FsLW5hbWVcIiwzLCExLCEwLGZ1bmN0aW9uKGEsYil7dmFyIGM9Yj9SYShiLmEoYSkpOmEuYTtyZXR1cm4gYz9jLmxvY2FsTmFtZXx8Yy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOlwiXCJ9LDAsMSwhMCk7UihcIm5hbWVcIiwzLCExLCEwLGZ1bmN0aW9uKGEsYil7dmFyIGM9Yj9SYShiLmEoYSkpOmEuYTtyZXR1cm4gYz9jLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk6XCJcIn0sMCwxLCEwKTtSKFwibmFtZXNwYWNlLXVyaVwiLDMsITAsITEsZnVuY3Rpb24oKXtyZXR1cm5cIlwifSwwLDEsITApO1xuUihcIm5vcm1hbGl6ZS1zcGFjZVwiLDMsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4oYj9MKGIsYSk6eihhLmEpKS5yZXBsYWNlKC9bXFxzXFx4YTBdKy9nLFwiIFwiKS5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLFwiXCIpfSwwLDEpO1IoXCJub3RcIiwyLCExLCExLGZ1bmN0aW9uKGEsYil7cmV0dXJuIU0oYixhKX0sMSk7UihcIm51bWJlclwiLDEsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj9LKGIsYSk6K3ooYS5hKX0sMCwxKTtSKFwicG9zaXRpb25cIiwxLCEwLCExLGZ1bmN0aW9uKGEpe3JldHVybiBhLmJ9LDApO1IoXCJyb3VuZFwiLDEsITEsITEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gTWF0aC5yb3VuZChLKGIsYSkpfSwxKTtSKFwic3RhcnRzLXdpdGhcIiwyLCExLCExLGZ1bmN0aW9uKGEsYixjKXtiPUwoYixhKTthPUwoYyxhKTtyZXR1cm4gMD09Yi5sYXN0SW5kZXhPZihhLDApfSwyKTtSKFwic3RyaW5nXCIsMywhMSwhMCxmdW5jdGlvbihhLGIpe3JldHVybiBiP0woYixhKTp6KGEuYSl9LDAsMSk7XG5SKFwic3RyaW5nLWxlbmd0aFwiLDEsITEsITAsZnVuY3Rpb24oYSxiKXtyZXR1cm4oYj9MKGIsYSk6eihhLmEpKS5sZW5ndGh9LDAsMSk7UihcInN1YnN0cmluZ1wiLDMsITEsITEsZnVuY3Rpb24oYSxiLGMsZCl7Yz1LKGMsYSk7aWYoaXNOYU4oYyl8fEluZmluaXR5PT1jfHwtSW5maW5pdHk9PWMpcmV0dXJuXCJcIjtkPWQ/SyhkLGEpOkluZmluaXR5O2lmKGlzTmFOKGQpfHwtSW5maW5pdHk9PT1kKXJldHVyblwiXCI7Yz1NYXRoLnJvdW5kKGMpLTE7dmFyIGU9TWF0aC5tYXgoYywwKTthPUwoYixhKTtyZXR1cm4gSW5maW5pdHk9PWQ/YS5zdWJzdHJpbmcoZSk6YS5zdWJzdHJpbmcoZSxjK01hdGgucm91bmQoZCkpfSwyLDMpO1IoXCJzdWJzdHJpbmctYWZ0ZXJcIiwzLCExLCExLGZ1bmN0aW9uKGEsYixjKXtiPUwoYixhKTthPUwoYyxhKTtjPWIuaW5kZXhPZihhKTtyZXR1cm4tMT09Yz9cIlwiOmIuc3Vic3RyaW5nKGMrYS5sZW5ndGgpfSwyKTtcblIoXCJzdWJzdHJpbmctYmVmb3JlXCIsMywhMSwhMSxmdW5jdGlvbihhLGIsYyl7Yj1MKGIsYSk7YT1MKGMsYSk7YT1iLmluZGV4T2YoYSk7cmV0dXJuLTE9PWE/XCJcIjpiLnN1YnN0cmluZygwLGEpfSwyKTtSKFwic3VtXCIsMSwhMSwhMSxmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz1IKGIuYShhKSksZD0wLGU9SShjKTtlO2U9SShjKSlkKz0reihlKTtyZXR1cm4gZH0sMSwxLCEwKTtSKFwidHJhbnNsYXRlXCIsMywhMSwhMSxmdW5jdGlvbihhLGIsYyxkKXtiPUwoYixhKTtjPUwoYyxhKTt2YXIgZT1MKGQsYSk7YT17fTtmb3IoZD0wO2Q8Yy5sZW5ndGg7ZCsrKXt2YXIgZj1jLmNoYXJBdChkKTtmIGluIGF8fChhW2ZdPWUuY2hhckF0KGQpKX1jPVwiXCI7Zm9yKGQ9MDtkPGIubGVuZ3RoO2QrKylmPWIuY2hhckF0KGQpLGMrPWYgaW4gYT9hW2ZdOmY7cmV0dXJuIGN9LDMpO1IoXCJ0cnVlXCIsMiwhMSwhMSxmdW5jdGlvbigpe3JldHVybiEwfSwwKTtmdW5jdGlvbiBHKGEsYil7dGhpcy5oPWE7dGhpcy5jPXZvaWQgMCE9PWI/YjpudWxsO3RoaXMuYj1udWxsO3N3aXRjaChhKXtjYXNlIFwiY29tbWVudFwiOnRoaXMuYj04O2JyZWFrO2Nhc2UgXCJ0ZXh0XCI6dGhpcy5iPTM7YnJlYWs7Y2FzZSBcInByb2Nlc3NpbmctaW5zdHJ1Y3Rpb25cIjp0aGlzLmI9NzticmVhaztjYXNlIFwibm9kZVwiOmJyZWFrO2RlZmF1bHQ6dGhyb3cgRXJyb3IoXCJVbmV4cGVjdGVkIGFyZ3VtZW50XCIpO319ZnVuY3Rpb24gZGIoYSl7cmV0dXJuXCJjb21tZW50XCI9PWF8fFwidGV4dFwiPT1hfHxcInByb2Nlc3NpbmctaW5zdHJ1Y3Rpb25cIj09YXx8XCJub2RlXCI9PWF9Ry5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtyZXR1cm4gbnVsbD09PXRoaXMuYnx8dGhpcy5iPT1hLm5vZGVUeXBlfTtHLnByb3RvdHlwZS5mPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuaH07XG5HLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhPVwiS2luZCBUZXN0OiBcIit0aGlzLmg7bnVsbD09PXRoaXMuY3x8KGErPUoodGhpcy5jKSk7cmV0dXJuIGF9O2Z1bmN0aW9uIGViKGEpe3RoaXMuYj1hO3RoaXMuYT0wfWZ1bmN0aW9uIGZiKGEpe2E9YS5tYXRjaChnYik7Zm9yKHZhciBiPTA7YjxhLmxlbmd0aDtiKyspaGIudGVzdChhW2JdKSYmYS5zcGxpY2UoYiwxKTtyZXR1cm4gbmV3IGViKGEpfXZhciBnYj0vXFwkPyg/Oig/IVswLTktXFwuXSkoPzpcXCp8W1xcdy1cXC5dKyk6KT8oPyFbMC05LVxcLl0pKD86XFwqfFtcXHctXFwuXSspfFxcL1xcL3xcXC5cXC58Ojp8XFxkKyg/OlxcLlxcZCopP3xcXC5cXGQrfFwiW15cIl0qXCJ8J1teJ10qJ3xbITw+XT18XFxzK3wuL2csaGI9L15cXHMvO2Z1bmN0aW9uIFMoYSxiKXtyZXR1cm4gYS5iW2EuYSsoYnx8MCldfWZ1bmN0aW9uIFQoYSl7cmV0dXJuIGEuYlthLmErK119ZnVuY3Rpb24gaWIoYSl7cmV0dXJuIGEuYi5sZW5ndGg8PWEuYX07ZnVuY3Rpb24gamIoYSl7bi5jYWxsKHRoaXMsMyk7dGhpcy5jPWEuc3Vic3RyaW5nKDEsYS5sZW5ndGgtMSl9bShqYik7amIucHJvdG90eXBlLmE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jfTtqYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIkxpdGVyYWw6IFwiK3RoaXMuY307ZnVuY3Rpb24gRShhLGIpe3RoaXMuaj1hLnRvTG93ZXJDYXNlKCk7dmFyIGM7Yz1cIipcIj09dGhpcy5qP1wiKlwiOlwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiO3RoaXMuYz1iP2IudG9Mb3dlckNhc2UoKTpjfUUucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9YS5ub2RlVHlwZTtpZigxIT1iJiYyIT1iKXJldHVybiExO2I9dm9pZCAwIT09YS5sb2NhbE5hbWU/YS5sb2NhbE5hbWU6YS5ub2RlTmFtZTtyZXR1cm5cIipcIiE9dGhpcy5qJiZ0aGlzLmohPWIudG9Mb3dlckNhc2UoKT8hMTpcIipcIj09dGhpcy5jPyEwOnRoaXMuYz09KGEubmFtZXNwYWNlVVJJP2EubmFtZXNwYWNlVVJJLnRvTG93ZXJDYXNlKCk6XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCIpfTtFLnByb3RvdHlwZS5mPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07XG5FLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiTmFtZSBUZXN0OiBcIisoXCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCI9PXRoaXMuYz9cIlwiOnRoaXMuYytcIjpcIikrdGhpcy5qfTtmdW5jdGlvbiBrYihhLGIpe24uY2FsbCh0aGlzLGEuaSk7dGhpcy5oPWE7dGhpcy5jPWI7dGhpcy5nPWEuZzt0aGlzLmI9YS5iO2lmKDE9PXRoaXMuYy5sZW5ndGgpe3ZhciBjPXRoaXMuY1swXTtjLnV8fGMuYyE9bGJ8fChjPWMubyxcIipcIiE9Yy5mKCkmJih0aGlzLmY9e25hbWU6Yy5mKCksczpudWxsfSkpfX1tKGtiKTtmdW5jdGlvbiBtYigpe24uY2FsbCh0aGlzLDQpfW0obWIpO21iLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBDO2E9YS5hOzk9PWEubm9kZVR5cGU/RihiLGEpOkYoYixhLm93bmVyRG9jdW1lbnQpO3JldHVybiBifTttYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm5cIlJvb3QgSGVscGVyIEV4cHJlc3Npb25cIn07ZnVuY3Rpb24gbmIoKXtuLmNhbGwodGhpcyw0KX1tKG5iKTtuYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj1uZXcgQztGKGIsYS5hKTtyZXR1cm4gYn07bmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJDb250ZXh0IEhlbHBlciBFeHByZXNzaW9uXCJ9O1xuZnVuY3Rpb24gb2IoYSl7cmV0dXJuXCIvXCI9PWF8fFwiLy9cIj09YX1rYi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmguYShhKTtpZighKGIgaW5zdGFuY2VvZiBDKSl0aHJvdyBFcnJvcihcIkZpbHRlciBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gbm9kZXNldC5cIik7YT10aGlzLmM7Zm9yKHZhciBjPTAsZD1hLmxlbmd0aDtjPGQmJmIubDtjKyspe3ZhciBlPWFbY10sZj1IKGIsZS5jLmEpLGc7aWYoZS5nfHxlLmMhPXBiKWlmKGUuZ3x8ZS5jIT1xYilmb3IoZz1JKGYpLGI9ZS5hKG5ldyBRKGcpKTtudWxsIT0oZz1JKGYpKTspZz1lLmEobmV3IFEoZykpLGI9UGEoYixnKTtlbHNlIGc9SShmKSxiPWUuYShuZXcgUShnKSk7ZWxzZXtmb3IoZz1JKGYpOyhiPUkoZikpJiYoIWcuY29udGFpbnN8fGcuY29udGFpbnMoYikpJiZiLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGcpJjg7Zz1iKTtiPWUuYShuZXcgUShnKSl9fXJldHVybiBifTtcbmtiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3ZhciBhO2E9XCJQYXRoIEV4cHJlc3Npb246XCIrSih0aGlzLmgpO2lmKHRoaXMuYy5sZW5ndGgpe3ZhciBiPXQodGhpcy5jLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGErSihiKX0sXCJTdGVwczpcIik7YSs9SihiKX1yZXR1cm4gYX07ZnVuY3Rpb24gcmIoYSl7bi5jYWxsKHRoaXMsNCk7dGhpcy5jPWE7VWEodGhpcyxqYSh0aGlzLmMsZnVuY3Rpb24oYSl7cmV0dXJuIGEuZ30pKTtWYSh0aGlzLGphKHRoaXMuYyxmdW5jdGlvbihhKXtyZXR1cm4gYS5ifSkpfW0ocmIpO3JiLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBDO3IodGhpcy5jLGZ1bmN0aW9uKGMpe2M9Yy5hKGEpO2lmKCEoYyBpbnN0YW5jZW9mIEMpKXRocm93IEVycm9yKFwiUGF0aCBleHByZXNzaW9uIG11c3QgZXZhbHVhdGUgdG8gTm9kZVNldC5cIik7Yj1QYShiLGMpfSk7cmV0dXJuIGJ9O3JiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0KHRoaXMuYyxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiVW5pb24gRXhwcmVzc2lvbjpcIil9O2Z1bmN0aW9uIHNiKGEsYil7dGhpcy5hPWE7dGhpcy5iPSEhYn1cbmZ1bmN0aW9uICRhKGEsYixjKXtmb3IoYz1jfHwwO2M8YS5hLmxlbmd0aDtjKyspZm9yKHZhciBkPWEuYVtjXSxlPUgoYiksZj1iLmwsZyxoPTA7Zz1JKGUpO2grKyl7dmFyIHA9YS5iP2YtaDpoKzE7Zz1kLmEobmV3IFEoZyxwLGYpKTtpZihcIm51bWJlclwiPT10eXBlb2YgZylwPXA9PWc7ZWxzZSBpZihcInN0cmluZ1wiPT10eXBlb2YgZ3x8XCJib29sZWFuXCI9PXR5cGVvZiBnKXA9ISFnO2Vsc2UgaWYoZyBpbnN0YW5jZW9mIEMpcD0wPGcubDtlbHNlIHRocm93IEVycm9yKFwiUHJlZGljYXRlLmV2YWx1YXRlIHJldHVybmVkIGFuIHVuZXhwZWN0ZWQgdHlwZS5cIik7aWYoIXApe3A9ZTtnPXAuZjt2YXIgeT1wLmE7aWYoIXkpdGhyb3cgRXJyb3IoXCJOZXh0IG11c3QgYmUgY2FsbGVkIGF0IGxlYXN0IG9uY2UgYmVmb3JlIHJlbW92ZS5cIik7dmFyIEQ9eS5iLHk9eS5hO0Q/RC5hPXk6Zy5hPXk7eT95LmI9RDpnLmI9RDtnLmwtLTtwLmE9bnVsbH19cmV0dXJuIGJ9XG5zYi5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdCh0aGlzLmEsZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStKKGIpfSxcIlByZWRpY2F0ZXM6XCIpfTtmdW5jdGlvbiBVKGEsYixjLGQpe24uY2FsbCh0aGlzLDQpO3RoaXMuYz1hO3RoaXMubz1iO3RoaXMuaD1jfHxuZXcgc2IoW10pO3RoaXMudT0hIWQ7Yj10aGlzLmg7Yj0wPGIuYS5sZW5ndGg/Yi5hWzBdLmY6bnVsbDthLmImJmImJihhPWIubmFtZSxhPXc/YS50b0xvd2VyQ2FzZSgpOmEsdGhpcy5mPXtuYW1lOmEsczpiLnN9KTthOnthPXRoaXMuaDtmb3IoYj0wO2I8YS5hLmxlbmd0aDtiKyspaWYoYz1hLmFbYl0sYy5nfHwxPT1jLml8fDA9PWMuaSl7YT0hMDticmVhayBhfWE9ITF9dGhpcy5nPWF9bShVKTtcblUucHJvdG90eXBlLmE9ZnVuY3Rpb24oYSl7dmFyIGI9YS5hLGM9bnVsbCxjPXRoaXMuZixkPW51bGwsZT1udWxsLGY9MDtjJiYoZD1jLm5hbWUsZT1jLnM/TChjLnMsYSk6bnVsbCxmPTEpO2lmKHRoaXMudSlpZih0aGlzLmd8fHRoaXMuYyE9dGIpaWYoYT1IKChuZXcgVSh1YixuZXcgRyhcIm5vZGVcIikpKS5hKGEpKSxiPUkoYSkpZm9yKGM9dGhpcy5tKGIsZCxlLGYpO251bGwhPShiPUkoYSkpOyljPVBhKGMsdGhpcy5tKGIsZCxlLGYpKTtlbHNlIGM9bmV3IEM7ZWxzZSBjPUIodGhpcy5vLGIsZCxlKSxjPSRhKHRoaXMuaCxjLGYpO2Vsc2UgYz10aGlzLm0oYS5hLGQsZSxmKTtyZXR1cm4gY307VS5wcm90b3R5cGUubT1mdW5jdGlvbihhLGIsYyxkKXthPXRoaXMuYy5mKHRoaXMubyxhLGIsYyk7cmV0dXJuIGE9JGEodGhpcy5oLGEsZCl9O1xuVS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgYTthPVwiU3RlcDpcIitKKFwiT3BlcmF0b3I6IFwiKyh0aGlzLnU/XCIvL1wiOlwiL1wiKSk7dGhpcy5jLmomJihhKz1KKFwiQXhpczogXCIrdGhpcy5jKSk7YSs9Sih0aGlzLm8pO2lmKHRoaXMuaC5hLmxlbmd0aCl7dmFyIGI9dCh0aGlzLmguYSxmdW5jdGlvbihhLGIpe3JldHVybiBhK0ooYil9LFwiUHJlZGljYXRlczpcIik7YSs9SihiKX1yZXR1cm4gYX07ZnVuY3Rpb24gdmIoYSxiLGMsZCl7dGhpcy5qPWE7dGhpcy5mPWI7dGhpcy5hPWM7dGhpcy5iPWR9dmIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuan07dmFyIHdiPXt9O2Z1bmN0aW9uIFYoYSxiLGMsZCl7aWYod2IuaGFzT3duUHJvcGVydHkoYSkpdGhyb3cgRXJyb3IoXCJBeGlzIGFscmVhZHkgY3JlYXRlZDogXCIrYSk7Yj1uZXcgdmIoYSxiLGMsISFkKTtyZXR1cm4gd2JbYV09Yn1cblYoXCJhbmNlc3RvclwiLGZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPW5ldyBDLGQ9YjtkPWQucGFyZW50Tm9kZTspYS5hKGQpJiZRYShjLGQpO3JldHVybiBjfSwhMCk7VihcImFuY2VzdG9yLW9yLXNlbGZcIixmdW5jdGlvbihhLGIpe3ZhciBjPW5ldyBDLGQ9YjtkbyBhLmEoZCkmJlFhKGMsZCk7d2hpbGUoZD1kLnBhcmVudE5vZGUpO3JldHVybiBjfSwhMCk7XG52YXIgbGI9VihcImF0dHJpYnV0ZVwiLGZ1bmN0aW9uKGEsYil7dmFyIGM9bmV3IEMsZD1hLmYoKTtpZihcInN0eWxlXCI9PWQmJncmJmIuc3R5bGUpcmV0dXJuIEYoYyxuZXcgeChiLnN0eWxlLGIsXCJzdHlsZVwiLGIuc3R5bGUuY3NzVGV4dCkpLGM7dmFyIGU9Yi5hdHRyaWJ1dGVzO2lmKGUpaWYoYSBpbnN0YW5jZW9mIEcmJm51bGw9PT1hLmJ8fFwiKlwiPT1kKWZvcih2YXIgZD0wLGY7Zj1lW2RdO2QrKyl3P2Yubm9kZVZhbHVlJiZGKGMsRGEoYixmKSk6RihjLGYpO2Vsc2UoZj1lLmdldE5hbWVkSXRlbShkKSkmJih3P2Yubm9kZVZhbHVlJiZGKGMsRGEoYixmKSk6RihjLGYpKTtyZXR1cm4gY30sITEpLHRiPVYoXCJjaGlsZFwiLGZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0dXJuKHc/SWE6SmEpLmNhbGwobnVsbCxhLGIsbChjKT9jOm51bGwsbChkKT9kOm51bGwsZXx8bmV3IEMpfSwhMSwhMCk7VihcImRlc2NlbmRhbnRcIixCLCExLCEwKTtcbnZhciB1Yj1WKFwiZGVzY2VuZGFudC1vci1zZWxmXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEM7QShiLGMsZCkmJmEuYShiKSYmRihlLGIpO3JldHVybiBCKGEsYixjLGQsZSl9LCExLCEwKSxwYj1WKFwiZm9sbG93aW5nXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEM7ZG8gZm9yKHZhciBmPWI7Zj1mLm5leHRTaWJsaW5nOylBKGYsYyxkKSYmYS5hKGYpJiZGKGUsZiksZT1CKGEsZixjLGQsZSk7d2hpbGUoYj1iLnBhcmVudE5vZGUpO3JldHVybiBlfSwhMSwhMCk7VihcImZvbGxvd2luZy1zaWJsaW5nXCIsZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9bmV3IEMsZD1iO2Q9ZC5uZXh0U2libGluZzspYS5hKGQpJiZGKGMsZCk7cmV0dXJuIGN9LCExKTtWKFwibmFtZXNwYWNlXCIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEN9LCExKTtcbnZhciB4Yj1WKFwicGFyZW50XCIsZnVuY3Rpb24oYSxiKXt2YXIgYz1uZXcgQztpZig5PT1iLm5vZGVUeXBlKXJldHVybiBjO2lmKDI9PWIubm9kZVR5cGUpcmV0dXJuIEYoYyxiLm93bmVyRWxlbWVudCksYzt2YXIgZD1iLnBhcmVudE5vZGU7YS5hKGQpJiZGKGMsZCk7cmV0dXJuIGN9LCExKSxxYj1WKFwicHJlY2VkaW5nXCIsZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IEMsZj1bXTtkbyBmLnVuc2hpZnQoYik7d2hpbGUoYj1iLnBhcmVudE5vZGUpO2Zvcih2YXIgZz0xLGg9Zi5sZW5ndGg7ZzxoO2crKyl7dmFyIHA9W107Zm9yKGI9ZltnXTtiPWIucHJldmlvdXNTaWJsaW5nOylwLnVuc2hpZnQoYik7Zm9yKHZhciB5PTAsRD1wLmxlbmd0aDt5PEQ7eSsrKWI9cFt5XSxBKGIsYyxkKSYmYS5hKGIpJiZGKGUsYiksZT1CKGEsYixjLGQsZSl9cmV0dXJuIGV9LCEwLCEwKTtcblYoXCJwcmVjZWRpbmctc2libGluZ1wiLGZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPW5ldyBDLGQ9YjtkPWQucHJldmlvdXNTaWJsaW5nOylhLmEoZCkmJlFhKGMsZCk7cmV0dXJuIGN9LCEwKTt2YXIgeWI9VihcInNlbGZcIixmdW5jdGlvbihhLGIpe3ZhciBjPW5ldyBDO2EuYShiKSYmRihjLGIpO3JldHVybiBjfSwhMSk7ZnVuY3Rpb24gemIoYSl7bi5jYWxsKHRoaXMsMSk7dGhpcy5jPWE7dGhpcy5nPWEuZzt0aGlzLmI9YS5ifW0oemIpO3piLnByb3RvdHlwZS5hPWZ1bmN0aW9uKGEpe3JldHVybi1LKHRoaXMuYyxhKX07emIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuXCJVbmFyeSBFeHByZXNzaW9uOiAtXCIrSih0aGlzLmMpfTtmdW5jdGlvbiBBYihhKXtuLmNhbGwodGhpcywxKTt0aGlzLmM9YX1tKEFiKTtBYi5wcm90b3R5cGUuYT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN9O0FiLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiTnVtYmVyOiBcIit0aGlzLmN9O2Z1bmN0aW9uIEJiKGEsYil7dGhpcy5hPWE7dGhpcy5iPWJ9ZnVuY3Rpb24gQ2IoYSl7Zm9yKHZhciBiLGM9W107Oyl7VyhhLFwiTWlzc2luZyByaWdodCBoYW5kIHNpZGUgb2YgYmluYXJ5IGV4cHJlc3Npb24uXCIpO2I9RGIoYSk7dmFyIGQ9VChhLmEpO2lmKCFkKWJyZWFrO3ZhciBlPShkPVlhW2RdfHxudWxsKSYmZC53O2lmKCFlKXthLmEuYS0tO2JyZWFrfWZvcig7Yy5sZW5ndGgmJmU8PWNbYy5sZW5ndGgtMV0udzspYj1uZXcgTihjLnBvcCgpLGMucG9wKCksYik7Yy5wdXNoKGIsZCl9Zm9yKDtjLmxlbmd0aDspYj1uZXcgTihjLnBvcCgpLGMucG9wKCksYik7cmV0dXJuIGJ9ZnVuY3Rpb24gVyhhLGIpe2lmKGliKGEuYSkpdGhyb3cgRXJyb3IoYik7fWZ1bmN0aW9uIEViKGEsYil7dmFyIGM9VChhLmEpO2lmKGMhPWIpdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW4sIGV4cGVjdGVkOiBcIitiK1wiIGdvdDogXCIrYyk7fVxuZnVuY3Rpb24gRmIoYSl7YT1UKGEuYSk7aWYoXCIpXCIhPWEpdGhyb3cgRXJyb3IoXCJCYWQgdG9rZW46IFwiK2EpO31mdW5jdGlvbiBHYihhKXthPVQoYS5hKTtpZigyPmEubGVuZ3RoKXRocm93IEVycm9yKFwiVW5jbG9zZWQgbGl0ZXJhbCBzdHJpbmdcIik7cmV0dXJuIG5ldyBqYihhKX1cbmZ1bmN0aW9uIEhiKGEpe3ZhciBiLGM9W10sZDtpZihvYihTKGEuYSkpKXtiPVQoYS5hKTtkPVMoYS5hKTtpZihcIi9cIj09YiYmKGliKGEuYSl8fFwiLlwiIT1kJiZcIi4uXCIhPWQmJlwiQFwiIT1kJiZcIipcIiE9ZCYmIS8oPyFbMC05XSlbXFx3XS8udGVzdChkKSkpcmV0dXJuIG5ldyBtYjtkPW5ldyBtYjtXKGEsXCJNaXNzaW5nIG5leHQgbG9jYXRpb24gc3RlcC5cIik7Yj1JYihhLGIpO2MucHVzaChiKX1lbHNle2E6e2I9UyhhLmEpO2Q9Yi5jaGFyQXQoMCk7c3dpdGNoKGQpe2Nhc2UgXCIkXCI6dGhyb3cgRXJyb3IoXCJWYXJpYWJsZSByZWZlcmVuY2Ugbm90IGFsbG93ZWQgaW4gSFRNTCBYUGF0aFwiKTtjYXNlIFwiKFwiOlQoYS5hKTtiPUNiKGEpO1coYSwndW5jbG9zZWQgXCIoXCInKTtFYihhLFwiKVwiKTticmVhaztjYXNlICdcIic6Y2FzZSBcIidcIjpiPUdiKGEpO2JyZWFrO2RlZmF1bHQ6aWYoaXNOYU4oK2IpKWlmKCFkYihiKSYmLyg/IVswLTldKVtcXHddLy50ZXN0KGQpJiZcIihcIj09UyhhLmEsMSkpe2I9VChhLmEpO1xuYj1jYltiXXx8bnVsbDtUKGEuYSk7Zm9yKGQ9W107XCIpXCIhPVMoYS5hKTspe1coYSxcIk1pc3NpbmcgZnVuY3Rpb24gYXJndW1lbnQgbGlzdC5cIik7ZC5wdXNoKENiKGEpKTtpZihcIixcIiE9UyhhLmEpKWJyZWFrO1QoYS5hKX1XKGEsXCJVbmNsb3NlZCBmdW5jdGlvbiBhcmd1bWVudCBsaXN0LlwiKTtGYihhKTtiPW5ldyBhYihiLGQpfWVsc2V7Yj1udWxsO2JyZWFrIGF9ZWxzZSBiPW5ldyBBYigrVChhLmEpKX1cIltcIj09UyhhLmEpJiYoZD1uZXcgc2IoSmIoYSkpLGI9bmV3IFphKGIsZCkpfWlmKGIpaWYob2IoUyhhLmEpKSlkPWI7ZWxzZSByZXR1cm4gYjtlbHNlIGI9SWIoYSxcIi9cIiksZD1uZXcgbmIsYy5wdXNoKGIpfWZvcig7b2IoUyhhLmEpKTspYj1UKGEuYSksVyhhLFwiTWlzc2luZyBuZXh0IGxvY2F0aW9uIHN0ZXAuXCIpLGI9SWIoYSxiKSxjLnB1c2goYik7cmV0dXJuIG5ldyBrYihkLGMpfVxuZnVuY3Rpb24gSWIoYSxiKXt2YXIgYyxkLGU7aWYoXCIvXCIhPWImJlwiLy9cIiE9Yil0aHJvdyBFcnJvcignU3RlcCBvcCBzaG91bGQgYmUgXCIvXCIgb3IgXCIvL1wiJyk7aWYoXCIuXCI9PVMoYS5hKSlyZXR1cm4gZD1uZXcgVSh5YixuZXcgRyhcIm5vZGVcIikpLFQoYS5hKSxkO2lmKFwiLi5cIj09UyhhLmEpKXJldHVybiBkPW5ldyBVKHhiLG5ldyBHKFwibm9kZVwiKSksVChhLmEpLGQ7dmFyIGY7aWYoXCJAXCI9PVMoYS5hKSlmPWxiLFQoYS5hKSxXKGEsXCJNaXNzaW5nIGF0dHJpYnV0ZSBuYW1lXCIpO2Vsc2UgaWYoXCI6OlwiPT1TKGEuYSwxKSl7aWYoIS8oPyFbMC05XSlbXFx3XS8udGVzdChTKGEuYSkuY2hhckF0KDApKSl0aHJvdyBFcnJvcihcIkJhZCB0b2tlbjogXCIrVChhLmEpKTtjPVQoYS5hKTtmPXdiW2NdfHxudWxsO2lmKCFmKXRocm93IEVycm9yKFwiTm8gYXhpcyB3aXRoIG5hbWU6IFwiK2MpO1QoYS5hKTtXKGEsXCJNaXNzaW5nIG5vZGUgbmFtZVwiKX1lbHNlIGY9dGI7Yz1TKGEuYSk7aWYoLyg/IVswLTldKVtcXHdcXCpdLy50ZXN0KGMuY2hhckF0KDApKSlpZihcIihcIj09XG5TKGEuYSwxKSl7aWYoIWRiKGMpKXRocm93IEVycm9yKFwiSW52YWxpZCBub2RlIHR5cGU6IFwiK2MpO2M9VChhLmEpO2lmKCFkYihjKSl0aHJvdyBFcnJvcihcIkludmFsaWQgdHlwZSBuYW1lOiBcIitjKTtFYihhLFwiKFwiKTtXKGEsXCJCYWQgbm9kZXR5cGVcIik7ZT1TKGEuYSkuY2hhckF0KDApO3ZhciBnPW51bGw7aWYoJ1wiJz09ZXx8XCInXCI9PWUpZz1HYihhKTtXKGEsXCJCYWQgbm9kZXR5cGVcIik7RmIoYSk7Yz1uZXcgRyhjLGcpfWVsc2UgaWYoYz1UKGEuYSksZT1jLmluZGV4T2YoXCI6XCIpLC0xPT1lKWM9bmV3IEUoYyk7ZWxzZXt2YXIgZz1jLnN1YnN0cmluZygwLGUpLGg7aWYoXCIqXCI9PWcpaD1cIipcIjtlbHNlIGlmKGg9YS5iKGcpLCFoKXRocm93IEVycm9yKFwiTmFtZXNwYWNlIHByZWZpeCBub3QgZGVjbGFyZWQ6IFwiK2cpO2M9Yy5zdWJzdHIoZSsxKTtjPW5ldyBFKGMsaCl9ZWxzZSB0aHJvdyBFcnJvcihcIkJhZCB0b2tlbjogXCIrVChhLmEpKTtlPW5ldyBzYihKYihhKSxmLmEpO3JldHVybiBkfHxcbm5ldyBVKGYsYyxlLFwiLy9cIj09Yil9ZnVuY3Rpb24gSmIoYSl7Zm9yKHZhciBiPVtdO1wiW1wiPT1TKGEuYSk7KXtUKGEuYSk7VyhhLFwiTWlzc2luZyBwcmVkaWNhdGUgZXhwcmVzc2lvbi5cIik7dmFyIGM9Q2IoYSk7Yi5wdXNoKGMpO1coYSxcIlVuY2xvc2VkIHByZWRpY2F0ZSBleHByZXNzaW9uLlwiKTtFYihhLFwiXVwiKX1yZXR1cm4gYn1mdW5jdGlvbiBEYihhKXtpZihcIi1cIj09UyhhLmEpKXJldHVybiBUKGEuYSksbmV3IHpiKERiKGEpKTt2YXIgYj1IYihhKTtpZihcInxcIiE9UyhhLmEpKWE9YjtlbHNle2ZvcihiPVtiXTtcInxcIj09VChhLmEpOylXKGEsXCJNaXNzaW5nIG5leHQgdW5pb24gbG9jYXRpb24gcGF0aC5cIiksYi5wdXNoKEhiKGEpKTthLmEuYS0tO2E9bmV3IHJiKGIpfXJldHVybiBhfTtmdW5jdGlvbiBLYihhKXtzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOnJldHVybiBlYShMYixhKTtjYXNlIDk6cmV0dXJuIEtiKGEuZG9jdW1lbnRFbGVtZW50KTtjYXNlIDExOmNhc2UgMTA6Y2FzZSA2OmNhc2UgMTI6cmV0dXJuIE1iO2RlZmF1bHQ6cmV0dXJuIGEucGFyZW50Tm9kZT9LYihhLnBhcmVudE5vZGUpOk1ifX1mdW5jdGlvbiBNYigpe3JldHVybiBudWxsfWZ1bmN0aW9uIExiKGEsYil7aWYoYS5wcmVmaXg9PWIpcmV0dXJuIGEubmFtZXNwYWNlVVJJfHxcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjt2YXIgYz1hLmdldEF0dHJpYnV0ZU5vZGUoXCJ4bWxuczpcIitiKTtyZXR1cm4gYyYmYy5zcGVjaWZpZWQ/Yy52YWx1ZXx8bnVsbDphLnBhcmVudE5vZGUmJjkhPWEucGFyZW50Tm9kZS5ub2RlVHlwZT9MYihhLnBhcmVudE5vZGUsYik6bnVsbH07ZnVuY3Rpb24gTmIoYSxiKXtpZighYS5sZW5ndGgpdGhyb3cgRXJyb3IoXCJFbXB0eSBYUGF0aCBleHByZXNzaW9uLlwiKTt2YXIgYz1mYihhKTtpZihpYihjKSl0aHJvdyBFcnJvcihcIkludmFsaWQgWFBhdGggZXhwcmVzc2lvbi5cIik7Yj9cImZ1bmN0aW9uXCI9PWFhKGIpfHwoYj1kYShiLmxvb2t1cE5hbWVzcGFjZVVSSSxiKSk6Yj1mdW5jdGlvbigpe3JldHVybiBudWxsfTt2YXIgZD1DYihuZXcgQmIoYyxiKSk7aWYoIWliKGMpKXRocm93IEVycm9yKFwiQmFkIHRva2VuOiBcIitUKGMpKTt0aGlzLmV2YWx1YXRlPWZ1bmN0aW9uKGEsYil7dmFyIGM9ZC5hKG5ldyBRKGEpKTtyZXR1cm4gbmV3IFkoYyxiKX19XG5mdW5jdGlvbiBZKGEsYil7aWYoMD09YilpZihhIGluc3RhbmNlb2YgQyliPTQ7ZWxzZSBpZihcInN0cmluZ1wiPT10eXBlb2YgYSliPTI7ZWxzZSBpZihcIm51bWJlclwiPT10eXBlb2YgYSliPTE7ZWxzZSBpZihcImJvb2xlYW5cIj09dHlwZW9mIGEpYj0zO2Vsc2UgdGhyb3cgRXJyb3IoXCJVbmV4cGVjdGVkIGV2YWx1YXRpb24gcmVzdWx0LlwiKTtpZigyIT1iJiYxIT1iJiYzIT1iJiYhKGEgaW5zdGFuY2VvZiBDKSl0aHJvdyBFcnJvcihcInZhbHVlIGNvdWxkIG5vdCBiZSBjb252ZXJ0ZWQgdG8gdGhlIHNwZWNpZmllZCB0eXBlXCIpO3RoaXMucmVzdWx0VHlwZT1iO3ZhciBjO3N3aXRjaChiKXtjYXNlIDI6dGhpcy5zdHJpbmdWYWx1ZT1hIGluc3RhbmNlb2YgQz9TYShhKTpcIlwiK2E7YnJlYWs7Y2FzZSAxOnRoaXMubnVtYmVyVmFsdWU9YSBpbnN0YW5jZW9mIEM/K1NhKGEpOithO2JyZWFrO2Nhc2UgMzp0aGlzLmJvb2xlYW5WYWx1ZT1hIGluc3RhbmNlb2YgQz8wPGEubDohIWE7YnJlYWs7Y2FzZSA0OmNhc2UgNTpjYXNlIDY6Y2FzZSA3OnZhciBkPVxuSChhKTtjPVtdO2Zvcih2YXIgZT1JKGQpO2U7ZT1JKGQpKWMucHVzaChlIGluc3RhbmNlb2YgeD9lLmE6ZSk7dGhpcy5zbmFwc2hvdExlbmd0aD1hLmw7dGhpcy5pbnZhbGlkSXRlcmF0b3JTdGF0ZT0hMTticmVhaztjYXNlIDg6Y2FzZSA5OmQ9UmEoYSk7dGhpcy5zaW5nbGVOb2RlVmFsdWU9ZCBpbnN0YW5jZW9mIHg/ZC5hOmQ7YnJlYWs7ZGVmYXVsdDp0aHJvdyBFcnJvcihcIlVua25vd24gWFBhdGhSZXN1bHQgdHlwZS5cIik7fXZhciBmPTA7dGhpcy5pdGVyYXRlTmV4dD1mdW5jdGlvbigpe2lmKDQhPWImJjUhPWIpdGhyb3cgRXJyb3IoXCJpdGVyYXRlTmV4dCBjYWxsZWQgd2l0aCB3cm9uZyByZXN1bHQgdHlwZVwiKTtyZXR1cm4gZj49Yy5sZW5ndGg/bnVsbDpjW2YrK119O3RoaXMuc25hcHNob3RJdGVtPWZ1bmN0aW9uKGEpe2lmKDYhPWImJjchPWIpdGhyb3cgRXJyb3IoXCJzbmFwc2hvdEl0ZW0gY2FsbGVkIHdpdGggd3JvbmcgcmVzdWx0IHR5cGVcIik7cmV0dXJuIGE+PWMubGVuZ3RofHxcbjA+YT9udWxsOmNbYV19fVkuQU5ZX1RZUEU9MDtZLk5VTUJFUl9UWVBFPTE7WS5TVFJJTkdfVFlQRT0yO1kuQk9PTEVBTl9UWVBFPTM7WS5VTk9SREVSRURfTk9ERV9JVEVSQVRPUl9UWVBFPTQ7WS5PUkRFUkVEX05PREVfSVRFUkFUT1JfVFlQRT01O1kuVU5PUkRFUkVEX05PREVfU05BUFNIT1RfVFlQRT02O1kuT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEU9NztZLkFOWV9VTk9SREVSRURfTk9ERV9UWVBFPTg7WS5GSVJTVF9PUkRFUkVEX05PREVfVFlQRT05O2Z1bmN0aW9uIE9iKGEpe3RoaXMubG9va3VwTmFtZXNwYWNlVVJJPUtiKGEpfVxuZnVuY3Rpb24gUGIoYSxiKXt2YXIgYz1hfHxrLGQ9Yy5Eb2N1bWVudCYmYy5Eb2N1bWVudC5wcm90b3R5cGV8fGMuZG9jdW1lbnQ7aWYoIWQuZXZhbHVhdGV8fGIpYy5YUGF0aFJlc3VsdD1ZLGQuZXZhbHVhdGU9ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuKG5ldyBOYihhLGMpKS5ldmFsdWF0ZShiLGQpfSxkLmNyZWF0ZUV4cHJlc3Npb249ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IE5iKGEsYil9LGQuY3JlYXRlTlNSZXNvbHZlcj1mdW5jdGlvbihhKXtyZXR1cm4gbmV3IE9iKGEpfX12YXIgUWI9W1wid2d4cGF0aFwiLFwiaW5zdGFsbFwiXSxaPWs7UWJbMF1pbiBafHwhWi5leGVjU2NyaXB0fHxaLmV4ZWNTY3JpcHQoXCJ2YXIgXCIrUWJbMF0pO2Zvcih2YXIgUmI7UWIubGVuZ3RoJiYoUmI9UWIuc2hpZnQoKSk7KVFiLmxlbmd0aHx8dm9pZCAwPT09UGI/WltSYl0/Wj1aW1JiXTpaPVpbUmJdPXt9OlpbUmJdPVBiO21vZHVsZS5leHBvcnRzLmluc3RhbGw9UGI7bW9kdWxlLmV4cG9ydHMuWFBhdGhSZXN1bHRUeXBlPXtBTllfVFlQRTowLE5VTUJFUl9UWVBFOjEsU1RSSU5HX1RZUEU6MixCT09MRUFOX1RZUEU6MyxVTk9SREVSRURfTk9ERV9JVEVSQVRPUl9UWVBFOjQsT1JERVJFRF9OT0RFX0lURVJBVE9SX1RZUEU6NSxVTk9SREVSRURfTk9ERV9TTkFQU0hPVF9UWVBFOjYsT1JERVJFRF9OT0RFX1NOQVBTSE9UX1RZUEU6NyxBTllfVU5PUkRFUkVEX05PREVfVFlQRTo4LEZJUlNUX09SREVSRURfTk9ERV9UWVBFOjl9O30pLmNhbGwoZ2xvYmFsKVxuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4vLyBCYWNrd2FyZCBDb21wYXQgVGFibGVcbid1c2Ugc3RyaWN0JztcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQob2JqKSB7IGlmIChvYmogJiYgb2JqLl9fZXNNb2R1bGUpIHsgcmV0dXJuIG9iajsgfSBlbHNlIHsgdmFyIG5ld09iaiA9IHt9OyBpZiAob2JqICE9IG51bGwpIHsgZm9yICh2YXIga2V5IGluIG9iaikgeyBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkgbmV3T2JqW2tleV0gPSBvYmpba2V5XTsgfSB9IG5ld09ialsnZGVmYXVsdCddID0gb2JqOyByZXR1cm4gbmV3T2JqOyB9IH1cblxudmFyIF9odHRwUHlkaW9Vc2Vyc0FwaSA9IHJlcXVpcmUoJy4vaHR0cC9QeWRpb1VzZXJzQXBpJyk7XG5cbnZhciBVc2Vyc0FwaSA9IF9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkKF9odHRwUHlkaW9Vc2Vyc0FwaSk7XG5cbnZhciBDb25uZXhpb24gPSByZXF1aXJlKCcuL2h0dHAvQ29ubmV4aW9uJyksXG4gICAgTWV0YUNhY2hlU2VydmljZSA9IHJlcXVpcmUoJy4vaHR0cC9NZXRhQ2FjaGVTZXJ2aWNlJyksXG4gICAgUHlkaW9BcGkgPSByZXF1aXJlKCcuL2h0dHAvUHlkaW9BcGknKSxcbiAgICBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi9odHRwL1Jlc291cmNlc01hbmFnZXInKSxcbiAgICBMb2dnZXIgPSByZXF1aXJlKCcuL2xhbmcvTG9nZ2VyJyksXG4gICAgT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4vbGFuZy9PYnNlcnZhYmxlJyksXG4gICAgQWN0aW9uID0gcmVxdWlyZSgnLi9tb2RlbC9BY3Rpb24nKSxcbiAgICBBanhwTm9kZSA9IHJlcXVpcmUoJy4vbW9kZWwvQWp4cE5vZGUnKSxcbiAgICBDb250cm9sbGVyID0gcmVxdWlyZSgnLi9tb2RlbC9Db250cm9sbGVyJyksXG4gICAgRW1wdHlOb2RlUHJvdmlkZXIgPSByZXF1aXJlKCcuL21vZGVsL0VtcHR5Tm9kZVByb3ZpZGVyJyksXG4gICAgUHlkaW9EYXRhTW9kZWwgPSByZXF1aXJlKCcuL21vZGVsL1B5ZGlvRGF0YU1vZGVsJyksXG4gICAgUmVnaXN0cnkgPSByZXF1aXJlKCcuL21vZGVsL1JlZ2lzdHJ5JyksXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyID0gcmVxdWlyZSgnLi9tb2RlbC9SZW1vdGVOb2RlUHJvdmlkZXInKSxcbiAgICBSZXBvc2l0b3J5ID0gcmVxdWlyZSgnLi9tb2RlbC9SZXBvc2l0b3J5JyksXG4gICAgVXNlciA9IHJlcXVpcmUoJy4vbW9kZWwvVXNlcicpLFxuICAgIENvbnRleHRNZW51ID0gcmVxdWlyZSgnLi9tb2RlbC9Db250ZXh0TWVudScpLFxuICAgIENvb2tpZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi91dGlsL0Nvb2tpZXNNYW5hZ2VyJyksXG4gICAgRE9NVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvRE9NVXRpbHMnKSxcbiAgICBGdW5jVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvRnVuY1V0aWxzJyksXG4gICAgSGFzaGVyVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvSGFzaGVyVXRpbHMnKSxcbiAgICBMYW5nVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvTGFuZ1V0aWxzJyksXG4gICAgUGFzc1V0aWxzID0gcmVxdWlyZSgnLi91dGlsL1Bhc3NVdGlscycpLFxuICAgIFBhdGhVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9QYXRoVXRpbHMnKSxcbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIgPSByZXF1aXJlKCcuL3V0aWwvUGVyaW9kaWNhbEV4ZWN1dGVyJyksXG4gICAgQWN0aXZpdHlNb25pdG9yID0gcmVxdWlyZSgnLi91dGlsL0FjdGl2aXR5TW9uaXRvcicpLFxuICAgIFhNTFV0aWxzID0gcmVxdWlyZSgnLi91dGlsL1hNTFV0aWxzJyksXG4gICAgUHlkaW8gPSByZXF1aXJlKCcuL1B5ZGlvJyk7XG5cbnZhciBQeWRpb1VzZXJzID0ge1xuICAgIENsaWVudDogVXNlcnNBcGkuVXNlcnNBcGksXG4gICAgVXNlcjogVXNlcnNBcGkuVXNlclxufTtcblxudmFyIG5hbWVzcGFjZSA9IHtcbiAgICBDb25uZXhpb246IENvbm5leGlvbixcbiAgICBNZXRhQ2FjaGVTZXJ2aWNlOiBNZXRhQ2FjaGVTZXJ2aWNlLFxuICAgIFB5ZGlvQXBpOiBQeWRpb0FwaSxcbiAgICBQeWRpb1VzZXJzOiBQeWRpb1VzZXJzLFxuICAgIFJlc291cmNlc01hbmFnZXI6IFJlc291cmNlc01hbmFnZXIsXG4gICAgTG9nZ2VyOiBMb2dnZXIsXG4gICAgT2JzZXJ2YWJsZTogT2JzZXJ2YWJsZSxcbiAgICBBY3Rpb246IEFjdGlvbixcbiAgICBBanhwTm9kZTogQWp4cE5vZGUsXG4gICAgQ29udHJvbGxlcjogQ29udHJvbGxlcixcbiAgICBFbXB0eU5vZGVQcm92aWRlcjogRW1wdHlOb2RlUHJvdmlkZXIsXG4gICAgUHlkaW9EYXRhTW9kZWw6IFB5ZGlvRGF0YU1vZGVsLFxuICAgIFJlZ2lzdHJ5OiBSZWdpc3RyeSxcbiAgICBSZW1vdGVOb2RlUHJvdmlkZXI6IFJlbW90ZU5vZGVQcm92aWRlcixcbiAgICBSZXBvc2l0b3J5OiBSZXBvc2l0b3J5LFxuICAgIFVzZXI6IFVzZXIsXG4gICAgQ29udGV4dE1lbnU6IENvbnRleHRNZW51LFxuICAgIENvb2tpZXNNYW5hZ2VyOiBDb29raWVzTWFuYWdlcixcbiAgICBET01VdGlsczogRE9NVXRpbHMsXG4gICAgRnVuY1V0aWxzOiBGdW5jVXRpbHMsXG4gICAgSGFzaGVyVXRpbHM6IEhhc2hlclV0aWxzLFxuICAgIExhbmdVdGlsczogTGFuZ1V0aWxzLFxuICAgIFBhc3NVdGlsczogUGFzc1V0aWxzLFxuICAgIFBhdGhVdGlsczogUGF0aFV0aWxzLFxuICAgIFBlcmlvZGljYWxFeGVjdXRlcjogUGVyaW9kaWNhbEV4ZWN1dGVyLFxuICAgIEFjdGl2aXR5TW9uaXRvcjogQWN0aXZpdHlNb25pdG9yLFxuICAgIFhNTFV0aWxzOiBYTUxVdGlscyxcbiAgICBQeWRpbzogUHlkaW9cbn07XG5cbk9iamVjdC5hc3NpZ24od2luZG93LCBfZXh0ZW5kcyh7fSwgbmFtZXNwYWNlLCB7IFB5ZGlvQ29yZTogbmFtZXNwYWNlIH0pKTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbi8qKlxuICogQVBJIENsaWVudFxuICovXG5cbnZhciBQeWRpb0FwaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHlkaW9BcGkoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQeWRpb0FwaSk7XG4gICAgfVxuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnNldFB5ZGlvT2JqZWN0ID0gZnVuY3Rpb24gc2V0UHlkaW9PYmplY3QocHlkaW9PYmplY3QpIHtcbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QgPSBweWRpb09iamVjdDtcbiAgICAgICAgdGhpcy5fYmFzZVVybCA9IHB5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KCdzZXJ2ZXJBY2Nlc3NQYXRoJyk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5yZXF1ZXN0ID0gZnVuY3Rpb24gcmVxdWVzdChwYXJhbWV0ZXJzKSB7XG4gICAgICAgIHZhciBvbkNvbXBsZXRlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIG9uRXJyb3IgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgc2V0dGluZ3MgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICAvLyBDb25uZXhpb24gYWxyZWFkeSBoYW5kbGVzIHNlY3VyZV90b2tlblxuICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oKTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmRpc2NyZXRlKSB7XG4gICAgICAgICAgICBjLmRpc2NyZXRlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjLnNldFBhcmFtZXRlcnMocGFyYW1ldGVycyk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5tZXRob2QpIHtcbiAgICAgICAgICAgIGMuc2V0TWV0aG9kKHNldHRpbmdzLm1ldGhvZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFvbkNvbXBsZXRlKSB7XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gKGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MKSByZXR1cm4gdGhpcy5wYXJzZVhtbE1lc3NhZ2UodHJhbnNwb3J0LnJlc3BvbnNlWE1MKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgYy5vbkNvbXBsZXRlID0gb25Db21wbGV0ZTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmFzeW5jID09PSBmYWxzZSkge1xuICAgICAgICAgICAgYy5zZW5kU3luYygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYy5zZW5kQXN5bmMoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUubG9hZEZpbGUgPSBmdW5jdGlvbiBsb2FkRmlsZShmaWxlUGF0aCkge1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBvbkVycm9yID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oZmlsZVBhdGgpO1xuICAgICAgICBjLnNldE1ldGhvZCgnR0VUJyk7XG4gICAgICAgIGMub25Db21wbGV0ZSA9IG9uQ29tcGxldGU7XG4gICAgICAgIGMuc2VuZEFzeW5jKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBmaWxlXG4gICAgICogQHBhcmFtIGZpbGVQYXJhbWV0ZXJOYW1lXG4gICAgICogQHBhcmFtIHF1ZXJ5U3RyaW5nUGFyYW1zXG4gICAgICogQHBhcmFtIG9uQ29tcGxldGVcbiAgICAgKiBAcGFyYW0gb25FcnJvclxuICAgICAqIEBwYXJhbSBvblByb2dyZXNzXG4gICAgICogQHJldHVybnMgWEhSIEhhbmRsZSB0byBhYm9ydCB0cmFuc2ZlclxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLnVwbG9hZEZpbGUgPSBmdW5jdGlvbiB1cGxvYWRGaWxlKGZpbGUsIGZpbGVQYXJhbWV0ZXJOYW1lKSB7XG4gICAgICAgIHZhciBxdWVyeVN0cmluZ1BhcmFtcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzJdO1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzNdO1xuICAgICAgICB2YXIgb25FcnJvciA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNCB8fCBhcmd1bWVudHNbNF0gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzRdO1xuICAgICAgICB2YXIgb25Qcm9ncmVzcyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNSB8fCBhcmd1bWVudHNbNV0gPT09IHVuZGVmaW5lZCA/IGZ1bmN0aW9uICgpIHt9IDogYXJndW1lbnRzWzVdO1xuICAgICAgICB2YXIgdXBsb2FkVXJsID0gYXJndW1lbnRzLmxlbmd0aCA8PSA2IHx8IGFyZ3VtZW50c1s2XSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbNl07XG4gICAgICAgIHZhciB4aHJTZXR0aW5ncyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gNyB8fCBhcmd1bWVudHNbN10gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzddO1xuXG4gICAgICAgIGlmICghdXBsb2FkVXJsKSB7XG4gICAgICAgICAgICB1cGxvYWRVcmwgPSBweWRpby5QYXJhbWV0ZXJzLmdldCgnYWp4cFNlcnZlckFjY2VzcycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChxdWVyeVN0cmluZ1BhcmFtcykge1xuICAgICAgICAgICAgdXBsb2FkVXJsICs9ICh1cGxvYWRVcmwuaW5kZXhPZignPycpID09PSAtMSA/ICc/JyA6ICcmJykgKyBxdWVyeVN0cmluZ1BhcmFtcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh3aW5kb3cuQ29ubmV4aW9uKSB7XG4gICAgICAgICAgICB2YXIgX3JldCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gV2FybmluZywgYXZvaWQgZG91YmxlIGVycm9yXG4gICAgICAgICAgICAgICAgdmFyIGVycm9yU2VudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBsb2NhbEVycm9yID0gZnVuY3Rpb24gbG9jYWxFcnJvcih4aHIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvclNlbnQpIG9uRXJyb3IoJ1JlcXVlc3QgZmFpbGVkIHdpdGggc3RhdHVzIDonICsgeGhyLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yU2VudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IG5ldyBDb25uZXhpb24oKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB2OiBjLnVwbG9hZEZpbGUoZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUsIHVwbG9hZFVybCwgb25Db21wbGV0ZSwgbG9jYWxFcnJvciwgb25Qcm9ncmVzcywgeGhyU2V0dGluZ3MpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pKCk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX3JldCA9PT0gJ29iamVjdCcpIHJldHVybiBfcmV0LnY7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdXNlclNlbGVjdGlvbiBVc2VyU2VsZWN0aW9uIEEgUHlkaW8gRGF0YU1vZGVsIHdpdGggc2VsZWN0ZWQgZmlsZXNcbiAgICAgKiBAcGFyYW0gcHJvdG90eXBlSGlkZGVuRm9ybSBFbGVtZW50IEEgaGlkZGVuIGZvcm0gZWxlbWVudDogY3VycmVudGx5IHJlbHlpbmcgb24gUHJvdG90eXBlSlMuXG4gICAgICogQHBhcmFtIGRsQWN0aW9uTmFtZSBTdHJpbmcgQWN0aW9uIG5hbWUgdG8gdHJpZ2dlciwgZG93bmxvYWQgYnkgZGVmYXVsdC5cbiAgICAgKiBAcGFyYW0gYWRkaXRpb25hbFBhcmFtZXRlcnMgT2JqZWN0IE9wdGlvbmFsIHNldCBvZiBrZXkvdmFsdWVzIHRvIHBhc3MgdG8gdGhlIGRvd25sb2FkLlxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmRvd25sb2FkU2VsZWN0aW9uID0gZnVuY3Rpb24gZG93bmxvYWRTZWxlY3Rpb24odXNlclNlbGVjdGlvbikge1xuICAgICAgICB2YXIgZGxBY3Rpb25OYW1lID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gJ2Rvd25sb2FkJyA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8ge30gOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgdmFyIGFqeHBTZXJ2ZXJBY2Nlc3MgPSB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldChcImFqeHBTZXJ2ZXJBY2Nlc3NcIik7XG4gICAgICAgIHZhciBhZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQgfHwgJyc7XG4gICAgICAgIHZhciBhZ2VudElzTW9iaWxlID0gYWdlbnQuaW5kZXhPZignaVBob25lJykgIT0gLTEgfHwgYWdlbnQuaW5kZXhPZignaVBvZCcpICE9IC0xIHx8IGFnZW50LmluZGV4T2YoJ2lQYWQnKSAhPSAtMSB8fCBhZ2VudC5pbmRleE9mKCdpT3MnKSAhPSAtMTtcbiAgICAgICAgdmFyIGhpZGRlbkZvcm0gPSBweWRpbyAmJiBweWRpby5VSSAmJiBweWRpby5VSS5oYXNIaWRkZW5Eb3dubG9hZEZvcm0oKTtcbiAgICAgICAgaWYgKGFnZW50SXNNb2JpbGUgfHwgIWhpZGRlbkZvcm0pIHtcbiAgICAgICAgICAgIHZhciBkb3dubG9hZFVybCA9IGFqeHBTZXJ2ZXJBY2Nlc3MgKyAnJmdldF9hY3Rpb249JyArIGRsQWN0aW9uTmFtZTtcbiAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1ldGVycykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHBhcmFtIGluIGFkZGl0aW9uYWxQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1ldGVycy5oYXNPd25Qcm9wZXJ0eShwYXJhbSkpIGRvd25sb2FkVXJsICs9IFwiJlwiICsgcGFyYW0gKyBcIj1cIiArIGFkZGl0aW9uYWxQYXJhbWV0ZXJzW3BhcmFtXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodXNlclNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgIGRvd25sb2FkVXJsID0gdXNlclNlbGVjdGlvbi51cGRhdGVGb3JtT3JVcmwobnVsbCwgZG93bmxvYWRVcmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZG9jdW1lbnQubG9jYXRpb24uaHJlZiA9IGRvd25sb2FkVXJsO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICB2YXIgcGFyYW1ldGVycyA9IF9leHRlbmRzKHt9LCBhZGRpdGlvbmFsUGFyYW1ldGVycywgeyBzZWN1cmVfdG9rZW46IHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KFwiU0VDVVJFX1RPS0VOXCIpLCBnZXRfYWN0aW9uOiBkbEFjdGlvbk5hbWUgfSk7XG4gICAgICAgICAgICB2YXIgbWluaXNpdGVfc2Vzc2lvbiA9IFB5ZGlvQXBpLmRldGVjdE1pbmlzaXRlU2Vzc2lvbihhanhwU2VydmVyQWNjZXNzKTtcbiAgICAgICAgICAgIGlmIChtaW5pc2l0ZV9zZXNzaW9uKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyc1snbWluaXNpdGVfc2Vzc2lvbiddID0gbWluaXNpdGVfc2Vzc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcHlkaW8uVUkuc2VuZERvd25sb2FkVG9IaWRkZW5Gb3JtKHVzZXJTZWxlY3Rpb24sIHBhcmFtZXRlcnMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmICh3aW5kb3cuY29uc29sZSkgd2luZG93LmNvbnNvbGUuZXJyb3IoXCJFcnJvciB3aGlsZSBzdWJtaXR0aW5nIGhpZGRlbiBmb3JtIGZvciBkb3dubG9hZFwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUucG9zdFBsYWluVGV4dENvbnRlbnQgPSBmdW5jdGlvbiBwb3N0UGxhaW5UZXh0Q29udGVudChmaWxlUGF0aCwgY29udGVudCwgZmluaXNoZWRDYWxsYmFjaykge1xuXG4gICAgICAgIHRoaXMucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAncHV0X2NvbnRlbnQnLFxuICAgICAgICAgICAgZmlsZTogZmlsZVBhdGgsXG4gICAgICAgICAgICBjb250ZW50OiBjb250ZW50XG4gICAgICAgIH0sIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB2YXIgc3VjY2VzcyA9IHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICBmaW5pc2hlZENhbGxiYWNrKHN1Y2Nlc3MpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBmaW5pc2hlZENhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdCBhIG1pbmlzaXRlX3Nlc3Npb24gcGFyYW1ldGVyIGluIHRoZSBVUkxcbiAgICAgKiBAcGFyYW0gc2VydmVyQWNjZXNzXG4gICAgICogQHJldHVybnMgc3RyaW5nfGJvb2xcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLmRldGVjdE1pbmlzaXRlU2Vzc2lvbiA9IGZ1bmN0aW9uIGRldGVjdE1pbmlzaXRlU2Vzc2lvbihzZXJ2ZXJBY2Nlc3MpIHtcbiAgICAgICAgdmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cCgnLio/WyZcXFxcP10nICsgJ21pbmlzaXRlX3Nlc3Npb24nICsgJz0oLio/KSY/Lio/Jyk7XG4gICAgICAgIHZhciB2YWwgPSBzZXJ2ZXJBY2Nlc3MucmVwbGFjZShyZWdleCwgXCIkMVwiKTtcbiAgICAgICAgcmV0dXJuIHZhbCA9PT0gc2VydmVyQWNjZXNzID8gZmFsc2UgOiB2YWw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIERldGVjdHMgaWYgY3VycmVudCBicm93c2VyIHN1cHBvcnRzIEhUTUw1IFVwbG9hZC5cbiAgICAgKiBAcmV0dXJucyBib29sZWFuXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5zdXBwb3J0c1VwbG9hZCA9IGZ1bmN0aW9uIHN1cHBvcnRzVXBsb2FkKCkge1xuICAgICAgICBpZiAod2luZG93LkNvbm5leGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5Gb3JtRGF0YSB8fCB3aW5kb3cuRmlsZVJlYWRlcjtcbiAgICAgICAgfSBlbHNlIGlmICh3aW5kb3cualF1ZXJ5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LkZvcm1EYXRhO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSW5zdGFuY2lhdGUgYSBQeWRpb0FwaSBjbGllbnQgaWYgaXQncyBub3QgYWxyZWFkeSBpbnN0YW5jaWF0ZWQgYW5kIHJldHVybiBpdC5cbiAgICAgKiBAcmV0dXJucyBQeWRpb0FwaVxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkuZ2V0Q2xpZW50ID0gZnVuY3Rpb24gZ2V0Q2xpZW50KCkge1xuICAgICAgICBpZiAoUHlkaW9BcGkuX1B5ZGlvQ2xpZW50KSByZXR1cm4gUHlkaW9BcGkuX1B5ZGlvQ2xpZW50O1xuICAgICAgICB2YXIgY2xpZW50ID0gbmV3IFB5ZGlvQXBpKCk7XG4gICAgICAgIFB5ZGlvQXBpLl9QeWRpb0NsaWVudCA9IGNsaWVudDtcbiAgICAgICAgcmV0dXJuIGNsaWVudDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIGphdmFzY3JpcHQgbGlicmFyeVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gb25Mb2FkZWRDb2RlIEZ1bmN0aW9uIENhbGxiYWNrXG4gICAgICogQHBhcmFtIGFTeW5jIEJvb2xlYW4gbG9hZCBsaWJyYXJ5IGFzeW5jaHJvbmVvdXNseVxuICAgICAqL1xuXG4gICAgUHlkaW9BcGkubG9hZExpYnJhcnkgPSBmdW5jdGlvbiBsb2FkTGlicmFyeShmaWxlTmFtZSwgb25Mb2FkZWRDb2RlLCBhU3luYykge1xuICAgICAgICBpZiAod2luZG93LnB5ZGlvICYmIHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KFwiYWp4cFZlcnNpb25cIikgJiYgZmlsZU5hbWUuaW5kZXhPZihcIj9cIikgPT0gLTEpIHtcbiAgICAgICAgICAgIGZpbGVOYW1lICs9IFwiP3Y9XCIgKyBweWRpby5QYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIFB5ZGlvQXBpLl9saWJVcmwgPSBmYWxzZTtcbiAgICAgICAgaWYgKHdpbmRvdy5weWRpbyAmJiBweWRpby5QYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSkge1xuICAgICAgICAgICAgUHlkaW9BcGkuX2xpYlVybCA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbm4gPSBuZXcgQ29ubmV4aW9uKCk7XG4gICAgICAgIGNvbm4uX2xpYlVybCA9IGZhbHNlO1xuICAgICAgICBpZiAocHlkaW8uUGFyYW1ldGVycy5nZXQoJ1NFUlZFUl9QUkVGSVhfVVJJJykpIHtcbiAgICAgICAgICAgIGNvbm4uX2xpYlVybCA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbm4ubG9hZExpYnJhcnkoZmlsZU5hbWUsIG9uTG9hZGVkQ29kZSwgYVN5bmMpO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3dpdGNoUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIHN3aXRjaFJlcG9zaXRvcnkocmVwb3NpdG9yeUlkLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnc3dpdGNoX3JlcG9zaXRvcnknLFxuICAgICAgICAgICAgcmVwb3NpdG9yeV9pZDogcmVwb3NpdG9yeUlkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3dpdGNoTGFuZ3VhZ2UgPSBmdW5jdGlvbiBzd2l0Y2hMYW5ndWFnZShsYW5nLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnZ2V0X2kxOG5fbWVzc2FnZXMnLFxuICAgICAgICAgICAgbGFuZzogbGFuZyxcbiAgICAgICAgICAgIGZvcm1hdDogJ2pzb24nXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUubG9hZFhtbFJlZ2lzdHJ5ID0gZnVuY3Rpb24gbG9hZFhtbFJlZ2lzdHJ5KGNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHhQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICB2YXIgcGFyYW1zID0geyBnZXRfYWN0aW9uOiAnZ2V0X3htbF9yZWdpc3RyeScgfTtcbiAgICAgICAgaWYgKHhQYXRoKSBwYXJhbXNbeFBhdGhdID0geFBhdGg7XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuZ2V0Qm9vdENvbmYgPSBmdW5jdGlvbiBnZXRCb290Q29uZihjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7IGdldF9hY3Rpb246ICdnZXRfYm9vdF9jb25mJyB9O1xuICAgICAgICB2YXIgY0IgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZUpTT04gJiYgdHJhbnNwb3J0LnJlc3BvbnNlSlNPTi5TRUNVUkVfVE9LRU4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLnNldCgnU0VDVVJFX1RPS0VOJywgdHJhbnNwb3J0LnJlc3BvbnNlSlNPTi5TRUNVUkVfVE9LRU4pO1xuICAgICAgICAgICAgICAgIENvbm5leGlvbi51cGRhdGVTZXJ2ZXJBY2Nlc3ModGhpcy5fcHlkaW9PYmplY3QuUGFyYW1ldGVycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGNvbXBsZXRlQ2FsbGJhY2sodHJhbnNwb3J0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHBhcmFtcywgY0IpO1xuICAgIH07XG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUudXNlclNhdmVQcmVmZXJlbmNlID0gZnVuY3Rpb24gdXNlclNhdmVQcmVmZXJlbmNlKHByZWZOYW1lLCBwcmVmVmFsdWUpIHtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHsgZ2V0X2FjdGlvbjogXCJzYXZlX3VzZXJfcHJlZlwiLCBcInByZWZfbmFtZV8wXCI6IHByZWZOYW1lLCBcInByZWZfdmFsdWVfMFwiOiBwcmVmVmFsdWUgfSwgbnVsbCwgbnVsbCwgeyBkaXNjcmV0ZTogdHJ1ZSwgbWV0aG9kOiAncG9zdCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS51c2VyU2F2ZVByZWZlcmVuY2VzID0gZnVuY3Rpb24gdXNlclNhdmVQcmVmZXJlbmNlcyhwcmVmZXJlbmNlcywgY29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICB2YXIgcGFyYW1zID0geyAnZ2V0X2FjdGlvbic6ICdzYXZlX3VzZXJfcHJlZicgfTtcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICBwcmVmZXJlbmNlcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICBwYXJhbXNbXCJwcmVmX25hbWVfXCIgKyBpXSA9IGtleTtcbiAgICAgICAgICAgIHBhcmFtc1tcInByZWZfdmFsdWVfXCIgKyBpXSA9IHZhbHVlO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0KHBhcmFtcywgY29tcGxldGVDYWxsYmFjaywgbnVsbCwgeyBkaXNjcmV0ZTogdHJ1ZSwgbWV0aG9kOiAncG9zdCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS51c2VyU2F2ZVBhc3N3b3JkID0gZnVuY3Rpb24gdXNlclNhdmVQYXNzd29yZChvbGRQYXNzLCBuZXdQYXNzLCBzZWVkLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnc2F2ZV91c2VyX3ByZWYnLFxuICAgICAgICAgICAgcHJlZl9uYW1lXzA6IFwicGFzc3dvcmRcIixcbiAgICAgICAgICAgIHByZWZfdmFsdWVfMDogbmV3UGFzcyxcbiAgICAgICAgICAgIGNydDogb2xkUGFzcyxcbiAgICAgICAgICAgIHBhc3Nfc2VlZDogc2VlZFxuICAgICAgICB9LCBjb21wbGV0ZUNhbGxiYWNrLCBudWxsLCB7IGRpc2NyZXRlOiB0cnVlLCBtZXRob2Q6ICdwb3N0JyB9KTtcbiAgICB9O1xuXG4gICAgUHlkaW9BcGkucHJvdG90eXBlLmJ1aWxkVXNlckF2YXRhclVybCA9IGZ1bmN0aW9uIGJ1aWxkVXNlckF2YXRhclVybCh1c2VySWQpIHtcbiAgICAgICAgdmFyIGF2YXRhcklkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAoYXZhdGFySWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9weWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldCgnYWp4cFNlcnZlckFjY2VzcycpICsgXCImZ2V0X2FjdGlvbj1nZXRfYmluYXJ5X3BhcmFtJmJpbmFyeV9pZD1cIiArIGF2YXRhcklkICsgXCImdXNlcl9pZD1cIiArIHVzZXJJZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5hcHBseUNoZWNrSG9vayA9IGZ1bmN0aW9uIGFwcGx5Q2hlY2tIb29rKG5vZGUsIGhvb2tOYW1lLCBob29rQXJnLCBjb21wbGV0ZUNhbGxiYWNrLCBhZGRpdGlvbmFsUGFyYW1zKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiBcImFwcGx5X2NoZWNrX2hvb2tcIixcbiAgICAgICAgICAgIGZpbGU6IG5vZGUuZ2V0UGF0aCgpLFxuICAgICAgICAgICAgaG9va19uYW1lOiBob29rTmFtZSxcbiAgICAgICAgICAgIGhvb2tfYXJnOiBob29rQXJnXG4gICAgICAgIH07XG4gICAgICAgIGlmIChhZGRpdGlvbmFsUGFyYW1zKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBMYW5nVXRpbHMub2JqZWN0TWVyZ2UocGFyYW1zLCBhZGRpdGlvbmFsUGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZUNhbGxiYWNrLCBudWxsLCB7IGFzeW5jOiBmYWxzZSB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3RhbmRhcmQgcGFyc2VyIGZvciBzZXJ2ZXIgWE1MIGFuc3dlcnNcbiAgICAgKiBAcGFyYW0geG1sUmVzcG9uc2UgRE9NRG9jdW1lbnRcbiAgICAgKi9cblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5wYXJzZVhtbE1lc3NhZ2UgPSBmdW5jdGlvbiBwYXJzZVhtbE1lc3NhZ2UoeG1sUmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKHhtbFJlc3BvbnNlID09IG51bGwgfHwgeG1sUmVzcG9uc2UuZG9jdW1lbnRFbGVtZW50ID09IG51bGwpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgY2hpbGRzID0geG1sUmVzcG9uc2UuZG9jdW1lbnRFbGVtZW50LmNoaWxkTm9kZXM7XG4gICAgICAgIHZhciByZWxvYWROb2RlcyA9IFtdLFxuICAgICAgICAgICAgZXJyb3IgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5MQVNUX0VSUk9SX0lEID0gbnVsbDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRzW2ldO1xuICAgICAgICAgICAgaWYgKGNoaWxkLnRhZ05hbWUgPT09IFwibWVzc2FnZVwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VUeHQgPSBcIk5vIG1lc3NhZ2VcIjtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuZmlyc3RDaGlsZCkgbWVzc2FnZVR4dCA9IGNoaWxkLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5nZXRBdHRyaWJ1dGUoJ3R5cGUnKSA9PSAnRVJST1InKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihtZXNzYWdlVHh0KTtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5sb2cobWVzc2FnZVR4dCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC50YWdOYW1lID09PSBcInByb21wdFwiKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAocHlkaW8gJiYgcHlkaW8uVUkgJiYgcHlkaW8uVUkub3BlblByb21wdERpYWxvZykge1xuICAgICAgICAgICAgICAgICAgICB2YXIganNvbkRhdGEgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShjaGlsZHNbaV0sIFwiZGF0YVwiKS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHlkaW8uVUkub3BlblByb21wdERpYWxvZyhKU09OLnBhcnNlKGpzb25EYXRhKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQudGFnTmFtZSA9PSBcInJlbG9hZF9pbnN0cnVjdGlvblwiKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgb2JOYW1lID0gY2hpbGQuZ2V0QXR0cmlidXRlKCdvYmplY3QnKTtcbiAgICAgICAgICAgICAgICBpZiAob2JOYW1lID09PSAnZGF0YScpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGUgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoJ25vZGUnKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbG9hZE5vZGVzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZmlsZSA9IGNoaWxkLmdldEF0dHJpYnV0ZSgnZmlsZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCkuc2V0UGVuZGluZ1NlbGVjdGlvbihmaWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbG9hZE5vZGVzLnB1c2godGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dE5vZGUoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9iTmFtZSA9PSAncmVwb3NpdG9yeV9saXN0Jykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5yZWxvYWRSZXBvc2l0b3JpZXNMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC5ub2RlTmFtZSA9PSAnbm9kZXNfZGlmZicpIHtcblxuICAgICAgICAgICAgICAgIHZhciBkbSA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHRIb2xkZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAoZG0uZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGVzRGlmZnMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG0uZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGVzRGlmZnMoY2hpbGRzW2ldLCBkbSwgdGhpcy5fcHlkaW9PYmplY3QudXNlci5hY3RpdmVSZXBvc2l0b3J5LCAhd2luZG93LmN1cnJlbnRMaWdodEJveCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC50YWdOYW1lID09IFwibG9nZ2luZ19yZXN1bHRcIikge1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkLmdldEF0dHJpYnV0ZShcInNlY3VyZV90b2tlblwiKSkge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuc2V0KCdTRUNVUkVfVE9LRU4nLCBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJzZWN1cmVfdG9rZW5cIikpO1xuICAgICAgICAgICAgICAgICAgICBDb25uZXhpb24udXBkYXRlU2VydmVyQWNjZXNzKHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gY2hpbGQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpO1xuICAgICAgICAgICAgICAgIHZhciBlcnJvcklkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnMSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5sb2FkWG1sUmVnaXN0cnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICcwJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnLTEnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JJZCA9IDI4NTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICcyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmxvYWRYbWxSZWdpc3RyeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJy0yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySWQgPSAyODU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnLTMnOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JJZCA9IDM2NjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICctNCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcklkID0gMzg2O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlcnJvcklkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5MQVNUX0VSUk9SX0lEID0gZXJyb3JJZDtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKHRoaXMuX3B5ZGlvT2JqZWN0Lk1lc3NhZ2VIYXNoW2Vycm9ySWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoaWxkLnRhZ05hbWUgPT0gXCJ0cmlnZ2VyX2JnX2FjdGlvblwiKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgX25hbWUgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpO1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlSWQgPSBjaGlsZC5nZXRBdHRyaWJ1dGUoXCJtZXNzYWdlSWRcIik7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtZXRlcnMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjaGlsZC5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJhbUNoaWxkID0gY2hpbGQuY2hpbGROb2Rlc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtQ2hpbGQudGFnTmFtZSA9PSAncGFyYW0nKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnNbcGFyYW1DaGlsZC5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpXSA9IHBhcmFtQ2hpbGQuZ2V0QXR0cmlidXRlKFwidmFsdWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocGFyYW1DaGlsZC50YWdOYW1lID09ICdjbGllbnRDYWxsYmFjaycgJiYgcGFyYW1DaGlsZC5maXJzdENoaWxkICYmIHBhcmFtQ2hpbGQuZmlyc3RDaGlsZC5ub2RlVmFsdWUpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrQ29kZSA9IHBhcmFtQ2hpbGQuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayA9IG5ldyBGdW5jdGlvbihjYWxsYmFja0NvZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfbmFtZSA9PSBcImphdmFzY3JpcHRfaW5zdHJ1Y3Rpb25cIiAmJiBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9weWRpb09iamVjdC5ub3RpZnkoXCJyZXNwb25zZS54bWxcIiwgeG1sUmVzcG9uc2UpO1xuICAgICAgICBpZiAocmVsb2FkTm9kZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0SG9sZGVyKCkubXVsdGlwbGVOb2Rlc1JlbG9hZChyZWxvYWROb2Rlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICFlcnJvcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3VibWl0cyBhIGZvcm0gdXNpbmcgQ29ubmV4aW9uIGNsYXNzLlxuICAgICAqIEBwYXJhbSBmb3JtTmFtZSBTdHJpbmcgVGhlIGlkIG9mIHRoZSBmb3JtXG4gICAgICogQHBhcmFtIHBvc3QgQm9vbGVhbiBXaGV0aGVyIHRvIFBPU1Qgb3IgR0VUXG4gICAgICogQHBhcmFtIGNvbXBsZXRlQ2FsbGJhY2sgRnVuY3Rpb24gQ2FsbGJhY2sgdG8gYmUgY2FsbGVkIG9uIGNvbXBsZXRlXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS5wcm90b3R5cGUuc3VibWl0Rm9ybSA9IGZ1bmN0aW9uIHN1Ym1pdEZvcm0oZm9ybU5hbWUpIHtcbiAgICAgICAgdmFyIHBvc3QgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY29tcGxldGVDYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgICAgdmFyIHBhcmFtcyA9IHt9O1xuICAgICAgICAvLyBUT0RPOiBVSSBJTVBMRU1FTlRBVElPTlxuICAgICAgICAkKGZvcm1OYW1lKS5nZXRFbGVtZW50cygpLmVhY2goZnVuY3Rpb24gKGZFbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgZlZhbHVlID0gZkVsZW1lbnQuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgIGlmIChmRWxlbWVudC5uYW1lID09ICdnZXRfYWN0aW9uJyAmJiBmVmFsdWUuc3Vic3RyKDAsIDQpID09ICdodHRwJykge1xuICAgICAgICAgICAgICAgIGZWYWx1ZSA9IFBhdGhVdGlscy5nZXRCYXNlbmFtZShmVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZFbGVtZW50LnR5cGUgPT0gJ3JhZGlvJyAmJiAhZkVsZW1lbnQuY2hlY2tlZCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKHBhcmFtc1tmRWxlbWVudC5uYW1lXSAmJiBmRWxlbWVudC5uYW1lLmVuZHNXaXRoKCdbXScpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4aXN0aW5nID0gcGFyYW1zW2ZFbGVtZW50Lm5hbWVdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT0gJ3N0cmluZycpIGV4aXN0aW5nID0gW2V4aXN0aW5nXTtcbiAgICAgICAgICAgICAgICBleGlzdGluZy5wdXNoKGZWYWx1ZSk7XG4gICAgICAgICAgICAgICAgcGFyYW1zW2ZFbGVtZW50Lm5hbWVdID0gZXhpc3Rpbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtc1tmRWxlbWVudC5uYW1lXSA9IGZWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLl9weWRpb09iamVjdC5nZXRDb250ZXh0Tm9kZSgpKSB7XG4gICAgICAgICAgICBwYXJhbXNbJ2RpciddID0gdGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICBvbkNvbXBsZXRlID0gY29tcGxldGVDYWxsYmFjaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9uQ29tcGxldGUgPSAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIG9uQ29tcGxldGUsIG51bGwsIHsgbWV0aG9kOiBwb3N0ID8gJ3Bvc3QnIDogJ2dldCcgfSk7XG4gICAgfTtcblxuICAgIFB5ZGlvQXBpLnByb3RvdHlwZS5wb3N0U2VsZWN0aW9uV2l0aEFjdGlvbiA9IGZ1bmN0aW9uIHBvc3RTZWxlY3Rpb25XaXRoQWN0aW9uKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIHNlbGVjdGlvbk1vZGVsID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICBpZiAoIXNlbGVjdGlvbk1vZGVsKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb25Nb2RlbCA9IHRoaXMuX3B5ZGlvT2JqZWN0LmdldENvbnRleHRIb2xkZXIoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogYWN0aW9uTmFtZSxcbiAgICAgICAgICAgIGRpcjogc2VsZWN0aW9uTW9kZWwuZ2V0Q29udGV4dE5vZGUoKS5nZXRQYXRoKClcbiAgICAgICAgfTtcbiAgICAgICAgcGFyYW1zWydub2Rlc1tdJ10gPSBzZWxlY3Rpb25Nb2RlbC5nZXRGaWxlTmFtZXMoKTtcbiAgICAgICAgaWYgKGFkZGl0aW9uYWxQYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBPYmplY3QuYXNzaWduKHBhcmFtcywgYWRkaXRpb25hbFBhcmFtZXRlcnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWVzdChwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciBhIHNpbXBsZSBkb3dubG9hZFxuICAgICAqIEBwYXJhbSB1cmwgU3RyaW5nXG4gICAgICovXG5cbiAgICBQeWRpb0FwaS50cmlnZ2VyRG93bmxvYWQgPSBmdW5jdGlvbiB0cmlnZ2VyRG93bmxvYWQodXJsKSB7XG4gICAgICAgIGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSB1cmw7XG4gICAgfTtcblxuICAgIHJldHVybiBQeWRpb0FwaTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFB5ZGlvQXBpO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbi8qKlxuICogUHlkaW8gZW5jYXBzdWxhdGlvbiBvZiBYSFIgLyBGZXRjaFxuICovXG5yZXF1aXJlKCd3aGF0d2ctZmV0Y2gnKTtcblxudmFyIENvbm5leGlvbiA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSBiYXNlVXJsIFN0cmluZyBUaGUgYmFzZSB1cmwgZm9yIHNlcnZpY2VzXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBDb25uZXhpb24oYmFzZVVybCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29ubmV4aW9uKTtcblxuICAgICAgICB0aGlzLl9weWRpbyA9IHdpbmRvdy5weWRpbztcbiAgICAgICAgdGhpcy5fYmFzZVVybCA9IGJhc2VVcmwgfHwgd2luZG93LmFqeHBTZXJ2ZXJBY2Nlc3NQYXRoO1xuICAgICAgICB0aGlzLl9saWJVcmwgPSB3aW5kb3cuYWp4cFJlc291cmNlc0ZvbGRlciArICcvYnVpbGQnO1xuICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLl9tZXRob2QgPSAncG9zdCc7XG4gICAgICAgIHRoaXMuZGlzY3JldGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBDb25uZXhpb24udXBkYXRlU2VydmVyQWNjZXNzID0gZnVuY3Rpb24gdXBkYXRlU2VydmVyQWNjZXNzKHBhcmFtZXRlcnMpIHtcblxuICAgICAgICBpZiAocGFyYW1ldGVycy5nZXQoJ1NFQ1VSRV9UT0tFTicpKSB7XG4gICAgICAgICAgICBDb25uZXhpb24uU0VDVVJFX1RPS0VOID0gcGFyYW1ldGVycy5nZXQoJ1NFQ1VSRV9UT0tFTicpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzZXJ2ZXJBY2Nlc3NQYXRoID0gcGFyYW1ldGVycy5nZXQoJ2FqeHBTZXJ2ZXJBY2Nlc3MnKS5zcGxpdCgnPycpLnNoaWZ0KCk7XG4gICAgICAgIGlmIChwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSkge1xuICAgICAgICAgICAgcGFyYW1ldGVycy5zZXQoJ2FqeHBSZXNvdXJjZXNGb2xkZXInLCBwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BSRUZJWF9VUkknKSArIHBhcmFtZXRlcnMuZ2V0KCdhanhwUmVzb3VyY2VzRm9sZGVyJykpO1xuICAgICAgICAgICAgc2VydmVyQWNjZXNzUGF0aCA9IHBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpICsgc2VydmVyQWNjZXNzUGF0aCArICc/JyArIChDb25uZXhpb24uU0VDVVJFX1RPS0VOID8gJ3NlY3VyZV90b2tlbj0nICsgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTiA6ICcnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlcnZlckFjY2Vzc1BhdGggPSBzZXJ2ZXJBY2Nlc3NQYXRoICsgJz8nICsgKENvbm5leGlvbi5TRUNVUkVfVE9LRU4gPyAnc2VjdXJlX3Rva2VuPScgKyBDb25uZXhpb24uU0VDVVJFX1RPS0VOIDogJycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BFUk1BTkVOVF9QQVJBTVMnKSkge1xuICAgICAgICAgICAgdmFyIHBlcm1QYXJhbXMgPSBwYXJhbWV0ZXJzLmdldCgnU0VSVkVSX1BFUk1BTkVOVF9QQVJBTVMnKTtcbiAgICAgICAgICAgIHZhciBwZXJtU3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgcGVybWFuZW50IGluIHBlcm1QYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGVybVBhcmFtcy5oYXNPd25Qcm9wZXJ0eShwZXJtYW5lbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBlcm1TdHJpbmdzLnB1c2gocGVybWFuZW50ICsgJz0nICsgcGVybVBhcmFtc1twZXJtYW5lbnRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZXJtU3RyaW5ncyA9IHBlcm1TdHJpbmdzLmpvaW4oJyYnKTtcbiAgICAgICAgICAgIGlmIChwZXJtU3RyaW5ncykge1xuICAgICAgICAgICAgICAgIHNlcnZlckFjY2Vzc1BhdGggKz0gJyYnICsgcGVybVN0cmluZ3M7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwYXJhbWV0ZXJzLnNldCgnYWp4cFNlcnZlckFjY2VzcycsIHNlcnZlckFjY2Vzc1BhdGgpO1xuICAgICAgICAvLyBCQUNLV0FSRCBDT01QQVRcbiAgICAgICAgd2luZG93LmFqeHBTZXJ2ZXJBY2Nlc3NQYXRoID0gc2VydmVyQWNjZXNzUGF0aDtcbiAgICAgICAgaWYgKHdpbmRvdy5weWRpb0Jvb3RzdHJhcCAmJiB3aW5kb3cucHlkaW9Cb290c3RyYXAucGFyYW1ldGVycykge1xuICAgICAgICAgICAgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5zZXQoXCJhanhwU2VydmVyQWNjZXNzXCIsIHNlcnZlckFjY2Vzc1BhdGgpO1xuICAgICAgICAgICAgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5zZXQoXCJTRUNVUkVfVE9LRU5cIiwgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLmxvZyA9IGZ1bmN0aW9uIGxvZyhhY3Rpb24sIHN5bmNTdGF0dXMpIHtcbiAgICAgICAgaWYgKCFDb25uZXhpb24uUHlkaW9Mb2dzKSB7XG4gICAgICAgICAgICBDb25uZXhpb24uUHlkaW9Mb2dzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgQ29ubmV4aW9uLlB5ZGlvTG9ncy5wdXNoKHsgYWN0aW9uOiBhY3Rpb24sIHN5bmM6IHN5bmNTdGF0dXMgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHBhcmFtZXRlciB0byB0aGUgcXVlcnlcbiAgICAgKiBAcGFyYW0gcGFyYW1OYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBwYXJhbVZhbHVlIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hZGRQYXJhbWV0ZXIgPSBmdW5jdGlvbiBhZGRQYXJhbWV0ZXIocGFyYW1OYW1lLCBwYXJhbVZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLl9wYXJhbWV0ZXJzLmdldChwYXJhbU5hbWUpICYmIHBhcmFtTmFtZS5lbmRzV2l0aCgnW10nKSkge1xuICAgICAgICAgICAgdmFyIGV4aXN0aW5nID0gdGhpcy5fcGFyYW1ldGVycy5nZXQocGFyYW1OYW1lKTtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmcgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICAgIGV4aXN0aW5nID0gW2V4aXN0aW5nXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV4aXN0aW5nLnB1c2gocGFyYW1WYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLnNldChwYXJhbU5hbWUsIGV4aXN0aW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3BhcmFtZXRlcnMuc2V0KHBhcmFtTmFtZSwgcGFyYW1WYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgd2hvbGUgcGFyYW1ldGVyIGFzIGEgYnVuY2hcbiAgICAgKiBAcGFyYW0gaFBhcmFtZXRlcnMgTWFwXG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnNldFBhcmFtZXRlcnMgPSBmdW5jdGlvbiBzZXRQYXJhbWV0ZXJzKGhQYXJhbWV0ZXJzKSB7XG4gICAgICAgIGlmIChoUGFyYW1ldGVycyBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycyA9IGhQYXJhbWV0ZXJzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGhQYXJhbWV0ZXJzLl9vYmplY3QpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdQYXNzZWQgYSBsZWdhY3kgSGFzaCBvYmplY3QgdG8gQ29ubmV4aW9uLnNldFBhcmFtZXRlcnMnKTtcbiAgICAgICAgICAgICAgICBoUGFyYW1ldGVycyA9IGhQYXJhbWV0ZXJzLl9vYmplY3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gaFBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoaFBhcmFtZXRlcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXJhbWV0ZXJzLnNldChrZXksIGhQYXJhbWV0ZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHF1ZXJ5IG1ldGhvZCAoZ2V0IHBvc3QpXG4gICAgICogQHBhcmFtIG1ldGhvZCBTdHJpbmdcbiAgICAgKi9cblxuICAgIENvbm5leGlvbi5wcm90b3R5cGUuc2V0TWV0aG9kID0gZnVuY3Rpb24gc2V0TWV0aG9kKG1ldGhvZCkge1xuICAgICAgICB0aGlzLl9tZXRob2QgPSBtZXRob2Q7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgc2VjdXJlIHRva2VuIHBhcmFtZXRlclxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5hZGRTZWN1cmVUb2tlbiA9IGZ1bmN0aW9uIGFkZFNlY3VyZVRva2VuKCkge1xuXG4gICAgICAgIGlmIChDb25uZXhpb24uU0VDVVJFX1RPS0VOICYmIHRoaXMuX2Jhc2VVcmwuaW5kZXhPZignc2VjdXJlX3Rva2VuJykgPT0gLTEgJiYgIXRoaXMuX3BhcmFtZXRlcnMuZ2V0KCdzZWN1cmVfdG9rZW4nKSkge1xuXG4gICAgICAgICAgICB0aGlzLmFkZFBhcmFtZXRlcignc2VjdXJlX3Rva2VuJywgQ29ubmV4aW9uLlNFQ1VSRV9UT0tFTik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fYmFzZVVybC5pbmRleE9mKCdzZWN1cmVfdG9rZW49JykgIT09IC0xKSB7XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSBmcm9tIGJhc2VVcmwgYW5kIHNldCBpbnNpZGUgcGFyYW1zXG4gICAgICAgICAgICB2YXIgcGFydHMgPSB0aGlzLl9iYXNlVXJsLnNwbGl0KCdzZWN1cmVfdG9rZW49Jyk7XG4gICAgICAgICAgICB2YXIgdG9rcyA9IHBhcnRzWzFdLnNwbGl0KCcmJyk7XG4gICAgICAgICAgICB2YXIgdG9rZW4gPSB0b2tzLnNoaWZ0KCk7XG4gICAgICAgICAgICB2YXIgcmVzdCA9IHRva3Muam9pbignJicpO1xuICAgICAgICAgICAgdGhpcy5fYmFzZVVybCA9IHBhcnRzWzBdICsgKHJlc3QgPyAnJicgKyByZXN0IDogJycpO1xuICAgICAgICAgICAgdGhpcy5fcGFyYW1ldGVycy5zZXQoJ3NlY3VyZV90b2tlbicsIHRva2VuKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmFkZFNlcnZlclBlcm1hbmVudFBhcmFtcyA9IGZ1bmN0aW9uIGFkZFNlcnZlclBlcm1hbmVudFBhcmFtcygpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9weWRpbyB8fCAhdGhpcy5fcHlkaW8uUGFyYW1ldGVycy5oYXMoJ1NFUlZFUl9QRVJNQU5FTlRfUEFSQU1TJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGVybVBhcmFtcyA9IHRoaXMuX3B5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUEVSTUFORU5UX1BBUkFNUycpO1xuICAgICAgICBmb3IgKHZhciBwZXJtYW5lbnQgaW4gcGVybVBhcmFtcykge1xuICAgICAgICAgICAgaWYgKHBlcm1QYXJhbXMuaGFzT3duUHJvcGVydHkocGVybWFuZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkUGFyYW1ldGVyKHBlcm1hbmVudCwgcGVybVBhcmFtc1twZXJtYW5lbnRdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGEgc21hbGwgbG9hZGVyXG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnNob3dMb2FkZXIgPSBmdW5jdGlvbiBzaG93TG9hZGVyKCkge1xuICAgICAgICBpZiAodGhpcy5kaXNjcmV0ZSB8fCAhdGhpcy5fcHlkaW8pIHJldHVybjtcbiAgICAgICAgdGhpcy5fcHlkaW8ubm90aWZ5KFwiY29ubmVjdGlvbi1zdGFydFwiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSGlkZSBhIHNtYWxsIGxvYWRlclxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5oaWRlTG9hZGVyID0gZnVuY3Rpb24gaGlkZUxvYWRlcigpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzY3JldGUgfHwgIXRoaXMuX3B5ZGlvKSByZXR1cm47XG4gICAgICAgIHRoaXMuX3B5ZGlvLm5vdGlmeShcImNvbm5lY3Rpb24tZW5kXCIpO1xuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLl9zZW5kID0gZnVuY3Rpb24gX3NlbmQoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGFTeW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICBDb25uZXhpb24ubG9nKHRoaXMuX3BhcmFtZXRlcnMuZ2V0KFwiZ2V0X2FjdGlvblwiKSwgYVN5bmMgPyAnYXN5bmMnIDogJ3N5bmMnKTtcbiAgICAgICAgdGhpcy5hZGRTZWN1cmVUb2tlbigpO1xuICAgICAgICB0aGlzLmFkZFNlcnZlclBlcm1hbmVudFBhcmFtcygpO1xuICAgICAgICB0aGlzLnNob3dMb2FkZXIoKTtcbiAgICAgICAgdmFyIG9UaGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBtZXRob2Q6IHRoaXMuX21ldGhvZCxcbiAgICAgICAgICAgIGNyZWRlbnRpYWxzOiAnc2FtZS1vcmlnaW4nXG4gICAgICAgIH07XG4gICAgICAgIHZhciB1cmwgPSB0aGlzLl9iYXNlVXJsO1xuICAgICAgICBpZiAoIWFTeW5jKSB7XG4gICAgICAgICAgICBvcHRpb25zLnN5bmNocm9ub3VzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYm9keVBhcnRzID0gW107XG4gICAgICAgIHRoaXMuX3BhcmFtZXRlcnMuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZS5tYXAoZnVuY3Rpb24gKG9uZVYpIHtcbiAgICAgICAgICAgICAgICAgICAgYm9keVBhcnRzLnB1c2goa2V5ICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KG9uZVYpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYm9keVBhcnRzLnB1c2goa2V5ICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgcXVlcnlTdHJpbmcgPSBib2R5UGFydHMuam9pbignJicpO1xuICAgICAgICBpZiAodGhpcy5fbWV0aG9kID09PSAncG9zdCcpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuaGVhZGVycyA9IHsgXCJDb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIiB9O1xuICAgICAgICAgICAgb3B0aW9ucy5ib2R5ID0gcXVlcnlTdHJpbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cmwgKz0gKHVybC5pbmRleE9mKCc/JykgPiAtMSA/ICcmJyA6ICc/JykgKyBxdWVyeVN0cmluZztcbiAgICAgICAgfVxuICAgICAgICB3aW5kb3cuZmV0Y2godXJsLCBvcHRpb25zKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXG4gICAgICAgICAgICB2YXIgaCA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdDb250ZW50LXR5cGUnKTtcbiAgICAgICAgICAgIGlmIChoLmluZGV4T2YoJy9qc29uJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuanNvbigpLnRoZW4oZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgICAgICAgICAgICAgb1RoaXMuYXBwbHlDb21wbGV0ZSh7IHJlc3BvbnNlSlNPTjoganNvbiB9LCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGguaW5kZXhPZignL3htbCcpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnRleHQoKS50aGVuKGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9UaGlzLmFwcGx5Q29tcGxldGUoeyByZXNwb25zZVhNTDogX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5wYXJzZVhtbCh0ZXh0KSB9LCByZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnRleHQoKS50aGVuKGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9UaGlzLmFwcGx5Q29tcGxldGUoeyByZXNwb25zZVRleHQ6IHRleHQgfSwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9KVsnY2F0Y2gnXShmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5fcHlkaW8pIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5fcHlkaW8uZGlzcGxheU1lc3NhZ2UoJ0VSUk9SJywgJ05ldHdvcmsgZXJyb3IgJyArIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VuZCBBc3luY2hyb25vdXNseVxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kQXN5bmMgPSBmdW5jdGlvbiBzZW5kQXN5bmMoKSB7XG4gICAgICAgIHRoaXMuX3NlbmQodHJ1ZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlbmQgc3luY2hyb25vdXNseVxuICAgICAqL1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kU3luYyA9IGZ1bmN0aW9uIHNlbmRTeW5jKCkge1xuICAgICAgICB0aGlzLl9zZW5kKGZhbHNlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQXBwbHkgdGhlIGNvbXBsZXRlIGNhbGxiYWNrLCB0cnkgdG8gZ3JhYiBtYXhpbXVtIG9mIGVycm9yc1xuICAgICAqIEBwYXJhbSBwYXJzZWRCb2R5IFRyYW5zcG90XG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmFwcGx5Q29tcGxldGUgPSBmdW5jdGlvbiBhcHBseUNvbXBsZXRlKHBhcnNlZEJvZHksIHJlc3BvbnNlKSB7XG4gICAgICAgIHRoaXMuaGlkZUxvYWRlcigpO1xuICAgICAgICB2YXIgcHlkaW8gPSB0aGlzLl9weWRpbztcbiAgICAgICAgdmFyIG1lc3NhZ2UgPSB1bmRlZmluZWQsXG4gICAgICAgICAgICB0b2tlbk1lc3NhZ2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciB0b2sxID0gXCJPb29wcywgaXQgc2VlbXMgdGhhdCB5b3VyIHNlY3VyaXR5IHRva2VuIGhhcyBleHBpcmVkISBQbGVhc2UgJXMgYnkgaGl0dGluZyByZWZyZXNoIG9yIEY1IGluIHlvdXIgYnJvd3NlciFcIjtcbiAgICAgICAgdmFyIHRvazIgPSBcInJlbG9hZCB0aGUgcGFnZVwiO1xuICAgICAgICBpZiAod2luZG93Lk1lc3NhZ2VIYXNoICYmIHdpbmRvdy5NZXNzYWdlSGFzaFs0MzddKSB7XG4gICAgICAgICAgICB0b2sxID0gd2luZG93Lk1lc3NhZ2VIYXNoWzQzN107XG4gICAgICAgICAgICB0b2syID0gd2luZG93Lk1lc3NhZ2VIYXNoWzQzOF07XG4gICAgICAgIH1cbiAgICAgICAgdG9rZW5NZXNzYWdlID0gdG9rMS5yZXBsYWNlKFwiJXNcIiwgXCI8YSBocmVmPSdqYXZhc2NyaXB0OmRvY3VtZW50LmxvY2F0aW9uLnJlbG9hZCgpJyBzdHlsZT0ndGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7Jz5cIiArIHRvazIgKyBcIjwvYT5cIik7XG5cbiAgICAgICAgdmFyIGN0eXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuICAgICAgICBpZiAocGFyc2VkQm9keS5yZXNwb25zZVhNTCAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudC5ub2RlTmFtZSA9PSBcInBhcnNlcmVycm9yXCIpIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiUGFyc2luZyBlcnJvciA6IFxcblwiICsgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZC50ZXh0Q29udGVudDtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJzZWRCb2R5LnJlc3BvbnNlWE1MICYmIHBhcnNlZEJvZHkucmVzcG9uc2VYTUwucGFyc2VFcnJvciAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLnBhcnNlRXJyb3IuZXJyb3JDb2RlICE9IDApIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiUGFyc2luZyBFcnJvciA6IFxcblwiICsgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5wYXJzZUVycm9yLnJlYXNvbjtcbiAgICAgICAgfSBlbHNlIGlmIChjdHlwZS5pbmRleE9mKFwidGV4dC94bWxcIikgPiAtMSAmJiBwYXJzZWRCb2R5LnJlc3BvbnNlWE1MID09IG51bGwpIHtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IFwiRXhwZWN0ZWQgWE1MIGJ1dCBnb3QgZW1wdHkgcmVzcG9uc2UhXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoY3R5cGUuaW5kZXhPZihcInRleHQveG1sXCIpID09IC0xICYmIGN0eXBlLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpID09IC0xICYmIHBhcnNlZEJvZHkucmVzcG9uc2VUZXh0LmluZGV4T2YoXCI8Yj5GYXRhbCBlcnJvcjwvYj5cIikgPiAtMSkge1xuXG4gICAgICAgICAgICBtZXNzYWdlID0gcGFyc2VkQm9keS5yZXNwb25zZVRleHQucmVwbGFjZShcIjxiciAvPlwiLCBcIlwiKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT0gNTAwKSB7XG5cbiAgICAgICAgICAgIG1lc3NhZ2UgPSBcIkludGVybmFsIFNlcnZlciBFcnJvcjogeW91IHNob3VsZCBjaGVjayB5b3VyIHdlYiBzZXJ2ZXIgbG9ncyB0byBmaW5kIHdoYXQncyBnb2luZyB3cm9uZyFcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVzc2FnZSkge1xuXG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zdGFydHNXaXRoKFwiWW91IGFyZSBub3QgYWxsb3dlZCB0byBhY2Nlc3MgdGhpcyByZXNvdXJjZS5cIikpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gdG9rZW5NZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHB5ZGlvKSB7XG4gICAgICAgICAgICAgICAgcHlkaW8uZGlzcGxheU1lc3NhZ2UoXCJFUlJPUlwiLCBtZXNzYWdlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxlcnQobWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnNlZEJvZHkucmVzcG9uc2VYTUwgJiYgcGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQpIHtcblxuICAgICAgICAgICAgdmFyIGF1dGhOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocGFyc2VkQm9keS5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQsIFwicmVxdWlyZV9hdXRoXCIpO1xuICAgICAgICAgICAgaWYgKGF1dGhOb2RlICYmIHB5ZGlvKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSBweWRpby5nZXRDb250ZXh0SG9sZGVyKCkuZ2V0Um9vdE5vZGUoKTtcbiAgICAgICAgICAgICAgICBpZiAocm9vdCkge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5nZXRDb250ZXh0SG9sZGVyKCkuc2V0Q29udGV4dE5vZGUocm9vdCk7XG4gICAgICAgICAgICAgICAgICAgIHJvb3QuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHlkaW8uZ2V0Q29udHJvbGxlcigpLmZpcmVBY3Rpb24oJ2xvZ291dCcpO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5nZXRDb250cm9sbGVyKCkuZmlyZUFjdGlvbignbG9naW4nKTtcbiAgICAgICAgICAgICAgICB9LCAzNTApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbWVzc2FnZU5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShwYXJzZWRCb2R5LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCwgXCJtZXNzYWdlXCIpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2VOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VUeXBlID0gbWVzc2FnZU5vZGUuZ2V0QXR0cmlidXRlKFwidHlwZVwiKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlQ29udGVudCA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uZ2V0RG9tTm9kZVRleHQobWVzc2FnZU5vZGUpO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlQ29udGVudC5zdGFydHNXaXRoKFwiWW91IGFyZSBub3QgYWxsb3dlZCB0byBhY2Nlc3MgdGhpcyByZXNvdXJjZS5cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUNvbnRlbnQgPSB0b2tlbk1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChweWRpbykge1xuICAgICAgICAgICAgICAgICAgICBweWRpby5kaXNwbGF5TWVzc2FnZShtZXNzYWdlVHlwZSwgbWVzc2FnZUNvbnRlbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlVHlwZSA9PSBcIkVSUk9SXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KG1lc3NhZ2VUeXBlICsgXCI6XCIgKyBtZXNzYWdlQ29udGVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VUeXBlID09IFwiU1VDQ0VTU1wiKSBtZXNzYWdlTm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG1lc3NhZ2VOb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5vbkNvbXBsZXRlKSB7XG5cbiAgICAgICAgICAgIHBhcnNlZEJvZHkuc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzO1xuICAgICAgICAgICAgcGFyc2VkQm9keS5yZXNwb25zZU9iamVjdCA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgdGhpcy5vbkNvbXBsZXRlKHBhcnNlZEJvZHkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChweWRpbykge1xuICAgICAgICAgICAgcHlkaW8uZmlyZShcInNlcnZlcl9hbnN3ZXJcIiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS51cGxvYWRGaWxlID0gZnVuY3Rpb24gdXBsb2FkRmlsZShmaWxlLCBmaWxlUGFyYW1ldGVyTmFtZSwgdXBsb2FkVXJsLCBvbkNvbXBsZXRlLCBvbkVycm9yLCBvblByb2dyZXNzLCB4aHJTZXR0aW5ncykge1xuXG4gICAgICAgIGlmICh4aHJTZXR0aW5ncyA9PT0gdW5kZWZpbmVkKSB4aHJTZXR0aW5ncyA9IHt9O1xuXG4gICAgICAgIGlmICghb25Db21wbGV0ZSkgb25Db21wbGV0ZSA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICBpZiAoIW9uRXJyb3IpIG9uRXJyb3IgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgaWYgKCFvblByb2dyZXNzKSBvblByb2dyZXNzID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgIHZhciB4aHIgPSB0aGlzLmluaXRpYWxpemVYSFJGb3JVcGxvYWQodXBsb2FkVXJsLCBvbkNvbXBsZXRlLCBvbkVycm9yLCBvblByb2dyZXNzLCB4aHJTZXR0aW5ncyk7XG4gICAgICAgIGlmICh3aW5kb3cuRm9ybURhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZEZpbGVVc2luZ0Zvcm1EYXRhKHhociwgZmlsZSwgZmlsZVBhcmFtZXRlck5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHdpbmRvdy5GaWxlUmVhZGVyKSB7XG4gICAgICAgICAgICB2YXIgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMueGhyU2VuZEFzQmluYXJ5KHhociwgZmlsZS5uYW1lLCBlLnRhcmdldC5yZXN1bHQsIGZpbGVQYXJhbWV0ZXJOYW1lKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgICAgICBmaWxlUmVhZGVyLnJlYWRBc0JpbmFyeVN0cmluZyhmaWxlKTtcbiAgICAgICAgfSBlbHNlIGlmIChmaWxlLmdldEFzQmluYXJ5KSB7XG4gICAgICAgICAgICB0aGlzLnhoclNlbmRBc0JpbmFyeSh4aHIsIGZpbGUubmFtZSwgZmlsZS5nZXRBc0JpbmFyeSgpLCBmaWxlUGFyYW1ldGVyTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5pbml0aWFsaXplWEhSRm9yVXBsb2FkID0gZnVuY3Rpb24gaW5pdGlhbGl6ZVhIUkZvclVwbG9hZCh1cmwsIG9uQ29tcGxldGUsIG9uRXJyb3IsIG9uUHJvZ3Jlc3MsIHhoclNldHRpbmdzKSB7XG5cbiAgICAgICAgaWYgKHhoclNldHRpbmdzID09PSB1bmRlZmluZWQpIHhoclNldHRpbmdzID0ge307XG5cbiAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICB2YXIgdXBsb2FkID0geGhyLnVwbG9hZDtcbiAgICAgICAgaWYgKHhoclNldHRpbmdzLndpdGhDcmVkZW50aWFscykge1xuICAgICAgICAgICAgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdXBsb2FkLmFkZEV2ZW50TGlzdGVuZXIoXCJwcm9ncmVzc1wiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgaWYgKCFlLmxlbmd0aENvbXB1dGFibGUpIHJldHVybjtcbiAgICAgICAgICAgIG9uUHJvZ3Jlc3MoZSk7XG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPT0gNCkge1xuICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgb25Db21wbGV0ZSh4aHIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9uRXJyb3IoeGhyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIHVwbG9hZC5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb25FcnJvcih4aHIpO1xuICAgICAgICB9O1xuICAgICAgICB4aHIub3BlbihcIlBPU1RcIiwgdXJsLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuXG4gICAgQ29ubmV4aW9uLnByb3RvdHlwZS5zZW5kRmlsZVVzaW5nRm9ybURhdGEgPSBmdW5jdGlvbiBzZW5kRmlsZVVzaW5nRm9ybURhdGEoeGhyLCBmaWxlLCBmaWxlUGFyYW1ldGVyTmFtZSkge1xuICAgICAgICB2YXIgZm9ybURhdGEgPSBuZXcgRm9ybURhdGEoKTtcbiAgICAgICAgZm9ybURhdGEuYXBwZW5kKGZpbGVQYXJhbWV0ZXJOYW1lLCBmaWxlKTtcbiAgICAgICAgeGhyLnNlbmQoZm9ybURhdGEpO1xuICAgIH07XG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLnhoclNlbmRBc0JpbmFyeSA9IGZ1bmN0aW9uIHhoclNlbmRBc0JpbmFyeSh4aHIsIGZpbGVOYW1lLCBmaWxlRGF0YSwgZmlsZVBhcmFtZXRlck5hbWUpIHtcbiAgICAgICAgdmFyIGJvdW5kYXJ5ID0gJy0tLS1NdWx0aVBhcnRGb3JtQm91bmRhcnknICsgbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKFwiQ29udGVudC1UeXBlXCIsIFwibXVsdGlwYXJ0L2Zvcm0tZGF0YSwgYm91bmRhcnk9XCIgKyBib3VuZGFyeSk7XG5cbiAgICAgICAgdmFyIGJvZHkgPSBcIi0tXCIgKyBib3VuZGFyeSArIFwiXFxyXFxuXCI7XG4gICAgICAgIGJvZHkgKz0gXCJDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9J1wiICsgZmlsZVBhcmFtZXRlck5hbWUgKyBcIic7IGZpbGVuYW1lPSdcIiArIHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChmaWxlTmFtZSkpICsgXCInXFxyXFxuXCI7XG4gICAgICAgIGJvZHkgKz0gXCJDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVxcclxcblxcclxcblwiO1xuICAgICAgICBib2R5ICs9IGZpbGVEYXRhICsgXCJcXHJcXG5cIjtcbiAgICAgICAgYm9keSArPSBcIi0tXCIgKyBib3VuZGFyeSArIFwiLS1cXHJcXG5cIjtcblxuICAgICAgICB4aHIuc2VuZEFzQmluYXJ5KGJvZHkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgamF2YXNjcmlwdCBsaWJyYXJ5XG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBvbkxvYWRlZENvZGUgRnVuY3Rpb24gQ2FsbGJhY2tcbiAgICAgICAgKiBAcGFyYW0gYVN5bmMgQm9vbGVhbiBsb2FkIGxpYnJhcnkgYXN5bmNocm9uZW91c2x5XG4gICAgICovXG5cbiAgICBDb25uZXhpb24ucHJvdG90eXBlLmxvYWRMaWJyYXJ5ID0gZnVuY3Rpb24gbG9hZExpYnJhcnkoZmlsZU5hbWUsIG9uTG9hZGVkQ29kZSwgYVN5bmMpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHdpbmRvdy5weWRpb0Jvb3RzdHJhcCAmJiB3aW5kb3cucHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJhanhwVmVyc2lvblwiKSAmJiBmaWxlTmFtZS5pbmRleE9mKFwiP1wiKSA9PSAtMSkge1xuICAgICAgICAgICAgZmlsZU5hbWUgKz0gXCI/dj1cIiArIHdpbmRvdy5weWRpb0Jvb3RzdHJhcC5wYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1cmwgPSB0aGlzLl9saWJVcmwgPyB0aGlzLl9saWJVcmwgKyAnLycgKyBmaWxlTmFtZSA6IGZpbGVOYW1lO1xuICAgICAgICB2YXIgcHlkaW8gPSB0aGlzLl9weWRpbztcblxuICAgICAgICB2YXIgc2NyaXB0TG9hZGVkID0gZnVuY3Rpb24gc2NyaXB0TG9hZGVkKHNjcmlwdCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAod2luZG93LmV4ZWNTY3JpcHQpIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmV4ZWNTY3JpcHQoc2NyaXB0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubXlfY29kZSA9IHNjcmlwdDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2NyaXB0X3RhZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHRfdGFnLnR5cGUgPSAndGV4dC9qYXZhc2NyaXB0JztcbiAgICAgICAgICAgICAgICAgICAgc2NyaXB0X3RhZy5pbm5lckhUTUwgPSAnZXZhbCh3aW5kb3cubXlfY29kZSknO1xuICAgICAgICAgICAgICAgICAgICBoZWFkLmFwcGVuZENoaWxkKHNjcmlwdF90YWcpO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgd2luZG93Lm15X2NvZGU7XG4gICAgICAgICAgICAgICAgICAgIGhlYWQucmVtb3ZlQ2hpbGQoc2NyaXB0X3RhZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvbkxvYWRlZENvZGUgIT0gbnVsbCkgb25Mb2FkZWRDb2RlKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgYWxlcnQoJ2Vycm9yIGxvYWRpbmcgJyArIGZpbGVOYW1lICsgJzonICsgZS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBpZiAoY29uc29sZSkgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChweWRpbykgcHlkaW8uZmlyZShcInNlcnZlcl9hbnN3ZXJcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGFTeW5jKSB7XG4gICAgICAgICAgICB3aW5kb3cuZmV0Y2godXJsLCB7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICAgICAgICBjcmVkZW50aWFsczogJ3NhbWUtb3JpZ2luJ1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoc2NyaXB0KSB7XG4gICAgICAgICAgICAgICAgc2NyaXB0TG9hZGVkKHNjcmlwdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gU0hPVUxEIEJFIFJFTU9WRUQhIVxuICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHRMb2FkZWQoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KCdlcnJvciBsb2FkaW5nICcgKyBmaWxlTmFtZSArICc6IFN0YXR1cyBjb2RlIHdhcyAnICsgeGhyLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKF90aGlzMik7XG4gICAgICAgICAgICAgICAgeGhyLm9wZW4oXCJHRVRcIiwgdXJsLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgeGhyLnNlbmQoKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIENvbm5leGlvbjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvbm5leGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG4vKipcbiAqIEFQSSBDbGllbnRcbiAqL1xuXG52YXIgTWV0YUNhY2hlU2VydmljZSA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoTWV0YUNhY2hlU2VydmljZSwgX09ic2VydmFibGUpO1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5nZXRJbnN0YW5jZSA9IGZ1bmN0aW9uIGdldEluc3RhbmNlKCkge1xuICAgICAgICBpZiAoIU1ldGFDYWNoZVNlcnZpY2UuSU5TVEFOQ0UpIHtcbiAgICAgICAgICAgIE1ldGFDYWNoZVNlcnZpY2UuSU5TVEFOQ0UgPSBuZXcgTWV0YUNhY2hlU2VydmljZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNZXRhQ2FjaGVTZXJ2aWNlLklOU1RBTkNFO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBNZXRhQ2FjaGVTZXJ2aWNlKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTWV0YUNhY2hlU2VydmljZSk7XG5cbiAgICAgICAgX09ic2VydmFibGUuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5fc3RyZWFtcyA9IG5ldyBNYXAoKTtcbiAgICB9XG5cbiAgICBNZXRhQ2FjaGVTZXJ2aWNlLnByb3RvdHlwZS5oYXNLZXkgPSBmdW5jdGlvbiBoYXNLZXkoc3RyZWFtTmFtZSwga2V5TmFtZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLmdldCgnZGF0YScpLmhhcyhrZXlOYW1lKTtcbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuZ2V0QnlLZXkgPSBmdW5jdGlvbiBnZXRCeUtleShzdHJlYW1OYW1lLCBrZXlOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKS5nZXQoa2V5TmFtZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLmRlbGV0ZUtleSA9IGZ1bmN0aW9uIGRlbGV0ZUtleShzdHJlYW1OYW1lLCBrZXlOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zdHJlYW1zLmdldChzdHJlYW1OYW1lKS5nZXQoJ2RhdGEnKVsnZGVsZXRlJ10oa2V5TmFtZSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLnNldEtleSA9IGZ1bmN0aW9uIHNldEtleShzdHJlYW1OYW1lLCBrZXlOYW1lLCB2YWx1ZSkge1xuICAgICAgICBpZiAoIXRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignU3RyZWFtICcgKyBzdHJlYW1OYW1lICsgJyBub3QgcmVnaXN0ZXJlZCwgcGxlYXNlIHJlZ2lzdGVyIGZpcnN0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSkuZ2V0KCdkYXRhJykuc2V0KGtleU5hbWUsIHZhbHVlKTtcbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuY2xlYXJNZXRhU3RyZWFtS2V5cyA9IGZ1bmN0aW9uIGNsZWFyTWV0YVN0cmVhbUtleXMoc3RyZWFtTmFtZSkge1xuICAgICAgICBpZiAodGhpcy5fc3RyZWFtcy5oYXMoc3RyZWFtTmFtZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLnNldCgnZGF0YScsIG5ldyBNYXAoKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJNZXRhU3RyZWFtID0gZnVuY3Rpb24gcmVnaXN0ZXJNZXRhU3RyZWFtKHN0cmVhbU5hbWUsIGV4cGlyYXRpb25Qb2xpY3kpIHtcbiAgICAgICAgaWYgKHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgIGRhdGEuc2V0KCdleHBpcmF0aW9uUG9saWN5JywgZXhwaXJhdGlvblBvbGljeSk7XG4gICAgICAgIGRhdGEuc2V0KCdkYXRhJywgbmV3IE1hcCgpKTtcbiAgICAgICAgdGhpcy5fc3RyZWFtcy5zZXQoc3RyZWFtTmFtZSwgZGF0YSk7XG4gICAgICAgIHB5ZGlvLm9ic2VydmUoXCJyZXBvc2l0b3J5X2xpc3RfcmVmcmVzaGVkXCIsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBBbHdheXMga2VlcCB0aGUgY2FjaGUgYXQgd29ya3NwYWNlIHNjb3BlXG4gICAgICAgICAgICB0aGlzLl9zdHJlYW1zWydkZWxldGUnXShzdHJlYW1OYW1lKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIE1ldGFDYWNoZVNlcnZpY2UucHJvdG90eXBlLm1ldGFGb3JOb2RlID0gZnVuY3Rpb24gbWV0YUZvck5vZGUoc3RyZWFtTmFtZSwgYWp4cE5vZGUsIGxvYWRlckNhbGxiYWNrLCByZW1vdGVQYXJzZXIsIGNhY2hlTG9hZGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmhhcyhzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBtZXRhIHN0cmVhbSAnICsgc3RyZWFtTmFtZSArICcsIHBsZWFzZSByZWdpc3RlciBpdCBiZWZvcmUgdXNpbmcgaXQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGVmID0gdGhpcy5fc3RyZWFtcy5nZXQoc3RyZWFtTmFtZSk7XG4gICAgICAgIHZhciBrZXkgPSBhanhwTm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIHZhciBleHBpcmF0aW9uUG9saWN5ID0gZGVmLmdldCgnZXhwaXJhdGlvblBvbGljeScpO1xuICAgICAgICBpZiAoZGVmLmdldCgnZGF0YScpLmhhcyhrZXkpKSB7XG4gICAgICAgICAgICBjYWNoZUxvYWRlcihkZWYuZ2V0KCdkYXRhJykuZ2V0KGtleSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2xlYXJWYWx1ZU9ic2VydmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVmLmdldCgnZGF0YScpWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2FjaGUgcmVzcG9uc2UgaWYgc3VjY2Vzc1xuICAgICAgICAgICAgICAgIHZhciBjYWNoZUNhbGxiYWNrID0gZnVuY3Rpb24gY2FjaGVDYWxsYmFjayh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0RhdGEgPSByZW1vdGVQYXJzZXIodHJhbnNwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0RhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYWNoZWREYXRhID0gbmV3RGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXdEYXRhIGluc3RhbmNlb2YgQWp4cE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWREYXRhID0gbmV3IEFqeHBOb2RlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGVkRGF0YS5yZXBsYWNlQnkobmV3RGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWYuZ2V0KCdkYXRhJykuc2V0KGtleSwgY2FjaGVkRGF0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXhwaXJhdGlvblBvbGljeSA9PSBNZXRhQ2FjaGVTZXJ2aWNlLkVYUElSQVRJT05fTE9DQUxfTk9ERSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFqeHBOb2RlLm9ic2VydmVPbmNlKFwibm9kZV9yZW1vdmVkXCIsIGNsZWFyVmFsdWVPYnNlcnZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWp4cE5vZGUub2JzZXJ2ZU9uY2UoXCJub2RlX3JlcGxhY2VkXCIsIGNsZWFyVmFsdWVPYnNlcnZlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGxvYWRlckNhbGxiYWNrKGFqeHBOb2RlLCBjYWNoZUNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgTWV0YUNhY2hlU2VydmljZS5wcm90b3R5cGUuaW52YWxpZGF0ZU1ldGFGb3JLZXlzID0gZnVuY3Rpb24gaW52YWxpZGF0ZU1ldGFGb3JLZXlzKHN0cmVhbU5hbWUsIGtleVBhdHRlcm4pIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zdHJlYW1zLmhhcyhzdHJlYW1OYW1lKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBtZXRhIHN0cmVhbSAnICsgc3RyZWFtTmFtZSArICcsIHBsZWFzZSByZWdpc3RlciBpdCBiZWZvcmUgdXNpbmcgaXQnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX3N0cmVhbXMuZ2V0KHN0cmVhbU5hbWUpLmdldCgnZGF0YScpO1xuICAgICAgICBkYXRhLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIGlmIChrZXkubWF0Y2goa2V5UGF0dGVybikpIHtcbiAgICAgICAgICAgICAgICBkYXRhWydkZWxldGUnXShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIE1ldGFDYWNoZVNlcnZpY2U7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5NZXRhQ2FjaGVTZXJ2aWNlLkVYUElSQVRJT05fTE9DQUxfTk9ERSA9ICdMT0NBTF9OT0RFJztcbk1ldGFDYWNoZVNlcnZpY2UuRVhQSVJBVElPTl9NQU5VQUxfVFJJR0dFUiA9ICdNQU5VQUxfVFJJR0dFUic7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IE1ldGFDYWNoZVNlcnZpY2U7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIFN5c3RlbUpTID0gcmVxdWlyZSgnc3lzdGVtanMnKTtcblxuLyoqXG4gKiBBIG1hbmFnZXIgdGhhdCBjYW4gaGFuZGxlIHRoZSBsb2FkaW5nIG9mIEpTLCBDU1MgYW5kIGNoZWNrcyBkZXBlbmRlbmNpZXNcbiAqL1xuXG52YXIgUmVzb3VyY2VzTWFuYWdlciA9IChmdW5jdGlvbiAoKSB7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvclxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gUmVzb3VyY2VzTWFuYWdlcigpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlc291cmNlc01hbmFnZXIpO1xuXG4gICAgICAgIHRoaXMubWFpbkZvcm1Db250YWluZXJJZCA9ICdhbGxfZm9ybXMnO1xuICAgICAgICB0aGlzLnJlc291cmNlcyA9IHt9O1xuICAgICAgICB0aGlzLmxvYWRlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBKYXZhc2NyaXB0IHJlc291cmNlXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqIEBwYXJhbSBjbGFzc05hbWUgU3RyaW5nXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGRKU1Jlc291cmNlID0gZnVuY3Rpb24gYWRkSlNSZXNvdXJjZShmaWxlTmFtZSwgY2xhc3NOYW1lKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuanMpIHtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmpzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNvdXJjZXMuanMucHVzaCh7XG4gICAgICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSxcbiAgICAgICAgICAgIGF1dG9sb2FkOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIENTUyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmFkZENTU1Jlc291cmNlID0gZnVuY3Rpb24gYWRkQ1NTUmVzb3VyY2UoZmlsZU5hbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlc291cmNlcy5jc3MpIHtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmNzcyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzb3VyY2VzLmNzcy5wdXNoKGZpbGVOYW1lKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIEZPUk0gZnJvbSBodG1sIHNuaXBwZXJcbiAgICAgKiBAcGFyYW0gZm9ybUlkIFN0cmluZ1xuICAgICAqIEBwYXJhbSBodG1sU25pcHBldCBTdHJpbmdcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmFkZEd1aUZvcm0gPSBmdW5jdGlvbiBhZGRHdWlGb3JtKGZvcm1JZCwgaHRtbFNuaXBwZXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlc291cmNlcy5mb3Jtcykge1xuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9ybXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9ybXMuc2V0KGZvcm1JZCwgaHRtbFNuaXBwZXQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBkZXBlbmRlbmN5IHRvIGFub3RoZXIgcGx1Z2luXG4gICAgICogQHBhcmFtIGRhdGEgT2JqZWN0XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5hZGREZXBlbmRlbmN5ID0gZnVuY3Rpb24gYWRkRGVwZW5kZW5jeShkYXRhKSB7XG4gICAgICAgIGlmICghdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMucHVzaChkYXRhKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgc29tZSBkZXBlbmRlbmNpZXMgbXVzdCBiZSBsb2FkZWQgYmVmb3JlXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUuaGFzRGVwZW5kZW5jaWVzID0gZnVuY3Rpb24gaGFzRGVwZW5kZW5jaWVzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXNvdXJjZXMuZGVwZW5kZW5jaWVzIHx8IGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIHJlc291cmNlc1xuICAgICAqIEBwYXJhbSByZXNvdXJjZXNSZWdpc3RyeSBQeWRpbyByZXNvdXJjZXMgcmVnaXN0cnlcbiAgICAgKi9cblxuICAgIFJlc291cmNlc01hbmFnZXIucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiBsb2FkKHJlc291cmNlc1JlZ2lzdHJ5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgdmFyIGpzQXV0b2xvYWRPbmx5ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IEZ1bmNVdGlscy5FbXB0eSA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICBpZiAodGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaGFzRGVwZW5kZW5jaWVzKCkgJiYgIXRoaXMuZGVwZW5kZW5jaWVzTG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5kZXBlbmRlbmNpZXMuZm9yRWFjaCgoZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc291cmNlc1JlZ2lzdHJ5W2VsXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBMb2FkIGRlcGVuZGVuY2llcyBhbmQgdHJ5IGFnYWluXG4gICAgICAgICAgICAgICAgICAgIHJlc291cmNlc1JlZ2lzdHJ5W2VsXS5sb2FkKHJlc291cmNlc1JlZ2lzdHJ5LCBmYWxzZSwgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZChyZXNvdXJjZXNSZWdpc3RyeSwgZmFsc2UsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucmVzb3VyY2VzLmZvcm1zKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5mb3Jtcy5mb3JFYWNoKChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgICAgIC8vIFJFTU9WRURcbiAgICAgICAgICAgICAgICAvL3RoaXMubG9hZEd1aUZvcm0oa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNvdXJjZXMuanMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGl0ID0gX3RoaXMucmVzb3VyY2VzLmpzLnZhbHVlcygpO1xuICAgICAgICAgICAgICAgIHZhciBjYiA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSBpdC5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3QudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChqc0F1dG9sb2FkT25seSAmJiAhb2JqZWN0LnZhbHVlLmF1dG9sb2FkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRKU1Jlc291cmNlKG9iamVjdC52YWx1ZS5maWxlTmFtZSwgb2JqZWN0LnZhbHVlLmNsYXNzTmFtZSwgY2IsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpO1xuICAgICAgICAgICAgICAgIGNiKCk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNvdXJjZXMuY3NzKSB7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlcy5jc3MuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkQ1NTUmVzb3VyY2UodmFsdWUpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIGphdmFzY3JpcHQgZmlsZVxuICAgICAqIEBwYXJhbSBmaWxlTmFtZSBTdHJpbmdcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIFN0cmluZ1xuICAgICAgICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvblxuICAgICAgICAqIEBwYXJhbSBhU3luYyBCb29sZWFuXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5sb2FkSlNSZXNvdXJjZSA9IGZ1bmN0aW9uIGxvYWRKU1Jlc291cmNlKGZpbGVOYW1lLCBjbGFzc05hbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBhU3luYyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgaWYgKCFSZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCkge1xuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgfVxuICAgICAgICBTeXN0ZW1KU1snaW1wb3J0J10oY2xhc3NOYW1lKS50aGVuKGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIENTUyBmaWxlXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZ1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5wcm90b3R5cGUubG9hZENTU1Jlc291cmNlID0gZnVuY3Rpb24gbG9hZENTU1Jlc291cmNlKGZpbGVOYW1lKSB7XG5cbiAgICAgICAgaWYgKHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpKSB7XG4gICAgICAgICAgICBmaWxlTmFtZSA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdTRVJWRVJfUFJFRklYX1VSSScpICsgZmlsZU5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgZmlsZU5hbWUgPSBmaWxlTmFtZSArIFwiP3Y9XCIgKyBweWRpby5QYXJhbWV0ZXJzLmdldChcImFqeHBWZXJzaW9uXCIpO1xuXG4gICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICB2YXIgbGlua3MgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbGluaycpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGluayA9IGxpbmtzW2ldO1xuICAgICAgICAgICAgaWYgKGxpbmsucmVsID09PSAnc3R5bGVzaGVldCcgJiYgbGluay5ocmVmLmVuZHNXaXRoKGZpbGVOYW1lKSkge1xuICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTticmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgICB2YXIgaGVhZCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJylbMF07XG4gICAgICAgICAgICB2YXIgY3NzTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTtcbiAgICAgICAgICAgIGNzc05vZGUudHlwZSA9ICd0ZXh0L2Nzcyc7XG4gICAgICAgICAgICBjc3NOb2RlLnJlbCA9ICdzdHlsZXNoZWV0JztcbiAgICAgICAgICAgIGNzc05vZGUuaHJlZiA9IGZpbGVOYW1lO1xuICAgICAgICAgICAgY3NzTm9kZS5tZWRpYSA9ICdzY3JlZW4nO1xuICAgICAgICAgICAgaGVhZC5hcHBlbmRDaGlsZChjc3NOb2RlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIHRoZSByZXNvdXJjZXMgZnJvbSBYTUxcbiAgICAgKiBAcGFyYW0gbm9kZSBYTUxOb2RlXG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLnByb3RvdHlwZS5sb2FkRnJvbVhtbE5vZGUgPSBmdW5jdGlvbiBsb2FkRnJvbVhtbE5vZGUobm9kZSkge1xuICAgICAgICB2YXIgY2xGb3JtID0ge30sXG4gICAgICAgICAgICBrID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAobm9kZS5ub2RlTmFtZSA9PSBcInJlc291cmNlc1wiKSB7XG4gICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuY2hpbGROb2Rlc1trXS5ub2RlTmFtZSA9PSAnanMnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkSlNSZXNvdXJjZShSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrKG5vZGUuY2hpbGROb2Rlc1trXSksIG5vZGUuY2hpbGROb2Rlc1trXS5nZXRBdHRyaWJ1dGUoJ2NsYXNzTmFtZScpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1trXS5ub2RlTmFtZSA9PSAnY3NzJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENTU1Jlc291cmNlKFJlc291cmNlc01hbmFnZXIuZ2V0RmlsZU9yRmFsbGJhY2sobm9kZS5jaGlsZE5vZGVzW2tdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJkZXBlbmRlbmNpZXNcIikge1xuICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmNoaWxkTm9kZXNba10ubm9kZU5hbWUgPT0gXCJwbHVnaW5SZXNvdXJjZXNcIikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZERlcGVuZGVuY3kobm9kZS5jaGlsZE5vZGVzW2tdLmdldEF0dHJpYnV0ZShcInBsdWdpbk5hbWVcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwiY2xpZW50Rm9ybVwiKSB7XG4gICAgICAgICAgICBpZiAoIW5vZGUuZ2V0QXR0cmlidXRlKFwidGhlbWVcIikgfHwgbm9kZS5nZXRBdHRyaWJ1dGUoXCJ0aGVtZVwiKSA9PSBweWRpby5QYXJhbWV0ZXJzLmdldChcInRoZW1lXCIpKSB7XG4gICAgICAgICAgICAgICAgY2xGb3JtID0geyBmb3JtSWQ6IG5vZGUuZ2V0QXR0cmlidXRlKFwiaWRcIiksIGZvcm1Db2RlOiBub2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNsRm9ybS5mb3JtSWQpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkR3VpRm9ybShjbEZvcm0uZm9ybUlkLCBjbEZvcm0uZm9ybUNvZGUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGFsaWFzTmFtZVxuICAgICAqIEBwYXJhbSBhbGlhc1BhdGhcbiAgICAgKiBAdG9kbyBNT1ZFIE9VVFNJREU/XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmFkZEltYWdlTGlicmFyeSA9IGZ1bmN0aW9uIGFkZEltYWdlTGlicmFyeShhbGlhc05hbWUsIGFsaWFzUGF0aCkge1xuICAgICAgICBpZiAoIXdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMpIHdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMgPSB7fTtcbiAgICAgICAgd2luZG93LkFqeHBJbWFnZUxpYnJhcmllc1thbGlhc05hbWVdID0gYWxpYXNQYXRoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBkZWZhdWx0IGltYWdlcyBwYXRoXG4gICAgICogQHBhcmFtIHNyYyBJY29uIHNvdXJjZVxuICAgICAqIEBwYXJhbSBkZWZhdWx0UGF0aCBEZWZhdWx0IHBhdGgsIGNhbiBjb250YWluIElDT05fU0laRVxuICAgICAqIEBwYXJhbSBzaXplIEludGVnZXIgc2l6ZSBvcHRpb25hbFxuICAgICAqIEByZXR1cm5zIHN0cmluZ1xuICAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5yZXNvbHZlSW1hZ2VTb3VyY2UgPSBmdW5jdGlvbiByZXNvbHZlSW1hZ2VTb3VyY2Uoc3JjLCBkZWZhdWx0UGF0aCwgc2l6ZSkge1xuICAgICAgICBpZiAoIXNyYykgcmV0dXJuIFwiXCI7XG4gICAgICAgIHZhciBpbWFnZXNGb2xkZXIgPSBhanhwUmVzb3VyY2VzRm9sZGVyICsgJy9pbWFnZXMnO1xuICAgICAgICBpZiAocHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoJ2FqeHBJbWFnZXNDb21tb24nKSkge1xuICAgICAgICAgICAgaW1hZ2VzRm9sZGVyID0gaW1hZ2VzRm9sZGVyLnJlcGxhY2UoJy8nICsgcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoJ3RoZW1lJykgKyAnLycsICcvY29tbW9uLycpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlZmF1bHRQYXRoICYmIGRlZmF1bHRQYXRoWzBdICE9PSAnLycpIHtcbiAgICAgICAgICAgIGRlZmF1bHRQYXRoID0gJy8nICsgZGVmYXVsdFBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXMgfHwgc3JjLmluZGV4T2YoXCIvXCIpID09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gaW1hZ2VzRm9sZGVyICsgKGRlZmF1bHRQYXRoID8gc2l6ZSA/IGRlZmF1bHRQYXRoLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBkZWZhdWx0UGF0aCA6ICcnKSArICcvJyArIHNyYztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmFkaWMgPSBzcmMuc3Vic3RyaW5nKDAsIHNyYy5pbmRleE9mKFwiL1wiKSk7XG4gICAgICAgIGlmICh3aW5kb3cuQWp4cEltYWdlTGlicmFyaWVzW3JhZGljXSkge1xuICAgICAgICAgICAgc3JjID0gc3JjLnJlcGxhY2UocmFkaWMsIHdpbmRvdy5BanhwSW1hZ2VMaWJyYXJpZXNbcmFkaWNdKTtcbiAgICAgICAgICAgIGlmIChweWRpb0Jvb3RzdHJhcC5wYXJhbWV0ZXJzLmdldChcIlNFUlZFUl9QUkVGSVhfVVJJXCIpKSB7XG4gICAgICAgICAgICAgICAgc3JjID0gcHlkaW9Cb290c3RyYXAucGFyYW1ldGVycy5nZXQoXCJTRVJWRVJfUFJFRklYX1VSSVwiKSArIHNyYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaXplID8gc3JjLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBzcmM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaW1hZ2VzRm9sZGVyICsgKGRlZmF1bHRQYXRoID8gc2l6ZSA/IGRlZmF1bHRQYXRoLnJlcGxhY2UoXCJJQ09OX1NJWkVcIiwgc2l6ZSkgOiBkZWZhdWx0UGF0aCA6ICcnKSArICcvJyArIHNyYztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAqIENoZWNrIGlmIHJlc291cmNlcyBhcmUgdGFnZ2VkIGF1dG9sb2FkIGFuZCBsb2FkIHRoZW1cbiAgICAqIEBwYXJhbSByZWdpc3RyeSBET01Eb2N1bWVudCBYTUwgUmVnaXN0cnlcbiAgICAqL1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQXV0b0xvYWRSZXNvdXJjZXMgPSBmdW5jdGlvbiBsb2FkQXV0b0xvYWRSZXNvdXJjZXMoKSB7XG4gICAgICAgIHZhciByZWdpc3RyeSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgaWYgKCFyZWdpc3RyeSkge1xuICAgICAgICAgICAgcmVnaXN0cnkgPSB3aW5kb3cucHlkaW8uUmVnaXN0cnkuZ2V0WE1MKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hbmFnZXIgPSBuZXcgUmVzb3VyY2VzTWFuYWdlcigpO1xuICAgICAgICB2YXIganNOb2RlcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2RlcyhyZWdpc3RyeSwgJ3BsdWdpbnMvKi9jbGllbnRfc2V0dGluZ3MvcmVzb3VyY2VzL2pzJyk7XG4gICAgICAgIHZhciBub2RlID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIHZhciBzeXNqc01hcCA9IHt9O1xuICAgICAgICB2YXIgc3lzanNNZXRhID0ge307XG4gICAgICAgIHZhciByZXF1aXJlcyA9IHt9O1xuXG4gICAgICAgIGZvciAodmFyIF9pdGVyYXRvciA9IGpzTm9kZXMsIF9pc0FycmF5ID0gQXJyYXkuaXNBcnJheShfaXRlcmF0b3IpLCBfaSA9IDAsIF9pdGVyYXRvciA9IF9pc0FycmF5ID8gX2l0ZXJhdG9yIDogX2l0ZXJhdG9yW1N5bWJvbC5pdGVyYXRvcl0oKTs7KSB7XG4gICAgICAgICAgICBpZiAoX2lzQXJyYXkpIHtcbiAgICAgICAgICAgICAgICBpZiAoX2kgPj0gX2l0ZXJhdG9yLmxlbmd0aCkgYnJlYWs7XG4gICAgICAgICAgICAgICAgbm9kZSA9IF9pdGVyYXRvcltfaSsrXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgX2kgPSBfaXRlcmF0b3IubmV4dCgpO1xuICAgICAgICAgICAgICAgIGlmIChfaS5kb25lKSBicmVhaztcbiAgICAgICAgICAgICAgICBub2RlID0gX2kudmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBuYW1lc3BhY2UgPSBub2RlLmdldEF0dHJpYnV0ZSgnY2xhc3NOYW1lJyk7XG4gICAgICAgICAgICB2YXIgZmlsZXBhdGggPSBSZXNvdXJjZXNNYW5hZ2VyLmdldEZpbGVPckZhbGxiYWNrKG5vZGUpO1xuICAgICAgICAgICAgdmFyIGRlcHMgPSBbXTtcbiAgICAgICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnZGVwZW5kcycpKSB7XG4gICAgICAgICAgICAgICAgZGVwcyA9IG5vZGUuZ2V0QXR0cmlidXRlKCdkZXBlbmRzJykuc3BsaXQoJywnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub2RlLmdldEF0dHJpYnV0ZSgnZXhwb3NlJykpIHtcbiAgICAgICAgICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLl9fcmVxdWlyZXNbbm9kZS5nZXRBdHRyaWJ1dGUoJ2V4cG9zZScpXSA9IG5hbWVzcGFjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN5c2pzTWFwW25hbWVzcGFjZV0gPSBmaWxlcGF0aDtcbiAgICAgICAgICAgIHN5c2pzTWV0YVtuYW1lc3BhY2VdID0geyBmb3JtYXQ6ICdnbG9iYWwnLCBkZXBzOiBkZXBzIH07XG4gICAgICAgIH1cbiAgICAgICAgU3lzdGVtSlMuY29uZmlnKHsgbWFwOiBzeXNqc01hcCwgbWV0YTogc3lzanNNZXRhIH0pO1xuICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLl9fY29uZmlnc1BhcnNlZCA9IHRydWU7XG5cbiAgICAgICAgdmFyIGNzc05vZGVzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHJlZ2lzdHJ5LCAncGx1Z2lucy8qL2NsaWVudF9zZXR0aW5ncy9yZXNvdXJjZXMvY3NzW0BhdXRvbG9hZD1cInRydWVcIl0nKTtcbiAgICAgICAgZm9yICh2YXIgX2l0ZXJhdG9yMiA9IGNzc05vZGVzLCBfaXNBcnJheTIgPSBBcnJheS5pc0FycmF5KF9pdGVyYXRvcjIpLCBfaTIgPSAwLCBfaXRlcmF0b3IyID0gX2lzQXJyYXkyID8gX2l0ZXJhdG9yMiA6IF9pdGVyYXRvcjJbU3ltYm9sLml0ZXJhdG9yXSgpOzspIHtcbiAgICAgICAgICAgIGlmIChfaXNBcnJheTIpIHtcbiAgICAgICAgICAgICAgICBpZiAoX2kyID49IF9pdGVyYXRvcjIubGVuZ3RoKSBicmVhaztcbiAgICAgICAgICAgICAgICBub2RlID0gX2l0ZXJhdG9yMltfaTIrK107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIF9pMiA9IF9pdGVyYXRvcjIubmV4dCgpO1xuICAgICAgICAgICAgICAgIGlmIChfaTIuZG9uZSkgYnJlYWs7XG4gICAgICAgICAgICAgICAgbm9kZSA9IF9pMi52YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbWFuYWdlci5sb2FkQ1NTUmVzb3VyY2UoUmVzb3VyY2VzTWFuYWdlci5nZXRGaWxlT3JGYWxsYmFjayhub2RlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5nZXRGaWxlT3JGYWxsYmFjayA9IGZ1bmN0aW9uIGdldEZpbGVPckZhbGxiYWNrKG5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUuZ2V0QXR0cmlidXRlKCdmYWxsYmFja0NvbmRpdGlvbicpICYmIGV2YWwobm9kZS5nZXRBdHRyaWJ1dGUoJ2ZhbGxiYWNrQ29uZGl0aW9uJykpKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZS5nZXRBdHRyaWJ1dGUoJ2ZhbGxiYWNrRmlsZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGUuZ2V0QXR0cmlidXRlKCdmaWxlJyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUmVzb3VyY2VzTWFuYWdlci5yZXF1aXJlTGliID0gZnVuY3Rpb24gcmVxdWlyZUxpYihtb2R1bGUpIHtcbiAgICAgICAgdmFyIHByb21pc2UgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAod2luZG93W21vZHVsZV0pIHJldHVybiB3aW5kb3dbbW9kdWxlXTtcbiAgICAgICAgaWYgKFJlc291cmNlc01hbmFnZXIuX19yZXF1aXJlcyAmJiBSZXNvdXJjZXNNYW5hZ2VyLl9fcmVxdWlyZXNbbW9kdWxlXSkge1xuICAgICAgICAgICAgdmFyIGdsb2JhbE5TID0gUmVzb3VyY2VzTWFuYWdlci5fX3JlcXVpcmVzW21vZHVsZV07XG4gICAgICAgICAgICBpZiAocHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBTeXN0ZW1KU1snaW1wb3J0J10oZ2xvYmFsTlMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHdpbmRvd1tnbG9iYWxOU10pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2luZG93W2dsb2JhbE5TXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXF1aXJpbmcgYSByZW1vdGUgbGliIHRoYXQgd2FzIG5vdCBwcmV2aW91c2x5IGxvYWRlZCAoJyArIGdsb2JhbE5TICsgJykuIFlvdSBtYXkgYmUgbWlzc2luZyBhIGRlcGVuZGVuY3kgZGVjbGFyYXRpb24gaW4gbWFuaWZlc3QsIG9yIHlvdSBjYW4gdXNlIHJlcXVpcmVMaWIobW9kdWxlTmFtZSwgdHJ1ZSkgdG8gcmVjZWl2ZSBhIFByb21pc2UuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIGFueSByZWZlcmVuY2UgdG8gbGliICcgKyBtb2R1bGUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbW9kdWxlIGlzIHJlZ2lzdGVyZWQgKG5vdCBuZWNlc3NhcmlseSBsb2FkZWQgeWV0KVxuICAgICAqIEBwYXJhbSBjbGFzc05hbWVcbiAgICAgKiBAcmV0dXJucyB7TWFwfGJvb2xlYW59XG4gICAgICovXG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLm1vZHVsZUlzQXZhaWxhYmxlID0gZnVuY3Rpb24gbW9kdWxlSXNBdmFpbGFibGUoY2xhc3NOYW1lKSB7XG4gICAgICAgIHZhciBjb25maWcgPSBTeXN0ZW1KUy5nZXRDb25maWcoKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZy5tYXAgJiYgY29uZmlnLm1hcFtjbGFzc05hbWVdO1xuICAgIH07XG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRDbGFzc2VzQW5kQXBwbHkgPSBmdW5jdGlvbiBsb2FkQ2xhc3Nlc0FuZEFwcGx5KGNsYXNzTmFtZXMsIGNhbGxiYWNrRnVuYykge1xuICAgICAgICBpZiAoIVJlc291cmNlc01hbmFnZXIuX19jb25maWdzUGFyc2VkKSB7XG4gICAgICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRBdXRvTG9hZFJlc291cmNlcygpO1xuICAgICAgICB9XG4gICAgICAgIFByb21pc2UuYWxsKGNsYXNzTmFtZXMubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgICAgICAgICByZXR1cm4gU3lzdGVtSlNbJ2ltcG9ydCddKGMpO1xuICAgICAgICB9KSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjYWxsYmFja0Z1bmMoKTtcbiAgICAgICAgfSlbJ2NhdGNoJ10oZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIExvYWRpbmcgJyArIGNsYXNzTmFtZXMuam9pbignLCAnKSArICcgOiAnLCByZWFzb24pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG5cbiAgICBSZXNvdXJjZXNNYW5hZ2VyLmRldGVjdE1vZHVsZVRvTG9hZEFuZEFwcGx5ID0gZnVuY3Rpb24gZGV0ZWN0TW9kdWxlVG9Mb2FkQW5kQXBwbHkoY2FsbGJhY2tTdHJpbmcsIGNhbGxiYWNrRnVuYykge1xuICAgICAgICB2YXIgYXN5bmMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzJdO1xuXG4gICAgICAgIGlmICghUmVzb3VyY2VzTWFuYWdlci5fX2NvbmZpZ3NQYXJzZWQpIHtcbiAgICAgICAgICAgIFJlc291cmNlc01hbmFnZXIubG9hZEF1dG9Mb2FkUmVzb3VyY2VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9IGNhbGxiYWNrU3RyaW5nLnNwbGl0KCcuJywgMSkuc2hpZnQoKTtcbiAgICAgICAgaWYgKGFzeW5jKSB7XG4gICAgICAgICAgICBTeXN0ZW1KU1snaW1wb3J0J10oY2xhc3NOYW1lKS50aGVuKGNhbGxiYWNrRnVuYyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBSZXNvdXJjZXNNYW5hZ2VyLmxvYWRTY3JpcHRTeW5jKGNsYXNzTmFtZSwgY2FsbGJhY2tGdW5jKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfTtcblxuICAgIFJlc291cmNlc01hbmFnZXIubG9hZFNjcmlwdFN5bmMgPSBmdW5jdGlvbiBsb2FkU2NyaXB0U3luYyhuYW1lLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gcmVnZW5lcmF0b3JSdW50aW1lLmFzeW5jKGZ1bmN0aW9uIGxvYWRTY3JpcHRTeW5jJChjb250ZXh0JDIkMCkge1xuICAgICAgICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoY29udGV4dCQyJDAucHJldiA9IGNvbnRleHQkMiQwLm5leHQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQkMiQwLm5leHQgPSAyO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVnZW5lcmF0b3JSdW50aW1lLmF3cmFwKFN5c3RlbUpTWydpbXBvcnQnXShuYW1lKSk7XG5cbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG5cbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgY2FzZSAnZW5kJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQkMiQwLnN0b3AoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgbnVsbCwgdGhpcyk7XG4gICAgfTtcblxuICAgIHJldHVybiBSZXNvdXJjZXNNYW5hZ2VyO1xufSkoKTtcblxuUmVzb3VyY2VzTWFuYWdlci5fX2NvbmZpZ3NQYXJzZWQgPSBmYWxzZTtcblJlc291cmNlc01hbmFnZXIuX19yZXF1aXJlcyA9IHt9O1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSZXNvdXJjZXNNYW5hZ2VyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfUHlkaW9BcGkgPSByZXF1aXJlKCcuL1B5ZGlvQXBpJyk7XG5cbnZhciBfUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfUHlkaW9BcGkpO1xuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvWE1MVXRpbHMnKTtcblxudmFyIF91dGlsWE1MVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFhNTFV0aWxzKTtcblxudmFyIFVzZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFVzZXIoaWQsIGxhYmVsLCB0eXBlLCBncm91cCwgYXZhdGFyLCB0ZW1wb3JhcnksIGV4dGVybmFsLCBleHRlbmRlZExhYmVsKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBVc2VyKTtcblxuICAgICAgICB0aGlzLl9pZCA9IGlkO1xuICAgICAgICB0aGlzLl9sYWJlbCA9IGxhYmVsO1xuICAgICAgICB0aGlzLl90eXBlID0gdHlwZTtcbiAgICAgICAgaWYgKHRoaXMuX3R5cGUgPT09ICdncm91cCcpIHtcbiAgICAgICAgICAgIHRoaXMuX2dyb3VwID0gaWQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fYXZhdGFyID0gYXZhdGFyO1xuICAgICAgICB0aGlzLl90ZW1wb3JhcnkgPSB0ZW1wb3Jhcnk7XG4gICAgICAgIHRoaXMuX2V4dGVybmFsID0gZXh0ZXJuYWw7XG4gICAgICAgIHRoaXMuX2V4dGVuZGVkTGFiZWwgPSBleHRlbmRlZExhYmVsO1xuICAgIH1cblxuICAgIFVzZXIuZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3QodXNlcikge1xuICAgICAgICByZXR1cm4gbmV3IFVzZXIodXNlci5pZCwgdXNlci5sYWJlbCwgdXNlci50eXBlLCB1c2VyLmdyb3VwLCB1c2VyLmF2YXRhciwgdXNlci50ZW1wb3JhcnksIHVzZXIuZXh0ZXJuYWwpO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5hc09iamVjdCA9IGZ1bmN0aW9uIGFzT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQ6IHRoaXMuX2lkLFxuICAgICAgICAgICAgbGFiZWw6IHRoaXMuX2xhYmVsLFxuICAgICAgICAgICAgdHlwZTogdGhpcy5fdHlwZSxcbiAgICAgICAgICAgIGdyb3VwOiB0aGlzLl9ncm91cCxcbiAgICAgICAgICAgIGF2YXRhcjogdGhpcy5fYXZhdGFyLFxuICAgICAgICAgICAgdGVtcG9yYXJ5OiB0aGlzLl90ZW1wb3JhcnksXG4gICAgICAgICAgICBleHRlcm5hbDogdGhpcy5fZXh0ZXJuYWwsXG4gICAgICAgICAgICBleHRlbmRlZExhYmVsOiB0aGlzLl9leHRlbmRlZExhYmVsXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldElkID0gZnVuY3Rpb24gZ2V0SWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pZDtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0TGFiZWwgPSBmdW5jdGlvbiBnZXRMYWJlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xhYmVsO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gZ2V0VHlwZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3R5cGU7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldEdyb3VwID0gZnVuY3Rpb24gZ2V0R3JvdXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ncm91cDtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0QXZhdGFyID0gZnVuY3Rpb24gZ2V0QXZhdGFyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXZhdGFyO1xuICAgIH07XG5cbiAgICBVc2VyLnByb3RvdHlwZS5nZXRUZW1wb3JhcnkgPSBmdW5jdGlvbiBnZXRUZW1wb3JhcnkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90ZW1wb3Jhcnk7XG4gICAgfTtcblxuICAgIFVzZXIucHJvdG90eXBlLmdldEV4dGVybmFsID0gZnVuY3Rpb24gZ2V0RXh0ZXJuYWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRlcm5hbDtcbiAgICB9O1xuXG4gICAgVXNlci5wcm90b3R5cGUuZ2V0RXh0ZW5kZWRMYWJlbCA9IGZ1bmN0aW9uIGdldEV4dGVuZGVkTGFiZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRlbmRlZExhYmVsO1xuICAgIH07XG5cbiAgICByZXR1cm4gVXNlcjtcbn0pKCk7XG5cbnZhciBVc2Vyc0FwaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVXNlcnNBcGkoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBVc2Vyc0FwaSk7XG4gICAgfVxuXG4gICAgVXNlcnNBcGkuYXV0aG9yaXplZFVzZXJzU3RhcnRpbmdXaXRoID0gZnVuY3Rpb24gYXV0aG9yaXplZFVzZXJzU3RhcnRpbmdXaXRoKHRva2VuLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgdXNlcnNPbmx5ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciBleGlzdGluZ09ubHkgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1szXTtcblxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfbGlzdF9hdXRob3JpemVkX3VzZXJzJyxcbiAgICAgICAgICAgIHZhbHVlOiB0b2tlbixcbiAgICAgICAgICAgIGZvcm1hdDogJ2pzb24nXG4gICAgICAgIH07XG4gICAgICAgIGlmICh1c2Vyc09ubHkpIHtcbiAgICAgICAgICAgIHBhcmFtc1sndXNlcnNfb25seSddID0gJ3RydWUnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChleGlzdGluZ09ubHkpIHtcbiAgICAgICAgICAgIHBhcmFtc1snZXhpc3Rpbmdfb25seSddID0gJ3RydWUnO1xuICAgICAgICB9XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHBhcmFtcywgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdmFyIHN1Z2dlc3Rpb25zID0gW107XG4gICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlWE1MKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpcyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyh0cmFuc3BvcnQucmVzcG9uc2VYTUwsICcvL2xpJyk7XG4gICAgICAgICAgICAgICAgbGlzLm1hcChmdW5jdGlvbiAobGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNwYW5MYWJlbCA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhHZXRTaW5nbGVOb2RlVGV4dChsaSwgJ3NwYW5bQGNsYXNzPVwidXNlcl9lbnRyeV9sYWJlbFwiXScpO1xuICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucy5wdXNoKG5ldyBVc2VyKGxpLmdldEF0dHJpYnV0ZSgnZGF0YS1lbnRyeV9pZCcpLCBsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtbGFiZWwnKSwgbGkuZ2V0QXR0cmlidXRlKCdjbGFzcycpLCBsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtZ3JvdXAnKSwgbGkuZ2V0QXR0cmlidXRlKCdkYXRhLWF2YXRhcicpLCBsaS5nZXRBdHRyaWJ1dGUoJ2RhdGEtdGVtcG9yYXJ5JykgPyB0cnVlIDogZmFsc2UsIGxpLmdldEF0dHJpYnV0ZSgnZGF0YS1leHRlcm5hbCcpID09ICd0cnVlJywgc3BhbkxhYmVsKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHRyYW5zcG9ydC5yZXNwb25zZUpTT047XG4gICAgICAgICAgICAgICAgZGF0YS5tYXAoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpZCA9IGVudHJ5LmlkO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGFiZWwgPSBlbnRyeS5sYWJlbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHR5cGUgPSBlbnRyeS50eXBlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXAgPSBlbnRyeS5ncm91cDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGF2YXRhciA9IGVudHJ5LmF2YXRhcjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRlbXBvcmFyeSA9IGVudHJ5LnRlbXBvcmFyeTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGV4dGVybmFsID0gZW50cnkuZXh0ZXJuYWw7XG5cbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMucHVzaChuZXcgVXNlcihpZCwgbGFiZWwsIHR5cGUsIGdyb3VwLCBhdmF0YXIsIHRlbXBvcmFyeSwgZXh0ZXJuYWwsIGxhYmVsKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhzdWdnZXN0aW9ucyk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5jcmVhdGVVc2VyRnJvbVBvc3QgPSBmdW5jdGlvbiBjcmVhdGVVc2VyRnJvbVBvc3QocG9zdFZhbHVlcywgY2FsbGJhY2spIHtcbiAgICAgICAgcG9zdFZhbHVlc1snZ2V0X2FjdGlvbiddID0gJ3VzZXJfY3JlYXRlX3VzZXInO1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwb3N0VmFsdWVzLCAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2socG9zdFZhbHVlcywgdHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgIH07XG5cbiAgICBVc2Vyc0FwaS5kZWxldGVVc2VyID0gZnVuY3Rpb24gZGVsZXRlVXNlcih1c2VySWQsIGNhbGxiYWNrKSB7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX2RlbGV0ZV91c2VyJyxcbiAgICAgICAgICAgIHVzZXJfaWQ6IHVzZXJJZFxuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuc2F2ZVNlbGVjdGlvblN1cHBvcnRlZCA9IGZ1bmN0aW9uIHNhdmVTZWxlY3Rpb25TdXBwb3J0ZWQoKSB7XG4gICAgICAgIHJldHVybiBnbG9iYWwucHlkaW8uZ2V0Q29udHJvbGxlcigpLmFjdGlvbnMuZ2V0KCd1c2VyX3RlYW1fY3JlYXRlJykgIT09IHVuZGVmaW5lZDtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkuZGVsZXRlVGVhbSA9IGZ1bmN0aW9uIGRlbGV0ZVRlYW0odGVhbUlkLCBjYWxsYmFjaykge1xuICAgICAgICB0ZWFtSWQgPSB0ZWFtSWQucmVwbGFjZSgnL0FKWFBfVEVBTS8nLCAnJyk7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX3RlYW1fZGVsZXRlJyxcbiAgICAgICAgICAgIHRlYW1faWQ6IHRlYW1JZFxuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLnNhdmVTZWxlY3Rpb25Bc1RlYW0gPSBmdW5jdGlvbiBzYXZlU2VsZWN0aW9uQXNUZWFtKHRlYW1OYW1lLCB1c2VySWRzLCBjYWxsYmFjaykge1xuICAgICAgICBfUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdCh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAndXNlcl90ZWFtX2NyZWF0ZScsXG4gICAgICAgICAgICB0ZWFtX2xhYmVsOiB0ZWFtTmFtZSxcbiAgICAgICAgICAgICd1c2VyX2lkc1tdJzogdXNlcklkc1xuICAgICAgICB9LCBmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0cmFuc3BvcnQucmVzcG9uc2VKU09OKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIFVzZXJzQXBpLmFkZFVzZXJUb1RlYW0gPSBmdW5jdGlvbiBhZGRVc2VyVG9UZWFtKHRlYW1JZCwgdXNlcklkLCBjYWxsYmFjaykge1xuICAgICAgICB0ZWFtSWQgPSB0ZWFtSWQucmVwbGFjZSgnL0FKWFBfVEVBTS8nLCAnJyk7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX3RlYW1fYWRkX3VzZXInLFxuICAgICAgICAgICAgdGVhbV9pZDogdGVhbUlkLFxuICAgICAgICAgICAgdXNlcl9pZDogdXNlcklkXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkucmVtb3ZlVXNlckZyb21UZWFtID0gZnVuY3Rpb24gcmVtb3ZlVXNlckZyb21UZWFtKHRlYW1JZCwgdXNlcklkLCBjYWxsYmFjaykge1xuICAgICAgICB0ZWFtSWQgPSB0ZWFtSWQucmVwbGFjZSgnL0FKWFBfVEVBTS8nLCAnJyk7XG4gICAgICAgIF9QeWRpb0FwaTJbJ2RlZmF1bHQnXS5nZXRDbGllbnQoKS5yZXF1ZXN0KHtcbiAgICAgICAgICAgIGdldF9hY3Rpb246ICd1c2VyX3RlYW1fZGVsZXRlX3VzZXInLFxuICAgICAgICAgICAgdGVhbV9pZDogdGVhbUlkLFxuICAgICAgICAgICAgdXNlcl9pZDogdXNlcklkXG4gICAgICAgIH0sIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRyYW5zcG9ydC5yZXNwb25zZUpTT04pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgVXNlcnNBcGkudXBkYXRlVGVhbUxhYmVsID0gZnVuY3Rpb24gdXBkYXRlVGVhbUxhYmVsKHRlYW1JZCwgbmV3TGFiZWwsIGNhbGxiYWNrKSB7XG4gICAgICAgIHRlYW1JZCA9IHRlYW1JZC5yZXBsYWNlKCcvQUpYUF9URUFNLycsICcnKTtcbiAgICAgICAgX1B5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3Qoe1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ3VzZXJfdGVhbV91cGRhdGVfbGFiZWwnLFxuICAgICAgICAgICAgdGVhbV9pZDogdGVhbUlkLFxuICAgICAgICAgICAgdGVhbV9sYWJlbDogbmV3TGFiZWxcbiAgICAgICAgfSwgZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgY2FsbGJhY2sodHJhbnNwb3J0LnJlc3BvbnNlSlNPTik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICByZXR1cm4gVXNlcnNBcGk7XG59KSgpO1xuXG5leHBvcnRzLlVzZXIgPSBVc2VyO1xuZXhwb3J0cy5Vc2Vyc0FwaSA9IFVzZXJzQXBpO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIExvZ2dlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTG9nZ2VyKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTG9nZ2VyKTtcbiAgICB9XG5cbiAgICBMb2dnZXIubG9nID0gZnVuY3Rpb24gbG9nKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5jb25zb2xlKSBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICB9O1xuXG4gICAgTG9nZ2VyLmVycm9yID0gZnVuY3Rpb24gZXJyb3IobWVzc2FnZSkge1xuICAgICAgICBpZiAod2luZG93LmNvbnNvbGUpIGNvbnNvbGUuZXJyb3IobWVzc2FnZSk7XG4gICAgfTtcblxuICAgIExvZ2dlci5kZWJ1ZyA9IGZ1bmN0aW9uIGRlYnVnKG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5jb25zb2xlKSBjb25zb2xlLmRlYnVnKG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICByZXR1cm4gTG9nZ2VyO1xufSkoKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBMb2dnZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgT2JzZXJ2YWJsZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JzZXJ2YWJsZSgpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIE9ic2VydmFibGUpO1xuICAgIH1cblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLl9vYmplY3RFdmVudFNldHVwID0gZnVuY3Rpb24gX29iamVjdEV2ZW50U2V0dXAoZXZlbnRfbmFtZSkge1xuICAgICAgICB0aGlzLl9vYnNlcnZlcnMgPSB0aGlzLl9vYnNlcnZlcnMgfHwge307XG4gICAgICAgIHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXSA9IHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXSB8fCBbXTtcbiAgICB9O1xuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIG9ic2VydmUoZXZlbnRfbmFtZSwgb2JzZXJ2ZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBldmVudF9uYW1lID09ICdzdHJpbmcnICYmIHR5cGVvZiBvYnNlcnZlciAhPSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhpcy5fb2JqZWN0RXZlbnRTZXR1cChldmVudF9uYW1lKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0uaW5kZXhPZihvYnNlcnZlcikgPT0gLTEpIHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXS5wdXNoKG9ic2VydmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAodmFyIGUgaW4gZXZlbnRfbmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChldmVudF9uYW1lLmhhc093blByb3BlcnR5KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub2JzZXJ2ZShlLCBldmVudF9uYW1lW2VdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUuc3RvcE9ic2VydmluZyA9IGZ1bmN0aW9uIHN0b3BPYnNlcnZpbmcoZXZlbnRfbmFtZSwgb2JzZXJ2ZXIpIHtcbiAgICAgICAgdGhpcy5fb2JqZWN0RXZlbnRTZXR1cChldmVudF9uYW1lKTtcbiAgICAgICAgaWYgKGV2ZW50X25hbWUgJiYgb2JzZXJ2ZXIpIHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXSA9IHRoaXMuX29ic2VydmVyc1tldmVudF9uYW1lXS5maWx0ZXIoZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgICAgIHJldHVybiBvICE9IG9ic2VydmVyO1xuICAgICAgICB9KTtlbHNlIGlmIChldmVudF9uYW1lKSB7XG4gICAgICAgICAgICB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0gPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX29ic2VydmVycyA9IHt9O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLm9ic2VydmVPbmNlID0gZnVuY3Rpb24gb2JzZXJ2ZU9uY2UoZXZlbnRfbmFtZSwgb3V0ZXJfb2JzZXJ2ZXIpIHtcbiAgICAgICAgdmFyIGlubmVyX29ic2VydmVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIG91dGVyX29ic2VydmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB0aGlzLnN0b3BPYnNlcnZpbmcoZXZlbnRfbmFtZSwgaW5uZXJfb2JzZXJ2ZXIpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLl9vYmplY3RFdmVudFNldHVwKGV2ZW50X25hbWUpO1xuICAgICAgICB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0ucHVzaChpbm5lcl9vYnNlcnZlcik7XG4gICAgfTtcblxuICAgIE9ic2VydmFibGUucHJvdG90eXBlLm5vdGlmeSA9IGZ1bmN0aW9uIG5vdGlmeShldmVudF9uYW1lKSB7XG4gICAgICAgIHRoaXMuX29iamVjdEV2ZW50U2V0dXAoZXZlbnRfbmFtZSk7XG4gICAgICAgIHZhciBjb2xsZWN0ZWRfcmV0dXJuX3ZhbHVlcyA9IFtdO1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LmZyb20oYXJndW1lbnRzKS5zbGljZSgxKTtcbiAgICAgICAgdmFyIG9ic2VydmVyc0NvcHkgPSB0aGlzLl9vYnNlcnZlcnNbZXZlbnRfbmFtZV0uc2xpY2UoMCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JzZXJ2ZXJzQ29weS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgY29sbGVjdGVkX3JldHVybl92YWx1ZXMucHVzaChvYnNlcnZlcnNDb3B5W2ldLmFwcGx5KG9ic2VydmVyc0NvcHlbaV0sIGFyZ3MpIHx8IG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2xsZWN0ZWRfcmV0dXJuX3ZhbHVlcztcbiAgICB9O1xuXG4gICAgT2JzZXJ2YWJsZS5wcm90b3R5cGUuaGFzT2JzZXJ2ZXJzID0gZnVuY3Rpb24gaGFzT2JzZXJ2ZXJzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIE9ic2VydmFibGU7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBPYnNlcnZhYmxlO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9MYW5nVXRpbHMnKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxMYW5nVXRpbHMpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi4vaHR0cC9SZXNvdXJjZXNNYW5hZ2VyJyk7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFJlc291cmNlc01hbmFnZXIpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfdXRpbFhNTFV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgX3V0aWxGdW5jVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL0Z1bmNVdGlscycpO1xuXG52YXIgX3V0aWxGdW5jVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbEZ1bmNVdGlscyk7XG5cbi8qKlxuICogQSBcIkNvbW1hbmRcIiBvYmplY3QsIGVuY2Fwc3VsYXRpbmcgaXRzIGNhbGxiYWNrcywgZGlzcGxheSBhdHRyaWJ1dGVzLCBldGMuXG4gKi9cblxudmFyIEFjdGlvbiA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcblx0X2luaGVyaXRzKEFjdGlvbiwgX09ic2VydmFibGUpO1xuXG5cdC8qKlxuICAqIFN0YW5kYXJkIGNvbnN0cnVjdG9yXG4gICovXG5cblx0ZnVuY3Rpb24gQWN0aW9uKCkge1xuXHRcdF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBY3Rpb24pO1xuXG5cdFx0X09ic2VydmFibGUuY2FsbCh0aGlzKTtcblx0XHR0aGlzLl9fREVGQVVMVF9JQ09OX1BBVEggPSBcImFjdGlvbnMvSUNPTl9TSVpFXCI7XG5cdFx0dGhpcy5vcHRpb25zID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ub2JqZWN0TWVyZ2Uoe1xuXHRcdFx0bmFtZTogJycsXG5cdFx0XHRpY29uX2NsYXNzOiAnJyxcblx0XHRcdHRleHQ6ICcnLFxuXHRcdFx0dGl0bGU6ICcnLFxuXHRcdFx0dGV4dF9pZDogJycsXG5cdFx0XHR0aXRsZV9pZDogJycsXG5cdFx0XHR3ZWlnaHQ6IDAsXG5cdFx0XHRoYXNBY2Nlc3NLZXk6IGZhbHNlLFxuXHRcdFx0YWNjZXNzS2V5OiAnJyxcblx0XHRcdHN1Yk1lbnU6IGZhbHNlLFxuXHRcdFx0c3ViTWVudVVwZGF0ZUltYWdlOiBmYWxzZSxcblx0XHRcdHN1Yk1lbnVVcGRhdGVUaXRsZTogZmFsc2UsXG5cdFx0XHRjYWxsYmFja0NvZGU6ICcnLFxuXHRcdFx0Y2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKCkge30sXG5cdFx0XHRsaXN0ZW5lcnM6IFtdLFxuXHRcdFx0YWN0aXZlQ29uZGl0aW9uOiBudWxsXG5cdFx0fSwgYXJndW1lbnRzWzBdIHx8IHt9KTtcblxuXHRcdHRoaXMuY29udGV4dCA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLm9iamVjdE1lcmdlKHtcblx0XHRcdHNlbGVjdGlvbjogdHJ1ZSxcblx0XHRcdGRpcjogZmFsc2UsXG5cdFx0XHRhbGxvd2VkTWltZXM6IFtdLFxuXHRcdFx0ZXZhbE1ldGFkYXRhOiAnJyxcblx0XHRcdHJvb3Q6IHRydWUsXG5cdFx0XHRpblppcDogdHJ1ZSxcblx0XHRcdHJlY3ljbGU6IGZhbHNlLFxuXHRcdFx0YmVoYXZpb3VyOiAnaGlkZGVuJyxcblx0XHRcdGFjdGlvbkJhcjogZmFsc2UsXG5cdFx0XHRhY3Rpb25CYXJHcm91cDogJ2RlZmF1bHQnLFxuXHRcdFx0Y29udGV4dE1lbnU6IGZhbHNlLFxuXHRcdFx0YWp4cFdpZGdldHM6IG51bGwsXG5cdFx0XHRpbmZvUGFuZWw6IGZhbHNlXG5cdFx0fSwgYXJndW1lbnRzWzFdIHx8IHt9KTtcblxuXHRcdHRoaXMuc2VsZWN0aW9uQ29udGV4dCA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLm9iamVjdE1lcmdlKHtcblx0XHRcdGRpcjogZmFsc2UsXG5cdFx0XHRmaWxlOiB0cnVlLFxuXHRcdFx0cmVjeWNsZTogZmFsc2UsXG5cdFx0XHRiZWhhdmlvdXI6ICdkaXNhYmxlZCcsXG5cdFx0XHRhbGxvd2VkTWltZXM6IFtdLFxuXHRcdFx0ZXZhbE1ldGFkYXRhOiAnJyxcblx0XHRcdHVuaXF1ZTogdHJ1ZSxcblx0XHRcdG11bHRpcGxlT25seTogZmFsc2UsXG5cdFx0XHRlbmFibGVSb290OiBmYWxzZVxuXHRcdH0sIGFyZ3VtZW50c1syXSB8fCB7fSk7XG5cblx0XHR0aGlzLnJpZ2h0c0NvbnRleHQgPSBfdXRpbExhbmdVdGlsczJbJ2RlZmF1bHQnXS5vYmplY3RNZXJnZSh7XG5cdFx0XHRub1VzZXI6IHRydWUsXG5cdFx0XHR1c2VyTG9nZ2VkOiB0cnVlLFxuXHRcdFx0Z3Vlc3RMb2dnZWQ6IGZhbHNlLFxuXHRcdFx0cmVhZDogZmFsc2UsXG5cdFx0XHR3cml0ZTogZmFsc2UsXG5cdFx0XHRhZG1pbk9ubHk6IGZhbHNlXG5cdFx0fSwgYXJndW1lbnRzWzNdIHx8IHt9KTtcblxuXHRcdHRoaXMuc3ViTWVudUl0ZW1zID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ub2JqZWN0TWVyZ2Uoe1xuXHRcdFx0c3RhdGljSXRlbXM6IG51bGwsXG5cdFx0XHRkeW5hbWljSXRlbXM6IG51bGwsXG5cdFx0XHRkeW5hbWljQnVpbGRlckNvZGU6IG51bGwsXG5cdFx0XHRwb3BvdmVyQ29udGVudDogbnVsbFxuXHRcdH0sIGFyZ3VtZW50c1s0XSB8fCB7fSk7XG5cblx0XHR0aGlzLmVsZW1lbnRzID0gW107XG5cdFx0dGhpcy5jb250ZXh0SGlkZGVuID0gZmFsc2U7XG5cdFx0dGhpcy5kZW55ID0gZmFsc2U7XG5cdFx0aWYgKHRoaXMuY29udGV4dC5zdWJNZW51KSB7XG5cdFx0XHRpZiAoIXRoaXMub3B0aW9ucy5hY3Rpb25CYXIpIHtcblx0XHRcdFx0YWxlcnQoJ1dhcm5pbmcsIHdyb25nIGFjdGlvbiBkZWZpbml0aW9uLiBDYW5ub3QgdXNlIGEgc3ViTWVudSBpZiBub3QgZGlzcGxheWVkIGluIHRoZSBhY3Rpb25CYXIhJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0QWN0aW9uLnByb3RvdHlwZS5fZXZhbFNjcmlwdHMgPSBmdW5jdGlvbiBfZXZhbFNjcmlwdHMoZGF0YSwgbG9jYWxTY29wZU1ldGFkYXRhKSB7XG5cdFx0dmFyIG1ldGFkYXRhID0gbG9jYWxTY29wZU1ldGFkYXRhO1xuXHRcdHJldHVybiBldmFsKGRhdGEpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldHMgdGhlIG1hbmFnZXIgZm9yIHRoaXMgYWN0aW9uXG4gICogQHBhcmFtIG1hbmFnZXIgQWN0aW9uc01hbmFnZXJcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnNldE1hbmFnZXIgPSBmdW5jdGlvbiBzZXRNYW5hZ2VyKG1hbmFnZXIpIHtcblx0XHR0aGlzLm1hbmFnZXIgPSBtYW5hZ2VyO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuc3ViTWVudSkge1xuXHRcdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY0l0ZW1zKSB7XG5cdFx0XHRcdHRoaXMuYnVpbGRTdWJtZW51U3RhdGljSXRlbXMoKTtcblx0XHRcdH1cblx0XHRcdGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljSXRlbXMgfHwgdGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJDb2RlKSB7XG5cdFx0XHRcdHRoaXMucHJlcGFyZVN1Ym1lbnVEeW5hbWljQnVpbGRlcigpO1xuXHRcdFx0fSBlbHNlIGlmICh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlck1vZHVsZSkge1xuXHRcdFx0XHRfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10uZGV0ZWN0TW9kdWxlVG9Mb2FkQW5kQXBwbHkodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJNb2R1bGUsIHRoaXMucHJlcGFyZVN1Ym1lbnVEeW5hbWljQnVpbGRlci5iaW5kKHRoaXMpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbJ2luaXQnXSkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0d2luZG93Lmxpc3RlbmVyQ29udGV4dCA9IHRoaXM7XG5cdFx0XHRcdGlmICh0eXBlb2YgdGhpcy5vcHRpb25zLmxpc3RlbmVyc1snaW5pdCddID09IFwic3RyaW5nXCIpIHtcblx0XHRcdFx0XHR0aGlzLl9ldmFsU2NyaXB0cyh0aGlzLm9wdGlvbnMubGlzdGVuZXJzWydpbml0J10pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbJ2luaXQnXSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKCdFcnJvciB3aGlsZSBldmFsdWF0aW5nIGluaXQgc2NyaXB0IGZvciBhY3Rpb24gJyArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogRXhlY3V0ZSB0aGUgYWN0aW9uIGNvZGVcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gYXBwbHkoKSB7XG5cdFx0aWYgKHRoaXMuZGVueSkgcmV0dXJuO1xuXHRcdHRoaXMubWFuYWdlci5wdWJsaXNoQWN0aW9uRXZlbnQoXCJiZWZvcmVBcHBseS1cIiArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0XHR3aW5kb3cuYWN0aW9uQXJndW1lbnRzID0gW107XG5cdFx0d2luZG93LmFjdGlvbk1hbmFnZXIgPSB0aGlzLm1hbmFnZXI7XG5cdFx0aWYgKGFyZ3VtZW50c1swXSkgd2luZG93LmFjdGlvbkFyZ3VtZW50cyA9IGFyZ3VtZW50c1swXTtcblx0XHRpZiAodGhpcy5vcHRpb25zLmNhbGxiYWNrQ29kZSkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0dGhpcy5fZXZhbFNjcmlwdHModGhpcy5vcHRpb25zLmNhbGxiYWNrQ29kZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKGUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAodGhpcy5vcHRpb25zLmNhbGxiYWNrKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuY2FsbGJhY2sodGhpcy5tYW5hZ2VyLCBhcmd1bWVudHNbMF0pO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLnN1Yk1lbnUgJiYgYXJndW1lbnRzWzBdICYmIGFyZ3VtZW50c1swXVswXSkge1xuXHRcdFx0dGhpcy5ub3RpZnkoXCJzdWJtZW51X2FjdGl2ZVwiLCBhcmd1bWVudHNbMF1bMF0pO1xuXHRcdH1cblx0XHR3aW5kb3cuYWN0aW9uQXJndW1lbnRzID0gbnVsbDtcblx0XHR3aW5kb3cuYWN0aW9uTWFuYWdlciA9IG51bGw7XG5cdFx0dGhpcy5tYW5hZ2VyLnB1Ymxpc2hBY3Rpb25FdmVudChcImFmdGVyQXBwbHktXCIgKyB0aGlzLm9wdGlvbnMubmFtZSk7XG5cdH07XG5cblx0LyoqXG4gICogVXBkYXRlcyB0aGUgYWN0aW9uIHN0YXR1cyBvbiBjb250ZXh0IGNoYW5nZVxuICAgICAqIEBwYXJhbSBQeWRpb0RhdGFNb2RlbCBkYXRhTW9kZWxcbiAgICAgKiBAcGFyYW0gYm9vbGVhbiB1c2Vyc0VuYWJsZWRcbiAgICAgKiBAcGFyYW0gc3RyaW5nIGNydFVzZXJcbiAgKiBAcmV0dXJucyB2b2lkXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5maXJlQ29udGV4dENoYW5nZSA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0Q2hhbmdlKGRhdGFNb2RlbCwgdXNlcnNFbmFibGVkLCBjcnRVc2VyKSB7XG5cblx0XHR2YXIgY3J0SXNSZWN5Y2xlID0gZmFsc2U7XG5cdFx0dmFyIGNydEluWmlwID0gZmFsc2U7XG5cdFx0dmFyIGNydElzUm9vdCA9IGZhbHNlO1xuXHRcdHZhciBjcnRBanhwTWltZSA9ICcnO1xuXHRcdHZhciBjcnRJc1JlYWRPbmx5ID0gZmFsc2U7XG5cblx0XHR2YXIgY3J0Tm9kZSA9IGRhdGFNb2RlbC5nZXRDb250ZXh0Tm9kZSgpO1xuXHRcdGlmIChjcnROb2RlKSB7XG5cdFx0XHRjcnRJc1JlY3ljbGUgPSBjcnROb2RlLmdldEFqeHBNaW1lKCkgPT0gXCJhanhwX3JlY3ljbGVcIjtcblx0XHRcdGNydEluWmlwID0gY3J0Tm9kZS5oYXNBanhwTWltZUluQnJhbmNoKFwiYWp4cF9icm93c2FibGVfYXJjaGl2ZVwiKTtcblx0XHRcdGNydElzUm9vdCA9IGNydE5vZGUuaXNSb290KCk7XG5cdFx0XHRjcnRBanhwTWltZSA9IGNydE5vZGUuZ2V0QWp4cE1pbWUoKTtcblx0XHRcdGNydElzUmVhZE9ubHkgPSBjcnROb2RlLmhhc01ldGFkYXRhSW5CcmFuY2goXCJhanhwX3JlYWRvbmx5XCIsIFwidHJ1ZVwiKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcImNvbnRleHRDaGFuZ2VcIl0pIHtcblx0XHRcdGlmICh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wiY29udGV4dENoYW5nZVwiXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJjb250ZXh0Q2hhbmdlXCJdKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3cubGlzdGVuZXJDb250ZXh0ID0gdGhpcztcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHR0aGlzLl9ldmFsU2NyaXB0cyh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wiY29udGV4dENoYW5nZVwiXSk7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihcIkVycm9yIHdoaWxlIGV2YWx1YXRpbmcgc2NyaXB0IGZvciBjb250ZXh0Q2hhbmdlIGV2ZW50IC0gYWN0aW9uIFwiICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHZhciByaWdodHNDb250ZXh0ID0gdGhpcy5yaWdodHNDb250ZXh0O1xuXHRcdGlmICghcmlnaHRzQ29udGV4dC5ub1VzZXIgJiYgIXVzZXJzRW5hYmxlZCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQudXNlckxvZ2dlZCA9PSAnb25seScgJiYgY3J0VXNlciA9PSBudWxsIHx8IHJpZ2h0c0NvbnRleHQuZ3Vlc3RMb2dnZWQgJiYgcmlnaHRzQ29udGV4dC5ndWVzdExvZ2dlZCA9PSAnaGlkZGVuJyAmJiBjcnRVc2VyICE9IG51bGwgJiYgY3J0VXNlci5pZCA9PSAnZ3Vlc3QnKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdH1cblx0XHRpZiAocmlnaHRzQ29udGV4dC51c2VyTG9nZ2VkID09ICdoaWRkZW4nICYmIGNydFVzZXIgIT0gbnVsbCAmJiAhKGNydFVzZXIuaWQgPT0gJ2d1ZXN0JyAmJiByaWdodHNDb250ZXh0Lmd1ZXN0TG9nZ2VkICYmIHJpZ2h0c0NvbnRleHQuZ3Vlc3RMb2dnZWQgPT0gJ3Nob3cnKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQuYWRtaW5Pbmx5ICYmIChjcnRVc2VyID09IG51bGwgfHwgIWNydFVzZXIuaXNBZG1pbikpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LnJlYWQgJiYgY3J0VXNlciAhPSBudWxsICYmICFjcnRVc2VyLmNhblJlYWQoKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKHJpZ2h0c0NvbnRleHQud3JpdGUgJiYgY3J0VXNlciAhPSBudWxsICYmICFjcnRVc2VyLmNhbldyaXRlKCkpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmIChyaWdodHNDb250ZXh0LndyaXRlICYmIGNydElzUmVhZE9ubHkpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmNvbnRleHQuYWxsb3dlZE1pbWVzLmxlbmd0aCkge1xuXHRcdFx0aWYgKHRoaXMuY29udGV4dC5hbGxvd2VkTWltZXMuaW5kZXhPZihcIipcIikgPT0gLTEgJiYgdGhpcy5jb250ZXh0LmFsbG93ZWRNaW1lcy5pbmRleE9mKGNydEFqeHBNaW1lKSA9PSAtMSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuY29udGV4dC5hbGxvd2VkTWltZXMuaW5kZXhPZihcIl5cIiArIGNydEFqeHBNaW1lKSAhPSAtMSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAodGhpcy5jb250ZXh0LnJlY3ljbGUpIHtcblx0XHRcdGlmICh0aGlzLmNvbnRleHQucmVjeWNsZSA9PSAnb25seScgJiYgIWNydElzUmVjeWNsZSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuY29udGV4dC5yZWN5Y2xlID09ICdoaWRkZW4nICYmIGNydElzUmVjeWNsZSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5oaWRlRm9yQ29udGV4dCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIXRoaXMuY29udGV4dC5pblppcCAmJiBjcnRJblppcCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuaGlkZUZvckNvbnRleHQoKTtcblx0XHR9XG5cdFx0aWYgKCF0aGlzLmNvbnRleHQucm9vdCAmJiBjcnRJc1Jvb3QpIHtcblx0XHRcdHJldHVybiB0aGlzLmhpZGVGb3JDb250ZXh0KCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zaG93Rm9yQ29udGV4dChkYXRhTW9kZWwpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFVwYXRlcyB0aGUgYWN0aW9uIHN0YXR1cyBvbiBzZWxlY3Rpb24gY2hhbmdlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5maXJlU2VsZWN0aW9uQ2hhbmdlID0gZnVuY3Rpb24gZmlyZVNlbGVjdGlvbkNoYW5nZSgpIHtcblx0XHRpZiAodGhpcy5vcHRpb25zLmxpc3RlbmVyc1tcInNlbGVjdGlvbkNoYW5nZVwiXSkge1xuXHRcdFx0aWYgKHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbXCJzZWxlY3Rpb25DaGFuZ2VcIl0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wic2VsZWN0aW9uQ2hhbmdlXCJdKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3cubGlzdGVuZXJDb250ZXh0ID0gdGhpcztcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHR0aGlzLl9ldmFsU2NyaXB0cyh0aGlzLm9wdGlvbnMubGlzdGVuZXJzW1wic2VsZWN0aW9uQ2hhbmdlXCJdKTtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKFwiRXJyb3Igd2hpbGUgZXZhbHVhdGluZyBzY3JpcHQgZm9yIHNlbGVjdGlvbkNoYW5nZSBldmVudCAtIGFjdGlvbiBcIiArIHRoaXMub3B0aW9ucy5uYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLmFjdGl2ZUNvbmRpdGlvbikge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IHRoaXMub3B0aW9ucy5hY3RpdmVDb25kaXRpb24oKTtcblx0XHRcdFx0aWYgKHJlc3VsdCA9PT0gZmFsc2UpIHRoaXMuZGlzYWJsZSgpO2Vsc2UgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkgdGhpcy5lbmFibGUoKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoXCJFcnJvciB3aGlsZSBldmFsdWF0aW5nIGFjdGl2ZUNvbmRpdGlvbigpIHNjcmlwdCBmb3IgYWN0aW9uIFwiICsgdGhpcy5vcHRpb25zLm5hbWUpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAodGhpcy5jb250ZXh0SGlkZGVuIHx8ICF0aGlzLmNvbnRleHQuc2VsZWN0aW9uKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHZhciB1c2VyU2VsZWN0aW9uID0gYXJndW1lbnRzWzBdO1xuXHRcdHZhciBoYXNSb290ID0gZmFsc2U7XG5cdFx0aWYgKHVzZXJTZWxlY3Rpb24gIT0gbnVsbCkge1xuXHRcdFx0aGFzUm9vdCA9IHVzZXJTZWxlY3Rpb24uc2VsZWN0aW9uSGFzUm9vdE5vZGUoKTtcblx0XHRcdHZhciBiVW5pcXVlID0gdXNlclNlbGVjdGlvbi5pc1VuaXF1ZSgpO1xuXHRcdFx0dmFyIGJGaWxlID0gdXNlclNlbGVjdGlvbi5oYXNGaWxlKCk7XG5cdFx0XHR2YXIgYkRpciA9IHVzZXJTZWxlY3Rpb24uaGFzRGlyKCk7XG5cdFx0XHR2YXIgYlJlY3ljbGUgPSB1c2VyU2VsZWN0aW9uLmlzUmVjeWNsZSgpO1xuXHRcdH1cblx0XHR2YXIgc2VsZWN0aW9uQ29udGV4dCA9IHRoaXMuc2VsZWN0aW9uQ29udGV4dDtcblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMubGVuZ3RoKSB7XG5cdFx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5iZWhhdmlvdXIgPT0gJ2hpZGRlbicpIHRoaXMuaGlkZSgpO2Vsc2UgdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmV2YWxNZXRhZGF0YSAmJiB1c2VyU2VsZWN0aW9uICYmIHVzZXJTZWxlY3Rpb24uaXNVbmlxdWUoKSkge1xuXHRcdFx0dmFyIHJlc3VsdCA9IHRoaXMuX2V2YWxTY3JpcHRzKHNlbGVjdGlvbkNvbnRleHQuZXZhbE1ldGFkYXRhLCB1c2VyU2VsZWN0aW9uLmdldFVuaXF1ZU5vZGUoKS5nZXRNZXRhZGF0YSgpKTtcblx0XHRcdGlmICghcmVzdWx0KSB7XG5cdFx0XHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmJlaGF2aW91ciA9PSAnaGlkZGVuJykgdGhpcy5oaWRlKCk7ZWxzZSB0aGlzLmRpc2FibGUoKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIXNlbGVjdGlvbkNvbnRleHQuZW5hYmxlUm9vdCAmJiBoYXNSb290KSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LnVuaXF1ZSAmJiAhYlVuaXF1ZSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5tdWx0aXBsZU9ubHkgJiYgYlVuaXF1ZSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoKHNlbGVjdGlvbkNvbnRleHQuZmlsZSB8fCBzZWxlY3Rpb25Db250ZXh0LmRpcikgJiYgIWJGaWxlICYmICFiRGlyKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3Rpb25Db250ZXh0LmRpciAmJiAhc2VsZWN0aW9uQ29udGV4dC5maWxlICYmIGJGaWxlIHx8ICFzZWxlY3Rpb25Db250ZXh0LmRpciAmJiBzZWxlY3Rpb25Db250ZXh0LmZpbGUgJiYgYkRpcikge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoIXNlbGVjdGlvbkNvbnRleHQucmVjeWNsZSAmJiBiUmVjeWNsZSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5yaWdodHNDb250ZXh0LndyaXRlICYmIHVzZXJTZWxlY3Rpb24uaGFzUmVhZE9ubHkoKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZGlzYWJsZSgpO1xuXHRcdH1cblx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMubGVuZ3RoICYmIHVzZXJTZWxlY3Rpb24gJiYgc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMuaW5kZXhPZignKicpID09IC0xICYmICF1c2VyU2VsZWN0aW9uLmhhc01pbWUoc2VsZWN0aW9uQ29udGV4dC5hbGxvd2VkTWltZXMpKSB7XG5cdFx0XHRpZiAoc2VsZWN0aW9uQ29udGV4dC5iZWhhdmlvdXIgPT0gJ2hpZGRlbicpIHJldHVybiB0aGlzLmhpZGUoKTtlbHNlIHJldHVybiB0aGlzLmRpc2FibGUoKTtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmxlbmd0aCAmJiB1c2VyU2VsZWN0aW9uICYmIHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmluZGV4T2YoXCJeXCIpICE9PSAtMSkge1xuXHRcdFx0dmFyIGZvcmJpZGRlblZhbHVlRm91bmQgPSBmYWxzZTtcblx0XHRcdHNlbGVjdGlvbkNvbnRleHQuYWxsb3dlZE1pbWVzLmZvckVhY2goZnVuY3Rpb24gKG0pIHtcblx0XHRcdFx0aWYgKG0uaW5kZXhPZihcIl5cIikgPT0gLTEpIHJldHVybjtcblx0XHRcdFx0aWYgKHVzZXJTZWxlY3Rpb24uaGFzTWltZShbbS5yZXBsYWNlKFwiXlwiLCBcIlwiKV0pKSB7XG5cdFx0XHRcdFx0Zm9yYmlkZGVuVmFsdWVGb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0Ly90aHJvdyAkYnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdFx0aWYgKGZvcmJpZGRlblZhbHVlRm91bmQpIHtcblx0XHRcdFx0aWYgKHNlbGVjdGlvbkNvbnRleHQuYmVoYXZpb3VyID09ICdoaWRkZW4nKSByZXR1cm4gdGhpcy5oaWRlKCk7ZWxzZSByZXR1cm4gdGhpcy5kaXNhYmxlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuc2hvdygpO1xuXHRcdHRoaXMuZW5hYmxlKCk7XG5cdH07XG5cblx0QWN0aW9uLnByb3RvdHlwZS5nZXRNZW51RGF0YSA9IGZ1bmN0aW9uIGdldE1lbnVEYXRhKCkge1xuXHRcdHZhciBtZW51SXRlbSA9IHtcblx0XHRcdG5hbWU6IHRoaXMuZ2V0S2V5ZWRUZXh0KCksXG5cdFx0XHRyYXdfbmFtZTogdGhpcy5vcHRpb25zLnRleHQsXG5cdFx0XHRhbHQ6IHRoaXMub3B0aW9ucy50aXRsZSxcblx0XHRcdGFjdGlvbl9pZDogdGhpcy5vcHRpb25zLm5hbWUsXG5cdFx0XHR3ZWlnaHQ6IHRoaXMub3B0aW9ucy53ZWlnaHQgfHwgMCxcblx0XHRcdGNhbGxiYWNrOiAoZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0dGhpcy5hcHBseSgpO1xuXHRcdFx0fSkuYmluZCh0aGlzKVxuXHRcdH07XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5pY29uX2NsYXNzKSB7XG5cdFx0XHRtZW51SXRlbS5pY29uX2NsYXNzID0gdGhpcy5vcHRpb25zLmljb25fY2xhc3M7XG5cdFx0fVxuXHRcdGlmICh0aGlzLm9wdGlvbnMuc3ViTWVudSkge1xuXHRcdFx0bWVudUl0ZW0uc3ViTWVudSA9IFtdO1xuXHRcdFx0aWYgKHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY09wdGlvbnMpIHtcblx0XHRcdFx0bWVudUl0ZW0uc3ViTWVudSA9IHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY09wdGlvbnM7XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXIpIHtcblx0XHRcdFx0bWVudUl0ZW0uc3ViTWVudUJlZm9yZVNob3cgPSB0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlcjtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG1lbnVJdGVtO1xuXHR9O1xuXG5cdC8qKlxuICAqIFBhcnNlcyBhbiBYTUwgZnJhZ21lbnQgdG8gY29uZmlndXJlIHRoaXMgYWN0aW9uXG4gICogQHBhcmFtIHhtbE5vZGUgTm9kZSBYTUwgRnJhZ21lbnQgZGVzY3JpYmluZyB0aGUgYWN0aW9uXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5jcmVhdGVGcm9tWE1MID0gZnVuY3Rpb24gY3JlYXRlRnJvbVhNTCh4bWxOb2RlKSB7XG5cdFx0dmFyIF90aGlzID0gdGhpcztcblxuXHRcdHRoaXMub3B0aW9ucy5uYW1lID0geG1sTm9kZS5nZXRBdHRyaWJ1dGUoJ25hbWUnKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHhtbE5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIG5vZGUgPSB4bWxOb2RlLmNoaWxkTm9kZXNbaV07XG5cdFx0XHR2YXIgZGVmYXVsdEF0dHJpYnV0ZXMgPSB7XG5cdFx0XHRcdGRpcjogXCJkaXJEZWZhdWx0XCIsXG5cdFx0XHRcdGZpbGU6IFwiZmlsZURlZmF1bHRcIixcblx0XHRcdFx0ZHJhZ25kcm9wOiBcImRyYWduZHJvcERlZmF1bHRcIixcblx0XHRcdFx0Y3RybGRyYWduZHJvcDogXCJjdHJsRHJhZ25kcm9wRGVmYXVsdFwiLFxuXHRcdFx0XHRleHBpcmU6IFwiZXhwaXJlRGVmYXVsdFwiXG5cdFx0XHR9O1xuXHRcdFx0Zm9yICh2YXIga2V5IGluIGRlZmF1bHRBdHRyaWJ1dGVzKSB7XG5cdFx0XHRcdGlmICghZGVmYXVsdEF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkoa2V5KSkgY29udGludWU7XG5cdFx0XHRcdHZhciB2YWx1ZSA9IGRlZmF1bHRBdHRyaWJ1dGVzW2tleV07XG5cdFx0XHRcdGlmICh4bWxOb2RlLmdldEF0dHJpYnV0ZSh2YWx1ZSkgJiYgeG1sTm9kZS5nZXRBdHRyaWJ1dGUodmFsdWUpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHRcdFx0aWYgKCF0aGlzLmRlZmF1bHRzKSB0aGlzLmRlZmF1bHRzID0ge307XG5cdFx0XHRcdFx0dGhpcy5kZWZhdWx0c1trZXldID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dmFyIGo7XG5cdFx0XHRpZiAobm9kZS5ub2RlTmFtZSA9PSBcInByb2Nlc3NpbmdcIikge1xuXHRcdFx0XHR2YXIgY2xpZW50Rm9ybURhdGEgPSB7fTtcblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdHZhciBwcm9jZXNzTm9kZSA9IG5vZGUuY2hpbGROb2Rlc1tqXTtcblx0XHRcdFx0XHRpZiAocHJvY2Vzc05vZGUubm9kZU5hbWUgPT0gXCJjbGllbnRDYWxsYmFja1wiKSB7XG5cdFx0XHRcdFx0XHRpZiAocHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCdtb2R1bGUnKSkge1xuXHRcdFx0XHRcdFx0XHQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBmTmFtZSA9IHByb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbW9kdWxlJyk7XG5cdFx0XHRcdFx0XHRcdFx0X3RoaXMub3B0aW9ucy5jYWxsYmFjayA9IGZ1bmN0aW9uIChtYW5hZ2VyLCBvdGhlckFyZ3VtZW50cykge1xuXHRcdFx0XHRcdFx0XHRcdFx0X2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLmRldGVjdE1vZHVsZVRvTG9hZEFuZEFwcGx5KGZOYW1lLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdF91dGlsRnVuY1V0aWxzMlsnZGVmYXVsdCddLmV4ZWN1dGVGdW5jdGlvbkJ5TmFtZShmTmFtZSwgd2luZG93LCBtYW5hZ2VyLCBvdGhlckFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0XHRcdGlmIChfdGhpcy5kZWZhdWx0cyAmJiAoX3RoaXMuZGVmYXVsdHNbJ2RyYWduZHJvcCddIHx8IF90aGlzLmRlZmF1bHRzWydjdHJsZHJhZ25kcm9wJ10pKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRfdGhpcy5vcHRpb25zLmRyYWduZHJvcENoZWNrTW9kdWxlID0gZk5hbWU7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9KSgpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChwcm9jZXNzTm9kZS5maXJzdENoaWxkKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMub3B0aW9ucy5jYWxsYmFja0NvZGUgPSBwcm9jZXNzTm9kZS5maXJzdENoaWxkLm5vZGVWYWx1ZS50cmltKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChwcm9jZXNzTm9kZS5ub2RlTmFtZSA9PSBcImNsaWVudExpc3RlbmVyXCIpIHtcblx0XHRcdFx0XHRcdGlmIChwcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpKSB7XG5cdFx0XHRcdFx0XHRcdChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdFx0dmFyIG1vZHVsZU5hbWUgPSBwcm9jZXNzTm9kZS5nZXRBdHRyaWJ1dGUoJ21vZHVsZScpO1xuXHRcdFx0XHRcdFx0XHRcdF90aGlzLm9wdGlvbnMubGlzdGVuZXJzW3Byb2Nlc3NOb2RlLmdldEF0dHJpYnV0ZSgnbmFtZScpXSA9IChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10uZGV0ZWN0TW9kdWxlVG9Mb2FkQW5kQXBwbHkobW9kdWxlTmFtZSwgKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dmFyIGZ1bmMgPSBfdXRpbEZ1bmNVdGlsczJbJ2RlZmF1bHQnXS5nZXRGdW5jdGlvbkJ5TmFtZShtb2R1bGVOYW1lLCB3aW5kb3cpO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoZnVuYykgZnVuYy5hcHBseSh0aGlzKTtcblx0XHRcdFx0XHRcdFx0XHRcdH0pLmJpbmQodGhpcykpO1xuXHRcdFx0XHRcdFx0XHRcdH0pLmJpbmQoX3RoaXMpO1xuXHRcdFx0XHRcdFx0XHR9KSgpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIGlmIChwcm9jZXNzTm9kZS5maXJzdENoaWxkKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMub3B0aW9ucy5saXN0ZW5lcnNbcHJvY2Vzc05vZGUuZ2V0QXR0cmlidXRlKCduYW1lJyldID0gcHJvY2Vzc05vZGUuZmlyc3RDaGlsZC5ub2RlVmFsdWUudHJpbSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAocHJvY2Vzc05vZGUubm9kZU5hbWUgPT0gXCJhY3RpdmVDb25kaXRpb25cIiAmJiBwcm9jZXNzTm9kZS5maXJzdENoaWxkKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuYWN0aXZlQ29uZGl0aW9uID0gbmV3IEZ1bmN0aW9uKHByb2Nlc3NOb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlLnRyaW0oKSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJndWlcIikge1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMudGV4dF9pZCA9IG5vZGUuZ2V0QXR0cmlidXRlKCd0ZXh0Jyk7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy50aXRsZV9pZCA9IG5vZGUuZ2V0QXR0cmlidXRlKCd0aXRsZScpO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMudGV4dCA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKG5vZGUuZ2V0QXR0cmlidXRlKCd0ZXh0JykpIHx8ICdub3RfZm91bmQnO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShub2RlLmdldEF0dHJpYnV0ZSgndGl0bGUnKSkgfHwgJ25vdF9mb3VuZCc7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy5zcmMgPSBub2RlLmdldEF0dHJpYnV0ZSgnc3JjJyk7XG5cdFx0XHRcdHRoaXMub3B0aW9ucy5pY29uX2NsYXNzID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2ljb25DbGFzcycpO1xuXHRcdFx0XHR0aGlzLm9wdGlvbnMud2VpZ2h0ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3dlaWdodCcpIHx8IDA7XG5cdFx0XHRcdGlmIChub2RlLmdldEF0dHJpYnV0ZSgnaGFzQWNjZXNzS2V5JykgJiYgbm9kZS5nZXRBdHRyaWJ1dGUoJ2hhc0FjY2Vzc0tleScpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLmFjY2Vzc0tleSA9IG5vZGUuZ2V0QXR0cmlidXRlKCdhY2Nlc3NLZXknKTtcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMuaGFzQWNjZXNzS2V5ID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm9kZS5nZXRBdHRyaWJ1dGUoJ3NwZWNpYWxBY2Nlc3NLZXknKSkge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5zcGVjaWFsQWNjZXNzS2V5ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ3NwZWNpYWxBY2Nlc3NLZXknKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRmb3IgKGogPSAwOyBqIDwgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0aWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZSA9PSBcImNvbnRleHRcIikge1xuXHRcdFx0XHRcdFx0dGhpcy5hdHRyaWJ1dGVzVG9PYmplY3QodGhpcy5jb250ZXh0LCBub2RlLmNoaWxkTm9kZXNbal0pO1xuXHRcdFx0XHRcdFx0aWYgKHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cykge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMgPSB0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMuc3BsaXQoJywnKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cyA9IFtdO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Ly8gQmFja3dhcmQgY29tcGF0aWJpbGl0eVxuXHRcdFx0XHRcdFx0aWYgKHRoaXMuY29udGV4dC5pbmZvUGFuZWwpIHRoaXMuY29udGV4dC5hanhwV2lkZ2V0cy5wdXNoKCdJbmZvUGFuZWwnKTtcblx0XHRcdFx0XHRcdGlmICh0aGlzLmNvbnRleHQuYWN0aW9uQmFyKSB0aGlzLmNvbnRleHQuYWp4cFdpZGdldHMucHVzaCgnQWN0aW9uc1Rvb2xiYXInKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKG5vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZSA9PSBcInNlbGVjdGlvbkNvbnRleHRcIikge1xuXHRcdFx0XHRcdFx0dGhpcy5hdHRyaWJ1dGVzVG9PYmplY3QodGhpcy5zZWxlY3Rpb25Db250ZXh0LCBub2RlLmNoaWxkTm9kZXNbal0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChub2RlLm5vZGVOYW1lID09IFwicmlnaHRzQ29udGV4dFwiKSB7XG5cdFx0XHRcdHRoaXMuYXR0cmlidXRlc1RvT2JqZWN0KHRoaXMucmlnaHRzQ29udGV4dCwgbm9kZSk7XG5cdFx0XHR9IGVsc2UgaWYgKG5vZGUubm9kZU5hbWUgPT0gXCJzdWJNZW51XCIpIHtcblx0XHRcdFx0dGhpcy5vcHRpb25zLnN1Yk1lbnUgPSB0cnVlO1xuXHRcdFx0XHRpZiAobm9kZS5nZXRBdHRyaWJ1dGUoXCJ1cGRhdGVJbWFnZU9uU2VsZWN0XCIpICYmIG5vZGUuZ2V0QXR0cmlidXRlKFwidXBkYXRlSW1hZ2VPblNlbGVjdFwiKSA9PSBcInRydWVcIikge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5zdWJNZW51VXBkYXRlSW1hZ2UgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChub2RlLmdldEF0dHJpYnV0ZShcInVwZGF0ZVRpdGxlT25TZWxlY3RcIikgJiYgbm9kZS5nZXRBdHRyaWJ1dGUoXCJ1cGRhdGVUaXRsZU9uU2VsZWN0XCIpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnN1Yk1lbnVVcGRhdGVUaXRsZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG5vZGUuY2hpbGROb2Rlcy5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRcdGlmIChub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWUgPT0gXCJzdGF0aWNJdGVtc1wiIHx8IG5vZGUuY2hpbGROb2Rlc1tqXS5ub2RlTmFtZSA9PSBcImR5bmFtaWNJdGVtc1wiKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnN1Yk1lbnVJdGVtc1tub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWVdID0gW107XG5cdFx0XHRcdFx0XHRmb3IgKHZhciBrID0gMDsgayA8IG5vZGUuY2hpbGROb2Rlc1tqXS5jaGlsZE5vZGVzLmxlbmd0aDsgaysrKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChub2RlLmNoaWxkTm9kZXNbal0uY2hpbGROb2Rlc1trXS5ub2RlTmFtZS5zdGFydHNXaXRoKFwiaXRlbVwiKSkge1xuXHRcdFx0XHRcdFx0XHRcdHZhciBpdGVtID0ge307XG5cdFx0XHRcdFx0XHRcdFx0Zm9yICh2YXIgeiA9IDA7IHogPCBub2RlLmNoaWxkTm9kZXNbal0uY2hpbGROb2Rlc1trXS5hdHRyaWJ1dGVzLmxlbmd0aDsgeisrKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2YXIgYXR0cmlidXRlID0gbm9kZS5jaGlsZE5vZGVzW2pdLmNoaWxkTm9kZXNba10uYXR0cmlidXRlc1t6XTtcblx0XHRcdFx0XHRcdFx0XHRcdGl0ZW1bYXR0cmlidXRlLm5vZGVOYW1lXSA9IGF0dHJpYnV0ZS52YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5zdWJNZW51SXRlbXNbbm9kZS5jaGlsZE5vZGVzW2pdLm5vZGVOYW1lXS5wdXNoKGl0ZW0pO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChub2RlLmNoaWxkTm9kZXNbal0ubm9kZU5hbWUgPT0gXCJkeW5hbWljQnVpbGRlclwiKSB7XG5cdFx0XHRcdFx0XHRpZiAobm9kZS5jaGlsZE5vZGVzW2pdLmdldEF0dHJpYnV0ZShcIm1vZHVsZVwiKSkge1xuXHRcdFx0XHRcdFx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlck1vZHVsZSA9IG5vZGUuY2hpbGROb2Rlc1tqXS5nZXRBdHRyaWJ1dGUoXCJtb2R1bGVcIik7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlckNvZGUgPSBub2RlLmNoaWxkTm9kZXNbal0uZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghdGhpcy5vcHRpb25zLmhhc0FjY2Vzc0tleSkgcmV0dXJuO1xuXHRcdGlmICh0aGlzLm9wdGlvbnMuYWNjZXNzS2V5ID09ICcnIHx8ICF0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZSh0aGlzLm9wdGlvbnMuYWNjZXNzS2V5KSB8fCB0aGlzLm9wdGlvbnMudGV4dC5pbmRleE9mKHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkpKSA9PSAtMSkge1xuXHRcdFx0dGhpcy5vcHRpb25zLmFjY2Vzc0tleSA9IHRoaXMub3B0aW9ucy50ZXh0LmNoYXJBdCgwKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vcHRpb25zLmFjY2Vzc0tleSA9IHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKHRoaXMub3B0aW9ucy5hY2Nlc3NLZXkpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBDcmVhdGVzIHRoZSBzdWJtZW51IGl0ZW1zXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5idWlsZFN1Ym1lbnVTdGF0aWNJdGVtcyA9IGZ1bmN0aW9uIGJ1aWxkU3VibWVudVN0YXRpY0l0ZW1zKCkge1xuXHRcdHZhciBtZW51SXRlbXMgPSBbXTtcblx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuc3RhdGljSXRlbXMpIHtcblx0XHRcdHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY0l0ZW1zLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcblx0XHRcdFx0dmFyIGl0ZW1UZXh0ID0gdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS50ZXh0KTtcblx0XHRcdFx0aWYgKGl0ZW0uaGFzQWNjZXNzS2V5ICYmIChpdGVtLmhhc0FjY2Vzc0tleSA9PSAndHJ1ZScgfHwgaXRlbS5oYXNBY2Nlc3NLZXkgPT09IHRydWUpICYmIHRoaXMubWFuYWdlci5nZXRNZXNzYWdlKGl0ZW0uYWNjZXNzS2V5KSkge1xuXHRcdFx0XHRcdGl0ZW1UZXh0ID0gdGhpcy5nZXRLZXllZFRleHQodGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS50ZXh0KSwgdHJ1ZSwgdGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS5hY2Nlc3NLZXkpKTtcblx0XHRcdFx0XHRpZiAoIXRoaXMuc3ViTWVudUl0ZW1zLmFjY2Vzc0tleXMpIHRoaXMuc3ViTWVudUl0ZW1zLmFjY2Vzc0tleXMgPSBbXTtcblx0XHRcdFx0XHR0aGlzLm1hbmFnZXIucmVnaXN0ZXJLZXkodGhpcy5tYW5hZ2VyLmdldE1lc3NhZ2UoaXRlbS5hY2Nlc3NLZXkpLCB0aGlzLm9wdGlvbnMubmFtZSwgaXRlbS5jb21tYW5kKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRtZW51SXRlbXMucHVzaCh7XG5cdFx0XHRcdFx0bmFtZTogaXRlbVRleHQsXG5cdFx0XHRcdFx0YWx0OiB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShpdGVtLnRpdGxlKSxcblx0XHRcdFx0XHRpbWFnZV91bnJlc29sdmVkOiBpdGVtLnNyYyxcblx0XHRcdFx0XHRpY29uX2NsYXNzOiBpdGVtLmljb25fY2xhc3MsXG5cdFx0XHRcdFx0aXNEZWZhdWx0OiBpdGVtLmlzRGVmYXVsdCA/IHRydWUgOiBmYWxzZSxcblx0XHRcdFx0XHRjYWxsYmFjazogKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHRoaXMuYXBwbHkoW2l0ZW1dKTtcblx0XHRcdFx0XHR9KS5iaW5kKHRoaXMpXG5cdFx0XHRcdH0pO1xuXHRcdFx0fSwgdGhpcyk7XG5cdFx0fVxuXHRcdHRoaXMuc3ViTWVudUl0ZW1zLnN0YXRpY09wdGlvbnMgPSBtZW51SXRlbXM7XG5cdH07XG5cblx0LyoqXG4gICogQ2FjaGVzIHNvbWUgZGF0YSBmb3IgZHluYW1pY2FsbHkgYnVpbHQgbWVudXNcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnByZXBhcmVTdWJtZW51RHluYW1pY0J1aWxkZXIgPSBmdW5jdGlvbiBwcmVwYXJlU3VibWVudUR5bmFtaWNCdWlsZGVyKCkge1xuXHRcdHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyID0gKGZ1bmN0aW9uIChjb250cm9sbGVyKSB7XG5cdFx0XHR2YXIgbWVudUl0ZW1zID0gW107XG5cdFx0XHRpZiAodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJDb2RlKSB7XG5cdFx0XHRcdHdpbmRvdy5idWlsZGVyQ29udGV4dCA9IHRoaXM7XG5cdFx0XHRcdHRoaXMuX2V2YWxTY3JpcHRzKHRoaXMuc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyQ29kZSk7XG5cdFx0XHRcdG1lbnVJdGVtcyA9IHRoaXMuYnVpbGRlck1lbnVJdGVtcyB8fCBbXTtcblx0XHRcdH0gZWxzZSBpZiAodGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0J1aWxkZXJNb2R1bGUpIHtcblx0XHRcdFx0dmFyIGZ1bmMgPSBfdXRpbEZ1bmNVdGlsczJbJ2RlZmF1bHQnXS5nZXRGdW5jdGlvbkJ5TmFtZSh0aGlzLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlck1vZHVsZSwgd2luZG93KTtcblx0XHRcdFx0aWYgKGZ1bmMpIHtcblx0XHRcdFx0XHRtZW51SXRlbXMgPSBmdW5jLmFwcGx5KHRoaXMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtZW51SXRlbXMgPSBbXTtcblx0XHRcdFx0dGhpcy5zdWJNZW51SXRlbXMuZHluYW1pY0l0ZW1zLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcblx0XHRcdFx0XHRpZiAoaXRlbS5zZXBhcmF0b3IpIHtcblx0XHRcdFx0XHRcdG1lbnVJdGVtcy5wdXNoKGl0ZW0pO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR2YXIgYWN0aW9uID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdGlmIChpdGVtWydhY3Rpb25JZCddIGluc3RhbmNlb2YgQWN0aW9uKSB7XG5cdFx0XHRcdFx0XHRhY3Rpb24gPSBpdGVtWydhY3Rpb25JZCddO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRhY3Rpb24gPSB0aGlzLm1hbmFnZXIuYWN0aW9ucy5nZXQoaXRlbVsnYWN0aW9uSWQnXSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChhY3Rpb24uZGVueSkgcmV0dXJuO1xuXHRcdFx0XHRcdHZhciBpdGVtRGF0YSA9IHtcblx0XHRcdFx0XHRcdG5hbWU6IGFjdGlvbi5nZXRLZXllZFRleHQoKSxcblx0XHRcdFx0XHRcdGFsdDogYWN0aW9uLm9wdGlvbnMudGl0bGUsXG5cdFx0XHRcdFx0XHRpY29uX2NsYXNzOiBhY3Rpb24ub3B0aW9ucy5pY29uX2NsYXNzLFxuXHRcdFx0XHRcdFx0aW1hZ2VfdW5yZXNvbHZlZDogYWN0aW9uLm9wdGlvbnMuc3JjLFxuXHRcdFx0XHRcdFx0Y2FsbGJhY2s6IChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuYXBwbHkoKTtcblx0XHRcdFx0XHRcdH0pLmJpbmQoYWN0aW9uKVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0aWYgKGFjdGlvbi5vcHRpb25zLnN1Yk1lbnUpIHtcblx0XHRcdFx0XHRcdGl0ZW1EYXRhLnN1Yk1lbnUgPSBbXTtcblx0XHRcdFx0XHRcdGlmIChhY3Rpb24uc3ViTWVudUl0ZW1zLnN0YXRpY09wdGlvbnMpIHtcblx0XHRcdFx0XHRcdFx0aXRlbURhdGEuc3ViTWVudSA9IGFjdGlvbi5zdWJNZW51SXRlbXMuc3RhdGljT3B0aW9ucztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChhY3Rpb24uc3ViTWVudUl0ZW1zLmR5bmFtaWNCdWlsZGVyKSB7XG5cdFx0XHRcdFx0XHRcdGl0ZW1EYXRhLnN1Yk1lbnVCZWZvcmVTaG93ID0gYWN0aW9uLnN1Yk1lbnVJdGVtcy5keW5hbWljQnVpbGRlcjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bWVudUl0ZW1zLnB1c2goaXRlbURhdGEpO1xuXHRcdFx0XHR9LCB0aGlzKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtZW51SXRlbXM7XG5cdFx0fSkuYmluZCh0aGlzKTtcblx0fTtcblxuXHQvKipcbiAgKiBSZWZyZXNoIGljb24gaW1hZ2Ugc291cmNlXG4gICogQHBhcmFtIG5ld1NyYyBTdHJpbmcgVGhlIGltYWdlIHNvdXJjZS4gQ2FuIHJlZmVyZW5jZSBhbiBpbWFnZSBsaWJyYXJ5XG4gICAgICogQHBhcmFtIGljb25DbGFzcyBTdHJpbmcgT3B0aW9uYWwgY2xhc3MgdG8gcmVwbGFjZSBpbWFnZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuc2V0SWNvbkNsYXNzTmFtZSA9IGZ1bmN0aW9uIHNldEljb25DbGFzc05hbWUoaWNvbkNsYXNzKSB7XG5cdFx0dmFyIGljb25fY2xhc3MgPSB0aGlzLm9wdGlvbnMuaWNvbl9jbGFzcztcblxuXHRcdHRoaXMubm90aWZ5KFwidXBkYXRlX2ljb25cIiwgeyBuZXdfY2xhc3M6IGljb25DbGFzcywgcHJldmlvdXNfY2xhc3M6IGljb25fY2xhc3MgfSk7XG5cdFx0dGhpcy5vcHRpb25zLmljb25fY2xhc3MgPSBpY29uQ2xhc3M7XG5cdH07XG5cblx0LyoqXG4gICogUmVmcmVzaCB0aGUgYWN0aW9uIGxhYmVsXG4gICogQHBhcmFtIG5ld0xhYmVsIFN0cmluZyB0aGUgbmV3IGxhYmVsXG4gICogQHBhcmFtIG5ld1RpdGxlIFN0cmluZyB0aGUgbmV3IHRvb2x0aXBcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnNldExhYmVsID0gZnVuY3Rpb24gc2V0TGFiZWwobmV3TGFiZWwsIG5ld1RpdGxlKSB7XG5cdFx0dGhpcy5vcHRpb25zLnRleHQgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShuZXdMYWJlbCk7XG5cdFx0dGhpcy5ub3RpZnkoXCJ1cGRhdGVfbGFiZWxcIiwgdGhpcy5nZXRLZXllZFRleHQoKSk7XG5cdFx0aWYgKG5ld1RpdGxlKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMudGl0bGUgPSB0aGlzLm1hbmFnZXIuZ2V0TWVzc2FnZShuZXdUaXRsZSk7XG5cdFx0XHR0aGlzLm5vdGlmeShcInVwZGF0ZV90aXRsZVwiLCB0aGlzLm9wdGlvbnMudGl0bGUpO1xuXHRcdH1cblx0fTtcblxuXHRBY3Rpb24ucHJvdG90eXBlLnJlZnJlc2hJbnN0YW5jZXMgPSBmdW5jdGlvbiByZWZyZXNoSW5zdGFuY2VzKCkge307XG5cblx0LyoqXG4gICogR3JhYiBpdHMgbGFiZWwgZnJvbSB0aGUgaTE4blxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUucmVmcmVzaEZyb21JMThOSGFzaCA9IGZ1bmN0aW9uIHJlZnJlc2hGcm9tSTE4Tkhhc2goKSB7XG5cdFx0dGhpcy5zZXRMYWJlbCh0aGlzLm9wdGlvbnMudGV4dF9pZCwgdGhpcy5vcHRpb25zLnRpdGxlX2lkKTtcblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm4gZGF0YSBuZWNlc3NhcnkgdG8gYnVpbGQgSW5mb1BhbmVsXG4gICogQHJldHVybnMgT2JqZWN0XG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS50b0luZm9QYW5lbCA9IGZ1bmN0aW9uIHRvSW5mb1BhbmVsKCkge1xuXHRcdHJldHVybiB0aGlzLm9wdGlvbnM7XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJuIG5lY2Vzc2FyeSBkYXRhIHRvIGJ1aWxkIGNvbnRleHR1YWwgbWVudVxuICAqIEByZXR1cm5zIE9iamVjdFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUudG9Db250ZXh0TWVudSA9IGZ1bmN0aW9uIHRvQ29udGV4dE1lbnUoKSB7XG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucztcblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIHNob3cvaGlkZSBzdGF0ZVxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuaGlkZUZvckNvbnRleHQgPSBmdW5jdGlvbiBoaWRlRm9yQ29udGV4dCgpIHtcblx0XHR0aGlzLmhpZGUoKTtcblx0XHR0aGlzLmNvbnRleHRIaWRkZW4gPSB0cnVlO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgc2hvdy9oaWRlIHN0YXRlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5zaG93Rm9yQ29udGV4dCA9IGZ1bmN0aW9uIHNob3dGb3JDb250ZXh0KGRhdGFNb2RlbCkge1xuXHRcdHRoaXMuY29udGV4dEhpZGRlbiA9IGZhbHNlO1xuXHRcdHRoaXMuc2hvdygpO1xuXHRcdGlmICh0aGlzLnNlbGVjdGlvbkNvbnRleHQpIHtcblx0XHRcdHRoaXMuZmlyZVNlbGVjdGlvbkNoYW5nZShkYXRhTW9kZWwpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBDaGFuZ2VzIHNob3cvaGlkZSBzdGF0ZVxuICAqIE5vdGlmaWVzIFwiaGlkZVwiIEV2ZW50XG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gaGlkZSgpIHtcblx0XHR0aGlzLmRlbnkgPSB0cnVlO1xuXHRcdHRoaXMubm90aWZ5KCdoaWRlJyk7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBzaG93L2hpZGUgc3RhdGVcbiAgKiBOb3RpZmllcyBcInNob3dcIiBFdmVudCBcbiAgKi9cblxuXHRBY3Rpb24ucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiBzaG93KCkge1xuXHRcdHRoaXMuZGVueSA9IGZhbHNlO1xuXHRcdHRoaXMubm90aWZ5KCdzaG93Jyk7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyBlbmFibGUvZGlzYWJsZSBzdGF0ZVxuICAqIE5vdGlmaWVzIFwiZGlzYWJsZVwiIEV2ZW50IFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uIGRpc2FibGUoKSB7XG5cdFx0dGhpcy5kZW55ID0gdHJ1ZTtcblx0XHR0aGlzLm5vdGlmeSgnZGlzYWJsZScpO1xuXHR9O1xuXG5cdC8qKlxuICAqIENoYW5nZXMgZW5hYmxlL2Rpc2FibGUgc3RhdGVcbiAgKiBOb3RpZmllcyBcImVuYWJsZVwiIEV2ZW50IFxuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gZW5hYmxlKCkge1xuXHRcdHRoaXMuZGVueSA9IGZhbHNlO1xuXHRcdHRoaXMubm90aWZ5KCdlbmFibGUnKTtcblx0fTtcblxuXHQvKipcbiAgKiBUbyBiZSBjYWxsZWQgd2hlbiByZW1vdmluZ1xuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gcmVtb3ZlKCkge1xuXHRcdHRoaXMubm90aWZ5KFwicmVtb3ZlXCIpO1xuXHR9O1xuXG5cdC8qKlxuICAqIENyZWF0ZSBhIHRleHQgbGFiZWwgd2l0aCBhY2Nlc3Mta2V5IHVuZGVybGluZWQuXG4gICogQHBhcmFtIGRpc3BsYXlTdHJpbmcgU3RyaW5nIHRoZSBsYWJlbFxuICAqIEBwYXJhbSBoYXNBY2Nlc3NLZXkgQm9vbGVhbiB3aGV0aGVyIHRoZXJlIGlzIGFuIGFjY2Vzc0tleSBvciBub3RcbiAgKiBAcGFyYW0gYWNjZXNzS2V5IFN0cmluZyBUaGUga2V5IHRvIHVuZGVybGluZVxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdEFjdGlvbi5wcm90b3R5cGUuZ2V0S2V5ZWRUZXh0ID0gZnVuY3Rpb24gZ2V0S2V5ZWRUZXh0KGRpc3BsYXlTdHJpbmcsIGhhc0FjY2Vzc0tleSwgYWNjZXNzS2V5KSB7XG5cdFx0aWYgKCFkaXNwbGF5U3RyaW5nKSB7XG5cdFx0XHRkaXNwbGF5U3RyaW5nID0gdGhpcy5vcHRpb25zLnRleHQ7XG5cdFx0fVxuXHRcdGlmICghaGFzQWNjZXNzS2V5KSB7XG5cdFx0XHRoYXNBY2Nlc3NLZXkgPSB0aGlzLm9wdGlvbnMuaGFzQWNjZXNzS2V5O1xuXHRcdH1cblx0XHRpZiAoIWFjY2Vzc0tleSkge1xuXHRcdFx0YWNjZXNzS2V5ID0gdGhpcy5vcHRpb25zLmFjY2Vzc0tleTtcblx0XHR9XG5cdFx0aWYgKCFoYXNBY2Nlc3NLZXkpIHJldHVybiBkaXNwbGF5U3RyaW5nO1xuXHRcdHZhciBrZXlQb3MgPSBkaXNwbGF5U3RyaW5nLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihhY2Nlc3NLZXkudG9Mb3dlckNhc2UoKSk7XG5cdFx0aWYgKGtleVBvcyA9PSAtMSkge1xuXHRcdFx0cmV0dXJuIGRpc3BsYXlTdHJpbmcgKyAnICg8dT4nICsgYWNjZXNzS2V5ICsgJzwvdT4pJztcblx0XHR9XG5cdFx0aWYgKGRpc3BsYXlTdHJpbmcuY2hhckF0KGtleVBvcykgIT0gYWNjZXNzS2V5KSB7XG5cdFx0XHQvLyBjYXNlIGRpZmZlclxuXHRcdFx0YWNjZXNzS2V5ID0gZGlzcGxheVN0cmluZy5jaGFyQXQoa2V5UG9zKTtcblx0XHR9XG5cdFx0dmFyIHJldHVyblN0cmluZyA9IGRpc3BsYXlTdHJpbmcuc3Vic3RyaW5nKDAsIGRpc3BsYXlTdHJpbmcuaW5kZXhPZihhY2Nlc3NLZXkpKTtcblx0XHRyZXR1cm5TdHJpbmcgKz0gJzx1PicgKyBhY2Nlc3NLZXkgKyAnPC91Pic7XG5cdFx0cmV0dXJuU3RyaW5nICs9IGRpc3BsYXlTdHJpbmcuc3Vic3RyaW5nKGRpc3BsYXlTdHJpbmcuaW5kZXhPZihhY2Nlc3NLZXkpICsgMSwgZGlzcGxheVN0cmluZy5sZW5ndGgpO1xuXHRcdHJldHVybiByZXR1cm5TdHJpbmc7XG5cdH07XG5cblx0LyoqXG4gICogVXRpbGl0YXJ5IGZ1bmN0aW9uIHRvIHRyYW5zZm9ybSBYTUwgTm9kZSBhdHRyaWJ1dGVzIGludG8gT2JqZWN0IG1hcHBpbmcga2V5cy5cbiAgKiBAcGFyYW0gb2JqZWN0IE9iamVjdCBUaGUgdGFyZ2V0IG9iamVjdFxuICAqIEBwYXJhbSBub2RlIE5vZGUgVGhlIHNvdXJjZSBub2RlXG4gICovXG5cblx0QWN0aW9uLnByb3RvdHlwZS5hdHRyaWJ1dGVzVG9PYmplY3QgPSBmdW5jdGlvbiBhdHRyaWJ1dGVzVG9PYmplY3Qob2JqZWN0LCBub2RlKSB7XG5cdFx0Zm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuXHRcdFx0aWYgKCFvYmplY3QuaGFzT3duUHJvcGVydHkoa2V5KSB8fCAhbm9kZS5nZXRBdHRyaWJ1dGUoa2V5KSkgY29udGludWU7XG5cdFx0XHR2YXIgdmFsdWUgPSBub2RlLmdldEF0dHJpYnV0ZShrZXkpO1xuXHRcdFx0aWYgKHZhbHVlID09ICd0cnVlJykgdmFsdWUgPSB0cnVlO2Vsc2UgaWYgKHZhbHVlID09ICdmYWxzZScpIHZhbHVlID0gZmFsc2U7XG5cdFx0XHRpZiAoa2V5ID09ICdhbGxvd2VkTWltZXMnKSB7XG5cdFx0XHRcdGlmICh2YWx1ZSAmJiB2YWx1ZS5zcGxpdCgnLCcpLmxlbmd0aCkge1xuXHRcdFx0XHRcdHZhbHVlID0gdmFsdWUuc3BsaXQoJywnKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR2YWx1ZSA9IFtdO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvYmplY3Rba2V5XSA9IHZhbHVlO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gQWN0aW9uO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQWN0aW9uO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cblwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBcImRlZmF1bHRcIjogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgXCIgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBDb250ZXh0TWVudU1vZGVsID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhDb250ZXh0TWVudU1vZGVsLCBfT2JzZXJ2YWJsZSk7XG5cbiAgICBmdW5jdGlvbiBDb250ZXh0TWVudU1vZGVsKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29udGV4dE1lbnVNb2RlbCk7XG5cbiAgICAgICAgX09ic2VydmFibGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZVtcInN1cGVyXCJdID0gZnVuY3Rpb24gX3N1cGVyKCkge1xuICAgICAgICB0aGlzLl9jdXJyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMuX3Bvc2l0aW9uID0gbnVsbDtcbiAgICB9O1xuXG4gICAgQ29udGV4dE1lbnVNb2RlbC5nZXRJbnN0YW5jZSA9IGZ1bmN0aW9uIGdldEluc3RhbmNlKCkge1xuICAgICAgICBpZiAoIUNvbnRleHRNZW51TW9kZWwuX19JTlNUQU5DRSkge1xuICAgICAgICAgICAgQ29udGV4dE1lbnVNb2RlbC5fX0lOU1RBTkNFID0gbmV3IENvbnRleHRNZW51TW9kZWwoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ29udGV4dE1lbnVNb2RlbC5fX0lOU1RBTkNFO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZS5vcGVuQXRQb3NpdGlvbiA9IGZ1bmN0aW9uIG9wZW5BdFBvc2l0aW9uKGNsaWVudFgsIGNsaWVudFkpIHtcbiAgICAgICAgdGhpcy5fY3VycmVudE5vZGUgPSBudWxsO1xuICAgICAgICB0aGlzLl9wb3NpdGlvbiA9IHsgeDogY2xpZW50WCwgeTogY2xpZW50WSB9O1xuICAgICAgICB0aGlzLm5vdGlmeShcIm9wZW5cIik7XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlLm9wZW5Ob2RlQXRQb3NpdGlvbiA9IGZ1bmN0aW9uIG9wZW5Ob2RlQXRQb3NpdGlvbihub2RlLCBjbGllbnRYLCBjbGllbnRZKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnROb2RlID0gbm9kZTtcbiAgICAgICAgdGhpcy5fcG9zaXRpb24gPSB7IHg6IGNsaWVudFgsIHk6IGNsaWVudFkgfTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJvcGVuXCIsIG5vZGUpO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZS5nZXROb2RlID0gZnVuY3Rpb24gZ2V0Tm9kZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnROb2RlO1xuICAgIH07XG5cbiAgICBDb250ZXh0TWVudU1vZGVsLnByb3RvdHlwZS5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uIGdldFBvc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcG9zaXRpb247XG4gICAgfTtcblxuICAgIENvbnRleHRNZW51TW9kZWwucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnROb2RlID0gbnVsbDtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJjbG9zZVwiKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIENvbnRleHRNZW51TW9kZWw7XG59KShfbGFuZ09ic2VydmFibGUyW1wiZGVmYXVsdFwiXSk7XG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gQ29udGV4dE1lbnVNb2RlbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1tcImRlZmF1bHRcIl07XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4uL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBfQWN0aW9uID0gcmVxdWlyZSgnLi9BY3Rpb24nKTtcblxudmFyIF9BY3Rpb24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQWN0aW9uKTtcblxuLyoqXG4gKiBTaW5nbGV0b24gY2xhc3MgdGhhdCBtYW5hZ2VzIGFsbCBhY3Rpb25zLiBDYW4gYmUgY2FsbGVkIGRpcmVjdGx5IHVzaW5nIHB5ZGlvLmdldENvbnRyb2xsZXIoKS5cbiAqL1xuXG52YXIgQ29udHJvbGxlciA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoQ29udHJvbGxlciwgX09ic2VydmFibGUpO1xuXG4gICAgLyoqXG4gICAgICogU3RhbmRhcmQgY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gcHlkaW9PYmplY3QgUHlkaW9cbiAgICAgKiBAcGFyYW0gZGF0YU1vZGVsRWxlbWVudElkXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBDb250cm9sbGVyKHB5ZGlvT2JqZWN0KSB7XG4gICAgICAgIHZhciBkYXRhTW9kZWxFbGVtZW50SWQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDb250cm9sbGVyKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLl9weWRpb09iamVjdCA9IHB5ZGlvT2JqZWN0O1xuICAgICAgICB0aGlzLl9yZWdpc3RlcmVkS2V5cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy51c2Vyc0VuYWJsZWQgPSBweWRpb09iamVjdC5QYXJhbWV0ZXJzLmdldChcInVzZXJzRW5hYmxlZFwiKTtcblxuICAgICAgICB0aGlzLnN1Yk1lbnVzID0gW107XG4gICAgICAgIHRoaXMuYWN0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5kZWZhdWx0QWN0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy50b29sYmFycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fZ3VpQWN0aW9ucyA9IG5ldyBNYXAoKTtcblxuICAgICAgICB0aGlzLmNvbnRleHRDaGFuZ2VkT2JzID0gKGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVDb250ZXh0Q2hhbmdlKCk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpLCAwKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkT2JzID0gKGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmVTZWxlY3Rpb25DaGFuZ2UoKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyksIDApO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuXG4gICAgICAgIGlmIChkYXRhTW9kZWxFbGVtZW50SWQpIHtcbiAgICAgICAgICAgIHRoaXMubG9jYWxEYXRhTW9kZWwgPSB0cnVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkYXRhTW9kZWxFbGVtZW50SWQpLmFqeHBQYW5lT2JqZWN0LmdldERhdGFNb2RlbCgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgIGlmICh0aGlzLl9kYXRhTW9kZWwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9jb25uZWN0RGF0YU1vZGVsKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0Lm9ic2VydmVPbmNlKFwiZGF0YW1vZGVsLWxvYWRlZC1cIiArIGRhdGFNb2RlbEVsZW1lbnRJZCwgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGF0YU1vZGVsRWxlbWVudElkKS5hanhwUGFuZU9iamVjdC5nZXREYXRhTW9kZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29ubmVjdERhdGFNb2RlbCgpO1xuICAgICAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sb2NhbERhdGFNb2RlbCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fY29ubmVjdERhdGFNb2RlbCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMudXNlcnNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5vYnNlcnZlKFwidXNlcl9sb2dnZWRcIiwgKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKHVzZXIpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fcHlkaW9PYmplY3QudXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXNlcih0aGlzLl9weWRpb09iamVjdC51c2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnB1Ymxpc2hBY3Rpb25FdmVudCA9IGZ1bmN0aW9uIHB1Ymxpc2hBY3Rpb25FdmVudChldmVudE5hbWUsIGRhdGEpIHtcbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZmlyZShldmVudE5hbWUsIGRhdGEpO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5fY29ubmVjdERhdGFNb2RlbCA9IGZ1bmN0aW9uIF9jb25uZWN0RGF0YU1vZGVsKCkge1xuICAgICAgICBpZiAodGhpcy5sb2NhbERhdGFNb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsLm9ic2VydmUoXCJjb250ZXh0X2NoYW5nZWRcIiwgdGhpcy5jb250ZXh0Q2hhbmdlZE9icyk7XG4gICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwub2JzZXJ2ZShcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZE9icyk7XG4gICAgICAgICAgICB0aGlzLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KCk7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5vYnNlcnZlKFwicmVnaXN0cnlfbG9hZGVkXCIsIChmdW5jdGlvbiAocmVnaXN0cnkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KHJlZ2lzdHJ5KTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3Qub2JzZXJ2ZShcImNvbnRleHRfY2hhbmdlZFwiLCB0aGlzLmNvbnRleHRDaGFuZ2VkT2JzKTtcbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0Lm9ic2VydmUoXCJzZWxlY3Rpb25fY2hhbmdlZFwiLCB0aGlzLnNlbGVjdGlvbkNoYW5nZWRPYnMpO1xuICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsID0gdGhpcy5fcHlkaW9PYmplY3QuZ2V0Q29udGV4dEhvbGRlcigpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnVwZGF0ZUd1aUFjdGlvbnMgPSBmdW5jdGlvbiB1cGRhdGVHdWlBY3Rpb25zKGFjdGlvbnMpIHtcbiAgICAgICAgYWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAodiwgaykge1xuICAgICAgICAgICAgdGhpcy5fZ3VpQWN0aW9ucy5zZXQoaywgdik7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyQWN0aW9uKHYpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgLy90aGlzLm5vdGlmeShcImFjdGlvbnNfcmVmcmVzaGVkXCIpO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5kZWxldGVGcm9tR3VpQWN0aW9ucyA9IGZ1bmN0aW9uIGRlbGV0ZUZyb21HdWlBY3Rpb25zKGFjdGlvbk5hbWUpIHtcbiAgICAgICAgdGhpcy5fZ3VpQWN0aW9uc1snZGVsZXRlJ10oYWN0aW9uTmFtZSk7XG4gICAgICAgIC8vdGhpcy5ub3RpZnkoXCJhY3Rpb25zX3JlZnJlc2hlZFwiKTtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucmVmcmVzaEd1aUFjdGlvbnNJMThuID0gZnVuY3Rpb24gcmVmcmVzaEd1aUFjdGlvbnNJMThuKCkge1xuICAgICAgICB0aGlzLl9ndWlBY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIHZhbHVlLnJlZnJlc2hGcm9tSTE4Tkhhc2goKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldERhdGFNb2RlbCA9IGZ1bmN0aW9uIGdldERhdGFNb2RlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGFNb2RlbDtcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgIGlmICh0aGlzLmxvY2FsRGF0YU1vZGVsICYmIHRoaXMuX2RhdGFNb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5fZGF0YU1vZGVsLnN0b3BPYnNlcnZpbmcoXCJjb250ZXh0X2NoYW5nZWRcIiwgdGhpcy5jb250ZXh0Q2hhbmdlZE9icyk7XG4gICAgICAgICAgICB0aGlzLl9kYXRhTW9kZWwuc3RvcE9ic2VydmluZyhcInNlbGVjdGlvbl9jaGFuZ2VkXCIsIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZE9icyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0TWVzc2FnZSA9IGZ1bmN0aW9uIGdldE1lc3NhZ2UobWVzc2FnZUlkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcHlkaW9PYmplY3QuTWVzc2FnZUhhc2hbbWVzc2FnZUlkXTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2VJZDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDT01QQVRJQklMSVRZIE1FVEhEXG4gICAgICogQHBhcmFtIHhtbERvY1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucGFyc2VYbWxNZXNzYWdlID0gZnVuY3Rpb24gcGFyc2VYbWxNZXNzYWdlKHhtbERvYykge1xuICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5kZWJ1ZyhcIkNvbnRyb2xsZXIucGFyc2VYbWxNZXNzYWdlKCkgaXMgZGVwcmVjYXRlZCwgdXNlIFB5ZGlvQXBpIGluc3RlYWRcIik7XG4gICAgICAgIHJldHVybiBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnBhcnNlWG1sTWVzc2FnZSh4bWxEb2MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTdWJtaXRzIGEgZm9ybSB1c2luZyBDb25uZXhpb24gY2xhc3MuXG4gICAgICogQHBhcmFtIGZvcm1OYW1lIFN0cmluZyBUaGUgaWQgb2YgdGhlIGZvcm1cbiAgICAgKiBAcGFyYW0gcG9zdCBCb29sZWFuIFdoZXRoZXIgdG8gUE9TVCBvciBHRVRcbiAgICAgKiBAcGFyYW0gY29tcGxldGVDYWxsYmFjayBGdW5jdGlvbiBDYWxsYmFjayB0byBiZSBjYWxsZWQgb24gY29tcGxldGVcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnN1Ym1pdEZvcm0gPSBmdW5jdGlvbiBzdWJtaXRGb3JtKGZvcm1OYW1lLCBwb3N0LCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmRlYnVnKFwiQ29udHJvbGxlci5zdWJtaXRGb3JtKCkgaXMgZGVwcmVjYXRlZCwgdXNlIFB5ZGlvQXBpIGluc3RlYWRcIik7XG4gICAgICAgIHJldHVybiBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnN1Ym1pdEZvcm0oZm9ybU5hbWUsIHBvc3QsIGNvbXBsZXRlQ2FsbGJhY2spO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTdG9yZXMgdGhlIGN1cnJlbnRseSBsb2dnZWQgdXNlciBvYmplY3RcbiAgICAgKiBAcGFyYW0gb1VzZXIgVXNlciBVc2VyIGluc3RhbmNlXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5zZXRVc2VyID0gZnVuY3Rpb24gc2V0VXNlcihvVXNlcikge1xuICAgICAgICB0aGlzLm9Vc2VyID0gb1VzZXI7XG4gICAgICAgIGlmIChvVXNlciAhPSBudWxsICYmIG9Vc2VyLmlkICE9ICdndWVzdCcgJiYgb1VzZXIuZ2V0UHJlZmVyZW5jZSgnbGFuZycpICE9IG51bGwgJiYgb1VzZXIuZ2V0UHJlZmVyZW5jZSgnbGFuZycpICE9IFwiXCIgJiYgb1VzZXIuZ2V0UHJlZmVyZW5jZSgnbGFuZycpICE9IHRoaXMuX3B5ZGlvT2JqZWN0LmN1cnJlbnRMYW5ndWFnZSAmJiAhb1VzZXIubG9jaykge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QubG9hZEkxOE5NZXNzYWdlcyhvVXNlci5nZXRQcmVmZXJlbmNlKCdsYW5nJykpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbHRlciB0aGUgYWN0aW9ucyBnaXZlbiB0aGUgc3JjRWxlbWVudCBwYXNzZWQgYXMgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSBhY3Rpb25zU2VsZWN0b3JBdHQgU3RyaW5nIEFuIGlkZW50aWZpZXIgYW1vbmcgc2VsZWN0aW9uQ29udGV4dCwgZ2VuZXJpY0NvbnRleHQsIGEgd2ViZnggb2JqZWN0IGlkXG4gICAgICAgICogQHBhcmFtIGlnbm9yZUdyb3VwcyBBcnJheSBhIGxpc3Qgb2YgZ3JvdXBzIHRvIGlnbm9yZVxuICAgICAqIEByZXR1cm5zIEFycmF5XG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDb250ZXh0QWN0aW9ucyA9IGZ1bmN0aW9uIGdldENvbnRleHRBY3Rpb25zKGFjdGlvbnNTZWxlY3RvckF0dCwgaWdub3JlR3JvdXBzLCBvbmx5R3JvdXBzKSB7XG4gICAgICAgIHZhciBjb250ZXh0QWN0aW9ucyA9IFtdO1xuICAgICAgICB2YXIgZGVmYXVsdEdyb3VwID0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgY29udGV4dEFjdGlvbnNHcm91cCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghYWN0aW9uLmNvbnRleHQuY29udGV4dE1lbnUgJiYgIShvbmx5R3JvdXBzICYmIG9ubHlHcm91cHMubGVuZ3RoKSkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNTZWxlY3RvckF0dCA9PSAnc2VsZWN0aW9uQ29udGV4dCcgJiYgIWFjdGlvbi5jb250ZXh0LnNlbGVjdGlvbikgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNTZWxlY3RvckF0dCA9PSAnZGlyZWN0b3J5Q29udGV4dCcgJiYgIWFjdGlvbi5jb250ZXh0LmRpcikgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNTZWxlY3RvckF0dCA9PSAnZ2VuZXJpY0NvbnRleHQnICYmIGFjdGlvbi5jb250ZXh0LnNlbGVjdGlvbikgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5jb250ZXh0SGlkZGVuIHx8IGFjdGlvbi5kZW55KSByZXR1cm47XG4gICAgICAgICAgICBhY3Rpb24uY29udGV4dC5hY3Rpb25CYXJHcm91cC5zcGxpdCgnLCcpLmZvckVhY2goZnVuY3Rpb24gKGJhckdyb3VwKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0QWN0aW9uc0dyb3VwLmhhcyhiYXJHcm91cCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dEFjdGlvbnNHcm91cC5zZXQoYmFyR3JvdXAsIFtdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBpc0RlZmF1bHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChhY3Rpb25zU2VsZWN0b3JBdHQgPT0gJ3NlbGVjdGlvbkNvbnRleHQnKSB7XG4gICAgICAgICAgICAgICAgLy8gc2V0IGRlZmF1bHQgaW4gYm9sZFxuICAgICAgICAgICAgICAgIHZhciB1c2VyU2VsZWN0aW9uID0gdGhpcy5fZGF0YU1vZGVsO1xuICAgICAgICAgICAgICAgIGlmICghdXNlclNlbGVjdGlvbi5pc0VtcHR5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmF1bHRBY3Rpb24gPSAnZmlsZSc7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1c2VyU2VsZWN0aW9uLmlzVW5pcXVlKCkgJiYgKHVzZXJTZWxlY3Rpb24uaGFzRGlyKCkgfHwgdXNlclNlbGVjdGlvbi5oYXNNaW1lKFsnYWp4cF9icm93c2FibGVfYXJjaGl2ZSddKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRBY3Rpb24gPSAnZGlyJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZWZhdWx0QWN0aW9ucy5nZXQoZGVmYXVsdEFjdGlvbikgJiYgYWN0aW9uLm9wdGlvbnMubmFtZSA9PSB0aGlzLmRlZmF1bHRBY3Rpb25zLmdldChkZWZhdWx0QWN0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNEZWZhdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGlvbi5jb250ZXh0LmFjdGlvbkJhckdyb3VwLnNwbGl0KCcsJykuZm9yRWFjaChmdW5jdGlvbiAoYmFyR3JvdXApIHtcbiAgICAgICAgICAgICAgICB2YXIgbWVudUl0ZW0gPSBhY3Rpb24uZ2V0TWVudURhdGEoKTtcbiAgICAgICAgICAgICAgICBtZW51SXRlbS5pc0RlZmF1bHQgPSBpc0RlZmF1bHQ7XG4gICAgICAgICAgICAgICAgY29udGV4dEFjdGlvbnNHcm91cC5nZXQoYmFyR3JvdXApLnB1c2gobWVudUl0ZW0pO1xuICAgICAgICAgICAgICAgIGlmIChpc0RlZmF1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdEdyb3VwID0gYmFyR3JvdXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB2YXIgZmlyc3QgPSB0cnVlLFxuICAgICAgICAgICAga2V5cyA9IFtdO1xuICAgICAgICBjb250ZXh0QWN0aW9uc0dyb3VwID0gdGhpcy5fc29ydFRvb2xiYXJzQWN0aW9ucyhjb250ZXh0QWN0aW9uc0dyb3VwKTtcbiAgICAgICAgY29udGV4dEFjdGlvbnNHcm91cC5mb3JFYWNoKGZ1bmN0aW9uICh2LCBrKSB7XG4gICAgICAgICAgICBpZiAoZGVmYXVsdEdyb3VwICYmIGsgPT0gZGVmYXVsdEdyb3VwKSByZXR1cm47XG4gICAgICAgICAgICBrZXlzLnB1c2goayk7XG4gICAgICAgIH0pO1xuICAgICAgICBrZXlzLnNvcnQoKTtcbiAgICAgICAgaWYgKGRlZmF1bHRHcm91cCAmJiBjb250ZXh0QWN0aW9uc0dyb3VwLmhhcyhkZWZhdWx0R3JvdXApKSB7XG4gICAgICAgICAgICBrZXlzLnVuc2hpZnQoZGVmYXVsdEdyb3VwKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYWN0aW9uc1B1c2hlZCA9IHt9O1xuICAgICAgICBrZXlzLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBjb250ZXh0QWN0aW9uc0dyb3VwLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKCFmaXJzdCkge1xuICAgICAgICAgICAgICAgIGNvbnRleHRBY3Rpb25zLnB1c2goeyBzZXBhcmF0b3I6IHRydWUgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaWdub3JlR3JvdXBzICYmIGlnbm9yZUdyb3Vwcy5pbmRleE9mKGtleSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9ubHlHcm91cHMgJiYgb25seUdyb3Vwcy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmlyc3QgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24gKG1JdGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjdGlvbklkID0gbUl0ZW0uYWN0aW9uX2lkO1xuICAgICAgICAgICAgICAgIGlmICghYWN0aW9uc1B1c2hlZFthY3Rpb25JZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dEFjdGlvbnMucHVzaChtSXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnNQdXNoZWRbYWN0aW9uSWRdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb250ZXh0QWN0aW9ucztcbiAgICB9O1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZ2V0VG9vbGJhcnNBY3Rpb25zID0gZnVuY3Rpb24gZ2V0VG9vbGJhcnNBY3Rpb25zKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIHZhciB0b29sYmFyc0xpc3QgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBbXSA6IGFyZ3VtZW50c1swXTtcbiAgICAgICAgdmFyIGdyb3VwT3RoZXJMaXN0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gW10gOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdmFyIHRvb2xiYXJzID0gbmV3IE1hcCgpLFxuICAgICAgICAgICAgZ3JvdXBPdGhlckJhcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHZhciBsYXN0VGJhckFkZGVkID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmFjdGlvbnMuZm9yRWFjaCgoZnVuY3Rpb24gKGFjdGlvbikge1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5jb250ZXh0LmFjdGlvbkJhcikge1xuICAgICAgICAgICAgICAgIGFjdGlvbi5jb250ZXh0LmFjdGlvbkJhckdyb3VwLnNwbGl0KFwiLFwiKS5tYXAoKGZ1bmN0aW9uIChiYXJHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodG9vbGJhcnNMaXN0LmluZGV4T2YoYmFyR3JvdXApID09PSAtMSAmJiBncm91cE90aGVyTGlzdC5pbmRleE9mKGJhckdyb3VwKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgdEJhclVwZGF0ZSA9IHRvb2xiYXJzTGlzdC5pbmRleE9mKGJhckdyb3VwKSAhPT0gLTEgPyB0b29sYmFycyA6IGdyb3VwT3RoZXJCYXJzO1xuICAgICAgICAgICAgICAgICAgICBpZiAodEJhclVwZGF0ZS5nZXQoYmFyR3JvdXApID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRCYXJVcGRhdGUuc2V0KGJhckdyb3VwLCBbXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdEJhclVwZGF0ZS5nZXQoYmFyR3JvdXApLnB1c2goYWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRCYXJVcGRhdGUgPT09IHRvb2xiYXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0VGJhckFkZGVkID0gYmFyR3JvdXA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gUmVncm91cCBhY3Rpb25zIGFydGlmaWNpYWxseVxuICAgICAgICBpZiAoZ3JvdXBPdGhlckxpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBzdWJtZW51SXRlbXMgPSBbXTtcbiAgICAgICAgICAgICAgICBncm91cE90aGVyTGlzdC5tYXAoKGZ1bmN0aW9uIChvdGhlclRvb2xiYXIpIHtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgb3RoZXJBY3Rpb25zID0gZ3JvdXBPdGhlckJhcnMuZ2V0KG90aGVyVG9vbGJhcik7XG4gICAgICAgICAgICAgICAgICAgIGlmICghb3RoZXJBY3Rpb25zKSByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQWN0aW9ucy5tYXAoZnVuY3Rpb24gKGFjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VibWVudUl0ZW1zLnB1c2goeyBhY3Rpb25JZDogYWN0IH0pO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwT3RoZXJMaXN0LmluZGV4T2Yob3RoZXJUb29sYmFyKSA8IGdyb3VwT3RoZXJMaXN0Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Ym1lbnVJdGVtcy5wdXNoKHsgc2VwYXJhdG9yOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSkuYmluZChfdGhpcykpO1xuICAgICAgICAgICAgICAgIHZhciBtb3JlQWN0aW9uID0gbmV3IF9BY3Rpb24yWydkZWZhdWx0J10oe1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAnZ3JvdXBfbW9yZV9hY3Rpb24nLFxuICAgICAgICAgICAgICAgICAgICBpY29uX2NsYXNzOiAnaWNvbi1ub25lJyxcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogTWVzc2FnZUhhc2hbNDU2XSxcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IE1lc3NhZ2VIYXNoWzQ1Nl0sXG4gICAgICAgICAgICAgICAgICAgIGhhc0FjY2Vzc0tleTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIHN1Yk1lbnU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiBjYWxsYmFjaygpIHt9XG4gICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb246IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBkaXI6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbkJhcjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uQmFyR3JvdXA6ICcnLFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0TWVudTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGluZm9QYW5lbDogZmFsc2VcblxuICAgICAgICAgICAgICAgIH0sIHt9LCB7fSwgeyBkeW5hbWljSXRlbXM6IHN1Ym1lbnVJdGVtcyB9KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZWdpc3RlckFjdGlvbihtb3JlQWN0aW9uKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hY3Rpb25zLnNldChcImdyb3VwX21vcmVfYWN0aW9uXCIsIG1vcmVBY3Rpb24pO1xuICAgICAgICAgICAgICAgIHRvb2xiYXJzLnNldCgnTU9SRV9BQ1RJT04nLCBbbW9yZUFjdGlvbl0pO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zb3J0VG9vbGJhcnNBY3Rpb25zKHRvb2xiYXJzKTtcbiAgICAgICAgcmV0dXJuIHRvb2xiYXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmljIG1ldGhvZCB0byBnZXQgYWN0aW9ucyBmb3IgYSBnaXZlbiBjb21wb25lbnQgcGFydC5cbiAgICAgKiBAcGFyYW0gYWp4cENsYXNzTmFtZSBTdHJpbmcgXG4gICAgICogQHBhcmFtIHdpZGdldElkIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIFtdXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5nZXRBY3Rpb25zRm9yQWp4cFdpZGdldCA9IGZ1bmN0aW9uIGdldEFjdGlvbnNGb3JBanhwV2lkZ2V0KGFqeHBDbGFzc05hbWUsIHdpZGdldElkKSB7XG4gICAgICAgIHZhciBhY3Rpb25zID0gW107XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGlmIChhY3Rpb24uY29udGV4dC5hanhwV2lkZ2V0cyAmJiAoYWN0aW9uLmNvbnRleHQuYWp4cFdpZGdldHMuaW5kZXhPZihhanhwQ2xhc3NOYW1lICsgJzo6JyArIHdpZGdldElkKSAhPSAtMSB8fCBhY3Rpb24uY29udGV4dC5hanhwV2lkZ2V0cy5pbmRleE9mKGFqeHBDbGFzc05hbWUpICE9IC0xKSAmJiAhYWN0aW9uLmRlbnkpIGFjdGlvbnMucHVzaChhY3Rpb24pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGFjdGlvbnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIGEgZGVmYXVsdCBhY3Rpb24gYW5kIGZpcmVzIGl0LlxuICAgICAqIEBwYXJhbSBkZWZhdWx0TmFtZSBTdHJpbmcgKFwiZmlsZVwiLCBcImRpclwiLCBcImRyYWduZHJvcFwiLCBcImN0cmxkcmFnbmRyb3BcIilcbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmZpcmVEZWZhdWx0QWN0aW9uID0gZnVuY3Rpb24gZmlyZURlZmF1bHRBY3Rpb24oZGVmYXVsdE5hbWUpIHtcbiAgICAgICAgdmFyIGFjdGlvbk5hbWUgPSB0aGlzLmRlZmF1bHRBY3Rpb25zLmdldChkZWZhdWx0TmFtZSk7XG4gICAgICAgIGlmIChhY3Rpb25OYW1lKSB7XG4gICAgICAgICAgICBhcmd1bWVudHNbMF0gPSBhY3Rpb25OYW1lO1xuICAgICAgICAgICAgaWYgKGFjdGlvbk5hbWUgPT09IFwibHNcIikge1xuICAgICAgICAgICAgICAgIHZhciBhY3Rpb24gPSB0aGlzLmFjdGlvbnMuZ2V0KGFjdGlvbk5hbWUpO1xuICAgICAgICAgICAgICAgIGlmIChhY3Rpb24pIGFjdGlvbi5lbmFibGUoKTsgLy8gRm9yY2UgZW5hYmxlIG9uIGRlZmF1bHQgYWN0aW9uXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmZpcmVBY3Rpb24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaXJlIGFuIGFjdGlvbiBiYXNlZCBvbiBpdHMgbmFtZVxuICAgICAqIEBwYXJhbSBhY3Rpb25OYW1lIFN0cmluZyBUaGUgbmFtZSBvZiB0aGUgYWN0aW9uXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5maXJlQWN0aW9uID0gZnVuY3Rpb24gZmlyZUFjdGlvbihhY3Rpb25OYW1lKSB7XG4gICAgICAgIHZhciBhY3Rpb24gPSB0aGlzLmFjdGlvbnMuZ2V0KGFjdGlvbk5hbWUpO1xuICAgICAgICBpZiAoYWN0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkuZnJvbShhcmd1bWVudHMpLnNsaWNlKDEpO1xuICAgICAgICAgICAgYWN0aW9uLmFwcGx5KGFyZ3MpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbiBhY2Nlc3NrZXkgZm9yIGEgZ2l2ZW4gYWN0aW9uLiBcbiAgICAgKiBAcGFyYW0ga2V5IFN0cmluZyBUaGUgYWNjZXNzIGtleVxuICAgICAqIEBwYXJhbSBhY3Rpb25OYW1lIFN0cmluZyBUaGUgbmFtZSBvZiB0aGUgYWN0aW9uXG4gICAgICogQHBhcmFtIG9wdGlvbm5hbENvbW1hbmQgU3RyaW5nIEFuIG9wdGlvbm5hbCBhcmd1bWVudCBcbiAgICAgKiB0aGF0IHdpbGwgYmUgcGFzc2VkIHRvIHRoZSBhY3Rpb24gd2hlbiBmaXJlZC5cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLnJlZ2lzdGVyS2V5ID0gZnVuY3Rpb24gcmVnaXN0ZXJLZXkoa2V5LCBhY3Rpb25OYW1lLCBvcHRpb25uYWxDb21tYW5kKSB7XG4gICAgICAgIGlmIChvcHRpb25uYWxDb21tYW5kKSB7XG4gICAgICAgICAgICBhY3Rpb25OYW1lID0gYWN0aW9uTmFtZSArIFwiOjpcIiArIG9wdGlvbm5hbENvbW1hbmQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmVnaXN0ZXJlZEtleXMuc2V0KGtleS50b0xvd2VyQ2FzZSgpLCBhY3Rpb25OYW1lKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFsbCByZWdpc3RlcmVkIGtleXMuXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5jbGVhclJlZ2lzdGVyZWRLZXlzID0gZnVuY3Rpb24gY2xlYXJSZWdpc3RlcmVkS2V5cygpIHtcbiAgICAgICAgdGhpcy5fcmVnaXN0ZXJlZEtleXMgPSBuZXcgTWFwKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXJzIGFuIGFjdGlvbiBieSBpdHMgYWNjZXNzIGtleS5cbiAgICAgKiBAcGFyYW0ga2V5TmFtZSBTdHJpbmcgQSBrZXkgbmFtZVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZmlyZUFjdGlvbkJ5S2V5ID0gZnVuY3Rpb24gZmlyZUFjdGlvbkJ5S2V5KGtleU5hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuX3JlZ2lzdGVyZWRLZXlzLmdldChrZXlOYW1lKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3JlZ2lzdGVyZWRLZXlzLmdldChrZXlOYW1lKS5pbmRleE9mKFwiOjpcIikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcnRzID0gdGhpcy5fcmVnaXN0ZXJlZEtleXMuZ2V0KGtleU5hbWUpLnNwbGl0KFwiOjpcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQWN0aW9uKHBhcnRzWzBdLCBwYXJ0c1sxXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUFjdGlvbih0aGlzLl9yZWdpc3RlcmVkS2V5cy5nZXQoa2V5TmFtZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDb21wbGV4IGZ1bmN0aW9uIGNhbGxlZCB3aGVuIGRyYWcnbidkcm9wcGluZy4gQmFzaWMgY2hlY2tzIG9mIHdobyBpcyBjaGlsZCBvZiB3aG8uXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFN0cmluZyBUaGUgZHJhZ2dlZCBlbGVtZW50IFxuICAgICAqIEBwYXJhbSBkZXN0RGlyIFN0cmluZyBUaGUgZHJvcCB0YXJnZXQgbm9kZSBwYXRoXG4gICAgICogQHBhcmFtIGRlc3ROb2RlTmFtZSBTdHJpbmcgVGhlIGRyb3AgdGFyZ2V0IG5vZGUgbmFtZVxuICAgICAqIEBwYXJhbSBjb3B5IEJvb2xlYW4gQ29weSBvciBNb3ZlXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5hcHBseURyYWdNb3ZlID0gZnVuY3Rpb24gYXBwbHlEcmFnTW92ZShmaWxlTmFtZSwgZGVzdERpciwgZGVzdE5vZGVOYW1lLCBjb3B5KSB7XG4gICAgICAgIGlmICghY29weSAmJiAoIXRoaXMuZGVmYXVsdEFjdGlvbnMuaGFzKCdkcmFnbmRyb3AnKSB8fCB0aGlzLmdldERlZmF1bHRBY3Rpb24oJ2RyYWduZHJvcCcpLmRlbnkpIHx8IGNvcHkgJiYgKCF0aGlzLmRlZmF1bHRBY3Rpb25zLmhhcygnY3RybGRyYWduZHJvcCcpIHx8IHRoaXMuZ2V0RGVmYXVsdEFjdGlvbignY3RybGRyYWduZHJvcCcpLmRlbnkpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZpbGVOYW1lcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGZpbGVOYW1lID09IG51bGwpIGZpbGVOYW1lcyA9IHRoaXMuX2RhdGFNb2RlbC5nZXRGaWxlTmFtZXMoKTtlbHNlIGZpbGVOYW1lcyA9IFtmaWxlTmFtZV07XG4gICAgICAgIC8vIENoZWNrIHRoYXQgZGVzdCBpcyBub3QgdGhlIGRpcmVjdCBwYXJlbnQgb2Ygc291cmNlLCBpZSBjdXJyZW50IHJlcCFcbiAgICAgICAgaWYgKGRlc3REaXIgPT0gdGhpcy5fZGF0YU1vZGVsLmdldENvbnRleHROb2RlKCkuZ2V0UGF0aCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9weWRpb09iamVjdC5kaXNwbGF5TWVzc2FnZSgnRVJST1InLCBNZXNzYWdlSGFzaFsyMDNdKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGVjayB0aGF0IGRlc3QgaXMgbm90IGNoaWxkIG9mIHNvdXJjZSBpdCBzZWxmXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmlsZU5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoZGVzdERpci5sYXN0SW5kZXhPZihmaWxlTmFtZXNbaV0sIDApID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZGlzcGxheU1lc3NhZ2UoJ0VSUk9SJywgTWVzc2FnZUhhc2hbMjAyXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB7fTtcbiAgICAgICAgcGFyYW1zWydnZXRfYWN0aW9uJ10gPSB0aGlzLmRlZmF1bHRBY3Rpb25zLmdldChjb3B5ID8gJ2N0cmxkcmFnbmRyb3AnIDogJ2RyYWduZHJvcCcpO1xuICAgICAgICBwYXJhbXNbJ25vZGVzW10nXSA9IGZpbGVOYW1lcztcbiAgICAgICAgcGFyYW1zWydkZXN0J10gPSBkZXN0RGlyO1xuICAgICAgICBwYXJhbXNbJ2RpciddID0gdGhpcy5fZGF0YU1vZGVsLmdldENvbnRleHROb2RlKCkuZ2V0UGF0aCgpO1xuICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdGhpcy5wYXJzZVhtbE1lc3NhZ2UodHJhbnNwb3J0LnJlc3BvbnNlWE1MKTtcbiAgICAgICAgfSkuYmluZChfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgYWN0aW9uIGRlZmluZWQgYXMgZGVmYXVsdCBmb3IgYSBnaXZlbiBkZWZhdWx0IHN0cmluZ1xuICAgICAqIEBwYXJhbSBkZWZhdWx0TmFtZSBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBBY3Rpb25cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldERlZmF1bHRBY3Rpb24gPSBmdW5jdGlvbiBnZXREZWZhdWx0QWN0aW9uKGRlZmF1bHROYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmRlZmF1bHRBY3Rpb25zLmhhcyhkZWZhdWx0TmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFjdGlvbnMuZ2V0KHRoaXMuZGVmYXVsdEFjdGlvbnMuZ2V0KGRlZmF1bHROYW1lKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNwcmVhZHMgYSBzZWxlY3Rpb24gY2hhbmdlIHRvIGFsbCBhY3Rpb25zIGFuZCB0byByZWdpc3RlcmVkIGNvbXBvbmVudHMgXG4gICAgICogYnkgdHJpZ2dlcmluZyBhamF4cGxvcmVyOmFjdGlvbnNfcmVmcmVzaGVkIGV2ZW50LlxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZmlyZVNlbGVjdGlvbkNoYW5nZSA9IGZ1bmN0aW9uIGZpcmVTZWxlY3Rpb25DaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKChmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgICAgICBhY3Rpb24uZmlyZVNlbGVjdGlvbkNoYW5nZSh0aGlzLl9kYXRhTW9kZWwpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJhY3Rpb25zX3JlZnJlc2hlZFwiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU3ByZWFkcyBhIGNvbnRleHQgY2hhbmdlIHRvIGFsbCBhY3Rpb25zIGFuZCB0byByZWdpc3RlcmVkIGNvbXBvbmVudHMgXG4gICAgICogYnkgdHJpZ2dlcmluZyBhamF4cGxvcmVyOmFjdGlvbnNfcmVmcmVzaGVkIGV2ZW50LlxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUuZmlyZUNvbnRleHRDaGFuZ2UgPSBmdW5jdGlvbiBmaXJlQ29udGV4dENoYW5nZSgpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGFjdGlvbi5maXJlQ29udGV4dENoYW5nZSh0aGlzLl9kYXRhTW9kZWwsIHRoaXMudXNlcnNFbmFibGVkLCB0aGlzLm9Vc2VyKTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiYWN0aW9uc19yZWZyZXNoZWRcIik7XG4gICAgfTtcblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLm5vdGlmeSA9IGZ1bmN0aW9uIG5vdGlmeShldmVudE5hbWUsIG1lbW8pIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWxEYXRhTW9kZWwpIHtcbiAgICAgICAgICAgIF9PYnNlcnZhYmxlLnByb3RvdHlwZS5ub3RpZnkuY2FsbCh0aGlzLCBcImFjdGlvbnNfcmVmcmVzaGVkXCIsIG1lbW8pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZmlyZShcImFjdGlvbnNfcmVmcmVzaGVkXCIpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhbGwgYWN0aW9uc1xuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucmVtb3ZlQWN0aW9ucyA9IGZ1bmN0aW9uIHJlbW92ZUFjdGlvbnMoKSB7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGFjdGlvbi5yZW1vdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWN0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5jbGVhclJlZ2lzdGVyZWRLZXlzKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhY3Rpb25zIGZyb20gWE1MIFJlZ2lzdHJ5XG4gICAgICogQHBhcmFtIHJlZ2lzdHJ5IERPTURvY3VtZW50XG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5sb2FkQWN0aW9uc0Zyb21SZWdpc3RyeSA9IGZ1bmN0aW9uIGxvYWRBY3Rpb25zRnJvbVJlZ2lzdHJ5KCkge1xuICAgICAgICB2YXIgcmVnaXN0cnkgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICAgIGlmICghcmVnaXN0cnkpIHtcbiAgICAgICAgICAgIHJlZ2lzdHJ5ID0gcHlkaW8uZ2V0WG1sUmVnaXN0cnkoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFjdGlvbnMoKTtcbiAgICAgICAgdGhpcy5wYXJzZUFjdGlvbnMocmVnaXN0cnkpO1xuICAgICAgICB0aGlzLl9ndWlBY3Rpb25zLmZvckVhY2goKGZ1bmN0aW9uIChhY3QpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJBY3Rpb24oYWN0KTtcbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMubm90aWZ5KFwiYWN0aW9uc19sb2FkZWRcIik7XG4gICAgICAgIHRoaXMuZmlyZUNvbnRleHRDaGFuZ2UoKTtcbiAgICAgICAgdGhpcy5maXJlU2VsZWN0aW9uQ2hhbmdlKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbiBhY3Rpb24gdG8gdGhpcyBtYW5hZ2VyIChkZWZhdWx0LCBhY2Nlc3NrZXkpLlxuICAgICAqIEBwYXJhbSBhY3Rpb24gQWN0aW9uXG4gICAgICovXG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5yZWdpc3RlckFjdGlvbiA9IGZ1bmN0aW9uIHJlZ2lzdGVyQWN0aW9uKGFjdGlvbikge1xuICAgICAgICB2YXIgYWN0aW9uTmFtZSA9IGFjdGlvbi5vcHRpb25zLm5hbWU7XG4gICAgICAgIHRoaXMuYWN0aW9ucy5zZXQoYWN0aW9uTmFtZSwgYWN0aW9uKTtcbiAgICAgICAgaWYgKGFjdGlvbi5kZWZhdWx0cykge1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGFjdGlvbi5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIGlmIChhY3Rpb24uZGVmYXVsdHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRBY3Rpb25zLnNldChrZXksIGFjdGlvbk5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoYWN0aW9uLm9wdGlvbnMuaGFzQWNjZXNzS2V5KSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyS2V5KGFjdGlvbi5vcHRpb25zLmFjY2Vzc0tleSwgYWN0aW9uTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjdGlvbi5vcHRpb25zLnNwZWNpYWxBY2Nlc3NLZXkpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJLZXkoXCJrZXlfXCIgKyBhY3Rpb24ub3B0aW9ucy5zcGVjaWFsQWNjZXNzS2V5LCBhY3Rpb25OYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBhY3Rpb24uc2V0TWFuYWdlcih0aGlzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGFyc2UgYW4gWE1MIGFjdGlvbiBub2RlIGFuZCByZWdpc3RlcnMgdGhlIGFjdGlvblxuICAgICAqIEBwYXJhbSBkb2N1bWVudEVsZW1lbnQgRE9NTm9kZSBUaGUgbm9kZSB0byBwYXJzZVxuICAgICAqL1xuXG4gICAgQ29udHJvbGxlci5wcm90b3R5cGUucGFyc2VBY3Rpb25zID0gZnVuY3Rpb24gcGFyc2VBY3Rpb25zKGRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICB2YXIgYWN0aW9ucyA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyhkb2N1bWVudEVsZW1lbnQsIFwiYWN0aW9ucy9hY3Rpb25cIik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWN0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNbaV0ubm9kZU5hbWUgIT0gJ2FjdGlvbicpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGFjdGlvbnNbaV0uZ2V0QXR0cmlidXRlKCdlbmFibGVkJykgPT0gJ2ZhbHNlJykgY29udGludWU7XG4gICAgICAgICAgICB2YXIgbmV3QWN0aW9uID0gbmV3IF9BY3Rpb24yWydkZWZhdWx0J10oKTtcbiAgICAgICAgICAgIG5ld0FjdGlvbi5zZXRNYW5hZ2VyKHRoaXMpO1xuICAgICAgICAgICAgbmV3QWN0aW9uLmNyZWF0ZUZyb21YTUwoYWN0aW9uc1tpXSk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyQWN0aW9uKG5ld0FjdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCBhbiBhY3Rpb24gYnkgaXRzIG5hbWVcbiAgICAgKiBAcGFyYW0gYWN0aW9uTmFtZSBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyBBY3Rpb25cbiAgICAgKi9cblxuICAgIENvbnRyb2xsZXIucHJvdG90eXBlLmdldEFjdGlvbkJ5TmFtZSA9IGZ1bmN0aW9uIGdldEFjdGlvbkJ5TmFtZShhY3Rpb25OYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFjdGlvbnMuZ2V0KGFjdGlvbk5hbWUpO1xuICAgIH07XG5cbiAgICBDb250cm9sbGVyLnByb3RvdHlwZS5fc29ydFRvb2xiYXJzQWN0aW9ucyA9IGZ1bmN0aW9uIF9zb3J0VG9vbGJhcnNBY3Rpb25zKHRvb2xiYXJzKSB7XG4gICAgICAgIC8vIFNvcnRcbiAgICAgICAgdG9vbGJhcnMuZm9yRWFjaChmdW5jdGlvbiAodiwgaykge1xuICAgICAgICAgICAgaWYgKCF2LnNvcnQpIHJldHVybjtcbiAgICAgICAgICAgIHYuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciB3QSA9IGEud2VpZ2h0IHx8IGEub3B0aW9ucyAmJiBhLm9wdGlvbnMud2VpZ2h0IHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIHdCID0gYi53ZWlnaHQgfHwgYi5vcHRpb25zICYmIGIub3B0aW9ucy53ZWlnaHQgfHwgMDtcbiAgICAgICAgICAgICAgICByZXR1cm4gd0EgPT09IHdCID8gMCA6IHdBID4gd0IgPyAxIDogLTE7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0b29sYmFycztcbiAgICB9O1xuXG4gICAgcmV0dXJuIENvbnRyb2xsZXI7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBDb250cm9sbGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4uL2xhbmcvT2JzZXJ2YWJsZScpO1xuXG52YXIgX2xhbmdPYnNlcnZhYmxlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdPYnNlcnZhYmxlKTtcblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX0FqeHBOb2RlID0gcmVxdWlyZSgnLi9BanhwTm9kZScpO1xuXG52YXIgX0FqeHBOb2RlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0FqeHBOb2RlKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC9MYW5nVXRpbHMnKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxMYW5nVXRpbHMpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1BhdGhVdGlscycpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFBhdGhVdGlscyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG4vKipcbiAqIEZ1bGwgY29udGFpbmVyIG9mIHRoZSBkYXRhIHRyZWUuIENvbnRhaW5zIHRoZSBTZWxlY3Rpb25Nb2RlbCBhcyB3ZWxsLlxuICovXG5cbnZhciBQeWRpb0RhdGFNb2RlbCA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcblx0X2luaGVyaXRzKFB5ZGlvRGF0YU1vZGVsLCBfT2JzZXJ2YWJsZSk7XG5cblx0LyoqXG4gICogQ29uc3RydWN0b3JcbiAgICAgKiA+IFdhcm5pbmcsIGV2ZW50cyBhcmUgbm93IExPQ0FMIGJ5IGRlZmF1bHRcbiAgKi9cblxuXHRmdW5jdGlvbiBQeWRpb0RhdGFNb2RlbCgpIHtcblx0XHR2YXIgbG9jYWxFdmVudHMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzBdO1xuXG5cdFx0X2NsYXNzQ2FsbENoZWNrKHRoaXMsIFB5ZGlvRGF0YU1vZGVsKTtcblxuXHRcdF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG5cdFx0dGhpcy5fY3VycmVudFJlcCA9ICcvJztcblx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzID0gW107XG5cdFx0dGhpcy5fYkVtcHR5ID0gdHJ1ZTtcblx0XHR0aGlzLl9nbG9iYWxFdmVudHMgPSAhbG9jYWxFdmVudHM7XG5cblx0XHR0aGlzLl9iRmlsZSA9IGZhbHNlO1xuXHRcdHRoaXMuX2JEaXIgPSBmYWxzZTtcblx0XHR0aGlzLl9pc1JlY3ljbGUgPSBmYWxzZTtcblxuXHRcdHRoaXMuX3BlbmRpbmdTZWxlY3Rpb24gPSBudWxsO1xuXHRcdHRoaXMuX3NlbGVjdGlvblNvdXJjZSA9IHt9O1xuXG5cdFx0dGhpcy5fcm9vdE5vZGUgPSBudWxsO1xuXHR9XG5cblx0UHlkaW9EYXRhTW9kZWwuUmVtb3RlRGF0YU1vZGVsRmFjdG9yeSA9IGZ1bmN0aW9uIFJlbW90ZURhdGFNb2RlbEZhY3RvcnkocHJvdmlkZXJQcm9wZXJ0aWVzKSB7XG5cdFx0dmFyIHJvb3RMYWJlbCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/ICcnIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0dmFyIGRhdGFNb2RlbCA9IG5ldyBQeWRpb0RhdGFNb2RlbCh0cnVlKTtcblx0XHR2YXIgck5vZGVQcm92aWRlciA9IG5ldyBSZW1vdGVOb2RlUHJvdmlkZXIocHJvdmlkZXJQcm9wZXJ0aWVzKTtcblx0XHRkYXRhTW9kZWwuc2V0QWp4cE5vZGVQcm92aWRlcihyTm9kZVByb3ZpZGVyKTtcblx0XHR2YXIgcm9vdE5vZGUgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKFwiL1wiLCBmYWxzZSwgcm9vdExhYmVsLCAnJywgck5vZGVQcm92aWRlcik7XG5cdFx0ZGF0YU1vZGVsLnNldFJvb3ROb2RlKHJvb3ROb2RlKTtcblx0XHRyZXR1cm4gZGF0YU1vZGVsO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldHMgdGhlIGRhdGEgc291cmNlIHRoYXQgd2lsbCBmZWVkIHRoZSBub2RlcyB3aXRoIGNoaWxkcmVuLlxuICAqIEBwYXJhbSBpQWp4cE5vZGVQcm92aWRlciBJQWp4cE5vZGVQcm92aWRlclxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRBanhwTm9kZVByb3ZpZGVyID0gZnVuY3Rpb24gc2V0QWp4cE5vZGVQcm92aWRlcihpQWp4cE5vZGVQcm92aWRlcikge1xuXHRcdHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyID0gaUFqeHBOb2RlUHJvdmlkZXI7XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJuIHRoZSBjdXJyZW50IGRhdGEgc291cmNlIHByb3ZpZGVyXG4gICogQHJldHVybiBJQWp4cE5vZGVQcm92aWRlclxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRBanhwTm9kZVByb3ZpZGVyID0gZnVuY3Rpb24gZ2V0QWp4cE5vZGVQcm92aWRlcigpIHtcblx0XHRyZXR1cm4gdGhpcy5faUFqeHBOb2RlUHJvdmlkZXI7XG5cdH07XG5cblx0LyoqXG4gICogQ2hhbmdlcyB0aGUgY3VycmVudCBjb250ZXh0IG5vZGUuXG4gICogQHBhcmFtIGFqeHBOb2RlIEFqeHBOb2RlIFRhcmdldCBub2RlLCBlaXRoZXIgYW4gZXhpc3Rpbmcgb25lIG9yIGEgZmFrZSBvbmUgY29udGFpbmluZyB0aGUgdGFyZ2V0IHBhcnQuXG4gICogQHBhcmFtIGZvcmNlUmVsb2FkIEJvb2xlYW4gSWYgc2V0IHRvIHRydWUsIHRoZSBub2RlIHdpbGwgYmUgcmVsb2FkZWQgZXZlbiBpZiBhbHJlYWR5IGxvYWRlZC5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUucmVxdWlyZUNvbnRleHRDaGFuZ2UgPSBmdW5jdGlvbiByZXF1aXJlQ29udGV4dENoYW5nZShhanhwTm9kZSkge1xuXHRcdHZhciBfdGhpcyA9IHRoaXM7XG5cblx0XHR2YXIgZm9yY2VSZWxvYWQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdGlmIChhanhwTm9kZSA9PSBudWxsKSByZXR1cm47XG5cdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKFtdKTtcblx0XHR2YXIgcGF0aCA9IGFqeHBOb2RlLmdldFBhdGgoKTtcblx0XHRpZiAoKHBhdGggPT0gXCJcIiB8fCBwYXRoID09IFwiL1wiKSAmJiBhanhwTm9kZSAhPSB0aGlzLl9yb290Tm9kZSkge1xuXHRcdFx0YWp4cE5vZGUgPSB0aGlzLl9yb290Tm9kZTtcblx0XHR9XG5cdFx0dmFyIHBhZ2luYXRpb25QYWdlID0gbnVsbDtcblx0XHRpZiAoYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5oYXMoJ3BhZ2luYXRpb25EYXRhJykgJiYgYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoJ3BhZ2luYXRpb25EYXRhJykuaGFzKCduZXdfcGFnZScpICYmIGFqeHBOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpLmdldCgnbmV3X3BhZ2UnKSAhPSBhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKS5nZXQoJ2N1cnJlbnQnKSkge1xuXHRcdFx0cGFnaW5hdGlvblBhZ2UgPSBhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKS5nZXQoJ25ld19wYWdlJyk7XG5cdFx0XHRmb3JjZVJlbG9hZCA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChhanhwTm9kZSAhPSB0aGlzLl9yb290Tm9kZSAmJiAoIWFqeHBOb2RlLmdldFBhcmVudCgpIHx8IGFqeHBOb2RlLmZha2UpKSB7XG5cdFx0XHQvLyBGaW5kIGluIGFyYm8gb3IgYnVpbGQgZmFrZSBhcmJvXG5cdFx0XHR2YXIgZmFrZU5vZGVzID0gW107XG5cdFx0XHRhanhwTm9kZSA9IGFqeHBOb2RlLmZpbmRJbkFyYm8odGhpcy5fcm9vdE5vZGUsIGZha2VOb2Rlcyk7XG5cdFx0XHRpZiAoZmFrZU5vZGVzLmxlbmd0aCkge1xuXHRcdFx0XHR2YXIgX3JldCA9IChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dmFyIGZpcnN0RmFrZSA9IGZha2VOb2Rlcy5zaGlmdCgpO1xuXHRcdFx0XHRcdGZpcnN0RmFrZS5vYnNlcnZlT25jZShcImZpcnN0X2xvYWRcIiwgKGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnJlcXVpcmVDb250ZXh0Q2hhbmdlKGFqeHBOb2RlKTtcblx0XHRcdFx0XHR9KS5iaW5kKF90aGlzKSk7XG5cdFx0XHRcdFx0Zmlyc3RGYWtlLm9ic2VydmVPbmNlKFwiZXJyb3JcIiwgKGZ1bmN0aW9uIChtZXNzYWdlKSB7XG5cdFx0XHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihtZXNzYWdlKTtcblx0XHRcdFx0XHRcdGZpcnN0RmFrZS5ub3RpZnkoXCJub2RlX3JlbW92ZWRcIik7XG5cdFx0XHRcdFx0XHR2YXIgcGFyZW50ID0gZmlyc3RGYWtlLmdldFBhcmVudCgpO1xuXHRcdFx0XHRcdFx0cGFyZW50LnJlbW92ZUNoaWxkKGZpcnN0RmFrZSk7XG5cdFx0XHRcdFx0XHQvL2RlbGV0ZShmaXJzdEZha2UpO1xuXHRcdFx0XHRcdFx0dGhpcy5yZXF1aXJlQ29udGV4dENoYW5nZShwYXJlbnQpO1xuXHRcdFx0XHRcdH0pLmJpbmQoX3RoaXMpKTtcblx0XHRcdFx0XHRfdGhpcy5wdWJsaXNoKFwiY29udGV4dF9sb2FkaW5nXCIpO1xuXHRcdFx0XHRcdGZpcnN0RmFrZS5sb2FkKF90aGlzLl9pQWp4cE5vZGVQcm92aWRlcik7XG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdHY6IHVuZGVmaW5lZFxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH0pKCk7XG5cblx0XHRcdFx0aWYgKHR5cGVvZiBfcmV0ID09PSAnb2JqZWN0JykgcmV0dXJuIF9yZXQudjtcblx0XHRcdH1cblx0XHR9XG5cdFx0YWp4cE5vZGUub2JzZXJ2ZU9uY2UoXCJsb2FkZWRcIiwgKGZ1bmN0aW9uICgpIHtcblx0XHRcdHRoaXMuc2V0Q29udGV4dE5vZGUoYWp4cE5vZGUsIHRydWUpO1xuXHRcdFx0dGhpcy5wdWJsaXNoKFwiY29udGV4dF9sb2FkZWRcIik7XG5cdFx0XHRpZiAodGhpcy5nZXRQZW5kaW5nU2VsZWN0aW9uKCkpIHtcblx0XHRcdFx0dmFyIHNlbFBhdGggPSBhanhwTm9kZS5nZXRQYXRoKCkgKyAoYWp4cE5vZGUuZ2V0UGF0aCgpID09IFwiL1wiID8gXCJcIiA6IFwiL1wiKSArIHRoaXMuZ2V0UGVuZGluZ1NlbGVjdGlvbigpO1xuXHRcdFx0XHR2YXIgc2VsTm9kZSA9IGFqeHBOb2RlLmZpbmRDaGlsZEJ5UGF0aChzZWxQYXRoKTtcblx0XHRcdFx0aWYgKHNlbE5vZGUpIHtcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMoW3NlbE5vZGVdLCB0aGlzKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpZiAoYWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJwYWdpbmF0aW9uRGF0YVwiKSAmJiBhcmd1bWVudHMubGVuZ3RoIDwgMykge1xuXHRcdFx0XHRcdFx0dmFyIG5ld1BhZ2UgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdFx0XHR2YXIgY3VycmVudFBhZ2UgPSBhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldChcInBhZ2luYXRpb25EYXRhXCIpLmdldChcImN1cnJlbnRcIik7XG5cdFx0XHRcdFx0XHR0aGlzLmxvYWRQYXRoSW5mb1N5bmMoc2VsUGF0aCwgZnVuY3Rpb24gKGZvdW5kTm9kZSkge1xuXHRcdFx0XHRcdFx0XHRuZXdQYWdlID0gZm91bmROb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicGFnZV9wb3NpdGlvblwiKTtcblx0XHRcdFx0XHRcdH0sIHsgcGFnZV9wb3NpdGlvbjogJ3RydWUnIH0pO1xuXHRcdFx0XHRcdFx0aWYgKG5ld1BhZ2UgJiYgbmV3UGFnZSAhPT0gY3VycmVudFBhZ2UpIHtcblx0XHRcdFx0XHRcdFx0YWp4cE5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJwYWdpbmF0aW9uRGF0YVwiKS5zZXQoXCJuZXdfcGFnZVwiLCBuZXdQYWdlKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5yZXF1aXJlQ29udGV4dENoYW5nZShhanhwTm9kZSwgdHJ1ZSwgdHJ1ZSk7XG5cdFx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5jbGVhclBlbmRpbmdTZWxlY3Rpb24oKTtcblx0XHRcdH1cblx0XHR9KS5iaW5kKHRoaXMpKTtcblx0XHRhanhwTm9kZS5vYnNlcnZlT25jZShcImVycm9yXCIsIChmdW5jdGlvbiAobWVzc2FnZSkge1xuXHRcdFx0X2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IobWVzc2FnZSk7XG5cdFx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2xvYWRlZFwiKTtcblx0XHR9KS5iaW5kKHRoaXMpKTtcblx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2xvYWRpbmdcIik7XG5cdFx0dHJ5IHtcblx0XHRcdGlmIChmb3JjZVJlbG9hZCkge1xuXHRcdFx0XHRpZiAocGFnaW5hdGlvblBhZ2UpIHtcblx0XHRcdFx0XHRhanhwTm9kZS5nZXRNZXRhZGF0YSgpLmdldCgncGFnaW5hdGlvbkRhdGEnKS5zZXQoJ2N1cnJlbnQnLCBwYWdpbmF0aW9uUGFnZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YWp4cE5vZGUucmVsb2FkKHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGFqeHBOb2RlLmxvYWQodGhpcy5faUFqeHBOb2RlUHJvdmlkZXIpO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdHRoaXMucHVibGlzaChcImNvbnRleHRfbG9hZGVkXCIpO1xuXHRcdH1cblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUucmVxdWlyZU5vZGVSZWxvYWQgPSBmdW5jdGlvbiByZXF1aXJlTm9kZVJlbG9hZChub2RlT3JQYXRoLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG5cdFx0aWYgKG5vZGVPclBhdGggaW5zdGFuY2VvZiBTdHJpbmcpIHtcblx0XHRcdG5vZGVPclBhdGggPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKG5vZGVPclBhdGgpO1xuXHRcdH1cblx0XHR2YXIgb25Db21wbGV0ZSA9IG51bGw7XG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoKSB7XG5cdFx0XHR2YXIgZm91bmQgPSAtMTtcblx0XHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMubWFwKGZ1bmN0aW9uIChub2RlLCBrZXkpIHtcblx0XHRcdFx0aWYgKG5vZGUuZ2V0UGF0aCgpID09IG5vZGVPclBhdGguZ2V0UGF0aCgpKSBmb3VuZCA9IGtleTtcblx0XHRcdH0pO1xuXHRcdFx0aWYgKGZvdW5kICE9PSAtMSkge1xuXHRcdFx0XHQvLyBNQUtFIFNVUkUgU0VMRUNUSU9OIElTIE9LIEFGVEVSIFJFTE9BRFxuXHRcdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10uYXJyYXlXaXRob3V0KHRoaXMuX3NlbGVjdGVkTm9kZXMsIGZvdW5kKTtcblx0XHRcdFx0dGhpcy5wdWJsaXNoKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcyk7XG5cdFx0XHRcdG9uQ29tcGxldGUgPSAoZnVuY3Rpb24gKG5ld05vZGUpIHtcblx0XHRcdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzLnB1c2gobmV3Tm9kZSk7XG5cdFx0XHRcdFx0dGhpcy5fc2VsZWN0aW9uU291cmNlID0ge307XG5cdFx0XHRcdFx0dGhpcy5wdWJsaXNoKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcyk7XG5cdFx0XHRcdFx0aWYgKGNvbXBsZXRlQ2FsbGJhY2spIGNvbXBsZXRlQ2FsbGJhY2sobmV3Tm9kZSk7XG5cdFx0XHRcdH0pLmJpbmQodGhpcyk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyLnJlZnJlc2hOb2RlQW5kUmVwbGFjZShub2RlT3JQYXRoLCBvbkNvbXBsZXRlKTtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUubG9hZFBhdGhJbmZvU3luYyA9IGZ1bmN0aW9uIGxvYWRQYXRoSW5mb1N5bmMocGF0aCwgY2FsbGJhY2spIHtcblx0XHR2YXIgYWRkaXRpb25hbFBhcmFtZXRlcnMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIgfHwgYXJndW1lbnRzWzJdID09PSB1bmRlZmluZWQgPyB7fSA6IGFyZ3VtZW50c1syXTtcblxuXHRcdHRoaXMuX2lBanhwTm9kZVByb3ZpZGVyLmxvYWRMZWFmTm9kZVN5bmMobmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShwYXRoKSwgY2FsbGJhY2ssIGZhbHNlLCBhZGRpdGlvbmFsUGFyYW1ldGVycyk7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmxvYWRQYXRoSW5mb0FzeW5jID0gZnVuY3Rpb24gbG9hZFBhdGhJbmZvQXN5bmMocGF0aCwgY2FsbGJhY2spIHtcblx0XHR0aGlzLl9pQWp4cE5vZGVQcm92aWRlci5sb2FkTGVhZk5vZGVTeW5jKG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10ocGF0aCksIGNhbGxiYWNrLCB0cnVlKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZXRzIHRoZSByb290IG9mIHRoZSBkYXRhIHN0b3JlXG4gICogQHBhcmFtIGFqeHBSb290Tm9kZSBBanhwTm9kZSBUaGUgcGFyZW50IG5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0Um9vdE5vZGUgPSBmdW5jdGlvbiBzZXRSb290Tm9kZShhanhwUm9vdE5vZGUpIHtcblx0XHR0aGlzLl9yb290Tm9kZSA9IGFqeHBSb290Tm9kZTtcblx0XHR0aGlzLl9yb290Tm9kZS5zZXRSb290KCk7XG5cdFx0dGhpcy5fcm9vdE5vZGUub2JzZXJ2ZShcImNoaWxkX2FkZGVkXCIsIGZ1bmN0aW9uIChjKSB7XG5cdFx0XHQvL2NvbnNvbGUubG9nKGMpO1xuXHRcdH0pO1xuXHRcdHRoaXMucHVibGlzaChcInJvb3Rfbm9kZV9jaGFuZ2VkXCIsIHRoaXMuX3Jvb3ROb2RlKTtcblx0XHR0aGlzLnNldENvbnRleHROb2RlKHRoaXMuX3Jvb3ROb2RlKTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBjdXJyZW50IHJvb3Qgbm9kZVxuICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFJvb3ROb2RlID0gZnVuY3Rpb24gZ2V0Um9vdE5vZGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3Jvb3ROb2RlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldHMgdGhlIGN1cnJlbnQgY29udGV4dCBub2RlXG4gICogQHBhcmFtIGFqeHBEYXRhTm9kZSBBanhwTm9kZVxuICAqIEBwYXJhbSBmb3JjZUV2ZW50IEJvb2xlYW4gSWYgc2V0IHRvIHRydWUsIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkIGV2ZW4gaWYgdGhlIGN1cnJlbnQgbm9kZSBpcyBhbHJlYWR5IHRoZSBzYW1lLlxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZXRDb250ZXh0Tm9kZSA9IGZ1bmN0aW9uIHNldENvbnRleHROb2RlKGFqeHBEYXRhTm9kZSwgZm9yY2VFdmVudCkge1xuXHRcdGlmICh0aGlzLl9jb250ZXh0Tm9kZSAmJiB0aGlzLl9jb250ZXh0Tm9kZSA9PSBhanhwRGF0YU5vZGUgJiYgdGhpcy5fY3VycmVudFJlcCA9PSBhanhwRGF0YU5vZGUuZ2V0UGF0aCgpICYmICFmb3JjZUV2ZW50KSB7XG5cdFx0XHRyZXR1cm47IC8vIE5vIGNoYW5nZXNcblx0XHR9XG5cdFx0aWYgKCFhanhwRGF0YU5vZGUpIHJldHVybjtcblx0XHRpZiAodGhpcy5fY29udGV4dE5vZGVSZXBsYWNlZE9ic2VydmVyICYmIHRoaXMuX2NvbnRleHROb2RlKSB7XG5cdFx0XHR0aGlzLl9jb250ZXh0Tm9kZS5zdG9wT2JzZXJ2aW5nKFwibm9kZV9yZXBsYWNlZFwiLCB0aGlzLl9jb250ZXh0Tm9kZVJlcGxhY2VkT2JzZXJ2ZXIpO1xuXHRcdH1cblx0XHR0aGlzLl9jb250ZXh0Tm9kZSA9IGFqeHBEYXRhTm9kZTtcblx0XHR0aGlzLl9jdXJyZW50UmVwID0gYWp4cERhdGFOb2RlLmdldFBhdGgoKTtcblx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2NoYW5nZWRcIiwgYWp4cERhdGFOb2RlKTtcblx0XHRpZiAoIXRoaXMuX2NvbnRleHROb2RlUmVwbGFjZWRPYnNlcnZlcikgdGhpcy5fY29udGV4dE5vZGVSZXBsYWNlZE9ic2VydmVyID0gdGhpcy5jb250ZXh0Tm9kZVJlcGxhY2VkLmJpbmQodGhpcyk7XG5cdFx0YWp4cERhdGFOb2RlLm9ic2VydmUoXCJub2RlX3JlcGxhY2VkXCIsIHRoaXMuX2NvbnRleHROb2RlUmVwbGFjZWRPYnNlcnZlcik7XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmNvbnRleHROb2RlUmVwbGFjZWQgPSBmdW5jdGlvbiBjb250ZXh0Tm9kZVJlcGxhY2VkKG5ld05vZGUpIHtcblx0XHR0aGlzLnNldENvbnRleHROb2RlKG5ld05vZGUpO1xuXHR9O1xuXG5cdC8qKlxuICAqXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnB1Ymxpc2ggPSBmdW5jdGlvbiBwdWJsaXNoKGV2ZW50TmFtZSwgb3B0aW9uYWxEYXRhKSB7XG5cdFx0dmFyIGFyZ3MgPSBbXTtcblx0XHRpZiAodGhpcy5fZ2xvYmFsRXZlbnRzKSB7XG5cdFx0XHRpZiAod2luZG93LnB5ZGlvKSB7XG5cdFx0XHRcdGFyZ3MucHVzaChldmVudE5hbWUpO1xuXHRcdFx0XHRpZiAob3B0aW9uYWxEYXRhKSBhcmdzLnB1c2gob3B0aW9uYWxEYXRhKTtcblx0XHRcdFx0d2luZG93LnB5ZGlvLmZpcmUuYXBwbHkod2luZG93LnB5ZGlvLCBhcmdzKTtcblx0XHRcdH0gZWxzZSBpZiAoZG9jdW1lbnQuZmlyZSkge1xuXHRcdFx0XHRhcmdzLnB1c2goXCJhamF4cGxvcmVyOlwiICsgZXZlbnROYW1lKTtcblx0XHRcdFx0aWYgKG9wdGlvbmFsRGF0YSkgYXJncy5wdXNoKG9wdGlvbmFsRGF0YSk7XG5cdFx0XHRcdGRvY3VtZW50LmZpcmUuYXBwbHkoZG9jdW1lbnQsIGFyZ3MpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKG9wdGlvbmFsRGF0YSkge1xuXHRcdFx0XHRhcmdzID0gW2V2ZW50TmFtZSwgeyBtZW1vOiBvcHRpb25hbERhdGEgfV07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRhcmdzID0gW2V2ZW50TmFtZV07XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm5vdGlmeS5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKG9wdGlvbmFsRGF0YSkge1xuXHRcdFx0XHRhcmdzID0gW2V2ZW50TmFtZSwgeyBtZW1vOiBvcHRpb25hbERhdGEgfV07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRhcmdzID0gW2V2ZW50TmFtZV07XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm5vdGlmeS5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogR2V0IHRoZSBjdXJyZW50IGNvbnRleHQgbm9kZVxuICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldENvbnRleHROb2RlID0gZnVuY3Rpb24gZ2V0Q29udGV4dE5vZGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2NvbnRleHROb2RlO1xuXHR9O1xuXG5cdC8qKlxuICAqIEFmdGVyIGEgY29weSBvciBtb3ZlIG9wZXJhdGlvbiwgbWFueSBub2RlcyBtYXkgaGF2ZSB0byBiZSByZWxvYWRlZFxuICAqIFRoaXMgZnVuY3Rpb24gdHJpZXMgdG8gcmVsb2FkIHRoZW0gaW4gdGhlIHJpZ2h0IG9yZGVyIGFuZCBpZiBuZWNlc3NhcnkuXG4gICogQHBhcmFtIG5vZGVzIEFqeHBOb2Rlc1tdIEFuIGFycmF5IG9mIG5vZGVzXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLm11bHRpcGxlTm9kZXNSZWxvYWQgPSBmdW5jdGlvbiBtdWx0aXBsZU5vZGVzUmVsb2FkKG5vZGVzKSB7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIG5vZGVQYXRoT3JOb2RlID0gbm9kZXNbaV07XG5cdFx0XHR2YXIgbm9kZTtcblx0XHRcdGlmIChub2RlUGF0aE9yTm9kZSBpbnN0YW5jZW9mIFN0cmluZykge1xuXHRcdFx0XHRub2RlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShub2RlUGF0aE9yTm9kZSk7XG5cdFx0XHRcdGlmIChub2RlLmdldFBhdGgoKSA9PSB0aGlzLl9yb290Tm9kZS5nZXRQYXRoKCkpIG5vZGUgPSB0aGlzLl9yb290Tm9kZTtlbHNlIG5vZGUgPSBub2RlLmZpbmRJbkFyYm8odGhpcy5fcm9vdE5vZGUsIFtdKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG5vZGUgPSBub2RlUGF0aE9yTm9kZTtcblx0XHRcdH1cblx0XHRcdG5vZGVzW2ldID0gbm9kZTtcblx0XHR9XG5cdFx0dmFyIGNoaWxkcmVuID0gW107XG5cdFx0bm9kZXMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuXHRcdFx0aWYgKGEuaXNQYXJlbnRPZihiKSkge1xuXHRcdFx0XHRjaGlsZHJlbi5wdXNoKGIpO1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoYS5pc0NoaWxkT2YoYikpIHtcblx0XHRcdFx0Y2hpbGRyZW4ucHVzaChhKTtcblx0XHRcdFx0cmV0dXJuICsxO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fSk7XG5cdFx0Y2hpbGRyZW4ubWFwKGZ1bmN0aW9uIChjKSB7XG5cdFx0XHRub2RlcyA9IF91dGlsTGFuZ1V0aWxzMlsnZGVmYXVsdCddLmFycmF5V2l0aG91dChub2RlcywgYyk7XG5cdFx0fSk7XG5cdFx0bm9kZXMubWFwKHRoaXMucXVldWVOb2RlUmVsb2FkLmJpbmQodGhpcykpO1xuXHRcdHRoaXMubmV4dE5vZGVSZWxvYWRlcigpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEFkZCBhIG5vZGUgdG8gdGhlIHF1ZXVlIG9mIG5vZGVzIHRvIHJlbG9hZC5cbiAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5xdWV1ZU5vZGVSZWxvYWQgPSBmdW5jdGlvbiBxdWV1ZU5vZGVSZWxvYWQobm9kZSkge1xuXHRcdGlmICghdGhpcy5xdWV1ZSkgdGhpcy5xdWV1ZSA9IFtdO1xuXHRcdGlmIChub2RlKSB7XG5cdFx0XHR0aGlzLnF1ZXVlLnB1c2gobm9kZSk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFF1ZXVlIHByb2Nlc3NvciBmb3IgdGhlIG5vZGVzIHRvIHJlbG9hZFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5uZXh0Tm9kZVJlbG9hZGVyID0gZnVuY3Rpb24gbmV4dE5vZGVSZWxvYWRlcigpIHtcblx0XHRpZiAoIXRoaXMucXVldWUubGVuZ3RoKSB7XG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCgoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLnB1Ymxpc2goXCJjb250ZXh0X2NoYW5nZWRcIiwgdGhpcy5fY29udGV4dE5vZGUpO1xuXHRcdFx0fSkuYmluZCh0aGlzKSwgMjAwKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dmFyIG5leHQgPSB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG5cdFx0dmFyIG9ic2VydmVyID0gdGhpcy5uZXh0Tm9kZVJlbG9hZGVyLmJpbmQodGhpcyk7XG5cdFx0bmV4dC5vYnNlcnZlT25jZShcImxvYWRlZFwiLCBvYnNlcnZlcik7XG5cdFx0bmV4dC5vYnNlcnZlT25jZShcImVycm9yXCIsIG9ic2VydmVyKTtcblx0XHRpZiAobmV4dCA9PSB0aGlzLl9jb250ZXh0Tm9kZSB8fCBuZXh0LmlzUGFyZW50T2YodGhpcy5fY29udGV4dE5vZGUpKSB7XG5cdFx0XHR0aGlzLnJlcXVpcmVDb250ZXh0Q2hhbmdlKG5leHQsIHRydWUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRuZXh0LnJlbG9hZCh0aGlzLl9pQWp4cE5vZGVQcm92aWRlcik7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEluc2VydCBhIG5vZGUgc29tZXdoZXJlIGluIHRoZSBkYXRhbW9kZWxcbiAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAqIEBwYXJhbSBzZXRTZWxlY3RlZEFmdGVyQWRkIGJvb2xcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuYWRkTm9kZSA9IGZ1bmN0aW9uIGFkZE5vZGUobm9kZSkge1xuXHRcdHZhciBzZXRTZWxlY3RlZEFmdGVyQWRkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cblx0XHR2YXIgcGFyZW50RmFrZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10oX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSkpO1xuXHRcdHZhciBwYXJlbnQgPSBwYXJlbnRGYWtlLmZpbmRJbkFyYm8odGhpcy5nZXRSb290Tm9kZSgpLCB1bmRlZmluZWQpO1xuXHRcdGlmICghcGFyZW50ICYmIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpID09IFwiXCIpIHBhcmVudCA9IHRoaXMuZ2V0Um9vdE5vZGUoKTtcblx0XHRpZiAocGFyZW50KSB7XG5cdFx0XHR2YXIgYWRkZWROb2RlID0gcGFyZW50LmFkZENoaWxkKG5vZGUpO1xuXHRcdFx0aWYgKGFkZGVkTm9kZSAmJiBzZXRTZWxlY3RlZEFmdGVyQWRkICYmIHRoaXMuZ2V0Q29udGV4dE5vZGUoKSA9PSBwYXJlbnQpIHtcblx0XHRcdFx0dGhpcy5zZXRTZWxlY3RlZE5vZGVzKFthZGRlZE5vZGVdLCB7fSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIFJlbW92ZSBhIG5vZGUgYnkgcGF0aCBzb21ld2hlcmVcbiAgKiBAcGFyYW0gcGF0aCBzdHJpbmdcbiAgKiBAcGFyYW0gaW1UaW1lIGludGVnZXJ8bnVsbFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5yZW1vdmVOb2RlQnlQYXRoID0gZnVuY3Rpb24gcmVtb3ZlTm9kZUJ5UGF0aChwYXRoKSB7XG5cdFx0dmFyIGltVGltZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cblx0XHR2YXIgZmFrZSA9IG5ldyBfQWp4cE5vZGUyWydkZWZhdWx0J10ocGF0aCk7XG5cdFx0dmFyIG4gPSBmYWtlLmZpbmRJbkFyYm8odGhpcy5nZXRSb290Tm9kZSgpLCB1bmRlZmluZWQpO1xuXHRcdGlmIChuKSB7XG5cdFx0XHRpZiAoaW1UaW1lICYmIG4uZ2V0TWV0YWRhdGEoKSAmJiBuLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpICYmIHBhcnNlSW50KG4uZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikpID49IGltVGltZSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHRuLmdldFBhcmVudCgpLnJlbW92ZUNoaWxkKG4pO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fTtcblxuXHQvKipcbiAgKiBVcGRhdGUgYSBub2RlIHNvbWV3aGVyZSBpbiB0aGUgZGF0YW1vZGVsXG4gICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgKiBAcGFyYW0gc2V0U2VsZWN0ZWRBZnRlclVwZGF0ZSBib29sXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnVwZGF0ZU5vZGUgPSBmdW5jdGlvbiB1cGRhdGVOb2RlKG5vZGUpIHtcblx0XHR2YXIgc2V0U2VsZWN0ZWRBZnRlclVwZGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG5cdFx0dmFyIG9yaWdpbmFsID0gbm9kZS5nZXRNZXRhZGF0YSgpLmdldChcIm9yaWdpbmFsX3BhdGhcIik7XG5cdFx0dmFyIGZha2UsIG47XG5cdFx0aWYgKG9yaWdpbmFsICYmIG9yaWdpbmFsICE9IG5vZGUuZ2V0UGF0aCgpICYmIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUob3JpZ2luYWwpICE9IF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpKSB7XG5cdFx0XHQvLyBOb2RlIHdhcyByZWFsbHkgbW92ZWQgdG8gYW5vdGhlciBmb2xkZXJcblx0XHRcdGZha2UgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKG9yaWdpbmFsKTtcblx0XHRcdG4gPSBmYWtlLmZpbmRJbkFyYm8odGhpcy5nZXRSb290Tm9kZSgpLCB1bmRlZmluZWQpO1xuXHRcdFx0aWYgKG4pIHtcblx0XHRcdFx0bi5nZXRQYXJlbnQoKS5yZW1vdmVDaGlsZChuKTtcblx0XHRcdH1cblx0XHRcdHZhciBwYXJlbnRGYWtlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXREaXJuYW1lKG5vZGUuZ2V0UGF0aCgpKSk7XG5cdFx0XHR2YXIgcGFyZW50ID0gcGFyZW50RmFrZS5maW5kSW5BcmJvKHRoaXMuZ2V0Um9vdE5vZGUoKSwgdW5kZWZpbmVkKTtcblx0XHRcdGlmICghcGFyZW50ICYmIF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpID09IFwiXCIpIHBhcmVudCA9IHRoaXMuZ2V0Um9vdE5vZGUoKTtcblx0XHRcdGlmIChwYXJlbnQpIHtcblx0XHRcdFx0bm9kZS5nZXRNZXRhZGF0YSgpLnNldChcIm9yaWdpbmFsX3BhdGhcIiwgdW5kZWZpbmVkKTtcblx0XHRcdFx0cGFyZW50LmFkZENoaWxkKG5vZGUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAobm9kZS5nZXRNZXRhZGF0YSgpLmdldChcIm9yaWdpbmFsX3BhdGhcIikgPT09IFwiL1wiICYmIG5vZGUuZ2V0UGF0aCgpID09PSBcIi9cIikge1xuXHRcdFx0XHRuID0gdGhpcy5nZXRSb290Tm9kZSgpO1xuXHRcdFx0XHRuLnJlcGxhY2VNZXRhZGF0YShub2RlLmdldE1ldGFkYXRhKCkpO1xuXHRcdFx0XHRpZiAoc2V0U2VsZWN0ZWRBZnRlclVwZGF0ZSAmJiB0aGlzLmdldENvbnRleHROb2RlKCkgPT0gbikge1xuXHRcdFx0XHRcdHRoaXMuc2V0U2VsZWN0ZWROb2Rlcyhbbl0sIHt9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRmYWtlID0gbmV3IF9BanhwTm9kZTJbJ2RlZmF1bHQnXShvcmlnaW5hbCk7XG5cdFx0XHRuID0gZmFrZS5maW5kSW5BcmJvKHRoaXMuZ2V0Um9vdE5vZGUoKSwgdW5kZWZpbmVkKTtcblx0XHRcdGlmIChuICYmICFuLmlzTW9yZVJlY2VudFRoYW4obm9kZSkpIHtcblx0XHRcdFx0bm9kZS5faXNMb2FkZWQgPSBuLl9pc0xvYWRlZDtcblx0XHRcdFx0bi5yZXBsYWNlQnkobm9kZSwgXCJvdmVycmlkZVwiKTtcblx0XHRcdFx0aWYgKHNldFNlbGVjdGVkQWZ0ZXJVcGRhdGUgJiYgdGhpcy5nZXRDb250ZXh0Tm9kZSgpID09IG4uZ2V0UGFyZW50KCkpIHtcblx0XHRcdFx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMoW25dLCB7fSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogU2V0cyBhbiBhcnJheSBvZiBub2RlcyB0byBiZSBzZWxlY3RlZCBhZnRlciB0aGUgY29udGV4dCBpcyAocmUpbG9hZGVkXG4gICogQHBhcmFtIHNlbGVjdGlvbiBBanhwTm9kZVtdXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldFBlbmRpbmdTZWxlY3Rpb24gPSBmdW5jdGlvbiBzZXRQZW5kaW5nU2VsZWN0aW9uKHNlbGVjdGlvbikge1xuXHRcdHRoaXMuX3BlbmRpbmdTZWxlY3Rpb24gPSBzZWxlY3Rpb247XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgYXJyYXkgb2Ygbm9kZXMgdG8gYmUgc2VsZWN0ZWQgYWZ0ZXIgdGhlIGNvbnRleHQgaXMgKHJlKWxvYWRlZFxuICAqIEByZXR1cm5zIEFqeHBOb2RlW11cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0UGVuZGluZ1NlbGVjdGlvbiA9IGZ1bmN0aW9uIGdldFBlbmRpbmdTZWxlY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3BlbmRpbmdTZWxlY3Rpb247XG5cdH07XG5cblx0LyoqXG4gICogQ2xlYXJzIHRoZSBub2RlcyB0byBiZSBzZWxlY3RlZFxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5jbGVhclBlbmRpbmdTZWxlY3Rpb24gPSBmdW5jdGlvbiBjbGVhclBlbmRpbmdTZWxlY3Rpb24oKSB7XG5cdFx0dGhpcy5fcGVuZGluZ1NlbGVjdGlvbiA9IG51bGw7XG5cdH07XG5cblx0LyoqXG4gICogU2V0IGFuIGFycmF5IG9mIG5vZGVzIGFzIHRoZSBjdXJyZW50IHNlbGVjdGlvblxuICAqIEBwYXJhbSBhanhwRGF0YU5vZGVzIEFqeHBOb2RlW10gVGhlIG5vZGVzIHRvIHNlbGVjdFxuICAqIEBwYXJhbSBzb3VyY2UgU3RyaW5nIFRoZSBzb3VyY2Ugb2YgdGhpcyBzZWxlY3Rpb24gYWN0aW9uXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNldFNlbGVjdGVkTm9kZXMgPSBmdW5jdGlvbiBzZXRTZWxlY3RlZE5vZGVzKGFqeHBEYXRhTm9kZXMsIHNvdXJjZSkge1xuXHRcdGlmICh0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCA9PSBhanhwRGF0YU5vZGVzLmxlbmd0aCkge1xuXHRcdFx0aWYgKGFqeHBEYXRhTm9kZXMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHZhciBlcXVhbCA9IHRydWU7XG5cdFx0XHRmb3IgKHZhciBrID0gMDsgayA8IGFqeHBEYXRhTm9kZXMubGVuZ3RoOyBrKyspIHtcblx0XHRcdFx0ZXF1YWwgPSBlcXVhbCAmJiBhanhwRGF0YU5vZGVzW2tdID09IHRoaXMuX3NlbGVjdGVkTm9kZXNba107XG5cdFx0XHR9XG5cdFx0XHRpZiAoZXF1YWwpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAoIXNvdXJjZSkge1xuXHRcdFx0dGhpcy5fc2VsZWN0aW9uU291cmNlID0ge307XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX3NlbGVjdGlvblNvdXJjZSA9IHNvdXJjZTtcblx0XHR9XG5cdFx0dGhpcy5fc2VsZWN0ZWROb2RlcyA9IGFqeHBEYXRhTm9kZXM7XG5cdFx0dGhpcy5fYkVtcHR5ID0gYWp4cERhdGFOb2RlcyAmJiBhanhwRGF0YU5vZGVzLmxlbmd0aCA/IGZhbHNlIDogdHJ1ZTtcblx0XHR0aGlzLl9iRmlsZSA9IHRoaXMuX2JEaXIgPSB0aGlzLl9pc1JlY3ljbGUgPSBmYWxzZTtcblx0XHRpZiAoIXRoaXMuX2JFbXB0eSkge1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhanhwRGF0YU5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHZhciBzZWxlY3RlZE5vZGUgPSBhanhwRGF0YU5vZGVzW2ldO1xuXHRcdFx0XHRpZiAoc2VsZWN0ZWROb2RlLmlzTGVhZigpKSB0aGlzLl9iRmlsZSA9IHRydWU7ZWxzZSB0aGlzLl9iRGlyID0gdHJ1ZTtcblx0XHRcdFx0aWYgKHNlbGVjdGVkTm9kZS5pc1JlY3ljbGUoKSkgdGhpcy5faXNSZWN5Y2xlID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5wdWJsaXNoKFwic2VsZWN0aW9uX2NoYW5nZWRcIiwgdGhpcyk7XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG5vZGVzXG4gICogQHJldHVybnMgQWp4cE5vZGVbXVxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRTZWxlY3RlZE5vZGVzID0gZnVuY3Rpb24gZ2V0U2VsZWN0ZWROb2RlcygpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2Rlcztcblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBzb3VyY2Ugb2YgdGhlIGxhc3Qgc2VsZWN0aW9uIGFjdGlvblxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRTZWxlY3Rpb25Tb3VyY2UgPSBmdW5jdGlvbiBnZXRTZWxlY3Rpb25Tb3VyY2UoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGlvblNvdXJjZTtcblx0fTtcblxuXHQvKipcbiAgKiBNYW51YWxseSBzZXRzIHRoZSBzb3VyY2Ugb2YgdGhlIHNlbGVjdGlvblxuICAqIEBwYXJhbSBvYmplY3RcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuc2V0U2VsZWN0aW9uU291cmNlID0gZnVuY3Rpb24gc2V0U2VsZWN0aW9uU291cmNlKG9iamVjdCkge1xuXHRcdHRoaXMuX3NlbGVjdGlvblNvdXJjZSA9IG9iamVjdDtcblx0fTtcblxuXHQvKipcbiAgKiBERVBSRUNBVEVEXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldFNlbGVjdGVkSXRlbXMgPSBmdW5jdGlvbiBnZXRTZWxlY3RlZEl0ZW1zKCkge1xuXHRcdHRocm93IG5ldyBFcnJvcihcIkRlcHJlY2F0ZWQgOiB1c2UgZ2V0U2VsZWN0ZWROb2RlcygpIGluc3RlYWRcIik7XG5cdH07XG5cblx0LyoqXG4gICogU2VsZWN0IGFsbCB0aGUgY2hpbGRyZW4gb2YgdGhlIGN1cnJlbnQgY29udGV4dCBub2RlXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLnNlbGVjdEFsbCA9IGZ1bmN0aW9uIHNlbGVjdEFsbCgpIHtcblx0XHR2YXIgbm9kZXMgPSBbXTtcblx0XHR2YXIgY2hpbGRyZW5NYXAgPSB0aGlzLl9jb250ZXh0Tm9kZS5nZXRDaGlsZHJlbigpO1xuXHRcdGNoaWxkcmVuTWFwLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XG5cdFx0XHRub2Rlcy5wdXNoKGNoaWxkKTtcblx0XHR9KTtcblx0XHR0aGlzLnNldFNlbGVjdGVkTm9kZXMobm9kZXMsIFwiZGF0YU1vZGVsXCIpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBpcyBlbXB0eVxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uIGlzRW1wdHkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXMgPyB0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCA9PSAwIDogdHJ1ZTtcblx0fTtcblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaGFzUmVhZE9ubHkgPSBmdW5jdGlvbiBoYXNSZWFkT25seSgpIHtcblx0XHR2YXIgdGVzdCA9IGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcblx0XHRcdFx0aWYgKG5vZGUuaGFzTWV0YWRhdGFJbkJyYW5jaChcImFqeHBfcmVhZG9ubHlcIiwgXCJ0cnVlXCIpKSB7XG5cdFx0XHRcdFx0dGVzdCA9IHRydWU7XG5cdFx0XHRcdFx0dGhyb3cgJGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9IGNhdGNoIChlKSB7fVxuXHRcdHJldHVybiB0ZXN0O1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5zZWxlY3Rpb25IYXNSb290Tm9kZSA9IGZ1bmN0aW9uIHNlbGVjdGlvbkhhc1Jvb3ROb2RlKCkge1xuXHRcdHZhciBmb3VuZCA9IGZhbHNlO1xuXHRcdHRyeSB7XG5cdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG5cdFx0XHRcdGlmIChlbC5pc1Jvb3QoKSkge1xuXHRcdFx0XHRcdGZvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBjYXRjaCAoZSkge31cblx0XHRyZXR1cm4gZm91bmQ7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGUgc2VsZWN0aW9uIGlzIHVuaXF1ZVxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaXNVbmlxdWUgPSBmdW5jdGlvbiBpc1VuaXF1ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2RlcyAmJiB0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCA9PT0gMTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaGFzIGEgZmlsZSBzZWxlY3RlZC5cbiAgKiBTaG91bGQgYmUgaGFzTGVhZlxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaGFzRmlsZSA9IGZ1bmN0aW9uIGhhc0ZpbGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2JGaWxlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBoYXMgYSBkaXIgc2VsZWN0ZWRcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmhhc0RpciA9IGZ1bmN0aW9uIGhhc0RpcigpIHtcblx0XHRyZXR1cm4gdGhpcy5fYkRpcjtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBjdXJyZW50IGNvbnRleHQgaXMgdGhlIHJlY3ljbGUgYmluXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5pc1JlY3ljbGUgPSBmdW5jdGlvbiBpc1JlY3ljbGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2lzUmVjeWNsZTtcblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBzZWxlY3Rpb24gaGFzIG1vcmUgdGhhbiBvbmUgbm9kZSBzZWxlY3RlZFxuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaXNNdWx0aXBsZSA9IGZ1bmN0aW9uIGlzTXVsdGlwbGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3NlbGVjdGVkTm9kZXMgJiYgdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGggPiAxO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdoZXRoZXIgdGhlIHNlbGVjdGlvbiBoYXMgYSBmaWxlIHdpdGggb25lIG9mIHRoZSBtaW1lc1xuICAqIEBwYXJhbSBtaW1lVHlwZXMgQXJyYXkgQXJyYXkgb2YgbWltZSB0eXBlc1xuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuaGFzTWltZSA9IGZ1bmN0aW9uIGhhc01pbWUobWltZVR5cGVzKSB7XG5cdFx0aWYgKG1pbWVUeXBlcy5sZW5ndGggPT0gMSAmJiBtaW1lVHlwZXNbMF0gPT0gXCIqXCIpIHJldHVybiB0cnVlO1xuXHRcdHZhciBoYXMgPSBmYWxzZTtcblx0XHRtaW1lVHlwZXMubWFwKChmdW5jdGlvbiAobWltZSkge1xuXHRcdFx0aWYgKGhhcykgcmV0dXJuO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRBanhwTWltZVR5cGUodGhpcy5fc2VsZWN0ZWROb2Rlc1tpXSkgPT09IG1pbWUpIHtcblx0XHRcdFx0XHRoYXMgPSB0cnVlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSkuYmluZCh0aGlzKSk7XG5cdFx0cmV0dXJuIGhhcztcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgYWxsIHNlbGVjdGVkIGZpbGVuYW1lcyBhcyBhbiBhcnJheS5cbiAgKiBAcGFyYW0gc2VwYXJhdG9yIFN0cmluZyBJcyBhIHNlcGFyYXRvciwgd2lsbCByZXR1cm4gYSBzdHJpbmcgam9pbmVkXG4gICogQHJldHVybnMgQXJyYXl8U3RyaW5nfGJvb2xcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0RmlsZU5hbWVzID0gZnVuY3Rpb24gZ2V0RmlsZU5hbWVzKHNlcGFyYXRvcikge1xuXHRcdGlmICghdGhpcy5fc2VsZWN0ZWROb2Rlcy5sZW5ndGgpIHtcblx0XHRcdGFsZXJ0KCdQbGVhc2Ugc2VsZWN0IGEgZmlsZSEnKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0dmFyIHRtcCA9IG5ldyBBcnJheSh0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0bXBbaV0gPSB0aGlzLl9zZWxlY3RlZE5vZGVzW2ldLmdldFBhdGgoKTtcblx0XHR9XG5cdFx0aWYgKHNlcGFyYXRvcikge1xuXHRcdFx0cmV0dXJuIHRtcC5qb2luKHNlcGFyYXRvcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB0bXA7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuICAqIEdldCBhbGwgdGhlIGZpbGVuYW1lcyBvZiB0aGUgY3VycmVudCBjb250ZXh0IG5vZGUgY2hpbGRyZW5cbiAgKiBAcGFyYW0gc2VwYXJhdG9yIFN0cmluZyBJZiBwYXNzZWQsIHdpbGwgam9pbiB0aGUgYXJyYXkgYXMgYSBzdHJpbmdcbiAgKiBAcmV0dXJuIEFycmF5fFN0cmluZ3xib29sXG4gICovXG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmdldENvbnRleHRGaWxlTmFtZXMgPSBmdW5jdGlvbiBnZXRDb250ZXh0RmlsZU5hbWVzKHNlcGFyYXRvcikge1xuXHRcdHZhciBhbGxJdGVtcyA9IHRoaXMuX2NvbnRleHROb2RlLmdldENoaWxkcmVuKCk7XG5cdFx0aWYgKCFhbGxJdGVtcy5sZW5ndGgpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0dmFyIG5hbWVzID0gW107XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhbGxJdGVtcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bmFtZXMucHVzaChfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShhbGxJdGVtc1tpXS5nZXRQYXRoKCkpKTtcblx0XHR9XG5cdFx0aWYgKHNlcGFyYXRvcikge1xuXHRcdFx0cmV0dXJuIG5hbWVzLmpvaW4oc2VwYXJhdG9yKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIG5hbWVzO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBXaGV0aGVyIHRoZSBjb250ZXh0IG5vZGUgaGFzIGEgY2hpbGQgd2l0aCB0aGlzIGJhc2VuYW1lXG4gICogQHBhcmFtIG5ld0ZpbGVOYW1lIFN0cmluZyBUaGUgbmFtZSB0byBjaGVja1xuICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgKiBAcGFyYW0gbG9jYWxcbiAgKiBAcGFyYW0gY29udGV4dE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZmlsZU5hbWVFeGlzdHMgPSBmdW5jdGlvbiBmaWxlTmFtZUV4aXN0cyhuZXdGaWxlTmFtZSwgbG9jYWwsIGNvbnRleHROb2RlKSB7XG5cdFx0aWYgKCFjb250ZXh0Tm9kZSkge1xuXHRcdFx0Y29udGV4dE5vZGUgPSB0aGlzLl9jb250ZXh0Tm9kZTtcblx0XHR9XG5cdFx0aWYgKGxvY2FsKSB7XG5cdFx0XHR2YXIgdGVzdCA9IChjb250ZXh0Tm9kZS5nZXRQYXRoKCkgPT0gXCIvXCIgPyBcIlwiIDogY29udGV4dE5vZGUuZ2V0UGF0aCgpKSArIFwiL1wiICsgbmV3RmlsZU5hbWU7XG5cdFx0XHR2YXIgZm91bmQgPSBmYWxzZTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGNvbnRleHROb2RlLmdldENoaWxkcmVuKCkuZm9yRWFjaChmdW5jdGlvbiAoYykge1xuXHRcdFx0XHRcdGlmIChjLmdldFBhdGgoKSA9PSB0ZXN0KSB7XG5cdFx0XHRcdFx0XHRmb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBjYXRjaCAoZSkge31cblx0XHRcdHJldHVybiBmb3VuZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIG5vZGVFeGlzdHMgPSBmYWxzZTtcblx0XHRcdHRoaXMubG9hZFBhdGhJbmZvU3luYyhjb250ZXh0Tm9kZS5nZXRQYXRoKCkgKyBcIi9cIiArIG5ld0ZpbGVOYW1lLCBmdW5jdGlvbiAoZm91bmROb2RlKSB7XG5cdFx0XHRcdG5vZGVFeGlzdHMgPSB0cnVlO1xuXHRcdFx0fSk7XG5cdFx0XHRyZXR1cm4gbm9kZUV4aXN0cztcblx0XHR9XG5cdH07XG5cblx0UHlkaW9EYXRhTW9kZWwucHJvdG90eXBlLmFwcGx5Q2hlY2tIb29rID0gZnVuY3Rpb24gYXBwbHlDaGVja0hvb2sobm9kZSkge1xuXHRcdHZhciBhZGRpdGlvbmFsUGFyYW1zID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuXHRcdHZhciBjbGllbnQgPSBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpO1xuXHRcdHZhciByZXN1bHQ7XG5cdFx0Y2xpZW50LmFwcGx5Q2hlY2tIb29rKG5vZGUsIFwiYmVmb3JlX2NyZWF0ZVwiLCBub2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwiZmlsZXNpemVcIikgfHwgLTEsIGZ1bmN0aW9uICh0cmFuc3BvcnQpIHtcblx0XHRcdHJlc3VsdCA9IGNsaWVudC5wYXJzZVhtbE1lc3NhZ2UodHJhbnNwb3J0LnJlc3BvbnNlWE1MKTtcblx0XHR9LCBhZGRpdGlvbmFsUGFyYW1zKTtcblx0XHRpZiAocmVzdWx0ID09PSBmYWxzZSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiQ2hlY2sgZmFpbGVkXCIpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBHZXRzIHRoZSBmaXJzdCBuYW1lIG9mIHRoZSBjdXJyZW50IHNlbGVjdGlvblxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5nZXRVbmlxdWVGaWxlTmFtZSA9IGZ1bmN0aW9uIGdldFVuaXF1ZUZpbGVOYW1lKCkge1xuXHRcdGlmICh0aGlzLmdldEZpbGVOYW1lcygpLmxlbmd0aCkgcmV0dXJuIHRoaXMuZ2V0RmlsZU5hbWVzKClbMF07XG5cdFx0cmV0dXJuIG51bGw7XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgZmlyc3Qgbm9kZSBvZiB0aGUgc2VsZWN0aW9uLCBvciBOdWxsXG4gICogQHJldHVybnMgQWp4cE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0VW5pcXVlTm9kZSA9IGZ1bmN0aW9uIGdldFVuaXF1ZU5vZGUoKSB7XG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkTm9kZXMubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWROb2Rlc1swXTtcblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyBhIG5vZGUgZnJvbSB0aGUgY3VycmVudCBzZWxlY3Rpb25cbiAgKiBAcGFyYW0gaSBJbnRlZ2VyIHRoZSBub2RlIGluZGV4XG4gICogQHJldHVybnMgQWp4cE5vZGVcbiAgKi9cblxuXHRQeWRpb0RhdGFNb2RlbC5wcm90b3R5cGUuZ2V0Tm9kZSA9IGZ1bmN0aW9uIGdldE5vZGUoaSkge1xuXHRcdHJldHVybiB0aGlzLl9zZWxlY3RlZE5vZGVzW2ldO1xuXHR9O1xuXG5cdC8qKlxuICAqIFdpbGwgYWRkIHRoZSBjdXJyZW50IHNlbGVjdGlvbiBub2RlcyBhcyBzZXJpYWxpemFibGUgZGF0YSB0byB0aGUgZWxlbWVudCBwYXNzZWQgOlxuICAqIGVpdGhlciBhcyBoaWRkZW4gaW5wdXQgZWxlbWVudHMgaWYgaXQncyBhIGZvcm0sIG9yIGFzIHF1ZXJ5IHBhcmFtZXRlcnMgaWYgaXQncyBhbiB1cmxcbiAgKiBAcGFyYW0gb0Zvcm1FbGVtZW50IEhUTUxGb3JtIFRoZSBmb3JtXG4gICogQHBhcmFtIHNVcmwgU3RyaW5nIEFuIHVybCB0byBjb21wbGV0ZVxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS51cGRhdGVGb3JtT3JVcmwgPSBmdW5jdGlvbiB1cGRhdGVGb3JtT3JVcmwob0Zvcm1FbGVtZW50LCBzVXJsKSB7XG5cdFx0Ly8gQ0xFQVIgRlJPTSBQUkVWSU9VUyBBQ1RJT05TIVxuXHRcdGlmIChvRm9ybUVsZW1lbnQpIHtcblx0XHRcdCQob0Zvcm1FbGVtZW50KS5zZWxlY3QoJ2lucHV0W3R5cGU9XCJoaWRkZW5cIl0nKS5tYXAoZnVuY3Rpb24gKGVsZW1lbnQpIHtcblx0XHRcdFx0aWYgKGVsZW1lbnQubmFtZSA9PSBcIm5vZGVzW11cIiB8fCBlbGVtZW50Lm5hbWUgPT0gXCJmaWxlXCIpIGVsZW1lbnQucmVtb3ZlKCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0Ly8gVVBEQVRFIFRIRSAnRElSJyBGSUVMRFNcblx0XHRpZiAob0Zvcm1FbGVtZW50ICYmIG9Gb3JtRWxlbWVudFsncmVwJ10pIG9Gb3JtRWxlbWVudFsncmVwJ10udmFsdWUgPSB0aGlzLl9jdXJyZW50UmVwO1xuXHRcdHNVcmwgKz0gJyZkaXI9JyArIGVuY29kZVVSSUNvbXBvbmVudCh0aGlzLl9jdXJyZW50UmVwKTtcblxuXHRcdC8vIFVQREFURSBUSEUgJ2ZpbGUnIEZJRUxEU1xuXHRcdGlmICh0aGlzLmlzRW1wdHkoKSkgcmV0dXJuIHNVcmw7XG5cdFx0dmFyIGZpbGVOYW1lcyA9IHRoaXMuZ2V0RmlsZU5hbWVzKCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBmaWxlTmFtZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHNVcmwgKz0gJyYnICsgJ25vZGVzW109JyArIGVuY29kZVVSSUNvbXBvbmVudChmaWxlTmFtZXNbaV0pO1xuXHRcdFx0aWYgKG9Gb3JtRWxlbWVudCkgdGhpcy5fYWRkSGlkZGVuRmllbGQob0Zvcm1FbGVtZW50LCAnbm9kZXNbXScsIGZpbGVOYW1lc1tpXSk7XG5cdFx0fVxuXHRcdGlmIChmaWxlTmFtZXMubGVuZ3RoID09IDEpIHtcblx0XHRcdHNVcmwgKz0gJyYnICsgJ2ZpbGU9JyArIGVuY29kZVVSSUNvbXBvbmVudChmaWxlTmFtZXNbMF0pO1xuXHRcdFx0aWYgKG9Gb3JtRWxlbWVudCkgdGhpcy5fYWRkSGlkZGVuRmllbGQob0Zvcm1FbGVtZW50LCAnZmlsZScsIGZpbGVOYW1lc1swXSk7XG5cdFx0fVxuXHRcdHJldHVybiBzVXJsO1xuXHR9O1xuXG5cdFB5ZGlvRGF0YU1vZGVsLnByb3RvdHlwZS5fYWRkSGlkZGVuRmllbGQgPSBmdW5jdGlvbiBfYWRkSGlkZGVuRmllbGQob0Zvcm1FbGVtZW50LCBzRmllbGROYW1lLCBzRmllbGRWYWx1ZSkge1xuXHRcdG9Gb3JtRWxlbWVudC5pbnNlcnQobmV3IEVsZW1lbnQoJ2lucHV0JywgeyB0eXBlOiAnaGlkZGVuJywgbmFtZTogc0ZpZWxkTmFtZSwgdmFsdWU6IHNGaWVsZFZhbHVlIH0pKTtcblx0fTtcblxuXHRyZXR1cm4gUHlkaW9EYXRhTW9kZWw7XG59KShfbGFuZ09ic2VydmFibGUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBQeWRpb0RhdGFNb2RlbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIE9iamVjdC5zZXRQcm90b3R5cGVPZiA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcykgOiBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGFuZ09ic2VydmFibGUgPSByZXF1aXJlKCcuLi9sYW5nL09ic2VydmFibGUnKTtcblxudmFyIF9sYW5nT2JzZXJ2YWJsZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nT2JzZXJ2YWJsZSk7XG5cbnZhciBFbXB0eU5vZGVQcm92aWRlciA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoRW1wdHlOb2RlUHJvdmlkZXIsIF9PYnNlcnZhYmxlKTtcblxuICAgIGZ1bmN0aW9uIEVtcHR5Tm9kZVByb3ZpZGVyKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRW1wdHlOb2RlUHJvdmlkZXIpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG4gICAgfVxuXG4gICAgRW1wdHlOb2RlUHJvdmlkZXIucHJvdG90eXBlLmluaXRQcm92aWRlciA9IGZ1bmN0aW9uIGluaXRQcm92aWRlcihwcm9wZXJ0aWVzKSB7XG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIG5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZUNhbGxiYWNrIEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNoaWxkQ2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgKi9cblxuICAgIEVtcHR5Tm9kZVByb3ZpZGVyLnByb3RvdHlwZS5sb2FkTm9kZSA9IGZ1bmN0aW9uIGxvYWROb2RlKG5vZGUsIG5vZGVDYWxsYmFjaywgY2hpbGRDYWxsYmFjaykge307XG5cbiAgICBFbXB0eU5vZGVQcm92aWRlci5wcm90b3R5cGUubG9hZExlYWZOb2RlU3luYyA9IGZ1bmN0aW9uIGxvYWRMZWFmTm9kZVN5bmMobm9kZSwgY2FsbGJhY2spIHt9O1xuXG4gICAgcmV0dXJuIEVtcHR5Tm9kZVByb3ZpZGVyO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRW1wdHlOb2RlUHJvdmlkZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1BhdGhVdGlscycpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbFBhdGhVdGlscyk7XG5cbnZhciBBanhwTm9kZSA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoQWp4cE5vZGUsIF9PYnNlcnZhYmxlKTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHBhdGggU3RyaW5nXG4gICAgICogQHBhcmFtIGlzTGVhZiBCb29sZWFuXG4gICAgICogQHBhcmFtIGxhYmVsIFN0cmluZ1xuICAgICAqIEBwYXJhbSBpY29uIFN0cmluZ1xuICAgICAqIEBwYXJhbSBpTm9kZVByb3ZpZGVyIElBanhwTm9kZVByb3ZpZGVyXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBBanhwTm9kZShwYXRoKSB7XG4gICAgICAgIHZhciBpc0xlYWYgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGxhYmVsID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciBpY29uID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbM107XG4gICAgICAgIHZhciBpTm9kZVByb3ZpZGVyID0gYXJndW1lbnRzLmxlbmd0aCA8PSA0IHx8IGFyZ3VtZW50c1s0XSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1s0XTtcblxuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQWp4cE5vZGUpO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuX3BhdGggPSBwYXRoO1xuICAgICAgICBpZiAodGhpcy5fcGF0aCAmJiB0aGlzLl9wYXRoLmxlbmd0aCAmJiB0aGlzLl9wYXRoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9wYXRoW3RoaXMuX3BhdGgubGVuZ3RoIC0gMV0gPT0gXCIvXCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXRoID0gdGhpcy5fcGF0aC5zdWJzdHJpbmcoMCwgdGhpcy5fcGF0aC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9pc0xlYWYgPSBpc0xlYWY7XG4gICAgICAgIHRoaXMuX2xhYmVsID0gbGFiZWw7XG4gICAgICAgIHRoaXMuX2ljb24gPSBpY29uO1xuICAgICAgICB0aGlzLl9pc1Jvb3QgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLl9tZXRhZGF0YSA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fY2hpbGRyZW4gPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5faXNMb2FkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5mYWtlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lOb2RlUHJvdmlkZXIgPSBpTm9kZVByb3ZpZGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBub2RlIGlzIGxvYWRlZCBvciBub3RcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNMb2FkZWQgPSBmdW5jdGlvbiBpc0xvYWRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzTG9hZGVkO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbm9kZSBpcyBjdXJyZW50bHkgbG9hZGluZ1xuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc0xvYWRpbmcgPSBmdW5jdGlvbiBpc0xvYWRpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0xvYWRpbmc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgbG9hZGVkIHN0YXR1c1xuICAgICAqIEBwYXJhbSBib29sIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5zZXRMb2FkZWQgPSBmdW5jdGlvbiBzZXRMb2FkZWQoYm9vbCkge1xuICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IGJvb2w7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSBub2RlIHByb3ZpZGVyXG4gICAgICogQHBhcmFtIGlBanhwTm9kZVByb3ZpZGVyXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUudXBkYXRlUHJvdmlkZXIgPSBmdW5jdGlvbiB1cGRhdGVQcm92aWRlcihpQWp4cE5vZGVQcm92aWRlcikge1xuICAgICAgICB0aGlzLl9pTm9kZVByb3ZpZGVyID0gaUFqeHBOb2RlUHJvdmlkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWRzIHRoZSBub2RlIHVzaW5nIGl0cyBvd24gcHJvdmlkZXIgb3IgdGhlIG9uZSBwYXNzZWRcbiAgICAgKiBAcGFyYW0gaUFqeHBOb2RlUHJvdmlkZXIgSUFqeHBOb2RlUHJvdmlkZXIgT3B0aW9ubmFsXG4gICAgICogQHBhcmFtIGFkZGl0aW9uYWxQYXJhbWV0ZXJzIE9iamVjdCBvZiBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uIGxvYWQoaUFqeHBOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgdmFyIGFkZGl0aW9uYWxQYXJhbWV0ZXJzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICBpZiAodGhpcy5faXNMb2FkaW5nKSByZXR1cm47XG4gICAgICAgIGlmICghaUFqeHBOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pTm9kZVByb3ZpZGVyKSB7XG4gICAgICAgICAgICAgICAgaUFqeHBOb2RlUHJvdmlkZXIgPSB0aGlzLl9pTm9kZVByb3ZpZGVyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpQWp4cE5vZGVQcm92aWRlciA9IG5ldyBSZW1vdGVOb2RlUHJvdmlkZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9pc0xvYWRpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLm5vdGlmeShcImxvYWRpbmdcIik7XG4gICAgICAgIGlmICh0aGlzLl9pc0xvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5faXNMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeShcImxvYWRlZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpQWp4cE5vZGVQcm92aWRlci5sb2FkTm9kZSh0aGlzLCAoZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX2lzTG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ub3RpZnkoXCJsb2FkZWRcIik7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeShcImZpcnN0X2xvYWRcIik7XG4gICAgICAgIH0pLmJpbmQodGhpcyksIG51bGwsIGZhbHNlLCAtMSwgYWRkaXRpb25hbFBhcmFtZXRlcnMpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgY2hpbGRyZW4gYW5kIHJlbG9hZCBub2RlXG4gICAgICogQHBhcmFtIGlBanhwTm9kZVByb3ZpZGVyIElBanhwTm9kZVByb3ZpZGVyIE9wdGlvbm5hbFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnJlbG9hZCA9IGZ1bmN0aW9uIHJlbG9hZChpQWp4cE5vZGVQcm92aWRlcikge1xuICAgICAgICB2YXIgc2lsZW50Q2xlYXIgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl9jaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCwga2V5KSB7XG4gICAgICAgICAgICBpZiAoIXNpbGVudENsZWFyKSBjaGlsZC5ub3RpZnkoXCJub2RlX3JlbW92ZWRcIik7XG4gICAgICAgICAgICBjaGlsZC5fcGFyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9jaGlsZHJlblsnZGVsZXRlJ10oa2V5KTtcbiAgICAgICAgICAgIGlmICghc2lsZW50Q2xlYXIpIHRoaXMubm90aWZ5KFwiY2hpbGRfcmVtb3ZlZFwiLCBjaGlsZCk7XG4gICAgICAgIH0sIHRoaXMpO1xuICAgICAgICB0aGlzLmxvYWQoaUFqeHBOb2RlUHJvdmlkZXIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVbmxvYWQgY2hpbGQgYW5kIG5vdGlmeSBcImZvcmNlX2NsZWFyXCJcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9jaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCwga2V5KSB7XG4gICAgICAgICAgICBjaGlsZC5ub3RpZnkoXCJub2RlX3JlbW92ZWRcIik7XG4gICAgICAgICAgICBjaGlsZC5fcGFyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9jaGlsZHJlblsnZGVsZXRlJ10oa2V5KTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KFwiY2hpbGRfcmVtb3ZlZFwiLCBjaGlsZCk7XG4gICAgICAgIH0sIHRoaXMpO1xuICAgICAgICB0aGlzLl9pc0xvYWRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5vdGlmeShcImZvcmNlX2NsZWFyXCIpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoaXMgQWp4cE5vZGUgYXMgYmVpbmcgdGhlIHJvb3QgcGFyZW50XG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuc2V0Um9vdCA9IGZ1bmN0aW9uIHNldFJvb3QoKSB7XG4gICAgICAgIHRoaXMuX2lzUm9vdCA9IHRydWU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgbm9kZSBjaGlsZHJlbiBhcyBhIGJ1bmNoXG4gICAgICogQHBhcmFtIGFqeHBOb2RlcyBBanhwTm9kZXNbXVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnNldENoaWxkcmVuID0gZnVuY3Rpb24gc2V0Q2hpbGRyZW4oYWp4cE5vZGVzKSB7XG4gICAgICAgIHRoaXMuX2NoaWxkcmVuID0gbmV3IE1hcCgpO1xuICAgICAgICBhanhwTm9kZXMuZm9yRWFjaCgoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl9jaGlsZHJlbi5zZXQodmFsdWUuZ2V0UGF0aCgpLCB2YWx1ZSk7XG4gICAgICAgICAgICB2YWx1ZS5zZXRQYXJlbnQodGhpcyk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIGNoaWxkcmVuIGFzIGEgYnVuY2hcbiAgICAgKiBAcmV0dXJucyBBanhwTm9kZVtdXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0Q2hpbGRyZW4gPSBmdW5jdGlvbiBnZXRDaGlsZHJlbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NoaWxkcmVuO1xuICAgIH07XG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0Rmlyc3RDaGlsZElmRXhpc3RzID0gZnVuY3Rpb24gZ2V0Rmlyc3RDaGlsZElmRXhpc3RzKCkge1xuICAgICAgICBpZiAodGhpcy5fY2hpbGRyZW4uc2l6ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NoaWxkcmVuLnZhbHVlcygpLm5leHQoKS52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmlzTW9yZVJlY2VudFRoYW4gPSBmdW5jdGlvbiBpc01vcmVSZWNlbnRUaGFuKG90aGVyTm9kZSkge1xuICAgICAgICByZXR1cm4gb3RoZXJOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpICYmIHRoaXMuZ2V0TWV0YWRhdGEoKS5nZXQoXCJhanhwX2ltX3RpbWVcIikgJiYgcGFyc2VJbnQodGhpcy5nZXRNZXRhZGF0YSgpLmdldChcImFqeHBfaW1fdGltZVwiKSkgPj0gcGFyc2VJbnQob3RoZXJOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwiYWp4cF9pbV90aW1lXCIpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGNoaWxkIHRvIGNoaWxkcmVuXG4gICAgICogQHBhcmFtIGFqeHBOb2RlIEFqeHBOb2RlIFRoZSBjaGlsZFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmFkZENoaWxkID0gZnVuY3Rpb24gYWRkQ2hpbGQoYWp4cE5vZGUpIHtcbiAgICAgICAgYWp4cE5vZGUuc2V0UGFyZW50KHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5faU5vZGVQcm92aWRlcikgYWp4cE5vZGUuX2lOb2RlUHJvdmlkZXIgPSB0aGlzLl9pTm9kZVByb3ZpZGVyO1xuICAgICAgICB2YXIgZXhpc3RpbmdOb2RlID0gdGhpcy5maW5kQ2hpbGRCeVBhdGgoYWp4cE5vZGUuZ2V0UGF0aCgpKTtcbiAgICAgICAgaWYgKGV4aXN0aW5nTm9kZSAmJiAhKGV4aXN0aW5nTm9kZSBpbnN0YW5jZW9mIFN0cmluZykpIHtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmdOb2RlLmlzTW9yZVJlY2VudFRoYW4oYWp4cE5vZGUpKSB7XG4gICAgICAgICAgICAgICAgZXhpc3RpbmdOb2RlLnJlcGxhY2VCeShhanhwTm9kZSwgXCJvdmVycmlkZVwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhpc3RpbmdOb2RlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9jaGlsZHJlbi5zZXQoYWp4cE5vZGUuZ2V0UGF0aCgpLCBhanhwTm9kZSk7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeShcImNoaWxkX2FkZGVkXCIsIGFqeHBOb2RlLmdldFBhdGgoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFqeHBOb2RlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBjaGlsZCBmcm9tIHRoZSBjaGlsZHJlblxuICAgICAqIEBwYXJhbSBhanhwTm9kZSBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnJlbW92ZUNoaWxkID0gZnVuY3Rpb24gcmVtb3ZlQ2hpbGQoYWp4cE5vZGUpIHtcbiAgICAgICAgdmFyIHJlbW92ZVBhdGggPSBhanhwTm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIGFqeHBOb2RlLm5vdGlmeShcIm5vZGVfcmVtb3ZlZFwiKTtcbiAgICAgICAgYWp4cE5vZGUuX3BhcmVudE5vZGUgPSBudWxsO1xuICAgICAgICB0aGlzLl9jaGlsZHJlblsnZGVsZXRlJ10oYWp4cE5vZGUuZ2V0UGF0aCgpKTtcbiAgICAgICAgdGhpcy5ub3RpZnkoXCJjaGlsZF9yZW1vdmVkXCIsIHJlbW92ZVBhdGgpO1xuICAgIH07XG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUucmVwbGFjZU1ldGFkYXRhID0gZnVuY3Rpb24gcmVwbGFjZU1ldGFkYXRhKG5ld01ldGEpIHtcbiAgICAgICAgdGhpcy5fbWV0YWRhdGEgPSBuZXdNZXRhO1xuICAgICAgICB0aGlzLm5vdGlmeShcIm1ldGFfcmVwbGFjZWRcIiwgdGhpcyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlcGxhY2VzIHRoZSBjdXJyZW50IG5vZGUgYnkgYSBuZXcgb25lLiBDb3B5IGFsbCBwcm9wZXJ0aWVzIGRlZXBseVxuICAgICAqIEBwYXJhbSBhanhwTm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSBtZXRhTWVyZ2VcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5yZXBsYWNlQnkgPSBmdW5jdGlvbiByZXBsYWNlQnkoYWp4cE5vZGUsIG1ldGFNZXJnZSkge1xuICAgICAgICB0aGlzLl9pc0xlYWYgPSBhanhwTm9kZS5faXNMZWFmO1xuICAgICAgICB2YXIgcGF0aENoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKGFqeHBOb2RlLmdldFBhdGgoKSAmJiB0aGlzLl9wYXRoICE9IGFqeHBOb2RlLmdldFBhdGgoKSkge1xuICAgICAgICAgICAgdmFyIG9yaWdpbmFsUGF0aCA9IHRoaXMuX3BhdGg7XG4gICAgICAgICAgICBpZiAodGhpcy5nZXRQYXJlbnQoKSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnRDaGlsZHJlbkluZGV4ID0gdGhpcy5nZXRQYXJlbnQoKS5fY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgcGFyZW50Q2hpbGRyZW5JbmRleC5zZXQoYWp4cE5vZGUuZ2V0UGF0aCgpLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBwYXJlbnRDaGlsZHJlbkluZGV4WydkZWxldGUnXShvcmlnaW5hbFBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcGF0aCA9IGFqeHBOb2RlLmdldFBhdGgoKTtcbiAgICAgICAgICAgIHBhdGhDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWp4cE5vZGUuX2xhYmVsKSB7XG4gICAgICAgICAgICB0aGlzLl9sYWJlbCA9IGFqeHBOb2RlLl9sYWJlbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWp4cE5vZGUuX2ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuX2ljb24gPSBhanhwTm9kZS5faWNvbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWp4cE5vZGUuX2lOb2RlUHJvdmlkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuX2lOb2RlUHJvdmlkZXIgPSBhanhwTm9kZS5faU5vZGVQcm92aWRlcjtcbiAgICAgICAgfVxuICAgICAgICAvL3RoaXMuX2lzUm9vdCA9IGFqeHBOb2RlLl9pc1Jvb3Q7XG4gICAgICAgIHRoaXMuX2lzTG9hZGVkID0gYWp4cE5vZGUuX2lzTG9hZGVkO1xuICAgICAgICB0aGlzLmZha2UgPSBhanhwTm9kZS5mYWtlO1xuICAgICAgICB2YXIgbWV0YSA9IGFqeHBOb2RlLmdldE1ldGFkYXRhKCk7XG4gICAgICAgIGlmIChtZXRhTWVyZ2UgPT0gXCJvdmVycmlkZVwiKSB0aGlzLl9tZXRhZGF0YSA9IG5ldyBNYXAoKTtcbiAgICAgICAgbWV0YS5mb3JFYWNoKChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgaWYgKG1ldGFNZXJnZSA9PSBcIm92ZXJyaWRlXCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tZXRhZGF0YS5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9tZXRhZGF0YS5oYXMoa2V5KSAmJiB2YWx1ZSA9PT0gXCJcIikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuX21ldGFkYXRhLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgIGlmIChwYXRoQ2hhbmdlZCAmJiAhdGhpcy5faXNMZWFmICYmIHRoaXMuZ2V0Q2hpbGRyZW4oKS5zaXplKSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVsb2FkKHRoaXMuX2lOb2RlUHJvdmlkZXIpO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKSwgMTAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBhanhwTm9kZS5nZXRDaGlsZHJlbigpLmZvckVhY2goKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICAgICAgdGhpcy5hZGRDaGlsZChjaGlsZCk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm5vdGlmeShcIm5vZGVfcmVwbGFjZWRcIiwgdGhpcyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIGEgY2hpbGQgbm9kZSBieSBpdHMgcGF0aFxuICAgICAqIEBwYXJhbSBwYXRoIFN0cmluZ1xuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZmluZENoaWxkQnlQYXRoID0gZnVuY3Rpb24gZmluZENoaWxkQnlQYXRoKHBhdGgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NoaWxkcmVuLmdldChwYXRoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWV0YWRhdGEgYXMgYSBidW5jaFxuICAgICAqIEBwYXJhbSBkYXRhIE1hcCBBIE1hcFxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnNldE1ldGFkYXRhID0gZnVuY3Rpb24gc2V0TWV0YWRhdGEoZGF0YSkge1xuICAgICAgICB0aGlzLl9tZXRhZGF0YSA9IGRhdGE7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG1ldGFkYXRcbiAgICAgKiBAcmV0dXJucyBNYXBcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIGdldE1ldGFkYXRhKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWV0YWRhdGE7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIElzIHRoaXMgbm9kZSBhIGxlYWZcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNMZWFmID0gZnVuY3Rpb24gaXNMZWFmKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNMZWFmO1xuICAgIH07XG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNCcm93c2FibGUgPSBmdW5jdGlvbiBpc0Jyb3dzYWJsZSgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLl9pc0xlYWYgfHwgdGhpcy5nZXRBanhwTWltZSgpID09PSAnYWp4cF9icm93c2FibGVfYXJjaGl2ZSc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldFBhdGggPSBmdW5jdGlvbiBnZXRQYXRoKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGF0aDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgU3RyaW5nXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0TGFiZWwgPSBmdW5jdGlvbiBnZXRMYWJlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xhYmVsO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBTdHJpbmdcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRJY29uID0gZnVuY3Rpb24gZ2V0SWNvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ljb247XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc1JlY3ljbGUgPSBmdW5jdGlvbiBpc1JlY3ljbGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEFqeHBNaW1lKCkgPT0gJ2FqeHBfcmVjeWNsZSc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFN0cmluZ1xuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmdldFN2Z1NvdXJjZSA9IGZ1bmN0aW9uIGdldFN2Z1NvdXJjZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWV0YWRhdGEoKS5nZXQoXCJmb250aWNvblwiKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VhcmNoIHRoZSBtaW1lIHR5cGUgaW4gdGhlIHBhcmVudCBicmFuY2hcbiAgICAgKiBAcGFyYW0gYWp4cE1pbWUgU3RyaW5nXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmhhc0FqeHBNaW1lSW5CcmFuY2ggPSBmdW5jdGlvbiBoYXNBanhwTWltZUluQnJhbmNoKGFqeHBNaW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmdldEFqeHBNaW1lKCkgPT0gYWp4cE1pbWUudG9Mb3dlckNhc2UoKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIHZhciBwYXJlbnQgPSB1bmRlZmluZWQsXG4gICAgICAgICAgICBjcnQgPSB0aGlzO1xuICAgICAgICB3aGlsZSAocGFyZW50ID0gY3J0Ll9wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICBpZiAocGFyZW50LmdldEFqeHBNaW1lKCkgPT0gYWp4cE1pbWUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3J0ID0gcGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VhcmNoIHRoZSBtaW1lIHR5cGUgaW4gdGhlIHBhcmVudCBicmFuY2hcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICogQHBhcmFtIG1ldGFkYXRhS2V5XG4gICAgICogQHBhcmFtIG1ldGFkYXRhVmFsdWVcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5oYXNNZXRhZGF0YUluQnJhbmNoID0gZnVuY3Rpb24gaGFzTWV0YWRhdGFJbkJyYW5jaChtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xuICAgICAgICBpZiAodGhpcy5nZXRNZXRhZGF0YSgpLmhhcyhtZXRhZGF0YUtleSkpIHtcbiAgICAgICAgICAgIGlmIChtZXRhZGF0YVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWV0YWRhdGEoKS5nZXQobWV0YWRhdGFLZXkpID09IG1ldGFkYXRhVmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJlbnQgPSB1bmRlZmluZWQsXG4gICAgICAgICAgICBjcnQgPSB0aGlzO1xuICAgICAgICB3aGlsZSAocGFyZW50ID0gY3J0Ll9wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICBpZiAocGFyZW50LmdldE1ldGFkYXRhKCkuaGFzKG1ldGFkYXRhS2V5KSkge1xuICAgICAgICAgICAgICAgIGlmIChtZXRhZGF0YVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnQuZ2V0TWV0YWRhdGEoKS5nZXQobWV0YWRhdGFLZXkpID09IG1ldGFkYXRhVmFsdWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3J0ID0gcGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIHJlZmVyZW5jZSB0byB0aGUgcGFyZW50IG5vZGVcbiAgICAgKiBAcGFyYW0gcGFyZW50Tm9kZSBBanhwTm9kZVxuICAgICAqL1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLnNldFBhcmVudCA9IGZ1bmN0aW9uIHNldFBhcmVudChwYXJlbnROb2RlKSB7XG4gICAgICAgIHRoaXMuX3BhcmVudE5vZGUgPSBwYXJlbnROb2RlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwYXJlbnQgTm9kZVxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZ2V0UGFyZW50ID0gZnVuY3Rpb24gZ2V0UGFyZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGFyZW50Tm9kZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhpcyBub2RlIGJ5IHBhdGggaWYgaXQgYWxyZWFkeSBleGlzdHMgaW4gYXJib3Jlc2NlbmNlXG4gICAgICogQHBhcmFtIHJvb3ROb2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIGZha2VOb2RlcyBBanhwTm9kZVtdXG4gICAgICogQHJldHVybnMgQWp4cE5vZGV8dW5kZWZpbmVkXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuZmluZEluQXJibyA9IGZ1bmN0aW9uIGZpbmRJbkFyYm8ocm9vdE5vZGUsIGZha2VOb2Rlcykge1xuICAgICAgICBpZiAoIXRoaXMuZ2V0UGF0aCgpKSByZXR1cm47XG4gICAgICAgIHZhciBwYXRoUGFydHMgPSB0aGlzLmdldFBhdGgoKS5zcGxpdChcIi9cIik7XG4gICAgICAgIHZhciBjcnRQYXRoID0gXCJcIixcbiAgICAgICAgICAgIGNydE5vZGUgPSB1bmRlZmluZWQsXG4gICAgICAgICAgICBjcnRQYXJlbnROb2RlID0gcm9vdE5vZGU7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0aFBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAocGF0aFBhcnRzW2ldID09IFwiXCIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgY3J0UGF0aCA9IGNydFBhdGggKyBcIi9cIiArIHBhdGhQYXJ0c1tpXTtcbiAgICAgICAgICAgIHZhciBub2RlID0gY3J0UGFyZW50Tm9kZS5maW5kQ2hpbGRCeVBhdGgoY3J0UGF0aCk7XG4gICAgICAgICAgICBpZiAobm9kZSAmJiAhKG5vZGUgaW5zdGFuY2VvZiBTdHJpbmcpKSB7XG4gICAgICAgICAgICAgICAgY3J0Tm9kZSA9IG5vZGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChmYWtlTm9kZXMgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBjcnROb2RlID0gbmV3IEFqeHBOb2RlKGNydFBhdGgsIGZhbHNlLCBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShjcnRQYXRoKSk7XG4gICAgICAgICAgICAgICAgY3J0Tm9kZS5mYWtlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjcnROb2RlLmdldE1ldGFkYXRhKCkuc2V0KFwidGV4dFwiLCBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShjcnRQYXRoKSk7XG4gICAgICAgICAgICAgICAgZmFrZU5vZGVzLnB1c2goY3J0Tm9kZSk7XG4gICAgICAgICAgICAgICAgY3J0UGFyZW50Tm9kZS5hZGRDaGlsZChjcnROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNydFBhcmVudE5vZGUgPSBjcnROb2RlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjcnROb2RlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBCb29sZWFuXG4gICAgICovXG5cbiAgICBBanhwTm9kZS5wcm90b3R5cGUuaXNSb290ID0gZnVuY3Rpb24gaXNSb290KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNSb290O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBpdCdzIHRoZSBwYXJlbnQgb2YgdGhlIGdpdmVuIG5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc1BhcmVudE9mID0gZnVuY3Rpb24gaXNQYXJlbnRPZihub2RlKSB7XG4gICAgICAgIHZhciBjaGlsZFBhdGggPSBub2RlLmdldFBhdGgoKTtcbiAgICAgICAgdmFyIHBhcmVudFBhdGggPSB0aGlzLmdldFBhdGgoKTtcbiAgICAgICAgcmV0dXJuIGNoaWxkUGF0aC5zdWJzdHJpbmcoMCwgcGFyZW50UGF0aC5sZW5ndGgpID09PSBwYXJlbnRQYXRoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBpdCdzIGEgY2hpbGQgb2YgdGhlIGdpdmVuIG5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBBanhwTm9kZVxuICAgICAqIEByZXR1cm5zIEJvb2xlYW5cbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5pc0NoaWxkT2YgPSBmdW5jdGlvbiBpc0NoaWxkT2Yobm9kZSkge1xuICAgICAgICB2YXIgY2hpbGRQYXRoID0gdGhpcy5nZXRQYXRoKCk7XG4gICAgICAgIHZhciBwYXJlbnRQYXRoID0gbm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIHJldHVybiBjaGlsZFBhdGguc3Vic3RyaW5nKDAsIHBhcmVudFBhdGgubGVuZ3RoKSA9PT0gcGFyZW50UGF0aDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgY3VycmVudCdzIG5vZGUgbWltZSB0eXBlLCBlaXRoZXIgYnkgYWp4cF9taW1lIG9yIGJ5IGV4dGVuc2lvbi5cbiAgICAgKiBAcmV0dXJucyBTdHJpbmdcbiAgICAgKi9cblxuICAgIEFqeHBOb2RlLnByb3RvdHlwZS5nZXRBanhwTWltZSA9IGZ1bmN0aW9uIGdldEFqeHBNaW1lKCkge1xuICAgICAgICBpZiAodGhpcy5fbWV0YWRhdGEgJiYgdGhpcy5fbWV0YWRhdGEuaGFzKFwiYWp4cF9taW1lXCIpKSByZXR1cm4gdGhpcy5fbWV0YWRhdGEuZ2V0KFwiYWp4cF9taW1lXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmICh0aGlzLl9tZXRhZGF0YSAmJiB0aGlzLmlzTGVhZigpKSByZXR1cm4gX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QWp4cE1pbWVUeXBlKHRoaXMuX21ldGFkYXRhKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB9O1xuXG4gICAgQWp4cE5vZGUucHJvdG90eXBlLmJ1aWxkUmFuZG9tU2VlZCA9IGZ1bmN0aW9uIGJ1aWxkUmFuZG9tU2VlZChhanhwTm9kZSkge1xuICAgICAgICB2YXIgbXRpbWVTdHJpbmcgPSBcIiZ0aW1lX3NlZWQ9XCIgKyB0aGlzLl9tZXRhZGF0YS5nZXQoXCJhanhwX21vZGlmdGltZVwiKTtcbiAgICAgICAgaWYgKHRoaXMuZ2V0UGFyZW50KCkpIHtcbiAgICAgICAgICAgIHZhciBwcmV2aWV3X3NlZWQgPSB0aGlzLmdldFBhcmVudCgpLmdldE1ldGFkYXRhKCkuZ2V0KCdwcmV2aWV3X3NlZWQnKTtcbiAgICAgICAgICAgIGlmIChwcmV2aWV3X3NlZWQpIHtcbiAgICAgICAgICAgICAgICBtdGltZVN0cmluZyArPSBcIiZyYW5kPVwiICsgcHJldmlld19zZWVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdGltZVN0cmluZztcbiAgICB9O1xuXG4gICAgcmV0dXJuIEFqeHBOb2RlO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQWp4cE5vZGU7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpID0gcmVxdWlyZSgnLi4vaHR0cC9QeWRpb0FwaScpO1xuXG52YXIgX2h0dHBQeWRpb0FwaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUHlkaW9BcGkpO1xuXG52YXIgX1VzZXIgPSByZXF1aXJlKCcuL1VzZXInKTtcblxudmFyIF9Vc2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX1VzZXIpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuLi9sYW5nL0xvZ2dlcicpO1xuXG52YXIgX2xhbmdMb2dnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ0xvZ2dlcik7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIgPSByZXF1aXJlKCcuLi9odHRwL1Jlc291cmNlc01hbmFnZXInKTtcblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9odHRwUmVzb3VyY2VzTWFuYWdlcik7XG5cbnZhciBSZWdpc3RyeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUmVnaXN0cnkocHlkaW9PYmplY3QpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlZ2lzdHJ5KTtcblxuICAgICAgICB0aGlzLl9yZWdpc3RyeSA9IG51bGw7XG4gICAgICAgIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeSA9IHsgXCJlZGl0b3JcIjogW10sIFwidXBsb2FkZXJcIjogW10gfTtcbiAgICAgICAgdGhpcy5fcmVzb3VyY2VzUmVnaXN0cnkgPSB7fTtcbiAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QgPSBweWRpb09iamVjdDtcbiAgICAgICAgdGhpcy5feFBhdGhMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2dsb2JhbExvYWRpbmcgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZSBYTUwgU3RyaW5nIGRpcmVjdGx5XG4gICAgICogQHBhcmFtIHNcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5sb2FkRnJvbVN0cmluZyA9IGZ1bmN0aW9uIGxvYWRGcm9tU3RyaW5nKHMpIHtcbiAgICAgICAgdGhpcy5fcmVnaXN0cnkgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLnBhcnNlWG1sKHMpLmRvY3VtZW50RWxlbWVudDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZCByZWdpc3RyeSBmcm9tIHNlcnZlclxuICAgICAqIEBwYXJhbSB4UGF0aFxuICAgICAqIEBwYXJhbSBjb21wbGV0ZUZ1bmNcbiAgICAgKiBAcGFyYW0gcmVwb3NpdG9yeUlkXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uIGxvYWQoKSB7XG4gICAgICAgIHZhciB4UGF0aCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMCB8fCBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMF07XG4gICAgICAgIHZhciBjb21wbGV0ZUZ1bmMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgcmVwb3NpdG9yeUlkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgICBpZiAoeFBhdGggPT09IG51bGwgJiYgdGhpcy5fZ2xvYmFsTG9hZGluZyB8fCB4UGF0aCAmJiB0aGlzLl94UGF0aExvYWRpbmcgPT09IHhQYXRoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHhQYXRoKSB0aGlzLl94UGF0aExvYWRpbmcgPSB4UGF0aDtlbHNlIHRoaXMuX2dsb2JhbExvYWRpbmcgPSB0cnVlO1xuICAgICAgICB2YXIgb25Db21wbGV0ZSA9IChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBpZiAoeFBhdGgpIHRoaXMuX3hQYXRoTG9hZGluZyA9IGZhbHNlO2Vsc2UgdGhpcy5fZ2xvYmFsTG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTCA9PSBudWxsIHx8IHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQgPT0gbnVsbCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgPT0gXCJhanhwX3JlZ2lzdHJ5XCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZWdpc3RyeSA9IHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYgKCFjb21wbGV0ZUZ1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHlkaW9PYmplY3QuZmlyZShcInJlZ2lzdHJ5X2xvYWRlZFwiLCB0aGlzLl9yZWdpc3RyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0cmFuc3BvcnQucmVzcG9uc2VYTUwuZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lID09IFwiYWp4cF9yZWdpc3RyeV9wYXJ0XCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZnJlc2hYbWxSZWdpc3RyeVBhcnQodHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29tcGxldGVGdW5jKSBjb21wbGV0ZUZ1bmModGhpcy5fcmVnaXN0cnkpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICB2YXIgcGFyYW1zID0geyBnZXRfYWN0aW9uOiAnZ2V0X3htbF9yZWdpc3RyeScgfTtcbiAgICAgICAgaWYgKHhQYXRoKSB7XG4gICAgICAgICAgICBwYXJhbXNbJ3hQYXRoJ10gPSB4UGF0aDtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVwb3NpdG9yeUlkKSB7XG4gICAgICAgICAgICBwYXJhbXNbJ3dzX2lkJ10gPSByZXBvc2l0b3J5SWQ7IC8vIGZvciBjYWNoaW5nIG9ubHlcbiAgICAgICAgfVxuICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCBvbkNvbXBsZXRlLCBudWxsLCB7IG1ldGhvZDogJ2dldCcgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEluc2VydHMgYSBkb2N1bWVudCBmcmFnbWVudCByZXRyaWV2ZWQgZnJvbSBzZXJ2ZXIgaW5zaWRlIHRoZSBmdWxsIHRyZWUuXG4gICAgICogVGhlIG5vZGUgbXVzdCBjb250YWlucyB0aGUgeFBhdGggYXR0cmlidXRlIHRvIGxvY2F0ZSBpdCBpbnNpZGUgdGhlIHJlZ2lzdHJ5LlxuICAgICAqIEV2ZW50IGFqYXhwbG9yZXI6cmVnaXN0cnlfcGFydF9sb2FkZWQgaXMgdHJpZ2dlcmQgb25jZSB0aGlzIGlzIGRvbmUuXG4gICAgICogQHBhcmFtIGRvY3VtZW50RWxlbWVudCBET01Ob2RlXG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUucmVmcmVzaFhtbFJlZ2lzdHJ5UGFydCA9IGZ1bmN0aW9uIHJlZnJlc2hYbWxSZWdpc3RyeVBhcnQoZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgIHZhciB4UGF0aCA9IGRvY3VtZW50RWxlbWVudC5nZXRBdHRyaWJ1dGUoXCJ4UGF0aFwiKTtcbiAgICAgICAgdmFyIGV4aXN0aW5nTm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCB4UGF0aCk7XG4gICAgICAgIHZhciBwYXJlbnROb2RlID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoZXhpc3RpbmdOb2RlICYmIGV4aXN0aW5nTm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICBwYXJlbnROb2RlID0gZXhpc3RpbmdOb2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGV4aXN0aW5nTm9kZSk7XG4gICAgICAgICAgICBpZiAoZG9jdW1lbnRFbGVtZW50LmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkLmNsb25lTm9kZSh0cnVlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoeFBhdGguaW5kZXhPZihcIi9cIikgPiAtMSkge1xuICAgICAgICAgICAgLy8gdHJ5IHNlbGVjdGluZyBwYXJlbnROb2RlXG4gICAgICAgICAgICB2YXIgcGFyZW50UGF0aCA9IHhQYXRoLnN1YnN0cmluZygwLCB4UGF0aC5sYXN0SW5kZXhPZihcIi9cIikpO1xuICAgICAgICAgICAgcGFyZW50Tm9kZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHRoaXMuX3JlZ2lzdHJ5LCBwYXJlbnRQYXRoKTtcbiAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZC5jbG9uZU5vZGUodHJ1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGRvY3VtZW50RWxlbWVudC5maXJzdENoaWxkKSB0aGlzLl9yZWdpc3RyeS5hcHBlbmRDaGlsZChkb2N1bWVudEVsZW1lbnQuZmlyc3RDaGlsZC5jbG9uZU5vZGUodHJ1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3B5ZGlvT2JqZWN0LmZpcmUoXCJyZWdpc3RyeV9wYXJ0X2xvYWRlZFwiLCB4UGF0aCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRyYW5zbGF0ZSB0aGUgWE1MIGFuc3dlciB0byBhIG5ldyBVc2VyIG9iamVjdFxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLnBhcnNlVXNlciA9IGZ1bmN0aW9uIHBhcnNlVXNlcigpIHtcbiAgICAgICAgdmFyIHVzZXIgPSBudWxsLFxuICAgICAgICAgICAgdXNlck5vZGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0aGlzLl9yZWdpc3RyeSkge1xuICAgICAgICAgICAgdXNlck5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgXCJ1c2VyXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1c2VyTm9kZSkge1xuICAgICAgICAgICAgdmFyIHVzZXJJZCA9IHVzZXJOb2RlLmdldEF0dHJpYnV0ZSgnaWQnKTtcbiAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHVzZXJOb2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICBpZiAodXNlcklkKSB7XG4gICAgICAgICAgICAgICAgdXNlciA9IG5ldyBfVXNlcjJbJ2RlZmF1bHQnXSh1c2VySWQsIGNoaWxkcmVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXNlcjtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7RWxlbWVudHwqfG51bGx9XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZ2V0WE1MID0gZnVuY3Rpb24gZ2V0WE1MKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVnaXN0cnk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgRXh0ZW5zaW9uIGluaXRpYWxpc2F0aW9uIG5vZGVzIChhY3RpdmVDb25kaXRpb24sIG9uSW5pdCwgZXRjKSwgcGFyc2VzXG4gICAgICogdGhlIFhNTCBhbmQgZXhlY3V0ZSBKUy5cbiAgICAgKiBAcGFyYW0geG1sTm9kZSB7RWxlbWVudH0gVGhlIGV4dGVuc2lvbiBub2RlXG4gICAgICogQHBhcmFtIGV4dGVuc2lvbkRlZmluaXRpb24gT2JqZWN0IEluZm9ybWF0aW9uIGFscmVhZHkgY29sbGVjdGVkIGFib3V0IHRoaXMgZXh0ZW5zaW9uXG4gICAgICogQHJldHVybnMgQm9vbGVhblxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmluaXRFeHRlbnNpb24gPSBmdW5jdGlvbiBpbml0RXh0ZW5zaW9uKHhtbE5vZGUsIGV4dGVuc2lvbkRlZmluaXRpb24pIHtcbiAgICAgICAgdmFyIGFjdGl2ZUNvbmRpdGlvbiA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2FjdGl2ZUNvbmRpdGlvbicpO1xuICAgICAgICBpZiAoYWN0aXZlQ29uZGl0aW9uICYmIGFjdGl2ZUNvbmRpdGlvbi5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jID0gbmV3IEZ1bmN0aW9uKGFjdGl2ZUNvbmRpdGlvbi5maXJzdENoaWxkLm5vZGVWYWx1ZS50cmltKCkpO1xuICAgICAgICAgICAgICAgIGlmIChmdW5jKCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB9XG4gICAgICAgIGlmICh4bWxOb2RlLm5vZGVOYW1lID09ICdlZGl0b3InKSB7XG5cbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZXh0ZW5zaW9uRGVmaW5pdGlvbiwge1xuICAgICAgICAgICAgICAgIG9wZW5hYmxlOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm9wZW5hYmxlXCIpID09IFwidHJ1ZVwiLFxuICAgICAgICAgICAgICAgIG1vZGFsT25seTogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJtb2RhbE9ubHlcIikgPT0gXCJ0cnVlXCIsXG4gICAgICAgICAgICAgICAgcHJldmlld1Byb3ZpZGVyOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcInByZXZpZXdQcm92aWRlclwiKSA9PSBcInRydWVcIixcbiAgICAgICAgICAgICAgICBvcmRlcjogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJvcmRlclwiKSA/IHBhcnNlSW50KHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwib3JkZXJcIikpIDogMCxcbiAgICAgICAgICAgICAgICBmb3JtSWQ6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiZm9ybUlkXCIpIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgdGV4dDogdGhpcy5fcHlkaW9PYmplY3QuTWVzc2FnZUhhc2hbeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJ0ZXh0XCIpXSxcbiAgICAgICAgICAgICAgICB0aXRsZTogdGhpcy5fcHlkaW9PYmplY3QuTWVzc2FnZUhhc2hbeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJ0aXRsZVwiKV0sXG4gICAgICAgICAgICAgICAgaWNvbjogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJpY29uXCIpLFxuICAgICAgICAgICAgICAgIGljb25fY2xhc3M6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiaWNvbkNsYXNzXCIpLFxuICAgICAgICAgICAgICAgIGVkaXRvckFjdGlvbnM6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiYWN0aW9uc1wiKSxcbiAgICAgICAgICAgICAgICBlZGl0b3JDbGFzczogeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJjbGFzc05hbWVcIiksXG4gICAgICAgICAgICAgICAgbWltZXM6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwibWltZXNcIikuc3BsaXQoXCIsXCIpLFxuICAgICAgICAgICAgICAgIHdyaXRlOiB4bWxOb2RlLmdldEF0dHJpYnV0ZShcIndyaXRlXCIpICYmIHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwid3JpdGVcIikgPT0gXCJ0cnVlXCIgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICAgICAgY2FuV3JpdGU6IHhtbE5vZGUuZ2V0QXR0cmlidXRlKFwiY2FuV3JpdGVcIikgJiYgeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJjYW5Xcml0ZVwiKSA9PSBcInRydWVcIiA/IHRydWUgOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoeG1sTm9kZS5ub2RlTmFtZSA9PSAndXBsb2FkZXInKSB7XG5cbiAgICAgICAgICAgIHZhciB0aCA9IHRoaXMuX3B5ZGlvT2JqZWN0LlBhcmFtZXRlcnMuZ2V0KCd0aGVtZScpO1xuICAgICAgICAgICAgdmFyIGNsaWVudEZvcm0gPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9jbGllbnRGb3JtW0B0aGVtZT1cIicgKyB0aCArICdcIl0nKTtcbiAgICAgICAgICAgIGlmICghY2xpZW50Rm9ybSkge1xuICAgICAgICAgICAgICAgIGNsaWVudEZvcm0gPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh4bWxOb2RlLCAncHJvY2Vzc2luZy9jbGllbnRGb3JtJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2xpZW50Rm9ybSAmJiBjbGllbnRGb3JtLmdldEF0dHJpYnV0ZSgnbW9kdWxlJykpIHtcbiAgICAgICAgICAgICAgICBleHRlbnNpb25EZWZpbml0aW9uLm1vZHVsZU5hbWUgPSBjbGllbnRGb3JtLmdldEF0dHJpYnV0ZSgnbW9kdWxlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeG1sTm9kZS5nZXRBdHRyaWJ1dGUoXCJvcmRlclwiKSkge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24ub3JkZXIgPSBwYXJzZUludCh4bWxOb2RlLmdldEF0dHJpYnV0ZShcIm9yZGVyXCIpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5vcmRlciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZXh0ZW5zaW9uT25Jbml0ID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvZXh0ZW5zaW9uT25Jbml0Jyk7XG4gICAgICAgICAgICBpZiAoZXh0ZW5zaW9uT25Jbml0ICYmIGV4dGVuc2lvbk9uSW5pdC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQFRPRE86IFRISVMgV0lMTCBMSUtFTFkgVFJJR0dFUiBQUk9UT1RZUEUgQ09ERVxuICAgICAgICAgICAgICAgICAgICBldmFsKGV4dGVuc2lvbk9uSW5pdC5maXJzdENoaWxkLm5vZGVWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5lcnJvcihcIklnbm9yaW5nIEVycm9yIGluIGV4dGVuc2lvbk9uSW5pdCBjb2RlOlwiKTtcbiAgICAgICAgICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoZXh0ZW5zaW9uT25Jbml0LmZpcnN0Q2hpbGQubm9kZVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoZS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlhbG9nT25PcGVuID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sTm9kZSwgJ3Byb2Nlc3NpbmcvZGlhbG9nT25PcGVuJyk7XG4gICAgICAgICAgICBpZiAoZGlhbG9nT25PcGVuICYmIGRpYWxvZ09uT3Blbi5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5kaWFsb2dPbk9wZW4gPSBkaWFsb2dPbk9wZW4uZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlhbG9nT25Db21wbGV0ZSA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3RTaW5nbGVOb2RlKHhtbE5vZGUsICdwcm9jZXNzaW5nL2RpYWxvZ09uQ29tcGxldGUnKTtcbiAgICAgICAgICAgIGlmIChkaWFsb2dPbkNvbXBsZXRlICYmIGRpYWxvZ09uQ29tcGxldGUuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgICAgIGV4dGVuc2lvbkRlZmluaXRpb24uZGlhbG9nT25Db21wbGV0ZSA9IGRpYWxvZ09uQ29tcGxldGUuZmlyc3RDaGlsZC5ub2RlVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZnJlc2ggdGhlIGN1cnJlbnRseSBhY3RpdmUgZXh0ZW5zaW9uc1xuICAgICAqIEV4dGVuc2lvbnMgYXJlIGVkaXRvcnMgYW5kIHVwbG9hZGVycyBmb3IgdGhlIG1vbWVudC5cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5yZWZyZXNoRXh0ZW5zaW9uc1JlZ2lzdHJ5ID0gZnVuY3Rpb24gcmVmcmVzaEV4dGVuc2lvbnNSZWdpc3RyeSgpIHtcblxuICAgICAgICB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnkgPSB7IFwiZWRpdG9yXCI6IFtdLCBcInVwbG9hZGVyXCI6IFtdIH07XG4gICAgICAgIHZhciBleHRlbnNpb25zID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHRoaXMuX3JlZ2lzdHJ5LCBcInBsdWdpbnMvZWRpdG9yfHBsdWdpbnMvdXBsb2FkZXJcIik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXh0ZW5zaW9ucy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICB2YXIgZXh0ZW5zaW9uRGVmaW5pdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBpZDogZXh0ZW5zaW9uc1tpXS5nZXRBdHRyaWJ1dGUoXCJpZFwiKSxcbiAgICAgICAgICAgICAgICB4bWxOb2RlOiBleHRlbnNpb25zW2ldLFxuICAgICAgICAgICAgICAgIHJlc291cmNlc01hbmFnZXI6IG5ldyBfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10oKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuX3Jlc291cmNlc1JlZ2lzdHJ5W2V4dGVuc2lvbkRlZmluaXRpb24uaWRdID0gZXh0ZW5zaW9uRGVmaW5pdGlvbi5yZXNvdXJjZXNNYW5hZ2VyO1xuICAgICAgICAgICAgdmFyIHJlc291cmNlTm9kZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoZXh0ZW5zaW9uc1tpXSwgXCJjbGllbnRfc2V0dGluZ3MvcmVzb3VyY2VzfGRlcGVuZGVuY2llc3xjbGllbnRGb3JtXCIpO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCByZXNvdXJjZU5vZGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uRGVmaW5pdGlvbi5yZXNvdXJjZXNNYW5hZ2VyLmxvYWRGcm9tWG1sTm9kZShyZXNvdXJjZU5vZGVzW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmluaXRFeHRlbnNpb24oZXh0ZW5zaW9uc1tpXSwgZXh0ZW5zaW9uRGVmaW5pdGlvbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnlbZXh0ZW5zaW9uc1tpXS5ub2RlTmFtZV0ucHVzaChleHRlbnNpb25EZWZpbml0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10ubG9hZEF1dG9Mb2FkUmVzb3VyY2VzKHRoaXMuX3JlZ2lzdHJ5KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCB0aGUgY3VycmVudGx5IGFjdGl2ZSBleHRlbnNpb25zIGJ5IHR5cGVcbiAgICAgKiBAcGFyYW0gZXh0ZW5zaW9uVHlwZSBTdHJpbmcgXCJlZGl0b3JcIiBvciBcInVwbG9hZGVyXCJcbiAgICAgKiBAcmV0dXJucyB7YXJyYXl9XG4gICAgICovXG5cbiAgICBSZWdpc3RyeS5wcm90b3R5cGUuZ2V0QWN0aXZlRXh0ZW5zaW9uQnlUeXBlID0gZnVuY3Rpb24gZ2V0QWN0aXZlRXh0ZW5zaW9uQnlUeXBlKGV4dGVuc2lvblR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeVtleHRlbnNpb25UeXBlXTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmluZCBhIGdpdmVuIGVkaXRvciBieSBpdHMgaWRcbiAgICAgKiBAcGFyYW0gZWRpdG9ySWQgU3RyaW5nXG4gICAgICogQHJldHVybnMgQWJzdHJhY3RFZGl0b3JcbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5maW5kRWRpdG9yQnlJZCA9IGZ1bmN0aW9uIGZpbmRFZGl0b3JCeUlkKGVkaXRvcklkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9leHRlbnNpb25zUmVnaXN0cnkuZWRpdG9yLmZpbmQoZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICByZXR1cm4gZWwuaWQgPT0gZWRpdG9ySWQ7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIEVkaXRvcnMgdGhhdCBjYW4gaGFuZGxlIGEgZ2l2ZW4gbWltZSB0eXBlXG4gICAgICogQHBhcmFtIG1pbWUgU3RyaW5nXG4gICAgICogQHJldHVybnMgQWJzdHJhY3RFZGl0b3JbXVxuICAgICAqIEBwYXJhbSByZXN0cmljdFRvUHJldmlld1Byb3ZpZGVyc1xuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmZpbmRFZGl0b3JzRm9yTWltZSA9IGZ1bmN0aW9uIGZpbmRFZGl0b3JzRm9yTWltZShtaW1lLCByZXN0cmljdFRvUHJldmlld1Byb3ZpZGVycykge1xuXG4gICAgICAgIHZhciB1c2VyID0gdGhpcy5fcHlkaW9PYmplY3QudXNlcjtcbiAgICAgICAgdmFyIGVkaXRvcnMgPSBbXSxcbiAgICAgICAgICAgIGNoZWNrV3JpdGUgPSBmYWxzZTtcblxuICAgICAgICBpZiAodXNlciAhPSBudWxsICYmICF1c2VyLmNhbldyaXRlKCkpIHtcbiAgICAgICAgICAgIGNoZWNrV3JpdGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2V4dGVuc2lvbnNSZWdpc3RyeS5lZGl0b3IuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbC5taW1lcy5pbmRleE9mKG1pbWUpICE9PSAtMSB8fCBlbC5taW1lcy5pbmRleE9mKCcqJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3RyaWN0VG9QcmV2aWV3UHJvdmlkZXJzICYmICFlbC5wcmV2aWV3UHJvdmlkZXIpIHJldHVybjtcbiAgICAgICAgICAgICAgICBpZiAoIWNoZWNrV3JpdGUgfHwgIWVsLndyaXRlKSBlZGl0b3JzLnB1c2goZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGVkaXRvcnMubGVuZ3RoICYmIGVkaXRvcnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZWRpdG9ycyA9IGVkaXRvcnMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiAoYS5vcmRlciB8fCAwKSAtIChiLm9yZGVyIHx8IDApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVkaXRvcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgdGhlIGxvYWQgbWV0aG9kIG9mIHRoZSByZXNvdXJjZXNNYW5hZ2VyLlxuICAgICAqIEBwYXJhbSByZXNvdXJjZXNNYW5hZ2VyIFJlc291cmNlc01hbmFnZXJcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgdHJpZ2dlcmVkIGFmdGVyIEpTIGxvYWRlZFxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmxvYWRFZGl0b3JSZXNvdXJjZXMgPSBmdW5jdGlvbiBsb2FkRWRpdG9yUmVzb3VyY2VzKHJlc291cmNlc01hbmFnZXIsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJlc291cmNlc01hbmFnZXIubG9hZCh0aGlzLl9yZXNvdXJjZXNSZWdpc3RyeSwgZmFsc2UsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGx1Z2luUXVlcnlcbiAgICAgKiBAcmV0dXJucyB7TWFwfVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmdldFBsdWdpbkNvbmZpZ3MgPSBmdW5jdGlvbiBnZXRQbHVnaW5Db25maWdzKHBsdWdpblF1ZXJ5KSB7XG5cbiAgICAgICAgdmFyIHhwYXRoID0gJ3BsdWdpbnMvKltAaWQ9XCJjb3JlLicgKyBwbHVnaW5RdWVyeSArICdcIl0vcGx1Z2luX2NvbmZpZ3MvcHJvcGVydHkgfCBwbHVnaW5zLypbQGlkPVwiJyArIHBsdWdpblF1ZXJ5ICsgJ1wiXS9wbHVnaW5fY29uZmlncy9wcm9wZXJ0eSc7XG4gICAgICAgIGlmIChwbHVnaW5RdWVyeS5pbmRleE9mKCcuJykgPT0gLTEpIHtcbiAgICAgICAgICAgIHhwYXRoID0gJ3BsdWdpbnMvJyArIHBsdWdpblF1ZXJ5ICsgJy9wbHVnaW5fY29uZmlncy9wcm9wZXJ0eSB8JyArIHhwYXRoO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcm9wZXJ0aWVzID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKHRoaXMuX3JlZ2lzdHJ5LCB4cGF0aCk7XG4gICAgICAgIHZhciBjb25maWdzID0gbmV3IE1hcCgpO1xuICAgICAgICBwcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKHByb3BOb2RlKSB7XG4gICAgICAgICAgICBjb25maWdzLnNldChwcm9wTm9kZS5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpLCBKU09OLnBhcnNlKHByb3BOb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29uZmlncztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGx1Z2luSWRcbiAgICAgKiBAcGFyYW0gcGFyYW1OYW1lXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cblxuICAgIFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXREZWZhdWx0SW1hZ2VGcm9tUGFyYW1ldGVycyA9IGZ1bmN0aW9uIGdldERlZmF1bHRJbWFnZUZyb21QYXJhbWV0ZXJzKHBsdWdpbklkLCBwYXJhbU5hbWUpIHtcbiAgICAgICAgdmFyIG5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgXCJwbHVnaW5zLypbQGlkPSdcIiArIHBsdWdpbklkICsgXCInXS9zZXJ2ZXJfc2V0dGluZ3MvZ2xvYmFsX3BhcmFtW0BuYW1lPSdcIiArIHBhcmFtTmFtZSArIFwiJ11cIik7XG4gICAgICAgIGlmICghbm9kZSkgcmV0dXJuICcnO1xuICAgICAgICByZXR1cm4gbm9kZS5nZXRBdHRyaWJ1dGUoXCJkZWZhdWx0SW1hZ2VcIikgfHwgJyc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHR5cGVcbiAgICAgKiBAcGFyYW0gbmFtZVxuICAgICAqIEByZXR1cm5zIHtib29sfVxuICAgICAqL1xuXG4gICAgUmVnaXN0cnkucHJvdG90eXBlLmhhc1BsdWdpbk9mVHlwZSA9IGZ1bmN0aW9uIGhhc1BsdWdpbk9mVHlwZSh0eXBlLCBuYW1lKSB7XG4gICAgICAgIHZhciBub2RlID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAobmFtZSA9PSBudWxsKSB7XG4gICAgICAgICAgICBub2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUodGhpcy5fcmVnaXN0cnksICdwbHVnaW5zL2FqeHBfcGx1Z2luW2NvbnRhaW5zKEBpZCwgXCInICsgdHlwZSArICcuXCIpXSB8IHBsdWdpbnMvJyArIHR5cGUgKyAnW0BpZF0nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSh0aGlzLl9yZWdpc3RyeSwgJ3BsdWdpbnMvYWp4cF9wbHVnaW5bQGlkPVwiJyArIHR5cGUgKyAnLicgKyBuYW1lICsgJ1wiXSB8IHBsdWdpbnMvJyArIHR5cGUgKyAnW0BpZD1cIicgKyB0eXBlICsgJy4nICsgbmFtZSArICdcIl0nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbm9kZSAhPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIHJldHVybiBSZWdpc3RyeTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJlZ2lzdHJ5O1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9odHRwTWV0YUNhY2hlU2VydmljZSA9IHJlcXVpcmUoJy4uL2h0dHAvTWV0YUNhY2hlU2VydmljZScpO1xuXG52YXIgX2h0dHBNZXRhQ2FjaGVTZXJ2aWNlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBNZXRhQ2FjaGVTZXJ2aWNlKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuLi9odHRwL1B5ZGlvQXBpJyk7XG5cbnZhciBfaHR0cFB5ZGlvQXBpMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBQeWRpb0FwaSk7XG5cbnZhciBfdXRpbFBhdGhVdGlscyA9IHJlcXVpcmUoJy4uL3V0aWwvUGF0aFV0aWxzJyk7XG5cbnZhciBfdXRpbFBhdGhVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsUGF0aFV0aWxzKTtcblxudmFyIF91dGlsWE1MVXRpbHMgPSByZXF1aXJlKCcuLi91dGlsL1hNTFV0aWxzJyk7XG5cbnZhciBfdXRpbFhNTFV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxYTUxVdGlscyk7XG5cbnZhciBfbGFuZ0xvZ2dlciA9IHJlcXVpcmUoJy4uL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9BanhwTm9kZSA9IHJlcXVpcmUoJy4vQWp4cE5vZGUnKTtcblxudmFyIF9BanhwTm9kZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9BanhwTm9kZSk7XG5cbi8qKlxuICogSW1wbGVtZW50YXRpb24gb2YgdGhlIElBanhwTm9kZVByb3ZpZGVyIGludGVyZmFjZSBiYXNlZCBvbiBhIHJlbW90ZSBzZXJ2ZXIgYWNjZXNzLlxuICogRGVmYXVsdCBmb3IgYWxsIHJlcG9zaXRvcmllcy5cbiAqL1xuXG52YXIgUmVtb3RlTm9kZVByb3ZpZGVyID0gKGZ1bmN0aW9uICgpIHtcblxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdG9yXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBSZW1vdGVOb2RlUHJvdmlkZXIoKSB7XG4gICAgICAgIHZhciBwcm9wZXJ0aWVzID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUmVtb3RlTm9kZVByb3ZpZGVyKTtcblxuICAgICAgICB0aGlzLmRpc2NyZXRlID0gZmFsc2U7XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzKSB0aGlzLmluaXRQcm92aWRlcihwcm9wZXJ0aWVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHByb3BlcnRpZXNcbiAgICAgKiBAcGFyYW0gcHJvcGVydGllcyBPYmplY3RcbiAgICAgKi9cblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUuaW5pdFByb3ZpZGVyID0gZnVuY3Rpb24gaW5pdFByb3ZpZGVyKHByb3BlcnRpZXMpIHtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gbmV3IE1hcCgpO1xuICAgICAgICBmb3IgKHZhciBwIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHApKSB0aGlzLnByb3BlcnRpZXMuc2V0KHAsIHByb3BlcnRpZXNbcF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMgJiYgdGhpcy5wcm9wZXJ0aWVzLmhhcygnY29ubmV4aW9uX2Rpc2NyZXRlJykpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzY3JldGUgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzWydkZWxldGUnXSgnY29ubmV4aW9uX2Rpc2NyZXRlJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcyAmJiB0aGlzLnByb3BlcnRpZXMuaGFzKCdjYWNoZV9zZXJ2aWNlJykpIHtcbiAgICAgICAgICAgIHRoaXMuY2FjaGVTZXJ2aWNlID0gdGhpcy5wcm9wZXJ0aWVzLmdldCgnY2FjaGVfc2VydmljZScpO1xuICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzWydkZWxldGUnXSgnY2FjaGVfc2VydmljZScpO1xuICAgICAgICAgICAgX2h0dHBNZXRhQ2FjaGVTZXJ2aWNlMlsnZGVmYXVsdCddLmdldEluc3RhbmNlKCkucmVnaXN0ZXJNZXRhU3RyZWFtKHRoaXMuY2FjaGVTZXJ2aWNlWydtZXRhU3RyZWFtTmFtZSddLCB0aGlzLmNhY2hlU2VydmljZVsnZXhwaXJhdGlvblBvbGljeSddKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgbm9kZVxuICAgICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIG5vZGVDYWxsYmFjayBGdW5jdGlvbiBPbiBub2RlIGxvYWRlZFxuICAgICAqIEBwYXJhbSBjaGlsZENhbGxiYWNrIEZ1bmN0aW9uIE9uIGNoaWxkIGFkZGVkXG4gICAgICogQHBhcmFtIHJlY3Vyc2l2ZVxuICAgICAqIEBwYXJhbSBkZXB0aFxuICAgICAqIEBwYXJhbSBvcHRpb25hbFBhcmFtZXRlcnNcbiAgICAgKi9cblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUubG9hZE5vZGUgPSBmdW5jdGlvbiBsb2FkTm9kZShub2RlKSB7XG4gICAgICAgIHZhciBub2RlQ2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY2hpbGRDYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMiB8fCBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciByZWN1cnNpdmUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDMgfHwgYXJndW1lbnRzWzNdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1szXTtcbiAgICAgICAgdmFyIGRlcHRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSA0IHx8IGFyZ3VtZW50c1s0XSA9PT0gdW5kZWZpbmVkID8gLTEgOiBhcmd1bWVudHNbNF07XG4gICAgICAgIHZhciBvcHRpb25hbFBhcmFtZXRlcnMgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDUgfHwgYXJndW1lbnRzWzVdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzVdO1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnbHMnLFxuICAgICAgICAgICAgb3B0aW9uczogJ2FsJ1xuICAgICAgICB9O1xuICAgICAgICBpZiAocmVjdXJzaXZlKSB7XG4gICAgICAgICAgICBwYXJhbXNbJ3JlY3Vyc2l2ZSddID0gdHJ1ZTtcbiAgICAgICAgICAgIHBhcmFtc1snZGVwdGgnXSA9IGRlcHRoO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXRoID0gbm9kZS5nZXRQYXRoKCk7XG4gICAgICAgIC8vIERvdWJsZSBlbmNvZGUgIyBjaGFyYWN0ZXJcbiAgICAgICAgdmFyIHBhZ2luYXRpb25IYXNoID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAobm9kZS5nZXRNZXRhZGF0YSgpLmhhcyhcInBhZ2luYXRpb25EYXRhXCIpKSB7XG4gICAgICAgICAgICBwYWdpbmF0aW9uSGFzaCA9IFwiJTIzXCIgKyBub2RlLmdldE1ldGFkYXRhKCkuZ2V0KFwicGFnaW5hdGlvbkRhdGFcIikuZ2V0KFwiY3VycmVudFwiKTtcbiAgICAgICAgICAgIHBhdGggKz0gcGFnaW5hdGlvbkhhc2g7XG4gICAgICAgICAgICBwYXJhbXNbJ3JlbW90ZV9vcmRlciddID0gJ3RydWUnO1xuICAgICAgICAgICAgdmFyIHJlbW90ZU9yZGVyRGF0YSA9IG5vZGUuZ2V0TWV0YWRhdGEoKS5nZXQoXCJyZW1vdGVfb3JkZXJcIik7XG4gICAgICAgICAgICBpZiAocmVtb3RlT3JkZXJEYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbW90ZU9yZGVyRGF0YS5fb2JqZWN0KSByZW1vdGVPcmRlckRhdGEgPSBQcm90b0NvbXBhdC5oYXNoMm1hcChyZW1vdGVPcmRlckRhdGEpO1xuICAgICAgICAgICAgICAgIHJlbW90ZU9yZGVyRGF0YS5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtc1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1zWydkaXInXSA9IHBhdGg7XG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zW2tleV0gPSB2YWx1ZSArIChrZXkgPT0gJ2RpcicgJiYgcGFnaW5hdGlvbkhhc2ggPyBwYWdpbmF0aW9uSGFzaCA6ICcnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25hbFBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgIHBhcmFtcyA9IF9leHRlbmRzKHt9LCBwYXJhbXMsIG9wdGlvbmFsUGFyYW1ldGVycyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcnNlciA9IChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB0aGlzLnBhcnNlTm9kZXMobm9kZSwgdHJhbnNwb3J0LCBub2RlQ2FsbGJhY2ssIGNoaWxkQ2FsbGJhY2spO1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmNhY2hlU2VydmljZSkge1xuICAgICAgICAgICAgdmFyIGxvYWRlciA9IChmdW5jdGlvbiAoYWp4cE5vZGUsIGNhY2hlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCBjYWNoZUNhbGxiYWNrLCBudWxsLCB7IGRpc2NyZXRlOiB0aGlzLmRpc2NyZXRlIH0pO1xuICAgICAgICAgICAgfSkuYmluZCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBjYWNoZUxvYWRlciA9IChmdW5jdGlvbiAobmV3Tm9kZSkge1xuICAgICAgICAgICAgICAgIG5vZGUucmVwbGFjZUJ5KG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIG5vZGVDYWxsYmFjayhub2RlKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcyk7XG4gICAgICAgICAgICBfaHR0cE1ldGFDYWNoZVNlcnZpY2UyWydkZWZhdWx0J10uZ2V0SW5zdGFuY2UoKS5tZXRhRm9yTm9kZSh0aGlzLmNhY2hlU2VydmljZVsnbWV0YVN0cmVhbU5hbWUnXSwgbm9kZSwgbG9hZGVyLCBwYXJzZXIsIGNhY2hlTG9hZGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkucmVxdWVzdChwYXJhbXMsIHBhcnNlciwgbnVsbCwgeyBkaXNjcmV0ZTogdGhpcy5kaXNjcmV0ZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgbm9kZVxuICAgICAqIEBwYXJhbSBub2RlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIG5vZGVDYWxsYmFjayBGdW5jdGlvbiBPbiBub2RlIGxvYWRlZFxuICAgICAqIEBwYXJhbSBhU3luYyBib29sXG4gICAgICogQHBhcmFtIGFkZGl0aW9uYWxQYXJhbWV0ZXJzIG9iamVjdFxuICAgICAqL1xuXG4gICAgUmVtb3RlTm9kZVByb3ZpZGVyLnByb3RvdHlwZS5sb2FkTGVhZk5vZGVTeW5jID0gZnVuY3Rpb24gbG9hZExlYWZOb2RlU3luYyhub2RlLCBub2RlQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGFTeW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMl07XG4gICAgICAgIHZhciBhZGRpdGlvbmFsUGFyYW1ldGVycyA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IHt9IDogYXJndW1lbnRzWzNdO1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSBfZXh0ZW5kcyh7XG4gICAgICAgICAgICBnZXRfYWN0aW9uOiAnbHMnLFxuICAgICAgICAgICAgb3B0aW9uczogJ2FsJyxcbiAgICAgICAgICAgIGRpcjogX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0RGlybmFtZShub2RlLmdldFBhdGgoKSksXG4gICAgICAgICAgICBmaWxlOiBfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShub2RlLmdldFBhdGgoKSlcbiAgICAgICAgfSwgYWRkaXRpb25hbFBhcmFtZXRlcnMpO1xuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSBfZXh0ZW5kcyh7fSwgcGFyYW1zLCB0aGlzLnByb3BlcnRpZXMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb21wbGV0ZSA9IChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmlzUm9vdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFyc2VOb2Rlcyhub2RlLCB0cmFuc3BvcnQsIG5vZGVDYWxsYmFjaywgbnVsbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJzZU5vZGVzKG5vZGUsIHRyYW5zcG9ydCwgbnVsbCwgbm9kZUNhbGxiYWNrLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IoJ0xvYWRpbmcgZXJyb3IgOicgKyBlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpO1xuICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCBjb21wbGV0ZSwgbnVsbCwgeyBhc3luYzogYVN5bmMgfSk7XG4gICAgfTtcblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUucmVmcmVzaE5vZGVBbmRSZXBsYWNlID0gZnVuY3Rpb24gcmVmcmVzaE5vZGVBbmRSZXBsYWNlKG5vZGUsIG9uQ29tcGxldGUpIHtcblxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0X2FjdGlvbjogJ2xzJyxcbiAgICAgICAgICAgIG9wdGlvbnM6ICdhbCcsXG4gICAgICAgICAgICBkaXI6IF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUobm9kZS5nZXRQYXRoKCkpLFxuICAgICAgICAgICAgZmlsZTogX3V0aWxQYXRoVXRpbHMyWydkZWZhdWx0J10uZ2V0QmFzZW5hbWUobm9kZS5nZXRQYXRoKCkpXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcykge1xuICAgICAgICAgICAgcGFyYW1zID0gX2V4dGVuZHMoe30sIHBhcmFtcywgdGhpcy5wcm9wZXJ0aWVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBub2RlQ2FsbGJhY2sgPSBmdW5jdGlvbiBub2RlQ2FsbGJhY2sobmV3Tm9kZSkge1xuICAgICAgICAgICAgbm9kZS5yZXBsYWNlQnkobmV3Tm9kZSwgXCJvdmVycmlkZVwiKTtcbiAgICAgICAgICAgIGlmIChvbkNvbXBsZXRlKSBvbkNvbXBsZXRlKG5vZGUpO1xuICAgICAgICB9O1xuICAgICAgICBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnJlcXVlc3QocGFyYW1zLCAoZnVuY3Rpb24gKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZS5pc1Jvb3QoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcnNlTm9kZXMobm9kZSwgdHJhbnNwb3J0LCBub2RlQ2FsbGJhY2ssIG51bGwsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFyc2VOb2Rlcyhub2RlLCB0cmFuc3BvcnQsIG51bGwsIG5vZGVDYWxsYmFjaywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmVycm9yKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGFyc2UgdGhlIGFuc3dlciBhbmQgY3JlYXRlIEFqeHBOb2Rlc1xuICAgICAqIEBwYXJhbSBvcmlnTm9kZSBBanhwTm9kZVxuICAgICAqIEBwYXJhbSB0cmFuc3BvcnQgQWpheC5SZXNwb25zZVxuICAgICAqIEBwYXJhbSBub2RlQ2FsbGJhY2sgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gY2hpbGRDYWxsYmFjayBGdW5jdGlvblxuICAgICAqIEBwYXJhbSBjaGlsZHJlbk9ubHlcbiAgICAgKi9cblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUucGFyc2VOb2RlcyA9IGZ1bmN0aW9uIHBhcnNlTm9kZXMob3JpZ05vZGUsIHRyYW5zcG9ydCwgbm9kZUNhbGxiYWNrLCBjaGlsZENhbGxiYWNrLCBjaGlsZHJlbk9ubHkpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICBpZiAoIXRyYW5zcG9ydC5yZXNwb25zZVhNTCB8fCAhdHJhbnNwb3J0LnJlc3BvbnNlWE1MLmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICAgICAgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZGVidWcoJ0xvYWRpbmcgbm9kZSAnICsgb3JpZ05vZGUuZ2V0UGF0aCgpICsgJyBoYXMgd3JvbmcgcmVzcG9uc2U6ICcgKyB0cmFuc3BvcnQucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgIGlmIChub2RlQ2FsbGJhY2spIG5vZGVDYWxsYmFjayhvcmlnTm9kZSk7XG4gICAgICAgICAgICBvcmlnTm9kZS5zZXRMb2FkZWQoZmFsc2UpO1xuICAgICAgICAgICAgaWYgKCF0cmFuc3BvcnQucmVzcG9uc2VUZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbXB0eSByZXNwb25zZSEnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBYTUwgRG9jdW1lbnQgKHNlZSBjb25zb2xlKScpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb290Tm9kZSA9IHRyYW5zcG9ydC5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgIGlmICghY2hpbGRyZW5Pbmx5KSB7XG4gICAgICAgICAgICB2YXIgY29udGV4dE5vZGUgPSB0aGlzLnBhcnNlQWp4cE5vZGUocm9vdE5vZGUpO1xuICAgICAgICAgICAgb3JpZ05vZGUucmVwbGFjZUJ5KGNvbnRleHROb2RlLCBcIm1lcmdlXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ0hFQ0sgRk9SIE1FU1NBR0UgT1IgRVJST1JTXG4gICAgICAgIHZhciBlcnJvck5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShyb290Tm9kZSwgXCJlcnJvcnxtZXNzYWdlXCIpO1xuICAgICAgICBpZiAoZXJyb3JOb2RlKSB7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChlcnJvck5vZGUubm9kZU5hbWUgPT0gXCJtZXNzYWdlXCIpIHtcbiAgICAgICAgICAgICAgICB0eXBlID0gZXJyb3JOb2RlLmdldEF0dHJpYnV0ZSgndHlwZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJFUlJPUlwiKSB7XG4gICAgICAgICAgICAgICAgb3JpZ05vZGUubm90aWZ5KFwiZXJyb3JcIiwgZXJyb3JOb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlICsgJyhTb3VyY2U6JyArIG9yaWdOb2RlLmdldFBhdGgoKSArICcpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDSEVDSyBGT1IgQVVUSCBQUk9NUFQgUkVRVUlSRURcbiAgICAgICAgdmFyIGF1dGhOb2RlID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUocm9vdE5vZGUsIFwicHJvbXB0XCIpO1xuICAgICAgICBpZiAoYXV0aE5vZGUgJiYgcHlkaW8gJiYgcHlkaW8uVUkgJiYgcHlkaW8uVUkub3BlblByb21wdERpYWxvZykge1xuICAgICAgICAgICAgdmFyIGpzb25EYXRhID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoYXV0aE5vZGUsIFwiZGF0YVwiKS5maXJzdENoaWxkLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIHB5ZGlvLlVJLm9wZW5Qcm9tcHREaWFsb2coSlNPTi5wYXJzZShqc29uRGF0YSkpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ0hFQ0sgRk9SIFBBR0lOQVRJT04gREFUQVxuICAgICAgICB2YXIgcGFnaW5hdGlvbk5vZGUgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShyb290Tm9kZSwgXCJwYWdpbmF0aW9uXCIpO1xuICAgICAgICBpZiAocGFnaW5hdGlvbk5vZGUpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhZ2luYXRpb25EYXRhID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgICAgIEFycmF5LmZyb20ocGFnaW5hdGlvbk5vZGUuYXR0cmlidXRlcykuZm9yRWFjaCgoZnVuY3Rpb24gKGF0dCkge1xuICAgICAgICAgICAgICAgICAgICBwYWdpbmF0aW9uRGF0YS5zZXQoYXR0Lm5vZGVOYW1lLCBhdHQudmFsdWUpO1xuICAgICAgICAgICAgICAgIH0pLmJpbmQoX3RoaXMpKTtcbiAgICAgICAgICAgICAgICBvcmlnTm9kZS5nZXRNZXRhZGF0YSgpLnNldCgncGFnaW5hdGlvbkRhdGEnLCBwYWdpbmF0aW9uRGF0YSk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9IGVsc2UgaWYgKG9yaWdOb2RlLmdldE1ldGFkYXRhKCkuZ2V0KCdwYWdpbmF0aW9uRGF0YScpKSB7XG4gICAgICAgICAgICBvcmlnTm9kZS5nZXRNZXRhZGF0YSgpWydkZWxldGUnXSgncGFnaW5hdGlvbkRhdGEnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENIRUNLIEZPUiBDT01QT05FTlQgQ09ORklHUyBDT05URVhUVUFMIERBVEFcbiAgICAgICAgdmFyIGNvbmZpZ3MgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0U2luZ2xlTm9kZShyb290Tm9kZSwgXCJjbGllbnRfY29uZmlnc1wiKTtcbiAgICAgICAgaWYgKGNvbmZpZ3MpIHtcbiAgICAgICAgICAgIG9yaWdOb2RlLmdldE1ldGFkYXRhKCkuc2V0KCdjbGllbnRfY29uZmlncycsIGNvbmZpZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTk9XIFBBUlNFIENISUxEUkVOXG4gICAgICAgIHZhciBjaGlsZHJlbiA9IF91dGlsWE1MVXRpbHMyWydkZWZhdWx0J10uWFBhdGhTZWxlY3ROb2Rlcyhyb290Tm9kZSwgXCJ0cmVlXCIpO1xuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKChmdW5jdGlvbiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLnBhcnNlQWp4cE5vZGUoY2hpbGROb2RlKTtcbiAgICAgICAgICAgIGlmICghY2hpbGRyZW5Pbmx5KSB7XG4gICAgICAgICAgICAgICAgb3JpZ05vZGUuYWRkQ2hpbGQoY2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNMb2FkZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAoX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdE5vZGVzKGNoaWxkTm9kZSwgJ3RyZWUnKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoY2hpbGROb2RlLCAndHJlZScpLmZvckVhY2goKGZ1bmN0aW9uIChjKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZCA9IHRoaXMucGFyc2VBanhwTm9kZShjKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0NoaWxkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZC5hZGRDaGlsZChuZXdDaGlsZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgICAgICBjTG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjaGlsZENhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgY2hpbGRDYWxsYmFjayhjaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY0xvYWRlZCkgY2hpbGQuc2V0TG9hZGVkKHRydWUpO1xuICAgICAgICB9KS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBpZiAobm9kZUNhbGxiYWNrKSB7XG4gICAgICAgICAgICBub2RlQ2FsbGJhY2sob3JpZ05vZGUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFJlbW90ZU5vZGVQcm92aWRlci5wcm90b3R5cGUucGFyc2VBanhwTm9kZXNEaWZmcyA9IGZ1bmN0aW9uIHBhcnNlQWp4cE5vZGVzRGlmZnMoeG1sRWxlbWVudCwgdGFyZ2V0RGF0YU1vZGVsLCB0YXJnZXRSZXBvc2l0b3J5SWQpIHtcbiAgICAgICAgdmFyIHNldENvbnRleHRDaGlsZHJlblNlbGVjdGVkID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdmFyIHJlbW92ZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoeG1sRWxlbWVudCwgXCJyZW1vdmUvdHJlZVwiKTtcbiAgICAgICAgdmFyIGFkZHMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoeG1sRWxlbWVudCwgXCJhZGQvdHJlZVwiKTtcbiAgICAgICAgdmFyIHVwZGF0ZXMgPSBfdXRpbFhNTFV0aWxzMlsnZGVmYXVsdCddLlhQYXRoU2VsZWN0Tm9kZXMoeG1sRWxlbWVudCwgXCJ1cGRhdGUvdHJlZVwiKTtcbiAgICAgICAgdmFyIG5vdGlmeVNlcnZlckNoYW5nZSA9IFtdO1xuICAgICAgICBpZiAocmVtb3ZlcyAmJiByZW1vdmVzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVtb3Zlcy5mb3JFYWNoKGZ1bmN0aW9uIChyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHAgPSByLmdldEF0dHJpYnV0ZShcImZpbGVuYW1lXCIpO1xuICAgICAgICAgICAgICAgIGlmIChyLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAmJiByLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAhPT0gdGFyZ2V0UmVwb3NpdG9yeUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGltVGltZSA9IHBhcnNlSW50KHIuZ2V0QXR0cmlidXRlKFwiYWp4cF9pbV90aW1lXCIpKTtcbiAgICAgICAgICAgICAgICB0YXJnZXREYXRhTW9kZWwucmVtb3ZlTm9kZUJ5UGF0aChwLCBpbVRpbWUpO1xuICAgICAgICAgICAgICAgIG5vdGlmeVNlcnZlckNoYW5nZS5wdXNoKHApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFkZHMgJiYgYWRkcy5sZW5ndGggJiYgdGFyZ2V0RGF0YU1vZGVsLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2RlKSB7XG4gICAgICAgICAgICBhZGRzLmZvckVhY2goZnVuY3Rpb24gKHRyZWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodHJlZS5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgJiYgdHJlZS5nZXRBdHRyaWJ1dGUoXCJub2RlX3JlcG9zaXRvcnlfaWRcIikgIT09IHRhcmdldFJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gdGFyZ2V0RGF0YU1vZGVsLmdldEFqeHBOb2RlUHJvdmlkZXIoKS5wYXJzZUFqeHBOb2RlKHRyZWUpO1xuICAgICAgICAgICAgICAgIHRhcmdldERhdGFNb2RlbC5hZGROb2RlKG5ld05vZGUsIHNldENvbnRleHRDaGlsZHJlblNlbGVjdGVkKTtcbiAgICAgICAgICAgICAgICBub3RpZnlTZXJ2ZXJDaGFuZ2UucHVzaChuZXdOb2RlLmdldFBhdGgoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXBkYXRlcyAmJiB1cGRhdGVzLmxlbmd0aCAmJiB0YXJnZXREYXRhTW9kZWwuZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGUpIHtcbiAgICAgICAgICAgIHVwZGF0ZXMuZm9yRWFjaChmdW5jdGlvbiAodHJlZSkge1xuICAgICAgICAgICAgICAgIGlmICh0cmVlLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAmJiB0cmVlLmdldEF0dHJpYnV0ZShcIm5vZGVfcmVwb3NpdG9yeV9pZFwiKSAhPT0gdGFyZ2V0UmVwb3NpdG9yeUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSB0YXJnZXREYXRhTW9kZWwuZ2V0QWp4cE5vZGVQcm92aWRlcigpLnBhcnNlQWp4cE5vZGUodHJlZSk7XG4gICAgICAgICAgICAgICAgdmFyIG9yaWdpbmFsID0gbmV3Tm9kZS5nZXRNZXRhZGF0YSgpLmdldChcIm9yaWdpbmFsX3BhdGhcIik7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RGF0YU1vZGVsLnVwZGF0ZU5vZGUobmV3Tm9kZSwgc2V0Q29udGV4dENoaWxkcmVuU2VsZWN0ZWQpO1xuICAgICAgICAgICAgICAgIG5vdGlmeVNlcnZlckNoYW5nZS5wdXNoKG5ld05vZGUuZ2V0UGF0aCgpKTtcbiAgICAgICAgICAgICAgICBpZiAob3JpZ2luYWwpIG5vdGlmeVNlcnZlckNoYW5nZS5wdXNoKG9yaWdpbmFsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub3RpZnlTZXJ2ZXJDaGFuZ2UubGVuZ3RoKSB7XG4gICAgICAgICAgICB0YXJnZXREYXRhTW9kZWwubm90aWZ5KFwic2VydmVyX3VwZGF0ZVwiLCBub3RpZnlTZXJ2ZXJDaGFuZ2UpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBhcnNlcyBYTUwgTm9kZSBhbmQgY3JlYXRlIEFqeHBOb2RlXG4gICAgICogQHBhcmFtIHhtbE5vZGUgWE1MTm9kZVxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBSZW1vdGVOb2RlUHJvdmlkZXIucHJvdG90eXBlLnBhcnNlQWp4cE5vZGUgPSBmdW5jdGlvbiBwYXJzZUFqeHBOb2RlKHhtbE5vZGUpIHtcbiAgICAgICAgdmFyIG5vZGUgPSBuZXcgX0FqeHBOb2RlMlsnZGVmYXVsdCddKHhtbE5vZGUuZ2V0QXR0cmlidXRlKCdmaWxlbmFtZScpLCB4bWxOb2RlLmdldEF0dHJpYnV0ZSgnaXNfZmlsZScpID09IFwiMVwiIHx8IHhtbE5vZGUuZ2V0QXR0cmlidXRlKCdpc19maWxlJykgPT0gXCJ0cnVlXCIsIHhtbE5vZGUuZ2V0QXR0cmlidXRlKCd0ZXh0JyksIHhtbE5vZGUuZ2V0QXR0cmlidXRlKCdpY29uJykpO1xuICAgICAgICB2YXIgbWV0YWRhdGEgPSBuZXcgTWFwKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgeG1sTm9kZS5hdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBtZXRhZGF0YS5zZXQoeG1sTm9kZS5hdHRyaWJ1dGVzW2ldLm5vZGVOYW1lLCB4bWxOb2RlLmF0dHJpYnV0ZXNbaV0udmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUuc2V0TWV0YWRhdGEobWV0YWRhdGEpO1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFJlbW90ZU5vZGVQcm92aWRlcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJlbW90ZU5vZGVQcm92aWRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tPi5cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyID0gcmVxdWlyZSgnLi4vaHR0cC9SZXNvdXJjZXNNYW5hZ2VyJyk7XG5cbnZhciBfaHR0cFJlc291cmNlc01hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFJlc291cmNlc01hbmFnZXIpO1xuXG4vKiogXG4gKiBDb250YWluZXIgZm9yIGEgUmVwb3NpdG9yeS5cbiAqL1xuXG52YXIgUmVwb3NpdG9yeSA9IChmdW5jdGlvbiAoKSB7XG5cblx0LyoqXG4gICogQ29uc3RydWN0b3JcbiAgKiBAcGFyYW0gaWQgU3RyaW5nXG4gICogQHBhcmFtIHhtbERlZiBYTUxOb2RlXG4gICovXG5cblx0ZnVuY3Rpb24gUmVwb3NpdG9yeShpZCwgeG1sRGVmKSB7XG5cdFx0X2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlcG9zaXRvcnkpO1xuXG5cdFx0dGhpcy5sYWJlbCA9ICcnO1xuXHRcdHRoaXMuaWQgPSBpZDtcblx0XHR0aGlzLmFjY2Vzc1R5cGUgPSAnJztcblx0XHR0aGlzLm5vZGVQcm92aWRlckRlZiA9IHVuZGVmaW5lZDtcblx0XHR0aGlzLmFsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weSA9IGZhbHNlO1xuXHRcdHRoaXMudXNlckVkaXRhYmxlID0gZmFsc2U7XG5cdFx0dGhpcy5zbHVnID0gJyc7XG5cdFx0dGhpcy5vd25lciA9ICcnO1xuXHRcdHRoaXMuZGVzY3JpcHRpb24gPSAnJztcblx0XHR0aGlzLl9oYXNDb250ZW50RmlsdGVyID0gZmFsc2U7XG5cdFx0dGhpcy5faGFzVXNlclNjb3BlID0gZmFsc2U7XG5cdFx0dGhpcy5fcmVwb3NpdG9yeVR5cGUgPSAnbG9jYWwnO1xuXHRcdHRoaXMuX2FjY2Vzc1N0YXR1cyA9IG51bGw7XG5cdFx0dGhpcy5fbGFzdENvbm5lY3Rpb24gPSBudWxsO1xuXHRcdHRoaXMuaWNvbiA9ICcnO1xuXHRcdHRoaXMucmVzb3VyY2VzTWFuYWdlciA9IG5ldyBfaHR0cFJlc291cmNlc01hbmFnZXIyWydkZWZhdWx0J10oKTtcblx0XHRpZiAoeG1sRGVmKSB0aGlzLmxvYWRGcm9tWG1sKHhtbERlZik7XG5cdH1cblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRJZCA9IGZ1bmN0aW9uIGdldElkKCkge1xuXHRcdHJldHVybiB0aGlzLmlkO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldFNoYXJlSWQgPSBmdW5jdGlvbiBnZXRTaGFyZUlkKCkge1xuXHRcdHJldHVybiB0aGlzLmlkLnJlcGxhY2UoL29jc19yZW1vdGVfc2hhcmVfLywgJycpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldExhYmVsID0gZnVuY3Rpb24gZ2V0TGFiZWwoKSB7XG5cdFx0cmV0dXJuIHRoaXMubGFiZWw7XG5cdH07XG5cblx0LyoqXG4gICogQHBhcmFtIGxhYmVsIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLnNldExhYmVsID0gZnVuY3Rpb24gc2V0TGFiZWwobGFiZWwpIHtcblx0XHR0aGlzLmxhYmVsID0gbGFiZWw7XG5cdH07XG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0TGV0dGVyc0JhZGdlID0gZnVuY3Rpb24gZ2V0TGV0dGVyc0JhZGdlKCkge1xuXHRcdGlmICghdGhpcy5sYWJlbCkgcmV0dXJuICcnO1xuXHRcdHJldHVybiB0aGlzLmxhYmVsLnNwbGl0KFwiIFwiKS5tYXAoZnVuY3Rpb24gKHdvcmQpIHtcblx0XHRcdHJldHVybiB3b3JkLnN1YnN0cigwLCAxKTtcblx0XHR9KS5zbGljZSgwLCAyKS5qb2luKFwiXCIpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm4gU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0RGVzY3JpcHRpb24gPSBmdW5jdGlvbiBnZXREZXNjcmlwdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5kZXNjcmlwdGlvbjtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRJY29uID0gZnVuY3Rpb24gZ2V0SWNvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5pY29uO1xuXHR9O1xuXG5cdC8qKlxuICAqIEBwYXJhbSBpY29uIFN0cmluZ1xuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLnNldEljb24gPSBmdW5jdGlvbiBzZXRJY29uKGljb24pIHtcblx0XHR0aGlzLmljb24gPSBpY29uO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm4gU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0T3duZXIgPSBmdW5jdGlvbiBnZXRPd25lcigpIHtcblx0XHRyZXR1cm4gdGhpcy5vd25lcjtcblx0fTtcblxuXHQvKipcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRBY2Nlc3NUeXBlID0gZnVuY3Rpb24gZ2V0QWNjZXNzVHlwZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5hY2Nlc3NUeXBlO1xuXHR9O1xuXG5cdC8qKlxuICAqIEBwYXJhbSBhY2Nlc3MgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuc2V0QWNjZXNzVHlwZSA9IGZ1bmN0aW9uIHNldEFjY2Vzc1R5cGUoYWNjZXNzKSB7XG5cdFx0dGhpcy5hY2Nlc3NUeXBlID0gYWNjZXNzO1xuXHR9O1xuXG5cdC8qKlxuICAqIFRyaWdnZXJzIFJlc291cmNlc01hbmFnZXIubG9hZFxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmxvYWRSZXNvdXJjZXMgPSBmdW5jdGlvbiBsb2FkUmVzb3VyY2VzKCkge1xuXHRcdHRoaXMucmVzb3VyY2VzTWFuYWdlci5sb2FkKG51bGwsIHRydWUpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIE9iamVjdFxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldE5vZGVQcm92aWRlckRlZiA9IGZ1bmN0aW9uIGdldE5vZGVQcm92aWRlckRlZigpIHtcblx0XHRyZXR1cm4gdGhpcy5ub2RlUHJvdmlkZXJEZWY7XG5cdH07XG5cblx0LyoqXG4gICogQHBhcmFtIHNsdWcgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuc2V0U2x1ZyA9IGZ1bmN0aW9uIHNldFNsdWcoc2x1Zykge1xuXHRcdHRoaXMuc2x1ZyA9IHNsdWc7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMgU3RyaW5nXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0U2x1ZyA9IGZ1bmN0aW9uIGdldFNsdWcoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2x1Zztcblx0fTtcblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRPdmVybGF5ID0gZnVuY3Rpb24gZ2V0T3ZlcmxheSgpIHtcblx0XHRyZXR1cm4gdGhpcy5nZXRPd25lcigpID8gX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLnJlc29sdmVJbWFnZVNvdXJjZShcInNoYXJlZC5wbmdcIiwgXCJvdmVybGF5cy9JQ09OX1NJWkVcIiwgOCkgOiBcIlwiO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIHtib29sZWFufVxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmhhc0NvbnRlbnRGaWx0ZXIgPSBmdW5jdGlvbiBoYXNDb250ZW50RmlsdGVyKCkge1xuXHRcdHJldHVybiB0aGlzLl9oYXNDb250ZW50RmlsdGVyO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIHtib29sZWFufVxuICAqL1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmhhc1VzZXJTY29wZSA9IGZ1bmN0aW9uIGhhc1VzZXJTY29wZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5faGFzVXNlclNjb3BlO1xuXHR9O1xuXG5cdC8qKlxuICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUuZ2V0UmVwb3NpdG9yeVR5cGUgPSBmdW5jdGlvbiBnZXRSZXBvc2l0b3J5VHlwZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fcmVwb3NpdG9yeVR5cGU7XG5cdH07XG5cblx0LyoqXG4gICogQHJldHVybnMge3N0cmluZ31cbiAgKi9cblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5nZXRBY2Nlc3NTdGF0dXMgPSBmdW5jdGlvbiBnZXRBY2Nlc3NTdGF0dXMoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FjY2Vzc1N0YXR1cztcblx0fTtcblxuXHRSZXBvc2l0b3J5LnByb3RvdHlwZS5zZXRBY2Nlc3NTdGF0dXMgPSBmdW5jdGlvbiBzZXRBY2Nlc3NTdGF0dXMoc3RhdHVzKSB7XG5cdFx0dGhpcy5fYWNjZXNzU3RhdHVzID0gc3RhdHVzO1xuXHR9O1xuXG5cdFJlcG9zaXRvcnkucHJvdG90eXBlLmdldExhc3RDb25uZWN0aW9uID0gZnVuY3Rpb24gZ2V0TGFzdENvbm5lY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2xhc3RDb25uZWN0aW9uO1xuXHR9O1xuXG5cdC8qKlxuICAqIFBhcnNlcyBYTUwgTm9kZVxuICAqIEBwYXJhbSByZXBvTm9kZSBYTUxOb2RlXG4gICovXG5cblx0UmVwb3NpdG9yeS5wcm90b3R5cGUubG9hZEZyb21YbWwgPSBmdW5jdGlvbiBsb2FkRnJvbVhtbChyZXBvTm9kZSkge1xuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weScpICYmIHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5JykgPT0gXCJ0cnVlXCIpIHtcblx0XHRcdHRoaXMuYWxsb3dDcm9zc1JlcG9zaXRvcnlDb3B5ID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnaGFzQ29udGVudEZpbHRlcicpICYmIHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnaGFzQ29udGVudEZpbHRlcicpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHR0aGlzLl9oYXNDb250ZW50RmlsdGVyID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgndXNlclNjb3BlJykgJiYgcmVwb05vZGUuZ2V0QXR0cmlidXRlKCd1c2VyU2NvcGUnKSA9PSBcInRydWVcIikge1xuXHRcdFx0dGhpcy5faGFzVXNlclNjb3BlID0gdHJ1ZTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgncmVwb3NpdG9yeV90eXBlJykpIHtcblx0XHRcdHRoaXMuX3JlcG9zaXRvcnlUeXBlID0gcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdyZXBvc2l0b3J5X3R5cGUnKTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnYWNjZXNzX3N0YXR1cycpKSB7XG5cdFx0XHR0aGlzLl9hY2Nlc3NTdGF0dXMgPSByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FjY2Vzc19zdGF0dXMnKTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnbGFzdF9jb25uZWN0aW9uJykpIHtcblx0XHRcdHRoaXMuX2xhc3RDb25uZWN0aW9uID0gcmVwb05vZGUuZ2V0QXR0cmlidXRlKCdsYXN0X2Nvbm5lY3Rpb24nKTtcblx0XHR9XG5cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCd1c2VyX2VkaXRhYmxlX3JlcG9zaXRvcnknKSAmJiByZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ3VzZXJfZWRpdGFibGVfcmVwb3NpdG9yeScpID09IFwidHJ1ZVwiKSB7XG5cdFx0XHR0aGlzLnVzZXJFZGl0YWJsZSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmIChyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FjY2Vzc190eXBlJykpIHtcblx0XHRcdHRoaXMuc2V0QWNjZXNzVHlwZShyZXBvTm9kZS5nZXRBdHRyaWJ1dGUoJ2FjY2Vzc190eXBlJykpO1xuXHRcdH1cblx0XHRpZiAocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdyZXBvc2l0b3J5U2x1ZycpKSB7XG5cdFx0XHR0aGlzLnNldFNsdWcocmVwb05vZGUuZ2V0QXR0cmlidXRlKCdyZXBvc2l0b3J5U2x1ZycpKTtcblx0XHR9XG5cdFx0aWYgKHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnb3duZXInKSkge1xuXHRcdFx0dGhpcy5vd25lciA9IHJlcG9Ob2RlLmdldEF0dHJpYnV0ZSgnb3duZXInKTtcblx0XHR9XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCByZXBvTm9kZS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgY2hpbGROb2RlID0gcmVwb05vZGUuY2hpbGROb2Rlc1tpXTtcblx0XHRcdGlmIChjaGlsZE5vZGUubm9kZU5hbWUgPT0gXCJsYWJlbFwiKSB7XG5cdFx0XHRcdHRoaXMuc2V0TGFiZWwoY2hpbGROb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlKTtcblx0XHRcdH0gZWxzZSBpZiAoY2hpbGROb2RlLm5vZGVOYW1lID09IFwiZGVzY3JpcHRpb25cIikge1xuXHRcdFx0XHR0aGlzLmRlc2NyaXB0aW9uID0gY2hpbGROb2RlLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuXHRcdFx0fSBlbHNlIGlmIChjaGlsZE5vZGUubm9kZU5hbWUgPT0gXCJjbGllbnRfc2V0dGluZ3NcIikge1xuXHRcdFx0XHRpZiAoY2hpbGROb2RlLmdldEF0dHJpYnV0ZSgnaWNvbl90cGxfaWQnKSkge1xuXHRcdFx0XHRcdHRoaXMuc2V0SWNvbih3aW5kb3cucHlkaW8uUGFyYW1ldGVycy5nZXQoJ3NlcnZlckFjY2Vzc1BhdGgnKSArICcmZ2V0X2FjdGlvbj1nZXRfdXNlcl90ZW1wbGF0ZV9sb2dvJnRlbXBsYXRlX2lkPScgKyBjaGlsZE5vZGUuZ2V0QXR0cmlidXRlKCdpY29uX3RwbF9pZCcpICsgJyZpY29uX2Zvcm1hdD1zbWFsbCcpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuc2V0SWNvbihjaGlsZE5vZGUuZ2V0QXR0cmlidXRlKCdpY29uJykpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGZvciAodmFyIGogPSAwOyBqIDwgY2hpbGROb2RlLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHR2YXIgc3ViQ2ggPSBjaGlsZE5vZGUuY2hpbGROb2Rlc1tqXTtcblx0XHRcdFx0XHRpZiAoc3ViQ2gubm9kZU5hbWUgPT0gJ3Jlc291cmNlcycpIHtcblx0XHRcdFx0XHRcdHRoaXMucmVzb3VyY2VzTWFuYWdlci5sb2FkRnJvbVhtbE5vZGUoc3ViQ2gpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoc3ViQ2gubm9kZU5hbWUgPT0gJ25vZGVfcHJvdmlkZXInKSB7XG5cdFx0XHRcdFx0XHR2YXIgbm9kZVByb3ZpZGVyTmFtZSA9IHN1YkNoLmdldEF0dHJpYnV0ZShcImFqeHBDbGFzc1wiKTtcblx0XHRcdFx0XHRcdHZhciBub2RlUHJvdmlkZXJPcHRpb25zID0gSlNPTi5wYXJzZShzdWJDaC5nZXRBdHRyaWJ1dGUoXCJhanhwT3B0aW9uc1wiKSk7XG5cdFx0XHRcdFx0XHR0aGlzLm5vZGVQcm92aWRlckRlZiA9IHsgbmFtZTogbm9kZVByb3ZpZGVyTmFtZSwgb3B0aW9uczogbm9kZVByb3ZpZGVyT3B0aW9ucyB9O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gUmVwb3NpdG9yeTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJlcG9zaXRvcnk7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9sYW5nTG9nZ2VyID0gcmVxdWlyZSgnLi4vbGFuZy9Mb2dnZXInKTtcblxudmFyIF9sYW5nTG9nZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xhbmdMb2dnZXIpO1xuXG52YXIgX2h0dHBQeWRpb0FwaSA9IHJlcXVpcmUoJy4uL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxudmFyIF9SZXBvc2l0b3J5ID0gcmVxdWlyZSgnLi9SZXBvc2l0b3J5Jyk7XG5cbnZhciBfUmVwb3NpdG9yeTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9SZXBvc2l0b3J5KTtcblxuLyoqXG4gKiBBYnN0cmFjdGlvbiBvZiB0aGUgY3VycmVudGx5IGxvZ2dlZCB1c2VyLiBDYW4gYmUgYSBcImZha2VcIiB1c2VyIHdoZW4gdXNlcnMgbWFuYWdlbWVudFxuICogc3lzdGVtIGlzIGRpc2FibGVkXG4gKi9cblxudmFyIFVzZXIgPSAoZnVuY3Rpb24gKCkge1xuXG5cdC8qKlxuICAqIENvbnN0cnVjdG9yXG4gICogQHBhcmFtIGlkIFN0cmluZyBUaGUgdXNlciB1bmlxdWUgaWRcbiAgKiBAcGFyYW0geG1sRGVmIFhNTE5vZGUgUmVnaXN0cnkgRnJhZ21lbnRcbiAgKi9cblxuXHRmdW5jdGlvbiBVc2VyKGlkLCB4bWxEZWYpIHtcblx0XHRfY2xhc3NDYWxsQ2hlY2sodGhpcywgVXNlcik7XG5cblx0XHQvKipcbiAgICogQHZhciBTdHJpbmdcbiAgICovXG5cdFx0dGhpcy5pZCA9IGlkO1xuXHRcdC8qKlxuICAgKiBAdmFyIFN0cmluZ1xuICAgKi9cblx0XHR0aGlzLmFjdGl2ZVJlcG9zaXRvcnkgPSB1bmRlZmluZWQ7XG5cdFx0LyoqXG4gICAqIEB2YXIgQm9vbGVhblxuICAgKi9cblx0XHR0aGlzLnJlYWQgPSBmYWxzZTtcblx0XHQvKipcbiAgICogQHZhciBCb29sZWFuXG4gICAqL1xuXHRcdHRoaXMud3JpdGUgPSBmYWxzZSxcblx0XHQvKipcbiAgICogQHZhciBCb29sZWFuXG4gICAqL1xuXHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3J5Q29weSA9IGZhbHNlLFxuXHRcdC8qKlxuICAgKiBAdmFyIE1hcCgpXG4gICAqL1xuXHRcdHRoaXMucHJlZmVyZW5jZXMgPSBuZXcgTWFwKCksXG5cdFx0LyoqXG4gICAqIEB2YXIgTWFwKClcbiAgICovXG5cdFx0dGhpcy5yZXBvc2l0b3JpZXMgPSBuZXcgTWFwKCksXG5cdFx0LyoqXG4gICAqIEB2YXIgTWFwKClcbiAgICovXG5cdFx0dGhpcy5jcm9zc1JlcG9zaXRvcmllcyA9IG5ldyBNYXAoKSxcblx0XHQvKipcbiAgICogQHZhciBNYXAoKVxuICAgKi9cblx0XHR0aGlzLnJlcG9JY29ucyA9IG5ldyBNYXAoKSxcblx0XHQvKipcbiAgICogQHZhciBNYXAoKVxuICAgKi9cblx0XHR0aGlzLnJlcG9TZWFyY2hFbmdpbmVzID0gbmV3IE1hcCgpLFxuXHRcdC8qKlxuICAgKiBAdmFyIEJvb2xlYW5cbiAgICovXG5cdFx0dGhpcy5pc0FkbWluID0gZmFsc2U7XG5cdFx0LyoqXG4gICAqIEB2YXIgU3RyaW5nXG4gICAqL1xuXHRcdHRoaXMubG9jayA9IGZhbHNlO1xuXHRcdC8qKlxuICAgKlxuICAgKiBAdHlwZSBNYXBcbiAgICogQHByaXZhdGVcbiAgICovXG5cdFx0dGhpcy5fcGFyc2VkSlNPTkNhY2hlID0gbmV3IE1hcCgpO1xuXG5cdFx0aWYgKHhtbERlZikgdGhpcy5sb2FkRnJvbVhtbCh4bWxEZWYpO1xuXHR9XG5cblx0LyoqXG4gICogU2V0IGN1cnJlbnQgcmVwb3NpdG9yeVxuICAqIEBwYXJhbSBpZCBTdHJpbmdcbiAgKiBAcGFyYW0gcmVhZCBCb29sZWFuXG4gICogQHBhcmFtIHdyaXRlIEJvb2xlYW5cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5zZXRBY3RpdmVSZXBvc2l0b3J5ID0gZnVuY3Rpb24gc2V0QWN0aXZlUmVwb3NpdG9yeShpZCwgcmVhZCwgd3JpdGUpIHtcblx0XHR0aGlzLmFjdGl2ZVJlcG9zaXRvcnkgPSBpZDtcblx0XHR0aGlzLnJlYWQgPSByZWFkID09IFwiMVwiO1xuXHRcdHRoaXMud3JpdGUgPSB3cml0ZSA9PSBcIjFcIjtcblx0XHRpZiAodGhpcy5yZXBvc2l0b3JpZXMuaGFzKGlkKSkge1xuXHRcdFx0dGhpcy5jcm9zc1JlcG9zaXRvcnlDb3B5ID0gdGhpcy5yZXBvc2l0b3JpZXMuZ2V0KGlkKS5hbGxvd0Nyb3NzUmVwb3NpdG9yeUNvcHk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmNyb3NzUmVwb3NpdG9yaWVzLmhhcyhpZCkpIHtcblx0XHRcdHRoaXMuY3Jvc3NSZXBvc2l0b3JpZXNbJ2RlbGV0ZSddKGlkKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogR2V0cyB0aGUgY3VycmVudCBhY3RpdmUgcmVwb3NpdG9yeVxuICAqIEByZXR1cm5zIFN0cmluZ1xuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldEFjdGl2ZVJlcG9zaXRvcnkgPSBmdW5jdGlvbiBnZXRBY3RpdmVSZXBvc2l0b3J5KCkge1xuXHRcdHJldHVybiB0aGlzLmFjdGl2ZVJlcG9zaXRvcnk7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciBjdXJyZW50IHJlcG8gaXMgYWxsb3dlZCB0byBiZSByZWFkXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmNhblJlYWQgPSBmdW5jdGlvbiBjYW5SZWFkKCkge1xuXHRcdHJldHVybiB0aGlzLnJlYWQ7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciBjdXJyZW50IHJlcG8gaXMgYWxsb3dlZCB0byBiZSB3cml0dGVuXG4gICogQHJldHVybnMgQm9vbGVhblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmNhbldyaXRlID0gZnVuY3Rpb24gY2FuV3JpdGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMud3JpdGU7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciBjdXJyZW50IHJlcG8gaXMgYWxsb3dlZCB0byBiZSBjcm9zcy1jb3BpZWRcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuY2FuQ3Jvc3NSZXBvc2l0b3J5Q29weSA9IGZ1bmN0aW9uIGNhbkNyb3NzUmVwb3NpdG9yeUNvcHkoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY3Jvc3NSZXBvc2l0b3J5Q29weTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgYSB1c2VyIHByZWZlcmVuY2UgYnkgaXRzIG5hbWVcbiAgKiBAcmV0dXJucyBNaXhlZFxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLmdldFByZWZlcmVuY2UgPSBmdW5jdGlvbiBnZXRQcmVmZXJlbmNlKHByZWZOYW1lLCBmcm9tSlNPTikge1xuXHRcdGlmIChmcm9tSlNPTikge1xuXHRcdFx0dmFyIHRlc3QgPSB0aGlzLl9wYXJzZWRKU09OQ2FjaGUuZ2V0KHByZWZOYW1lKTtcblx0XHRcdGlmICh0ZXN0KSByZXR1cm4gdGVzdDtcblx0XHR9XG5cdFx0dmFyIHZhbHVlID0gdGhpcy5wcmVmZXJlbmNlcy5nZXQocHJlZk5hbWUpO1xuXHRcdGlmIChmcm9tSlNPTikge1xuXHRcdFx0aWYgKHZhbHVlKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiKSByZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0dmFyIHBhcnNlZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuXHRcdFx0XHRcdHRoaXMuX3BhcnNlZEpTT05DYWNoZS5zZXQocHJlZk5hbWUsIHBhcnNlZCk7XG5cdFx0XHRcdFx0aWYgKCFwYXJzZWQpIHJldHVybiB7fTtcblx0XHRcdFx0XHRyZXR1cm4gcGFyc2VkO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0aWYgKHdpbmRvdy5jb25zb2xlKSB7XG5cdFx0XHRcdFx0XHRfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5sb2coXCJFcnJvciBwYXJzaW5nIEpTT04gaW4gcHJlZmVyZW5jZXMgKFwiICsgcHJlZk5hbWUgKyBcIikuIFlvdSBzaG91bGQgY29udGFjdCBzeXN0ZW0gYWRtaW4gYW5kIGNsZWFyIHVzZXIgcHJlZmVyZW5jZXMuXCIpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRhbGVydChcIkVycm9yIHBhcnNpbmcgSlNPTiBpbiBwcmVmZXJlbmNlcy4gWW91IHNob3VsZCBjb250YWN0IHN5c3RlbSBhZG1pbiBhbmQgY2xlYXIgdXNlciBwcmVmZXJlbmNlcy5cIik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4ge307XG5cdFx0fVxuXHRcdHJldHVybiB2YWx1ZTtcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgYWxsIHJlcG9zaXRvcmllcyBcbiAgKiBAcmV0dXJucyBNYXBcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRSZXBvc2l0b3JpZXNMaXN0ID0gZnVuY3Rpb24gZ2V0UmVwb3NpdG9yaWVzTGlzdCgpIHtcblx0XHRyZXR1cm4gdGhpcy5yZXBvc2l0b3JpZXM7XG5cdH07XG5cblx0LyoqXG4gICogU2V0IGEgcHJlZmVyZW5jZSB2YWx1ZVxuICAqIEBwYXJhbSBwcmVmTmFtZSBTdHJpbmdcbiAgKiBAcGFyYW0gcHJlZlZhbHVlIE1peGVkXG4gICogQHBhcmFtIHRvSlNPTiBCb29sZWFuIFdoZXRoZXIgdG8gY29udmVydCB0aGUgdmFsdWUgdG8gSlNPTiByZXByZXNlbnRhdGlvblxuICAqL1xuXG5cdFVzZXIucHJvdG90eXBlLnNldFByZWZlcmVuY2UgPSBmdW5jdGlvbiBzZXRQcmVmZXJlbmNlKHByZWZOYW1lLCBwcmVmVmFsdWUpIHtcblx0XHR2YXIgdG9KU09OID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMl07XG5cblx0XHRpZiAodG9KU09OKSB7XG5cdFx0XHR0aGlzLl9wYXJzZWRKU09OQ2FjaGVbJ2RlbGV0ZSddKHByZWZOYW1lKTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHByZWZWYWx1ZSA9IEpTT04uc3RyaW5naWZ5KHByZWZWYWx1ZSk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGlmIChjb25zb2xlKSB7XG5cdFx0XHRcdFx0dmFyIGlzQ3ljbGljID0gZnVuY3Rpb24gaXNDeWNsaWMob2JqKSB7XG5cdFx0XHRcdFx0XHR2YXIgc2Vlbk9iamVjdHMgPSBbXTtcblxuXHRcdFx0XHRcdFx0ZnVuY3Rpb24gZGV0ZWN0KG9iaikge1xuXHRcdFx0XHRcdFx0XHRpZiAob2JqICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKHNlZW5PYmplY3RzLmluZGV4T2Yob2JqKSAhPT0gLTEpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRzZWVuT2JqZWN0cy5wdXNoKG9iaik7XG5cdFx0XHRcdFx0XHRcdFx0Zm9yICh2YXIga2V5IGluIG9iaikge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGRldGVjdChvYmpba2V5XSkpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Y29uc29sZS5sb2cob2JqLCAnY3ljbGUgYXQgJyArIGtleSk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRyZXR1cm4gZGV0ZWN0KG9iaik7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdGNvbnNvbGUubG9nKFwiQ2F1Z2h0IHRvSlNPTiBlcnJvciBcIiArIGUubWVzc2FnZSwgcHJlZlZhbHVlLCBpc0N5Y2xpYyhwcmVmVmFsdWUpKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMucHJlZmVyZW5jZXMuc2V0KHByZWZOYW1lLCBwcmVmVmFsdWUpO1xuXHR9O1xuXG5cdC8qKlxuICAqIFNldCB0aGUgcmVwb3NpdG9yaWVzIGFzIGEgYnVuY2hcbiAgKiBAcGFyYW0gcmVwb0hhc2ggTWFwXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuc2V0UmVwb3NpdG9yaWVzTGlzdCA9IGZ1bmN0aW9uIHNldFJlcG9zaXRvcmllc0xpc3QocmVwb0hhc2gpIHtcblx0XHR0aGlzLnJlcG9zaXRvcmllcyA9IHJlcG9IYXNoO1xuXHRcdC8vIGZpbHRlciByZXBvc2l0b3JpZXMgb25jZSBmb3IgYWxsXG5cdFx0dGhpcy5jcm9zc1JlcG9zaXRvcmllcyA9IG5ldyBNYXAoKTtcblx0XHR0aGlzLnJlcG9zaXRvcmllcy5mb3JFYWNoKChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuXHRcdFx0aWYgKHZhbHVlLmFsbG93Q3Jvc3NSZXBvc2l0b3J5Q29weSAmJiB2YWx1ZS5hY2Nlc3NUeXBlICE9ICdpbmJveCcpIHtcblx0XHRcdFx0dGhpcy5jcm9zc1JlcG9zaXRvcmllcy5zZXQoa2V5LCB2YWx1ZSk7XG5cdFx0XHR9XG5cdFx0fSkuYmluZCh0aGlzKSk7XG5cdH07XG5cblx0LyoqXG4gICogV2hldGhlciB0aGVyZSBhcmUgYW55IHJlcG9zaXRvcmllcyBhbGxvd2luZyBjcm9zc0NvcHlcbiAgKiBAcmV0dXJucyBCb29sZWFuXG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuaGFzQ3Jvc3NSZXBvc2l0b3JpZXMgPSBmdW5jdGlvbiBoYXNDcm9zc1JlcG9zaXRvcmllcygpIHtcblx0XHRyZXR1cm4gdGhpcy5jcm9zc1JlcG9zaXRvcmllcy5zaXplO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCByZXBvc2l0b3JpZXMgYWxsb3dpbmcgY3Jvc3MgY29weVxuICAqIEByZXR1cm5zIHtNYXB9XG4gICovXG5cblx0VXNlci5wcm90b3R5cGUuZ2V0Q3Jvc3NSZXBvc2l0b3JpZXMgPSBmdW5jdGlvbiBnZXRDcm9zc1JlcG9zaXRvcmllcygpIHtcblx0XHRyZXR1cm4gdGhpcy5jcm9zc1JlcG9zaXRvcmllcztcblx0fTtcblxuXHQvKipcbiAgKiBHZXQgdGhlIGN1cnJlbnQgcmVwb3NpdG9yeSBJY29uXG4gICogQHBhcmFtIHJlcG9JZCBTdHJpbmdcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRSZXBvc2l0b3J5SWNvbiA9IGZ1bmN0aW9uIGdldFJlcG9zaXRvcnlJY29uKHJlcG9JZCkge1xuXHRcdHJldHVybiB0aGlzLnJlcG9JY29uLmdldChyZXBvSWQpO1xuXHR9O1xuXG5cdC8qKlxuICAqIEdldCB0aGUgcmVwb3NpdG9yeSBzZWFyY2ggZW5naW5lXG4gICogQHBhcmFtIHJlcG9JZCBTdHJpbmdcbiAgKiBAcmV0dXJucyBTdHJpbmdcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5nZXRSZXBvU2VhcmNoRW5naW5lID0gZnVuY3Rpb24gZ2V0UmVwb1NlYXJjaEVuZ2luZShyZXBvSWQpIHtcblx0XHRyZXR1cm4gdGhpcy5yZXBvU2VhcmNoRW5naW5lcy5nZXQocmVwb0lkKTtcblx0fTtcblxuXHQvKipcbiAgKiBTZW5kIHRoZSBwcmVmZXJlbmNlIHRvIHRoZSBzZXJ2ZXIgZm9yIHNhdmluZ1xuICAqIEBwYXJhbSBwcmVmTmFtZSBTdHJpbmdcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5zYXZlUHJlZmVyZW5jZSA9IGZ1bmN0aW9uIHNhdmVQcmVmZXJlbmNlKHByZWZOYW1lKSB7XG5cdFx0aWYgKCF0aGlzLnByZWZlcmVuY2VzLmhhcyhwcmVmTmFtZSkpIHJldHVybjtcblx0XHR2YXIgcHJlZlZhbHVlID0gdGhpcy5wcmVmZXJlbmNlcy5nZXQocHJlZk5hbWUpO1xuXHRcdHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkudXNlclNhdmVQcmVmZXJlbmNlKHByZWZOYW1lLCBwcmVmVmFsdWUpO1xuXHRcdH0sIDI1MCk7XG5cdH07XG5cblx0LyoqXG4gICogU2VuZCBhbGwgcHJlZmVyZW5jZXMgdG8gdGhlIHNlcnZlci4gSWYgb2xkUGFzcywgbmV3UGFzcyBhbmQgc2VlZCBhcmUgc2V0LCBhbHNvIHNhdmUgcGFzcy5cbiAgKiBAcGFyYW0gb2xkUGFzcyBTdHJpbmdcbiAgKiBAcGFyYW0gbmV3UGFzcyBTdHJpbmdcbiAgKiBAcGFyYW0gc2VlZCBTdHJpbmdcbiAgKiBAcGFyYW0gb25Db21wbGV0ZUZ1bmMgRnVuY3Rpb25cbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5zYXZlUHJlZmVyZW5jZXMgPSBmdW5jdGlvbiBzYXZlUHJlZmVyZW5jZXMob2xkUGFzcywgbmV3UGFzcywgc2VlZCwgb25Db21wbGV0ZUZ1bmMpIHtcblx0XHRpZiAob2xkUGFzcyAmJiBuZXdQYXNzKSB7XG5cdFx0XHRfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnVzZXJTYXZlUGFzc3dvcmQob2xkUGFzcywgbmV3UGFzcywgc2VlZCwgb25Db21wbGV0ZUZ1bmMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpLnVzZXJTYXZlUHJlZmVyZW5jZXModGhpcy5wcmVmZXJlbmNlcywgb25Db21wbGV0ZUZ1bmMpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcbiAgKiBQYXJzZSB0aGUgcmVnaXN0cnkgZnJhZ21lbnQgdG8gbG9hZCB0aGlzIHVzZXJcbiAgKiBAcGFyYW0gdXNlck5vZGVzIERPTU5vZGVcbiAgKi9cblxuXHRVc2VyLnByb3RvdHlwZS5sb2FkRnJvbVhtbCA9IGZ1bmN0aW9uIGxvYWRGcm9tWG1sKHVzZXJOb2Rlcykge1xuXG5cdFx0dmFyIHJlcG9zaXRvcmllcyA9IG5ldyBNYXAoKSxcblx0XHQgICAgYWN0aXZlTm9kZSA9IHVuZGVmaW5lZDtcblx0XHR2YXIgaSA9IHVuZGVmaW5lZCxcblx0XHQgICAgaiA9IHVuZGVmaW5lZDtcblx0XHRmb3IgKGkgPSAwOyBpIDwgdXNlck5vZGVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpZiAodXNlck5vZGVzW2ldLm5vZGVOYW1lID09IFwiYWN0aXZlX3JlcG9cIikge1xuXHRcdFx0XHRhY3RpdmVOb2RlID0gdXNlck5vZGVzW2ldO1xuXHRcdFx0fSBlbHNlIGlmICh1c2VyTm9kZXNbaV0ubm9kZU5hbWUgPT0gXCJyZXBvc2l0b3JpZXNcIikge1xuXHRcdFx0XHRmb3IgKGogPSAwOyBqIDwgdXNlck5vZGVzW2ldLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHR2YXIgcmVwb0NoaWxkID0gdXNlck5vZGVzW2ldLmNoaWxkTm9kZXNbal07XG5cdFx0XHRcdFx0aWYgKHJlcG9DaGlsZC5ub2RlTmFtZSA9PSBcInJlcG9cIikge1xuXHRcdFx0XHRcdFx0dmFyIHJlcG9zaXRvcnkgPSBuZXcgX1JlcG9zaXRvcnkyWydkZWZhdWx0J10ocmVwb0NoaWxkLmdldEF0dHJpYnV0ZShcImlkXCIpLCByZXBvQ2hpbGQpO1xuXHRcdFx0XHRcdFx0cmVwb3NpdG9yaWVzLnNldChyZXBvQ2hpbGQuZ2V0QXR0cmlidXRlKFwiaWRcIiksIHJlcG9zaXRvcnkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0aGlzLnNldFJlcG9zaXRvcmllc0xpc3QocmVwb3NpdG9yaWVzKTtcblx0XHRcdH0gZWxzZSBpZiAodXNlck5vZGVzW2ldLm5vZGVOYW1lID09IFwicHJlZmVyZW5jZXNcIikge1xuXHRcdFx0XHRmb3IgKGogPSAwOyBqIDwgdXNlck5vZGVzW2ldLmNoaWxkTm9kZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0XHR2YXIgcHJlZkNoaWxkID0gdXNlck5vZGVzW2ldLmNoaWxkTm9kZXNbal07XG5cdFx0XHRcdFx0aWYgKHByZWZDaGlsZC5ub2RlTmFtZSA9PSBcInByZWZcIikge1xuXHRcdFx0XHRcdFx0dmFyIHZhbHVlID0gcHJlZkNoaWxkLmdldEF0dHJpYnV0ZShcInZhbHVlXCIpO1xuXHRcdFx0XHRcdFx0aWYgKCF2YWx1ZSAmJiBwcmVmQ2hpbGQuZmlyc3RDaGlsZCkge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXRyaWV2ZSB2YWx1ZSBmcm9tIENEQVRBXG5cdFx0XHRcdFx0XHRcdHZhbHVlID0gcHJlZkNoaWxkLmZpcnN0Q2hpbGQubm9kZVZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0dGhpcy5zZXRQcmVmZXJlbmNlKHByZWZDaGlsZC5nZXRBdHRyaWJ1dGUoXCJuYW1lXCIpLCB2YWx1ZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKHVzZXJOb2Rlc1tpXS5ub2RlTmFtZSA9PSBcInNwZWNpYWxfcmlnaHRzXCIpIHtcblx0XHRcdFx0dmFyIGF0dHIgPSB1c2VyTm9kZXNbaV0uZ2V0QXR0cmlidXRlKFwiaXNfYWRtaW5cIik7XG5cdFx0XHRcdGlmIChhdHRyICYmIGF0dHIgPT09IFwiMVwiKSB0aGlzLmlzQWRtaW4gPSB0cnVlO1xuXHRcdFx0XHRpZiAodXNlck5vZGVzW2ldLmdldEF0dHJpYnV0ZShcImxvY2tcIikpIHtcblx0XHRcdFx0XHR0aGlzLmxvY2sgPSB1c2VyTm9kZXNbaV0uZ2V0QXR0cmlidXRlKFwibG9ja1wiKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBNYWtlIHN1cmUgaXQgaGFwcGVucyBhdCB0aGUgZW5kXG5cdFx0aWYgKGFjdGl2ZU5vZGUpIHtcblx0XHRcdHRoaXMuc2V0QWN0aXZlUmVwb3NpdG9yeShhY3RpdmVOb2RlLmdldEF0dHJpYnV0ZSgnaWQnKSwgYWN0aXZlTm9kZS5nZXRBdHRyaWJ1dGUoJ3JlYWQnKSwgYWN0aXZlTm9kZS5nZXRBdHRyaWJ1dGUoJ3dyaXRlJykpO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gVXNlcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFVzZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbT4uXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xhbmdPYnNlcnZhYmxlID0gcmVxdWlyZSgnLi4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG4vKipcbiAqIEEgbW9uaXRvciBmb3IgdXNlciBcImlkbGVcIiBzdGF0ZSB0byBwcmV2ZW50IHNlc3Npb24gdGltaW5nIG91dC5cbiAqL1xuXG52YXIgQWN0aXZpdHlNb25pdG9yID0gKGZ1bmN0aW9uIChfT2JzZXJ2YWJsZSkge1xuICAgIF9pbmhlcml0cyhBY3Rpdml0eU1vbml0b3IsIF9PYnNlcnZhYmxlKTtcblxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHB5ZGlvIFB5ZGlvXG4gICAgICovXG5cbiAgICBmdW5jdGlvbiBBY3Rpdml0eU1vbml0b3IocHlkaW8pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQWN0aXZpdHlNb25pdG9yKTtcblxuICAgICAgICBfT2JzZXJ2YWJsZS5jYWxsKHRoaXMpO1xuXG4gICAgICAgIHZhciBzZXJ2ZXJTZXNzaW9uVGltZSA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdzZXNzaW9uX3RpbWVvdXQnKTtcbiAgICAgICAgdmFyIGNsaWVudFNlc3Npb25UaW1lID0gcHlkaW8uUGFyYW1ldGVycy5nZXQoJ2NsaWVudF90aW1lb3V0Jyk7XG4gICAgICAgIHZhciB3YXJuaW5nTWludXRlcyA9IHB5ZGlvLlBhcmFtZXRlcnMuZ2V0KCdjbGllbnRfdGltZW91dF93YXJuaW5nJyk7XG5cbiAgICAgICAgdGhpcy5fcHlkaW8gPSBweWRpbztcbiAgICAgICAgdGhpcy5fd2FybmluZ01pbnV0ZXMgPSAzO1xuICAgICAgICB0aGlzLl9yZW5ld01pbnV0ZXMgPSAxMDtcbiAgICAgICAgdGhpcy5fbG9nb3V0TWludXRlcyA9IDA7XG5cbiAgICAgICAgdGhpcy5fbGFzdEFjdGl2ZSA9IDA7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gJ2FjdGl2ZSc7XG4gICAgICAgIHRoaXMuX2xvbmdUYXNrUnVubmluZyA9IGZhbHNlO1xuXG4gICAgICAgIGlmICghc2VydmVyU2Vzc2lvblRpbWUpIHJldHVybjtcblxuICAgICAgICBpZiAoc2VydmVyU2Vzc2lvblRpbWUgPD0gNjAgKiB0aGlzLl9yZW5ld01pbnV0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmV3TWludXRlcyA9IDI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNsaWVudFNlc3Npb25UaW1lID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5fcmVuZXdUaW1lID0gc2VydmVyU2Vzc2lvblRpbWUgLSB0aGlzLl9yZW5ld01pbnV0ZXMgKiA2MDtcbiAgICAgICAgICAgIGlmICh0aGlzLl9weWRpby51c2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGFydFNlcnZlckxvbmdQb2xsZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ3VzZXJfbG9nZ2VkJywgZnVuY3Rpb24gKHUpIHtcbiAgICAgICAgICAgICAgICBpZiAodSkgX3RoaXMuc3RhcnRTZXJ2ZXJMb25nUG9sbGVyKCk7ZWxzZSBfdGhpcy5zdG9wU2VydmVyTG9uZ1BvbGxlcigpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXJ2ZXJTZXNzaW9uVGltZSA9IHNlcnZlclNlc3Npb25UaW1lO1xuICAgICAgICBpZiAod2FybmluZ01pbnV0ZXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3dhcm5pbmdNaW51dGVzID0gd2FybmluZ01pbnV0ZXM7XG4gICAgICAgICAgICB0aGlzLl93YXJuaW5nVGltZSA9IGNsaWVudFNlc3Npb25UaW1lIC0gdGhpcy5fd2FybmluZ01pbnV0ZXMgKiA2MDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3dhcm5pbmdUaW1lID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fbG9nb3V0VGltZSA9IGNsaWVudFNlc3Npb25UaW1lIC0gdGhpcy5fbG9nb3V0TWludXRlcyAqIDYwO1xuICAgICAgICB0aGlzLl9yZW5ld1RpbWUgPSBzZXJ2ZXJTZXNzaW9uVGltZSAtIHRoaXMuX3JlbmV3TWludXRlcyAqIDYwO1xuICAgICAgICB0aGlzLl9sYXN0QWN0aXZlID0gdGhpcy5nZXROb3coKTtcblxuICAgICAgICB0aGlzLl9hY3Rpdml0eU9ic2VydmVyID0gbnVsbDtcblxuICAgICAgICBpZiAodGhpcy5fcHlkaW8udXNlcikge1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ3VzZXJfbG9nZ2VkJywgZnVuY3Rpb24gKHUpIHtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUxhc3RBY3RpdmUoKTtcbiAgICAgICAgICAgIGlmICh1KSBfdGhpcy5yZWdpc3RlcigpO2Vsc2UgX3RoaXMudW5yZWdpc3RlcigpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvKlxuICAgICAgICBkb2N1bWVudC5vYnNlcnZlKFwiYWpheHBsb3Jlcjp1c2VyX2xvZ2dlZFwiLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgLy8gQmUgc3VyZSBub3QgdG8gbXVsdGlwbHkgdGhlIHNldEludGVydmFsXG4gICAgICAgICAgICB0aGlzLl9sYXN0QWN0aXZlID0gdGhpcy5nZXROb3coKTtcbiAgICAgICAgICAgIGlmKHRoaXMuaW50ZXJ2YWwpIGNsZWFySW50ZXJ2YWwodGhpcy5pbnRlcnZhbCk7XG4gICAgICAgICAgICBpZih0aGlzLnNlcnZlckludGVydmFsKSBjbGVhckludGVydmFsKHRoaXMuc2VydmVySW50ZXJ2YWwpO1xuICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5zdG9wT2JzZXJ2aW5nKFwia2V5cHJlc3NcIiwgYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLnN0b3BPYnNlcnZpbmcoXCJtb3VzZW92ZXJcIiwgYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLnN0b3BPYnNlcnZpbmcoXCJtb3VzZW1vdmVcIiwgYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgICAgICBkb2N1bWVudC5zdG9wT2JzZXJ2aW5nKFwiYWpheHBsb3JlcjpzZXJ2ZXJfYW5zd2VyXCIsIGFjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSAnaW5hY3RpdmUnO1xuICAgICAgICAgICAgaWYoYWpheHBsb3Jlci51c2VyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSAnYWN0aXZlJztcbiAgICAgICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLm9ic2VydmUoXCJrZXlwcmVzc1wiLCBhY3Rpdml0eU9ic2VydmVyICk7XG4gICAgICAgICAgICAgICAgJChkb2N1bWVudC5ib2R5KS5vYnNlcnZlKFwibW91c2VvdmVyXCIsIGFjdGl2aXR5T2JzZXJ2ZXIgKTtcbiAgICAgICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLm9ic2VydmUoXCJtb3VzZW1vdmVcIiwgYWN0aXZpdHlPYnNlcnZlciApO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50Lm9ic2VydmUoXCJhamF4cGxvcmVyOnNlcnZlcl9hbnN3ZXJcIiwgYWN0aXZpdHlPYnNlcnZlciApO1xuICAgICAgICAgICAgICAgIHRoaXMuaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLmlkbGVPYnNlcnZlci5iaW5kKHRoaXMpLCA1MDAwKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlcnZlckludGVydmFsID0gc2V0SW50ZXJ2YWwodGhpcy5zZXJ2ZXJPYnNlcnZlci5iaW5kKHRoaXMpLCBNYXRoLm1pbigoTWF0aC5wb3coMiwzMSktMSksIHRoaXMuX3JlbmV3VGltZSoxMDAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIGRvY3VtZW50Lm9ic2VydmUoXCJhamF4cGxvcmVyOmxvbmd0YXNrX3N0YXJ0aW5nXCIsIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICB0aGlzLl9sb25nVGFza1J1bm5pbmcgPSB0cnVlO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICBkb2N1bWVudC5vYnNlcnZlKFwiYWpheHBsb3Jlcjpsb25ndGFza19maW5pc2hlZFwiLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgdGhpcy5fbG9uZ1Rhc2tSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgICovXG4gICAgfVxuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zdGFydFNlcnZlckxvbmdQb2xsZXIgPSBmdW5jdGlvbiBzdGFydFNlcnZlckxvbmdQb2xsZXIoKSB7XG4gICAgICAgIGlmICh0aGlzLl9zZXJ2ZXJJbnRlcnZhbCkgcmV0dXJuO1xuICAgICAgICB0aGlzLl9zZXJ2ZXJJbnRlcnZhbCA9IHNldEludGVydmFsKHRoaXMuc2VydmVyUG9sbGVyLmJpbmQodGhpcyksIE1hdGgubWluKE1hdGgucG93KDIsIDMxKSAtIDEsIHRoaXMuX3JlbmV3VGltZSAqIDEwMDApKTtcbiAgICB9O1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zdG9wU2VydmVyTG9uZ1BvbGxlciA9IGZ1bmN0aW9uIHN0b3BTZXJ2ZXJMb25nUG9sbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5fc2VydmVySW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5fc2VydmVySW50ZXJ2YWwpO1xuICAgICAgICAgICAgdGhpcy5fc2VydmVySW50ZXJ2YWwgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuc3RhcnRJZGxlUG9sbGVyID0gZnVuY3Rpb24gc3RhcnRJZGxlUG9sbGVyKCkge1xuICAgICAgICB2YXIgcmVzdGFydEF0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICBpZiAocmVzdGFydEF0KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faWRsZUludGVydmFsKSBjbGVhckludGVydmFsKHRoaXMuX2lkbGVJbnRlcnZhbCk7XG4gICAgICAgICAgICB0aGlzLl9pZGxlSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLmlkbGVPYnNlcnZlci5iaW5kKHRoaXMpLCByZXN0YXJ0QXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2lkbGVJbnRlcnZhbCkgcmV0dXJuO1xuICAgICAgICAgICAgdGhpcy5faWRsZUludGVydmFsID0gc2V0SW50ZXJ2YWwodGhpcy5pZGxlT2JzZXJ2ZXIuYmluZCh0aGlzKSwgNTAwMCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zdG9wSWRsZVBvbGxlciA9IGZ1bmN0aW9uIHN0b3BJZGxlUG9sbGVyKCkge1xuICAgICAgICBpZiAodGhpcy5faWRsZUludGVydmFsKSB7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHRoaXMuX2lkbGVJbnRlcnZhbCk7XG4gICAgICAgICAgICB0aGlzLl9pZGxlSW50ZXJ2YWwgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUucmVnaXN0ZXIgPSBmdW5jdGlvbiByZWdpc3RlcigpIHtcbiAgICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3N0YXRlID0gJ2FjdGl2ZSc7XG4gICAgICAgIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIgPSB0aGlzLmFjdGl2aXR5T2JzZXJ2ZXIuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgndXNlcl9hY3Rpdml0eScsIHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLl9weWRpby5vYnNlcnZlKCdzZXJ2ZXJfYW5zd2VyJywgdGhpcy5fYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgIHRoaXMuX3B5ZGlvLm9ic2VydmUoJ2xvbmd0YXNrX3N0YXJ0aW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMyLl9sb25nVGFza1J1bm5pbmcgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fcHlkaW8ub2JzZXJ2ZSgnbG9uZ3Rhc2tfZmluaXNoZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpczIuX2xvbmdUYXNrUnVubmluZyA9IGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zdGFydElkbGVQb2xsZXIoKTtcbiAgICAgICAgdGhpcy5zdGFydFNlcnZlckxvbmdQb2xsZXIoKTtcbiAgICB9O1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS51bnJlZ2lzdGVyID0gZnVuY3Rpb24gdW5yZWdpc3RlcigpIHtcbiAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2aXR5T2JzZXJ2ZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIEFscmVhZHkgaW5hY3RpdmVcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0b3BJZGxlUG9sbGVyKCk7XG4gICAgICAgIHRoaXMuc3RvcFNlcnZlckxvbmdQb2xsZXIoKTtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSAnaW5hY3RpdmUnO1xuICAgICAgICB0aGlzLl9weWRpby5zdG9wT2JzZXJ2aW5nKCd1c2VyX2FjdGl2aXR5JywgdGhpcy5fYWN0aXZpdHlPYnNlcnZlcik7XG4gICAgICAgIHRoaXMuX3B5ZGlvLnN0b3BPYnNlcnZpbmcoJ3NlcnZlcl9hbnN3ZXInLCB0aGlzLl9hY3Rpdml0eU9ic2VydmVyKTtcbiAgICAgICAgdGhpcy5fcHlkaW8uc3RvcE9ic2VydmluZygnbG9uZ3Rhc2tfc3RhcnRpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpczMuX2xvbmdUYXNrUnVubmluZyA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9weWRpby5zdG9wT2JzZXJ2aW5nKCdsb25ndGFza19maW5pc2hlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzMy5fbG9uZ1Rhc2tSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9hY3Rpdml0eU9ic2VydmVyID0gbnVsbDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTGlzdGVuZXIgdG8gY2xlYXIgdGhlIHRpbWVyXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLmFjdGl2aXR5T2JzZXJ2ZXIgPSBmdW5jdGlvbiBhY3Rpdml0eU9ic2VydmVyKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudCAmJiAoZXZlbnQubWVtbyAmJiBldmVudC5tZW1vLmRpc2NyZXRlIHx8IGV2ZW50LmRpc2NyZXRlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gJ3dhcm5pbmcnKSB7XG4gICAgICAgICAgICB0aGlzLmV4aXRJZGxlU3RhdGUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5faW50ZXJuYWxUaW1lcikgY2xlYXJUaW1lb3V0KHRoaXMuX2ludGVybmFsVGltZXIpO1xuICAgICAgICB0aGlzLl9pbnRlcm5hbFRpbWVyID0gc2V0VGltZW91dCh0aGlzLnVwZGF0ZUxhc3RBY3RpdmUuYmluZCh0aGlzKSwgMTAwMCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNldCBsYXN0IGFjdGl2aXR5IHRpbWVcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUudXBkYXRlTGFzdEFjdGl2ZSA9IGZ1bmN0aW9uIHVwZGF0ZUxhc3RBY3RpdmUoKSB7XG4gICAgICAgIHRoaXMuX2xhc3RBY3RpdmUgPSB0aGlzLmdldE5vdygpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQaW5ncyB0aGUgc2VydmVyXG4gICAgICovXG5cbiAgICBBY3Rpdml0eU1vbml0b3IucHJvdG90eXBlLnNlcnZlclBvbGxlciA9IGZ1bmN0aW9uIHNlcnZlclBvbGxlcigpIHtcbiAgICAgICAgUHlkaW9BcGkuZ2V0Q2xpZW50KCkucmVxdWVzdCh7IGdldF9hY3Rpb246ICdwaW5nJyB9LCBudWxsLCBudWxsLCB7IG1ldGhvZDogJ2dldCcsIGRpc2NyZXRlOiB0cnVlIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW5lciBmb3IgXCJpZGxlXCIgc3RhdGUgb2YgdGhlIHVzZXJcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuaWRsZU9ic2VydmVyID0gZnVuY3Rpb24gaWRsZU9ic2VydmVyKCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICB2YXIgaWRsZVRpbWUgPSB0aGlzLmdldE5vdygpIC0gdGhpcy5fbGFzdEFjdGl2ZTtcbiAgICAgICAgaWYgKHRoaXMuX3N0YXRlID09PSAnaW5hY3RpdmUnKSByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLl9sb25nVGFza1J1bm5pbmcpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTGFzdEFjdGl2ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vY29uc29sZS5sb2coaWRsZVRpbWUsIHRoaXMuX2xvZ291dFRpbWUpO1xuICAgICAgICBpZiAoaWRsZVRpbWUgPj0gdGhpcy5fbG9nb3V0VGltZSkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVXYXJuaW5nU3RhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gJ2FjdGl2ZSc7XG4gICAgICAgICAgICB0aGlzLnN0b3BJZGxlUG9sbGVyKCk7XG4gICAgICAgICAgICB0aGlzLnN0b3BTZXJ2ZXJMb25nUG9sbGVyKCk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpczQuX3B5ZGlvLmdldENvbnRyb2xsZXIoKS5maXJlRGVmYXVsdEFjdGlvbihcImV4cGlyZVwiKTtcbiAgICAgICAgICAgIH0sIDEwMDApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl93YXJuaW5nVGltZSAmJiBpZGxlVGltZSA+PSB0aGlzLl93YXJuaW5nVGltZSkge1xuICAgICAgICAgICAgdmFyIHRpbWVyU3RyaW5nID0gdGhpcy5nZXRXYXJuaW5nVGltZXIodGhpcy5fbG9nb3V0VGltZSAtIGlkbGVUaW1lKTtcbiAgICAgICAgICAgIHRoaXMuc2V0V2FybmluZ1N0YXRlKHRpbWVyU3RyaW5nKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWFjdGl2YXRlIHdpbmRvd1xuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5leGl0SWRsZVN0YXRlID0gZnVuY3Rpb24gZXhpdElkbGVTdGF0ZSgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVXYXJuaW5nU3RhdGUoKTtcbiAgICAgICAgdGhpcy51cGRhdGVMYXN0QWN0aXZlKCk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gJ2FjdGl2ZSc7XG4gICAgICAgIHRoaXMuc3RhcnRJZGxlUG9sbGVyKDUwMDApO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQdXQgdGhlIHdpbmRvdyBpbiBcIndhcm5pbmdcIiBzdGF0ZSA6IG92ZXJsYXksIHNoYWtpbmcgdGltZXIsIGNocm9ub21ldGVyLlxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5zZXRXYXJuaW5nU3RhdGUgPSBmdW5jdGlvbiBzZXRXYXJuaW5nU3RhdGUod2FybmluZ1RpbWVyU3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gJ3dhcm5pbmcnO1xuICAgICAgICB0aGlzLnN0YXJ0SWRsZVBvbGxlcigxMDAwKTtcblxuICAgICAgICB0aGlzLl9weWRpby5ub3RpZnkoJ2FjdGl2aXR5X3N0YXRlX2NoYW5nZScsIHtcbiAgICAgICAgICAgIGFjdGl2ZVN0YXRlOiAnd2FybmluZycsXG4gICAgICAgICAgICBsYXN0QWN0aXZlU2luY2U6IHRoaXMuX3dhcm5pbmdUaW1lIC8gNjAsXG4gICAgICAgICAgICB0aW1lclN0cmluZzogd2FybmluZ1RpbWVyU3RyaW5nXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDaHJvbm9tZXRlciBmb3Igd2FybmluZyBiZWZvcmUgdGltZW91dFxuICAgICAqIEBwYXJhbSB0aW1lIEludGVnZXJcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuZ2V0V2FybmluZ1RpbWVyID0gZnVuY3Rpb24gZ2V0V2FybmluZ1RpbWVyKHRpbWUpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IodGltZSAvIDYwKSArICdtbicgKyB0aW1lICUgNjAgKyAncyc7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIG92ZXJsYXkgb2Ygd2FybmluZyBzdGF0ZVxuICAgICAqL1xuXG4gICAgQWN0aXZpdHlNb25pdG9yLnByb3RvdHlwZS5yZW1vdmVXYXJuaW5nU3RhdGUgPSBmdW5jdGlvbiByZW1vdmVXYXJuaW5nU3RhdGUoKSB7XG4gICAgICAgIHRoaXMuX3B5ZGlvLm5vdGlmeSgnYWN0aXZpdHlfc3RhdGVfY2hhbmdlJywge1xuICAgICAgICAgICAgYWN0aXZlU3RhdGU6ICdhY3RpdmUnXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVdGlsaXR5IHRvIGdldCB0aGUgdGltZVxuICAgICAqIEByZXR1cm5zIEludGVnZXJcbiAgICAgKi9cblxuICAgIEFjdGl2aXR5TW9uaXRvci5wcm90b3R5cGUuZ2V0Tm93ID0gZnVuY3Rpb24gZ2V0Tm93KCkge1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApO1xuICAgIH07XG5cbiAgICByZXR1cm4gQWN0aXZpdHlNb25pdG9yO1xufSkoX2xhbmdPYnNlcnZhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQWN0aXZpdHlNb25pdG9yO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKiBQdXJlIEphdmFzY3JpcHQgKEVTNikgQ29va2llIE1hbmFnZXIgaW5zcGlyZWQgYnkgQ29va2llSmFyIHRoYXQgd2FzIHJlbHlpbmcgb24gUHJvdG90eXBlSlMuXG4gKlxuICogLS0tLVxuICogQ29va2llSkFSIE9yaWdpbmFsIEhlYWRlclxuICpcbiAqIEphdmFzY3JpcHQgY29kZSB0byBzdG9yZSBkYXRhIGFzIEpTT04gc3RyaW5ncyBpbiBjb29raWVzLiBcbiAqIEl0IHVzZXMgcHJvdG90eXBlLmpzIDEuNS4xIChodHRwOi8vd3d3LnByb3RvdHlwZWpzLm9yZylcbiAqIFxuICogQXV0aG9yIDogTGFsaXQgUGF0ZWxcbiAqIFdlYnNpdGU6IGh0dHA6Ly93d3cubGFsaXQub3JnL2xhYi9qc29uY29va2llc1xuICogTGljZW5zZTogQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDIuNVxuICogICAgICAgICAgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMi41L1xuICogVmVyc2lvbjogMC40XG4gKiBVcGRhdGVkOiBBdWcgMTEsIDIwMDcgMTA6MDlhbVxuICogXG4gKiBDaG5hZ2UgTG9nOlxuICogICB2IDAuNFxuICogICAtICBSZW1vdmVkIGEgZXh0cmEgY29tbWEgaW4gb3B0aW9ucyAod2FzIGJyZWFraW5nIGluIElFIGFuZCBPcGVyYSkuIChUaGFua3MgSmFzb24pXG4gKiAgIC0gIFJlbW92ZWQgdGhlIHBhcmFtZXRlciBuYW1lIGZyb20gdGhlIGluaXRpYWxpemUgZnVuY3Rpb25cbiAqICAgLSAgQ2hhbmdlZCB0aGUgd2F5IGV4cGlyZXMgZGF0ZSB3YXMgYmVpbmcgY2FsY3VsYXRlZC4gKFRoYW5rcyBEYXZpZClcbiAqICAgdiAwLjNcbiAqICAgLSAgUmVtb3ZlZCBkZXBlbmRhbmN5IG9uIGpzb24uanMgKGh0dHA6Ly93d3cuanNvbi5vcmcvanNvbi5qcylcbiAqICAgLSAgZW1wdHkoKSBmdW5jdGlvbiBvbmx5IGRlbGV0ZXMgdGhlIGNvb2tpZXMgc2V0IGJ5IENvb2tpZUphclxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBDb29raWVzTWFuYWdlciA9IChmdW5jdGlvbiAoKSB7XG5cdENvb2tpZXNNYW5hZ2VyLnN1cHBvcnRlZCA9IGZ1bmN0aW9uIHN1cHBvcnRlZCgpIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQgJiYgZG9jdW1lbnQuY29va2llICE9PSB1bmRlZmluZWQ7XG5cdH07XG5cblx0LyoqXG4gICogSW5pdGlhbGl6ZXMgdGhlIGNvb2tpZSBqYXIgd2l0aCB0aGUgb3B0aW9ucy5cbiAgKi9cblxuXHRmdW5jdGlvbiBDb29raWVzTWFuYWdlcihvcHRpb25zKSB7XG5cdFx0X2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvb2tpZXNNYW5hZ2VyKTtcblxuXHRcdC8qKlxuICAgKiBBcHBlbmQgYmVmb3JlIGFsbCBjb29raWUgbmFtZXMgdG8gZGlmZmVybnRpYXRlIHRoZW0uXG4gICAqL1xuXHRcdHRoaXMuX2FwcGVuZFN0cmluZyA9IFwiX19QWURJT19fXCI7XG5cblx0XHR0aGlzLm9wdGlvbnMgPSB7XG5cdFx0XHRleHBpcmVzOiAzNjAwLCAvLyBzZWNvbmRzICgxIGhyKVxuXHRcdFx0cGF0aDogJycsIC8vIGNvb2tpZSBwYXRoXG5cdFx0XHRkb21haW46ICcnLCAvLyBjb29raWUgZG9tYWluXG5cdFx0XHRzZWN1cmU6ICcnIC8vIHNlY3VyZSA/XG5cdFx0fTtcblx0XHR0aGlzLm9wdGlvbnMgPSBMYW5nVXRpbHMub2JqZWN0TWVyZ2UodGhpcy5vcHRpb25zLCBvcHRpb25zIHx8IHt9KTtcblxuXHRcdGlmICh0aGlzLm9wdGlvbnMuZXhwaXJlcyAhPSAnJykge1xuXHRcdFx0dmFyIGRhdGUgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0ZGF0ZSA9IG5ldyBEYXRlKGRhdGUuZ2V0VGltZSgpICsgdGhpcy5vcHRpb25zLmV4cGlyZXMgKiAxMDAwKTtcblx0XHRcdHRoaXMub3B0aW9ucy5leHBpcmVzID0gJzsgZXhwaXJlcz0nICsgZGF0ZS50b0dNVFN0cmluZygpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLnBhdGggIT0gJycpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5wYXRoID0gJzsgcGF0aD0nICsgZW5jb2RlVVJJKHRoaXMub3B0aW9ucy5wYXRoKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5kb21haW4gIT0gJycpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5kb21haW4gPSAnOyBkb21haW49JyArIGVuY29kZVVSSSh0aGlzLm9wdGlvbnMuZG9tYWluKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5zZWN1cmUgPT0gJ3NlY3VyZScpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zZWN1cmUgPSAnOyBzZWN1cmUnO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuc2VjdXJlID0gJyc7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG4gICogQWRkcyBhIG5hbWUgdmFsdWVzIHBhaXIuXG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLnB1dENvb2tpZSA9IGZ1bmN0aW9uIHB1dENvb2tpZShuYW1lLCB2YWx1ZSkge1xuXHRcdG5hbWUgPSB0aGlzLl9hcHBlbmRTdHJpbmcgKyBuYW1lO1xuXHRcdHZhciBjb29raWUgPSB0aGlzLm9wdGlvbnM7XG5cdFx0dmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cdFx0c3dpdGNoICh0eXBlKSB7XG5cdFx0XHRjYXNlICd1bmRlZmluZWQnOlxuXHRcdFx0Y2FzZSAnZnVuY3Rpb24nOlxuXHRcdFx0Y2FzZSAndW5rbm93bic6XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdGNhc2UgJ2Jvb2xlYW4nOlxuXHRcdFx0Y2FzZSAnc3RyaW5nJzpcblx0XHRcdGNhc2UgJ251bWJlcic6XG5cdFx0XHRcdHZhbHVlID0gU3RyaW5nKHZhbHVlLnRvU3RyaW5nKCkpO1xuXHRcdH1cblx0XHR2YXIgY29va2llX3N0ciA9IG5hbWUgKyBcIj1cIiArIGVuY29kZVVSSShKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xuXHRcdHRyeSB7XG5cdFx0XHRkb2N1bWVudC5jb29raWUgPSBjb29raWVfc3RyICsgY29va2llLmV4cGlyZXMgKyBjb29raWUucGF0aCArIGNvb2tpZS5kb21haW4gKyBjb29raWUuc2VjdXJlO1xuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH07XG5cblx0LyoqXG4gICogUmVtb3ZlcyBhIHBhcnRpY3VsYXIgY29va2llIChuYW1lIHZhbHVlIHBhaXIpIGZvcm0gdGhlIENvb2tpZSBKYXIuXG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLnJlbW92ZUNvb2tpZSA9IGZ1bmN0aW9uIHJlbW92ZUNvb2tpZShuYW1lKSB7XG5cdFx0bmFtZSA9IHRoaXMuX2FwcGVuZFN0cmluZyArIG5hbWU7XG5cdFx0dmFyIGNvb2tpZSA9IHRoaXMub3B0aW9ucztcblx0XHR0cnkge1xuXHRcdFx0dmFyIGRhdGUgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0ZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpIC0gMzYwMCAqIDEwMDApO1xuXHRcdFx0dmFyIGV4cGlyZXMgPSAnOyBleHBpcmVzPScgKyBkYXRlLnRvR01UU3RyaW5nKCk7XG5cdFx0XHRkb2N1bWVudC5jb29raWUgPSBuYW1lICsgXCI9XCIgKyBleHBpcmVzICsgY29va2llLnBhdGggKyBjb29raWUuZG9tYWluICsgY29va2llLnNlY3VyZTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cdC8qKlxuICAqIFJldHVybiBhIHBhcnRpY3VsYXIgY29va2llIGJ5IG5hbWU7XG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLmdldENvb2tpZSA9IGZ1bmN0aW9uIGdldENvb2tpZShuYW1lKSB7XG5cdFx0bmFtZSA9IHRoaXMuX2FwcGVuZFN0cmluZyArIG5hbWU7XG5cdFx0dmFyIGNvb2tpZXMgPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmFtZSArICc9KC4qPykoO3wkKScpO1xuXHRcdGlmIChjb29raWVzKSB7XG5cdFx0XHRyZXR1cm4gSlNPTi5wYXJzZShkZWNvZGVVUkkoY29va2llc1sxXSkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogRW1wdGllcyB0aGUgQ29va2llIEphci4gRGVsZXRlcyBhbGwgdGhlIGNvb2tpZXMuXG4gICovXG5cblx0Q29va2llc01hbmFnZXIucHJvdG90eXBlLmVtcHR5QWxsID0gZnVuY3Rpb24gZW1wdHlBbGwoKSB7XG5cdFx0dmFyIGtleXMgPSB0aGlzLmdldEtleXMoKTtcblx0XHR2YXIgc2l6ZSA9IGtleXMuc2l6ZSgpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG5cdFx0XHR0aGlzLnJlbW92ZUNvb2tpZShrZXlzW2ldKTtcblx0XHR9XG5cdH07XG5cblx0LyoqXG4gICogUmV0dXJucyBhbGwgY29va2llcyBhcyBhIHNpbmdsZSBvYmplY3RcbiAgKi9cblxuXHRDb29raWVzTWFuYWdlci5wcm90b3R5cGUuZ2V0UGFjayA9IGZ1bmN0aW9uIGdldFBhY2soKSB7XG5cdFx0dmFyIHBhY2sgPSB7fTtcblx0XHR2YXIga2V5cyA9IHRoaXMuZ2V0S2V5cygpO1xuXG5cdFx0dmFyIHNpemUgPSBrZXlzLnNpemUoKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuXHRcdFx0cGFja1trZXlzW2ldXSA9IHRoaXMuZ2V0KGtleXNbaV0pO1xuXHRcdH1cblx0XHRyZXR1cm4gcGFjaztcblx0fTtcblxuXHQvKipcbiAgKiBSZXR1cm5zIGFsbCBrZXlzLlxuICAqL1xuXG5cdENvb2tpZXNNYW5hZ2VyLnByb3RvdHlwZS5nZXRLZXlzID0gZnVuY3Rpb24gZ2V0S2V5cygpIHtcblx0XHR2YXIga2V5cyA9IFtdO1xuXHRcdHZhciBrZXlSZSA9IC9bXj07IF0rKD89XFw9KS9nO1xuXHRcdHZhciBzdHIgPSBkb2N1bWVudC5jb29raWU7XG5cdFx0dmFyIENKUmUgPSBuZXcgUmVnRXhwKFwiXlwiICsgdGhpcy5fYXBwZW5kU3RyaW5nKTtcblx0XHR2YXIgbWF0Y2g7XG5cdFx0d2hpbGUgKChtYXRjaCA9IGtleVJlLmV4ZWMoc3RyKSkgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRpZiAoQ0pSZS50ZXN0KG1hdGNoWzBdLnN0cmlwKCkpKSB7XG5cdFx0XHRcdGtleXMucHVzaChtYXRjaFswXS5zdHJpcCgpLmdzdWIoXCJeXCIgKyB0aGlzLl9hcHBlbmRTdHJpbmcsIFwiXCIpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGtleXM7XG5cdH07XG5cblx0cmV0dXJuIENvb2tpZXNNYW5hZ2VyO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ29va2llc01hbmFnZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcbiIsIi8qXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDE3IENoYXJsZXMgZHUgSmV1IC0gQWJzdHJpdW0gU0FTIDx0ZWFtIChhdCkgcHlkLmlvPlxuICogVGhpcyBmaWxlIGlzIHBhcnQgb2YgUHlkaW8uXG4gKlxuICogUHlkaW8gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBQeWRpbyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCBQeWRpby4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAqXG4gKiBUaGUgbGF0ZXN0IGNvZGUgY2FuIGJlIGZvdW5kIGF0IDxodHRwczovL3B5ZGlvLmNvbS8+LlxuICpcbiAqL1xuLyoqXG4gKiBVdGlsaXRhcnkgY2xhc3MgZm9yIGxhbmd1YWdlIHNwZWNpZmljIG1ldGhvZHNcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIERPTVV0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBET01VdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIERPTVV0aWxzKTtcbiAgICB9XG5cbiAgICBET01VdGlscy5nZXRCZXppZXJzVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGdldEJlemllcnNUcmFuc2l0aW9uKCkge1xuICAgICAgICByZXR1cm4gJ2FsbCA1NTBtcyBjdWJpYy1iZXppZXIoMC4yMywgMSwgMC4zMiwgMSkgMG1zJztcbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuZ2V0Qm94U2hhZG93RGVwdGggPSBmdW5jdGlvbiBnZXRCb3hTaGFkb3dEZXB0aCgpIHtcbiAgICAgICAgdmFyIGRlcHRoID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gMSA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgICByZXR1cm4gJzAgM3B4IDZweCByZ2JhKDAsIDAsIDAsIDAuMTYpLCAwIDNweCA2cHggcmdiYSgwLCAwLCAwLCAwLjIzKSc7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLmdldFVybEZyb21CYXNlID0gZnVuY3Rpb24gZ2V0VXJsRnJvbUJhc2UoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnYmFzZScpLmxlbmd0aCA/IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdiYXNlJylbMF0uaHJlZiA6ICcnO1xuICAgIH07XG5cbiAgICBET01VdGlscy5nZXRWaWV3cG9ydFdpZHRoID0gZnVuY3Rpb24gZ2V0Vmlld3BvcnRXaWR0aCgpIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aCB8fCBkb2N1bWVudC5ib2R5LmNsaWVudFdpZHRoO1xuICAgIH07XG5cbiAgICBET01VdGlscy5nZXRWaWV3cG9ydEhlaWdodCA9IGZ1bmN0aW9uIGdldFZpZXdwb3J0SGVpZ2h0KCkge1xuICAgICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQgfHwgZG9jdW1lbnQuYm9keS5jbGllbnRIZWlnaHQ7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLmltYWdlTG9hZGVyID0gZnVuY3Rpb24gaW1hZ2VMb2FkZXIoaW1hZ2VVcmwsIG9uTG9hZCwgb25FcnJvcikge1xuICAgICAgICB2YXIgbG9hZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XG4gICAgICAgIGxvYWRlci5vbmxvYWQgPSBvbkxvYWQuYmluZChsb2FkZXIpO1xuICAgICAgICBsb2FkZXIub25lcnJvciA9IG9uRXJyb3IuYmluZChsb2FkZXIpO1xuICAgICAgICBsb2FkZXIuc3JjID0gaW1hZ2VVcmw7XG4gICAgfTtcblxuICAgIERPTVV0aWxzLm9ic2VydmVXaW5kb3dSZXNpemUgPSBmdW5jdGlvbiBvYnNlcnZlV2luZG93UmVzaXplKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICh3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGNhbGxiYWNrKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdpbmRvdy5hdHRhY2hFdmVudCgnb25yZXNpemUnLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgRE9NVXRpbHMuc3RvcE9ic2VydmluZ1dpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uIHN0b3BPYnNlcnZpbmdXaW5kb3dSZXNpemUoY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgY2FsbGJhY2spO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2luZG93LmRldGFjaEV2ZW50KCdvbnJlc2l6ZScsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gRE9NVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBET01VdGlscztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgbGFuZ3VhZ2Ugc3BlY2lmaWMgbWV0aG9kc1xuICovXG5cInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIEZ1bmNVdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRnVuY1V0aWxzKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRnVuY1V0aWxzKTtcbiAgICB9XG5cbiAgICBGdW5jVXRpbHMuRW1wdHkgPSBmdW5jdGlvbiBFbXB0eSgpIHt9O1xuXG4gICAgRnVuY1V0aWxzLklkZW50aXR5ID0gZnVuY3Rpb24gSWRlbnRpdHkob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfTtcblxuICAgIEZ1bmNVdGlscy5leGVjdXRlRnVuY3Rpb25CeU5hbWUgPSBmdW5jdGlvbiBleGVjdXRlRnVuY3Rpb25CeU5hbWUoZnVuY3Rpb25OYW1lLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICAgICAgdmFyIG5hbWVzcGFjZXMgPSBmdW5jdGlvbk5hbWUuc3BsaXQoXCIuXCIpO1xuICAgICAgICB2YXIgZnVuYyA9IG5hbWVzcGFjZXMucG9wKCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXNwYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udGV4dCA9IGNvbnRleHRbbmFtZXNwYWNlc1tpXV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbnRleHRbZnVuY10uYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgfTtcblxuICAgIEZ1bmNVdGlscy5nZXRGdW5jdGlvbkJ5TmFtZSA9IGZ1bmN0aW9uIGdldEZ1bmN0aW9uQnlOYW1lKGZ1bmN0aW9uTmFtZSwgY29udGV4dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgIHZhciBuYW1lc3BhY2VzID0gZnVuY3Rpb25OYW1lLnNwbGl0KFwiLlwiKTtcbiAgICAgICAgdmFyIGZ1bmMgPSBuYW1lc3BhY2VzLnBvcCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5hbWVzcGFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICghY29udGV4dFtuYW1lc3BhY2VzW2ldXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGV4dCA9IGNvbnRleHRbbmFtZXNwYWNlc1tpXV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbnRleHRbZnVuY107XG4gICAgfTtcblxuICAgIEZ1bmNVdGlscy5idWZmZXJDYWxsYmFjayA9IGZ1bmN0aW9uIGJ1ZmZlckNhbGxiYWNrKG5hbWUsIHRpbWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICh3aW5kb3dbbmFtZV0pIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQod2luZG93W25hbWVdKTtcbiAgICAgICAgfVxuICAgICAgICB3aW5kb3dbbmFtZV0gPSB3aW5kb3cuc2V0VGltZW91dChjYWxsYmFjaywgdGltZSk7XG4gICAgfTtcblxuICAgIHJldHVybiBGdW5jVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IEZ1bmNVdGlscztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1tcImRlZmF1bHRcIl07XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBoYXNoaW5nIG1ldGhvZHNcbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIEhhc2hlclV0aWxzID0gKGZ1bmN0aW9uICgpIHtcblxuICAgIC8qXG4gICAgICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBSU0EgRGF0YSBTZWN1cml0eSwgSW5jLiBNRDUgTWVzc2FnZVxuICAgICAqIERpZ2VzdCBBbGdvcml0aG0sIGFzIGRlZmluZWQgaW4gUkZDIDEzMjEuXG4gICAgICogVmVyc2lvbiAyLjEgQ29weXJpZ2h0IChDKSBQYXVsIEpvaG5zdG9uIDE5OTkgLSAyMDAyLlxuICAgICAqIE90aGVyIGNvbnRyaWJ1dG9yczogR3JlZyBIb2x0LCBBbmRyZXcgS2VwZXJ0LCBZZG5hciwgTG9zdGluZXRcbiAgICAgKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQlNEIExpY2Vuc2VcbiAgICAgKiBTZWUgaHR0cDovL3BhamhvbWUub3JnLnVrL2NyeXB0L21kNSBmb3IgbW9yZSBpbmZvLlxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gSGFzaGVyVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBIYXNoZXJVdGlscyk7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb25maWd1cmFibGUgdmFyaWFibGVzLiBZb3UgbWF5IG5lZWQgdG8gdHdlYWsgdGhlc2UgdG8gYmUgY29tcGF0aWJsZSB3aXRoXG4gICAgICogdGhlIHNlcnZlci1zaWRlLCBidXQgdGhlIGRlZmF1bHRzIHdvcmsgaW4gbW9zdCBjYXNlcy5cbiAgICAgKi9cblxuICAgIC8qXG4gICAgICogVGhlc2UgYXJlIHRoZSBmdW5jdGlvbnMgeW91J2xsIHVzdWFsbHkgd2FudCB0byBjYWxsXG4gICAgICogVGhleSB0YWtlIHN0cmluZyBhcmd1bWVudHMgYW5kIHJldHVybiBlaXRoZXIgaGV4IG9yIGJhc2UtNjQgZW5jb2RlZCBzdHJpbmdzXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5oZXhfbWQ1ID0gZnVuY3Rpb24gaGV4X21kNShzKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMmhleChIYXNoZXJVdGlscy5jb3JlX21kNShIYXNoZXJVdGlscy5zdHIyYmlubChzKSwgcy5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzeikpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5iNjRfbWQ1ID0gZnVuY3Rpb24gYjY0X21kNShzKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMmI2NChIYXNoZXJVdGlscy5jb3JlX21kNShIYXNoZXJVdGlscy5zdHIyYmlubChzKSwgcy5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzeikpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5zdHJfbWQ1ID0gZnVuY3Rpb24gc3RyX21kNShzKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMnN0cihIYXNoZXJVdGlscy5jb3JlX21kNShIYXNoZXJVdGlscy5zdHIyYmlubChzKSwgcy5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzeikpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5oZXhfaG1hY19tZDUgPSBmdW5jdGlvbiBoZXhfaG1hY19tZDUoa2V5LCBkYXRhKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMmhleChIYXNoZXJVdGlscy5jb3JlX2htYWNfbWQ1KGtleSwgZGF0YSkpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5iNjRfaG1hY19tZDUgPSBmdW5jdGlvbiBiNjRfaG1hY19tZDUoa2V5LCBkYXRhKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMmI2NChIYXNoZXJVdGlscy5jb3JlX2htYWNfbWQ1KGtleSwgZGF0YSkpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5zdHJfaG1hY19tZDUgPSBmdW5jdGlvbiBzdHJfaG1hY19tZDUoa2V5LCBkYXRhKSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5iaW5sMnN0cihIYXNoZXJVdGlscy5jb3JlX2htYWNfbWQ1KGtleSwgZGF0YSkpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5iYXNlNjRfZW5jb2RlID0gZnVuY3Rpb24gYmFzZTY0X2VuY29kZShkYXRhKSB7XG4gICAgICAgIC8vIGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0XG4gICAgICAgIC8vICsgICBvcmlnaW5hbCBieTogVHlsZXIgQWtpbnMgKGh0dHA6Ly9ydW1raW4uY29tKVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IEJheXJvbiBHdWV2YXJhXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogVGh1bmRlci5tXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogS2V2aW4gdmFuIFpvbm5ldmVsZCAoaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXQpXG4gICAgICAgIC8vICsgICBidWdmaXhlZCBieTogUGVsbGVudGVzcXVlIE1hbGVzdWFkYVxuICAgICAgICAvLyArICAgaW1wcm92ZWQgYnk6IEtldmluIHZhbiBab25uZXZlbGQgKGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0KVxuICAgICAgICAvLyAtICAgIGRlcGVuZHMgb246IHV0ZjhfZW5jb2RlXG4gICAgICAgIC8vICogICAgIGV4YW1wbGUgMTogYmFzZTY0X2VuY29kZSgnS2V2aW4gdmFuIFpvbm5ldmVsZCcpO1xuICAgICAgICAvLyAqICAgICByZXR1cm5zIDE6ICdTMlYyYVc0Z2RtRnVJRnB2Ym01bGRtVnNaQT09J1xuXG4gICAgICAgIC8vIG1vemlsbGEgaGFzIHRoaXMgbmF0aXZlXG4gICAgICAgIC8vIC0gYnV0IGJyZWFrcyBpbiAyLjAuMC4xMiFcbiAgICAgICAgLy9pZiAodHlwZW9mIHdpbmRvd1snYXRvYiddID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gICAgcmV0dXJuIGF0b2IoZGF0YSk7XG4gICAgICAgIC8vfVxuXG4gICAgICAgIHZhciBiNjQgPSBcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky89XCI7XG4gICAgICAgIHZhciBvMSxcbiAgICAgICAgICAgIG8yLFxuICAgICAgICAgICAgbzMsXG4gICAgICAgICAgICBoMSxcbiAgICAgICAgICAgIGgyLFxuICAgICAgICAgICAgaDMsXG4gICAgICAgICAgICBoNCxcbiAgICAgICAgICAgIGJpdHMsXG4gICAgICAgICAgICBpID0gMCxcbiAgICAgICAgICAgIGFjID0gMCxcbiAgICAgICAgICAgIGVuYyxcbiAgICAgICAgICAgIHRtcF9hcnIgPSBbXTtcblxuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YSA9IEhhc2hlclV0aWxzLnV0ZjhfZW5jb2RlKGRhdGEgKyAnJyk7XG5cbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgLy8gcGFjayB0aHJlZSBvY3RldHMgaW50byBmb3VyIGhleGV0c1xuICAgICAgICAgICAgbzEgPSBkYXRhLmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgICAgICAgIG8yID0gZGF0YS5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgICAgICBvMyA9IGRhdGEuY2hhckNvZGVBdChpKyspO1xuXG4gICAgICAgICAgICBiaXRzID0gbzEgPDwgMTYgfCBvMiA8PCA4IHwgbzM7XG5cbiAgICAgICAgICAgIGgxID0gYml0cyA+PiAxOCAmIDB4M2Y7XG4gICAgICAgICAgICBoMiA9IGJpdHMgPj4gMTIgJiAweDNmO1xuICAgICAgICAgICAgaDMgPSBiaXRzID4+IDYgJiAweDNmO1xuICAgICAgICAgICAgaDQgPSBiaXRzICYgMHgzZjtcblxuICAgICAgICAgICAgLy8gdXNlIGhleGV0cyB0byBpbmRleCBpbnRvIGI2NCwgYW5kIGFwcGVuZCByZXN1bHQgdG8gZW5jb2RlZCBzdHJpbmdcbiAgICAgICAgICAgIHRtcF9hcnJbYWMrK10gPSBiNjQuY2hhckF0KGgxKSArIGI2NC5jaGFyQXQoaDIpICsgYjY0LmNoYXJBdChoMykgKyBiNjQuY2hhckF0KGg0KTtcbiAgICAgICAgfSB3aGlsZSAoaSA8IGRhdGEubGVuZ3RoKTtcblxuICAgICAgICBlbmMgPSB0bXBfYXJyLmpvaW4oJycpO1xuXG4gICAgICAgIHN3aXRjaCAoZGF0YS5sZW5ndGggJSAzKSB7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgZW5jID0gZW5jLnNsaWNlKDAsIC0yKSArICc9PSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgZW5jID0gZW5jLnNsaWNlKDAsIC0xKSArICc9JztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbmM7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLnV0ZjhfZW5jb2RlID0gZnVuY3Rpb24gdXRmOF9lbmNvZGUoc3RyaW5nKSB7XG4gICAgICAgIC8vIGh0dHA6Ly9rZXZpbi52YW56b25uZXZlbGQubmV0XG4gICAgICAgIC8vICsgICBvcmlnaW5hbCBieTogV2VidG9vbGtpdC5pbmZvIChodHRwOi8vd3d3LndlYnRvb2xraXQuaW5mby8pXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogS2V2aW4gdmFuIFpvbm5ldmVsZCAoaHR0cDovL2tldmluLnZhbnpvbm5ldmVsZC5uZXQpXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogc293YmVycnlcbiAgICAgICAgLy8gKyAgICB0d2Vha2VkIGJ5OiBKYWNrXG4gICAgICAgIC8vICsgICBidWdmaXhlZCBieTogT25ubyBNYXJzbWFuXG4gICAgICAgIC8vICsgICBpbXByb3ZlZCBieTogWXZlcyBTdWNhZXRcbiAgICAgICAgLy8gKyAgIGJ1Z2ZpeGVkIGJ5OiBPbm5vIE1hcnNtYW5cbiAgICAgICAgLy8gKiAgICAgZXhhbXBsZSAxOiB1dGY4X2VuY29kZSgnS2V2aW4gdmFuIFpvbm5ldmVsZCcpO1xuICAgICAgICAvLyAqICAgICByZXR1cm5zIDE6ICdLZXZpbiB2YW4gWm9ubmV2ZWxkJ1xuXG4gICAgICAgIHN0cmluZyA9IChzdHJpbmcgKyAnJykucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLnJlcGxhY2UoL1xcci9nLCBcIlxcblwiKTtcblxuICAgICAgICB2YXIgdXRmdGV4dCA9IFwiXCI7XG4gICAgICAgIHZhciBzdGFydCwgZW5kO1xuICAgICAgICB2YXIgc3RyaW5nbDtcblxuICAgICAgICBzdGFydCA9IGVuZCA9IDA7XG4gICAgICAgIHN0cmluZ2wgPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgICBmb3IgKHZhciBuID0gMDsgbiA8IHN0cmluZ2w7IG4rKykge1xuICAgICAgICAgICAgdmFyIGMxID0gc3RyaW5nLmNoYXJDb2RlQXQobik7XG4gICAgICAgICAgICB2YXIgZW5jID0gbnVsbDtcblxuICAgICAgICAgICAgaWYgKGMxIDwgMTI4KSB7XG4gICAgICAgICAgICAgICAgZW5kKys7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGMxID4gMTI3ICYmIGMxIDwgMjA0OCkge1xuICAgICAgICAgICAgICAgIGVuYyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYzEgPj4gNiB8IDE5MikgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxICYgNjMgfCAxMjgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbmMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxID4+IDEyIHwgMjI0KSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYzEgPj4gNiAmIDYzIHwgMTI4KSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYzEgJiA2MyB8IDEyOCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZW5jICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoZW5kID4gc3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdXRmdGV4dCArPSBzdHJpbmcuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IGVuYztcbiAgICAgICAgICAgICAgICBzdGFydCA9IGVuZCA9IG4gKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVuZCA+IHN0YXJ0KSB7XG4gICAgICAgICAgICB1dGZ0ZXh0ICs9IHN0cmluZy5zdWJzdHJpbmcoc3RhcnQsIHN0cmluZy5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHV0ZnRleHQ7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogUGVyZm9ybSBhIHNpbXBsZSBzZWxmLXRlc3QgdG8gc2VlIGlmIHRoZSBWTSBpcyB3b3JraW5nXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5tZDVfdm1fdGVzdCA9IGZ1bmN0aW9uIG1kNV92bV90ZXN0KCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMuaGV4X21kNShcImFiY1wiKSA9PSBcIjkwMDE1MDk4M2NkMjRmYjBkNjk2M2Y3ZDI4ZTE3ZjcyXCI7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ2FsY3VsYXRlIHRoZSBNRDUgb2YgYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3JkcywgYW5kIGEgYml0IGxlbmd0aFxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuY29yZV9tZDUgPSBmdW5jdGlvbiBjb3JlX21kNSh4LCBsZW4pIHtcbiAgICAgICAgLyogYXBwZW5kIHBhZGRpbmcgKi9cbiAgICAgICAgeFtsZW4gPj4gNV0gfD0gMHg4MCA8PCBsZW4gJSAzMjtcbiAgICAgICAgeFsobGVuICsgNjQgPj4+IDkgPDwgNCkgKyAxNF0gPSBsZW47XG5cbiAgICAgICAgdmFyIGEgPSAxNzMyNTg0MTkzO1xuICAgICAgICB2YXIgYiA9IC0yNzE3MzM4Nzk7XG4gICAgICAgIHZhciBjID0gLTE3MzI1ODQxOTQ7XG4gICAgICAgIHZhciBkID0gMjcxNzMzODc4O1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkgKz0gMTYpIHtcbiAgICAgICAgICAgIHZhciBvbGRhID0gYTtcbiAgICAgICAgICAgIHZhciBvbGRiID0gYjtcbiAgICAgICAgICAgIHZhciBvbGRjID0gYztcbiAgICAgICAgICAgIHZhciBvbGRkID0gZDtcblxuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9mZihhLCBiLCBjLCBkLCB4W2kgKyAwXSwgNywgLTY4MDg3NjkzNik7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGQsIGEsIGIsIGMsIHhbaSArIDFdLCAxMiwgLTM4OTU2NDU4Nik7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGMsIGQsIGEsIGIsIHhbaSArIDJdLCAxNywgNjA2MTA1ODE5KTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZmYoYiwgYywgZCwgYSwgeFtpICsgM10sIDIyLCAtMTA0NDUyNTMzMCk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGEsIGIsIGMsIGQsIHhbaSArIDRdLCA3LCAtMTc2NDE4ODk3KTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZmYoZCwgYSwgYiwgYywgeFtpICsgNV0sIDEyLCAxMjAwMDgwNDI2KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZmYoYywgZCwgYSwgYiwgeFtpICsgNl0sIDE3LCAtMTQ3MzIzMTM0MSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGIsIGMsIGQsIGEsIHhbaSArIDddLCAyMiwgLTQ1NzA1OTgzKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZmYoYSwgYiwgYywgZCwgeFtpICsgOF0sIDcsIDE3NzAwMzU0MTYpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9mZihkLCBhLCBiLCBjLCB4W2kgKyA5XSwgMTIsIC0xOTU4NDE0NDE3KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZmYoYywgZCwgYSwgYiwgeFtpICsgMTBdLCAxNywgLTQyMDYzKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZmYoYiwgYywgZCwgYSwgeFtpICsgMTFdLCAyMiwgLTE5OTA0MDQxNjIpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9mZihhLCBiLCBjLCBkLCB4W2kgKyAxMl0sIDcsIDE4MDQ2MDM2ODIpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9mZihkLCBhLCBiLCBjLCB4W2kgKyAxM10sIDEyLCAtNDAzNDExMDEpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9mZihjLCBkLCBhLCBiLCB4W2kgKyAxNF0sIDE3LCAtMTUwMjAwMjI5MCk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2ZmKGIsIGMsIGQsIGEsIHhbaSArIDE1XSwgMjIsIDEyMzY1MzUzMjkpO1xuXG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2dnKGEsIGIsIGMsIGQsIHhbaSArIDFdLCA1LCAtMTY1Nzk2NTEwKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfZ2coZCwgYSwgYiwgYywgeFtpICsgNl0sIDksIC0xMDY5NTAxNjMyKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZ2coYywgZCwgYSwgYiwgeFtpICsgMTFdLCAxNCwgNjQzNzE3NzEzKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZ2coYiwgYywgZCwgYSwgeFtpICsgMF0sIDIwLCAtMzczODk3MzAyKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZ2coYSwgYiwgYywgZCwgeFtpICsgNV0sIDUsIC03MDE1NTg2OTEpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9nZyhkLCBhLCBiLCBjLCB4W2kgKyAxMF0sIDksIDM4MDE2MDgzKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZ2coYywgZCwgYSwgYiwgeFtpICsgMTVdLCAxNCwgLTY2MDQ3ODMzNSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2dnKGIsIGMsIGQsIGEsIHhbaSArIDRdLCAyMCwgLTQwNTUzNzg0OCk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2dnKGEsIGIsIGMsIGQsIHhbaSArIDldLCA1LCA1Njg0NDY0MzgpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9nZyhkLCBhLCBiLCBjLCB4W2kgKyAxNF0sIDksIC0xMDE5ODAzNjkwKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfZ2coYywgZCwgYSwgYiwgeFtpICsgM10sIDE0LCAtMTg3MzYzOTYxKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfZ2coYiwgYywgZCwgYSwgeFtpICsgOF0sIDIwLCAxMTYzNTMxNTAxKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfZ2coYSwgYiwgYywgZCwgeFtpICsgMTNdLCA1LCAtMTQ0NDY4MTQ2Nyk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2dnKGQsIGEsIGIsIGMsIHhbaSArIDJdLCA5LCAtNTE0MDM3ODQpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9nZyhjLCBkLCBhLCBiLCB4W2kgKyA3XSwgMTQsIDE3MzUzMjg0NzMpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9nZyhiLCBjLCBkLCBhLCB4W2kgKyAxMl0sIDIwLCAtMTkyNjYwNzczNCk7XG5cbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaGgoYSwgYiwgYywgZCwgeFtpICsgNV0sIDQsIC0zNzg1NTgpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9oaChkLCBhLCBiLCBjLCB4W2kgKyA4XSwgMTEsIC0yMDIyNTc0NDYzKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaGgoYywgZCwgYSwgYiwgeFtpICsgMTFdLCAxNiwgMTgzOTAzMDU2Mik7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2hoKGIsIGMsIGQsIGEsIHhbaSArIDE0XSwgMjMsIC0zNTMwOTU1Nik7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2hoKGEsIGIsIGMsIGQsIHhbaSArIDFdLCA0LCAtMTUzMDk5MjA2MCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2hoKGQsIGEsIGIsIGMsIHhbaSArIDRdLCAxMSwgMTI3Mjg5MzM1Myk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2hoKGMsIGQsIGEsIGIsIHhbaSArIDddLCAxNiwgLTE1NTQ5NzYzMik7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2hoKGIsIGMsIGQsIGEsIHhbaSArIDEwXSwgMjMsIC0xMDk0NzMwNjQwKTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaGgoYSwgYiwgYywgZCwgeFtpICsgMTNdLCA0LCA2ODEyNzkxNzQpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9oaChkLCBhLCBiLCBjLCB4W2kgKyAwXSwgMTEsIC0zNTg1MzcyMjIpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9oaChjLCBkLCBhLCBiLCB4W2kgKyAzXSwgMTYsIC03MjI1MjE5NzkpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9oaChiLCBjLCBkLCBhLCB4W2kgKyA2XSwgMjMsIDc2MDI5MTg5KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaGgoYSwgYiwgYywgZCwgeFtpICsgOV0sIDQsIC02NDAzNjQ0ODcpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9oaChkLCBhLCBiLCBjLCB4W2kgKyAxMl0sIDExLCAtNDIxODE1ODM1KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaGgoYywgZCwgYSwgYiwgeFtpICsgMTVdLCAxNiwgNTMwNzQyNTIwKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaGgoYiwgYywgZCwgYSwgeFtpICsgMl0sIDIzLCAtOTk1MzM4NjUxKTtcblxuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9paShhLCBiLCBjLCBkLCB4W2kgKyAwXSwgNiwgLTE5ODYzMDg0NCk7XG4gICAgICAgICAgICBkID0gSGFzaGVyVXRpbHMubWQ1X2lpKGQsIGEsIGIsIGMsIHhbaSArIDddLCAxMCwgMTEyNjg5MTQxNSk7XG4gICAgICAgICAgICBjID0gSGFzaGVyVXRpbHMubWQ1X2lpKGMsIGQsIGEsIGIsIHhbaSArIDE0XSwgMTUsIC0xNDE2MzU0OTA1KTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaWkoYiwgYywgZCwgYSwgeFtpICsgNV0sIDIxLCAtNTc0MzQwNTUpO1xuICAgICAgICAgICAgYSA9IEhhc2hlclV0aWxzLm1kNV9paShhLCBiLCBjLCBkLCB4W2kgKyAxMl0sIDYsIDE3MDA0ODU1NzEpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9paShkLCBhLCBiLCBjLCB4W2kgKyAzXSwgMTAsIC0xODk0OTg2NjA2KTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5tZDVfaWkoYywgZCwgYSwgYiwgeFtpICsgMTBdLCAxNSwgLTEwNTE1MjMpO1xuICAgICAgICAgICAgYiA9IEhhc2hlclV0aWxzLm1kNV9paShiLCBjLCBkLCBhLCB4W2kgKyAxXSwgMjEsIC0yMDU0OTIyNzk5KTtcbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5tZDVfaWkoYSwgYiwgYywgZCwgeFtpICsgOF0sIDYsIDE4NzMzMTMzNTkpO1xuICAgICAgICAgICAgZCA9IEhhc2hlclV0aWxzLm1kNV9paShkLCBhLCBiLCBjLCB4W2kgKyAxNV0sIDEwLCAtMzA2MTE3NDQpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9paShjLCBkLCBhLCBiLCB4W2kgKyA2XSwgMTUsIC0xNTYwMTk4MzgwKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5tZDVfaWkoYiwgYywgZCwgYSwgeFtpICsgMTNdLCAyMSwgMTMwOTE1MTY0OSk7XG4gICAgICAgICAgICBhID0gSGFzaGVyVXRpbHMubWQ1X2lpKGEsIGIsIGMsIGQsIHhbaSArIDRdLCA2LCAtMTQ1NTIzMDcwKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5tZDVfaWkoZCwgYSwgYiwgYywgeFtpICsgMTFdLCAxMCwgLTExMjAyMTAzNzkpO1xuICAgICAgICAgICAgYyA9IEhhc2hlclV0aWxzLm1kNV9paShjLCBkLCBhLCBiLCB4W2kgKyAyXSwgMTUsIDcxODc4NzI1OSk7XG4gICAgICAgICAgICBiID0gSGFzaGVyVXRpbHMubWQ1X2lpKGIsIGMsIGQsIGEsIHhbaSArIDldLCAyMSwgLTM0MzQ4NTU1MSk7XG5cbiAgICAgICAgICAgIGEgPSBIYXNoZXJVdGlscy5zYWZlX2FkZChhLCBvbGRhKTtcbiAgICAgICAgICAgIGIgPSBIYXNoZXJVdGlscy5zYWZlX2FkZChiLCBvbGRiKTtcbiAgICAgICAgICAgIGMgPSBIYXNoZXJVdGlscy5zYWZlX2FkZChjLCBvbGRjKTtcbiAgICAgICAgICAgIGQgPSBIYXNoZXJVdGlscy5zYWZlX2FkZChkLCBvbGRkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW2EsIGIsIGMsIGRdO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIFRoZXNlIGZ1bmN0aW9ucyBpbXBsZW1lbnQgdGhlIGZvdXIgYmFzaWMgb3BlcmF0aW9ucyB0aGUgYWxnb3JpdGhtIHVzZXMuXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5tZDVfY21uID0gZnVuY3Rpb24gbWQ1X2NtbihxLCBhLCBiLCB4LCBzLCB0KSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5zYWZlX2FkZChIYXNoZXJVdGlscy5iaXRfcm9sKEhhc2hlclV0aWxzLnNhZmVfYWRkKEhhc2hlclV0aWxzLnNhZmVfYWRkKGEsIHEpLCBIYXNoZXJVdGlscy5zYWZlX2FkZCh4LCB0KSksIHMpLCBiKTtcbiAgICB9O1xuXG4gICAgSGFzaGVyVXRpbHMubWQ1X2ZmID0gZnVuY3Rpb24gbWQ1X2ZmKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLm1kNV9jbW4oYiAmIGMgfCB+YiAmIGQsIGEsIGIsIHgsIHMsIHQpO1xuICAgIH07XG5cbiAgICBIYXNoZXJVdGlscy5tZDVfZ2cgPSBmdW5jdGlvbiBtZDVfZ2coYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICAgICAgICByZXR1cm4gSGFzaGVyVXRpbHMubWQ1X2NtbihiICYgZCB8IGMgJiB+ZCwgYSwgYiwgeCwgcywgdCk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLm1kNV9oaCA9IGZ1bmN0aW9uIG1kNV9oaChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5tZDVfY21uKGIgXiBjIF4gZCwgYSwgYiwgeCwgcywgdCk7XG4gICAgfTtcblxuICAgIEhhc2hlclV0aWxzLm1kNV9paSA9IGZ1bmN0aW9uIG1kNV9paShhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gICAgICAgIHJldHVybiBIYXNoZXJVdGlscy5tZDVfY21uKGMgXiAoYiB8IH5kKSwgYSwgYiwgeCwgcywgdCk7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ2FsY3VsYXRlIHRoZSBITUFDLU1ENSwgb2YgYSBrZXkgYW5kIHNvbWUgZGF0YVxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuY29yZV9obWFjX21kNSA9IGZ1bmN0aW9uIGNvcmVfaG1hY19tZDUoa2V5LCBkYXRhKSB7XG4gICAgICAgIHZhciBia2V5ID0gSGFzaGVyVXRpbHMuc3RyMmJpbmwoa2V5KTtcbiAgICAgICAgaWYgKGJrZXkubGVuZ3RoID4gMTYpIGJrZXkgPSBIYXNoZXJVdGlscy5jb3JlX21kNShia2V5LCBrZXkubGVuZ3RoICogSGFzaGVyVXRpbHMuY2hyc3opO1xuXG4gICAgICAgIHZhciBpcGFkID0gbmV3IEFycmF5KDE2KSxcbiAgICAgICAgICAgIG9wYWQgPSBuZXcgQXJyYXkoMTYpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgICAgICAgIGlwYWRbaV0gPSBia2V5W2ldIF4gMHgzNjM2MzYzNjtcbiAgICAgICAgICAgIG9wYWRbaV0gPSBia2V5W2ldIF4gMHg1QzVDNUM1QztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBoYXNoID0gSGFzaGVyVXRpbHMuY29yZV9tZDUoaXBhZC5jb25jYXQoSGFzaGVyVXRpbHMuc3RyMmJpbmwoZGF0YSkpLCA1MTIgKyBkYXRhLmxlbmd0aCAqIEhhc2hlclV0aWxzLmNocnN6KTtcbiAgICAgICAgcmV0dXJuIEhhc2hlclV0aWxzLmNvcmVfbWQ1KG9wYWQuY29uY2F0KGhhc2gpLCA1MTIgKyAxMjgpO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIEFkZCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zIGludGVybmFsbHlcbiAgICAgKiB0byB3b3JrIGFyb3VuZCBidWdzIGluIHNvbWUgSlMgaW50ZXJwcmV0ZXJzLlxuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuc2FmZV9hZGQgPSBmdW5jdGlvbiBzYWZlX2FkZCh4LCB5KSB7XG4gICAgICAgIHZhciBsc3cgPSAoeCAmIDB4RkZGRikgKyAoeSAmIDB4RkZGRik7XG4gICAgICAgIHZhciBtc3cgPSAoeCA+PiAxNikgKyAoeSA+PiAxNikgKyAobHN3ID4+IDE2KTtcbiAgICAgICAgcmV0dXJuIG1zdyA8PCAxNiB8IGxzdyAmIDB4RkZGRjtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBCaXR3aXNlIHJvdGF0ZSBhIDMyLWJpdCBudW1iZXIgdG8gdGhlIGxlZnQuXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5iaXRfcm9sID0gZnVuY3Rpb24gYml0X3JvbChudW0sIGNudCkge1xuICAgICAgICByZXR1cm4gbnVtIDw8IGNudCB8IG51bSA+Pj4gMzIgLSBjbnQ7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhIHN0cmluZyB0byBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzXG4gICAgICogSWYgSGFzaGVyVXRpbHMuY2hyc3ogaXMgQVNDSUksIGNoYXJhY3RlcnMgPjI1NSBoYXZlIHRoZWlyIGhpLWJ5dGUgc2lsZW50bHkgaWdub3JlZC5cbiAgICAgKi9cblxuICAgIEhhc2hlclV0aWxzLnN0cjJiaW5sID0gZnVuY3Rpb24gc3RyMmJpbmwoc3RyKSB7XG4gICAgICAgIHZhciBiaW4gPSBbXTtcbiAgICAgICAgdmFyIG1hc2sgPSAoMSA8PCBIYXNoZXJVdGlscy5jaHJzeikgLSAxO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGggKiBIYXNoZXJVdGlscy5jaHJzejsgaSArPSBIYXNoZXJVdGlscy5jaHJzeikgYmluW2kgPj4gNV0gfD0gKHN0ci5jaGFyQ29kZUF0KGkgLyBIYXNoZXJVdGlscy5jaHJzeikgJiBtYXNrKSA8PCBpICUgMzI7XG4gICAgICAgIHJldHVybiBiaW47XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzIHRvIGEgc3RyaW5nXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5iaW5sMnN0ciA9IGZ1bmN0aW9uIGJpbmwyc3RyKGJpbikge1xuICAgICAgICB2YXIgc3RyID0gXCJcIjtcbiAgICAgICAgdmFyIG1hc2sgPSAoMSA8PCBIYXNoZXJVdGlscy5jaHJzeikgLSAxO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbi5sZW5ndGggKiAzMjsgaSArPSBIYXNoZXJVdGlscy5jaHJzeikgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYmluW2kgPj4gNV0gPj4+IGkgJSAzMiAmIG1hc2spO1xuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgbGl0dGxlLWVuZGlhbiB3b3JkcyB0byBhIGhleCBzdHJpbmcuXG4gICAgICovXG5cbiAgICBIYXNoZXJVdGlscy5iaW5sMmhleCA9IGZ1bmN0aW9uIGJpbmwyaGV4KGJpbmFycmF5KSB7XG4gICAgICAgIHZhciBoZXhfdGFiID0gSGFzaGVyVXRpbHMuaGV4Y2FzZSA/IFwiMDEyMzQ1Njc4OUFCQ0RFRlwiIDogXCIwMTIzNDU2Nzg5YWJjZGVmXCI7XG4gICAgICAgIHZhciBzdHIgPSBcIlwiO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbmFycmF5Lmxlbmd0aCAqIDQ7IGkrKykge1xuICAgICAgICAgICAgc3RyICs9IGhleF90YWIuY2hhckF0KGJpbmFycmF5W2kgPj4gMl0gPj4gaSAlIDQgKiA4ICsgNCAmIDB4RikgKyBoZXhfdGFiLmNoYXJBdChiaW5hcnJheVtpID4+IDJdID4+IGkgJSA0ICogOCAmIDB4Rik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMgdG8gYSBiYXNlLTY0IHN0cmluZ1xuICAgICAqL1xuXG4gICAgSGFzaGVyVXRpbHMuYmlubDJiNjQgPSBmdW5jdGlvbiBiaW5sMmI2NChiaW5hcnJheSkge1xuICAgICAgICB2YXIgdGFiID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvXCI7XG4gICAgICAgIHZhciBzdHIgPSBcIlwiO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbmFycmF5Lmxlbmd0aCAqIDQ7IGkgKz0gMykge1xuICAgICAgICAgICAgdmFyIHRyaXBsZXQgPSAoYmluYXJyYXlbaSA+PiAyXSA+PiA4ICogKGkgJSA0KSAmIDB4RkYpIDw8IDE2IHwgKGJpbmFycmF5W2kgKyAxID4+IDJdID4+IDggKiAoKGkgKyAxKSAlIDQpICYgMHhGRikgPDwgOCB8IGJpbmFycmF5W2kgKyAyID4+IDJdID4+IDggKiAoKGkgKyAyKSAlIDQpICYgMHhGRjtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgNDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgKiA4ICsgaiAqIDYgPiBiaW5hcnJheS5sZW5ndGggKiAzMikgc3RyICs9IEhhc2hlclV0aWxzLmI2NHBhZDtlbHNlIHN0ciArPSB0YWIuY2hhckF0KHRyaXBsZXQgPj4gNiAqICgzIC0gaikgJiAweDNGKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH07XG5cbiAgICByZXR1cm4gSGFzaGVyVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBIYXNoZXJVdGlscztcbkhhc2hlclV0aWxzLmhleGNhc2UgPSAwOyAvKiBoZXggb3V0cHV0IGZvcm1hdC4gMCAtIGxvd2VyY2FzZTsgMSAtIHVwcGVyY2FzZSAgICAgICAgKi9cbkhhc2hlclV0aWxzLmI2NHBhZCA9IFwiXCI7IC8qIGJhc2UtNjQgcGFkIGNoYXJhY3Rlci4gXCI9XCIgZm9yIHN0cmljdCBSRkMgY29tcGxpYW5jZSAgICovXG5IYXNoZXJVdGlscy5jaHJzeiA9IDg7IC8qIGJpdHMgcGVyIGlucHV0IGNoYXJhY3Rlci4gOCAtIEFTQ0lJOyAxNiAtIFVuaWNvZGUgICAgICAqL1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbi8qKlxuICogVXRpbGl0YXJ5IGNsYXNzIGZvciBsYW5ndWFnZSBzcGVjaWZpYyBtZXRob2RzXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBMYW5nVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExhbmdVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIExhbmdVdGlscyk7XG4gICAgfVxuXG4gICAgTGFuZ1V0aWxzLmFycmF5V2l0aG91dCA9IGZ1bmN0aW9uIGFycmF5V2l0aG91dChhcnJheSwga2V5KSB7XG4gICAgICAgIGlmICghYXJyYXkubGVuZ3RoKSByZXR1cm4gYXJyYXk7XG4gICAgICAgIGlmIChrZXkgPj0gYXJyYXkubGVuZ3RoKSByZXR1cm4gYXJyYXk7XG4gICAgICAgIHZhciBuZXdBcnJheTtcbiAgICAgICAgaWYgKGtleSA9PSAwKSBuZXdBcnJheSA9IGFycmF5LnNsaWNlKDEpO2Vsc2UgaWYgKGtleSA9PSBhcnJheS5sZW5ndGggLSAxKSBuZXdBcnJheSA9IGFycmF5LnNsaWNlKDAsIC0xKTtlbHNlIG5ld0FycmF5ID0gYXJyYXkuc2xpY2UoMCwga2V5KS5jb25jYXQoYXJyYXkuc2xpY2Uoa2V5ICsgMSkpO1xuICAgICAgICByZXR1cm4gbmV3QXJyYXk7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5vYmplY3RNZXJnZSA9IGZ1bmN0aW9uIG9iamVjdE1lcmdlKG9iajEsIG9iajIpIHtcbiAgICAgICAgcmV0dXJuIF9leHRlbmRzKHt9LCBvYmoxLCBvYmoyKTtcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLnBhcnNlVXJsID0gZnVuY3Rpb24gcGFyc2VVcmwoZGF0YSkge1xuICAgICAgICB2YXIgbWF0Y2hlcyA9IFtdO1xuICAgICAgICAvL3ZhciBlPS8oKGh0dHB8ZnRwKTpcXC8pP1xcLz8oW146XFwvXFxzXSspKChcXC9cXHcrKSpcXC8pKFtcXHdcXC1cXC5dK1xcLlteIz9cXHNdKykoI1tcXHdcXC1dKyk/LztcbiAgICAgICAgdmFyIGRldGVjdCA9IC8ocHlkaW86XFwvKT9cXC8/KFteOlxcL1xcc10rKSgoXFwvXFx3KykqXFwvKSguKikoI1tcXHdcXC1dKyk/L2c7XG4gICAgICAgIHZhciByZXN1bHRzID0gZGF0YS5tYXRjaChkZXRlY3QpO1xuICAgICAgICBpZiAocmVzdWx0cyAmJiByZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGUgPSAvXigocHlkaW8pOlxcLyk/XFwvPyhbXjpcXC9cXHNdKykoKFxcL1xcdyspKlxcLykoLiopKCNbXFx3XFwtXSspPyQvO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN1bHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdHNbaV0ubWF0Y2goZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKHsgdXJsOiBSZWdFeHBbJyQmJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm90b2NvbDogUmVnRXhwLiQyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogUmVnRXhwLiQzLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogUmVnRXhwLiQ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZTogUmVnRXhwLiQ2LFxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzaDogUmVnRXhwLiQ3IH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWF0Y2hlcztcbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLmNvbXB1dGVTdHJpbmdTbHVnID0gZnVuY3Rpb24gY29tcHV0ZVN0cmluZ1NsdWcodmFsdWUpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IExhbmdVdGlscy5zbHVnVGFibGUubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHZhbHVlID0gdmFsdWUucmVwbGFjZShMYW5nVXRpbHMuc2x1Z1RhYmxlW2ldLnJlLCBMYW5nVXRpbHMuc2x1Z1RhYmxlW2ldLmNoKTtcblxuICAgICAgICAvLyAxKSBtZXQgZW4gYmFzIGRlIGNhc3NlXG4gICAgICAgIC8vIDIpIHJlbXBsYWNlIGxlcyBlc3BhY2UgcGFyIGRlcyB0aXJldHNcbiAgICAgICAgLy8gMykgZW5sZXZlIHRvdXQgbGVzIGNhcmF0w6hyZXMgbm9uIGFscGhhbnVtZXJpcXVlc1xuICAgICAgICAvLyA0KSBlbmzDqHZlIGxlcyBkb3VibGVzIHRpcmV0c1xuICAgICAgICByZXR1cm4gdmFsdWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2csICctJykucmVwbGFjZSgvW15hLXowLTktXS9nLCAnJykucmVwbGFjZSgvXFwtezIsfS9nLCAnLScpO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMuZm9yY2VKU09OQXJyYXlUb09iamVjdCA9IGZ1bmN0aW9uIGZvcmNlSlNPTkFycmF5VG9PYmplY3QoY29udGFpbmVyLCB2YWx1ZSkge1xuICAgICAgICBpZiAoY29udGFpbmVyW3ZhbHVlXSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICAvLyBDbG9uZVxuICAgICAgICAgICAgdmFyIGNvcHkgPSBjb250YWluZXJbdmFsdWVdLnNsaWNlKDApO1xuICAgICAgICAgICAgY29udGFpbmVyW3ZhbHVlXSA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3B5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyW3ZhbHVlXVtpXSA9IGNvcHlbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgTGFuZ1V0aWxzLmRlZXBDb3B5ID0gZnVuY3Rpb24gZGVlcENvcHkoc291cmNlKSB7XG4gICAgICAgIHJldHVybiBMYW5nVXRpbHMubWVyZ2VPYmplY3RzUmVjdXJzaXZlKHt9LCBzb3VyY2UpO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMuc2ltcGxlQ29weSA9IGZ1bmN0aW9uIHNpbXBsZUNvcHkoc291cmNlKSB7XG4gICAgICAgIHZhciBjb3B5ID0ge307XG4gICAgICAgIGZvciAodmFyIHByb3BlcnR5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgICAgICBjb3B5W3Byb3BlcnR5XSA9IHNvdXJjZVtwcm9wZXJ0eV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy5tZXJnZU9iamVjdHNSZWN1cnNpdmUgPSBmdW5jdGlvbiBtZXJnZU9iamVjdHNSZWN1cnNpdmUoc291cmNlLCBkZXN0aW5hdGlvbikge1xuICAgICAgICB2YXIgbmV3T2JqZWN0ID0ge30sXG4gICAgICAgICAgICBwcm9wZXJ0eTtcbiAgICAgICAgZm9yIChwcm9wZXJ0eSBpbiBzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgLy9pZiAoc291cmNlW3Byb3BlcnR5XSA9PT0gbnVsbCkgY29udGludWU7XG4gICAgICAgICAgICAgICAgaWYgKGRlc3RpbmF0aW9uLmhhc093blByb3BlcnR5KHByb3BlcnR5KSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlW3Byb3BlcnR5XSBpbnN0YW5jZW9mIE9iamVjdCAmJiBkZXN0aW5hdGlvbiBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IExhbmdVdGlscy5tZXJnZU9iamVjdHNSZWN1cnNpdmUoc291cmNlW3Byb3BlcnR5XSwgZGVzdGluYXRpb25bcHJvcGVydHldKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBkZXN0aW5hdGlvbltwcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlW3Byb3BlcnR5XSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IExhbmdVdGlscy5tZXJnZU9iamVjdHNSZWN1cnNpdmUoc291cmNlW3Byb3BlcnR5XSwge30pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IHNvdXJjZVtwcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChwcm9wZXJ0eSBpbiBkZXN0aW5hdGlvbikge1xuICAgICAgICAgICAgaWYgKGRlc3RpbmF0aW9uLmhhc093blByb3BlcnR5KHByb3BlcnR5KSAmJiAhbmV3T2JqZWN0Lmhhc093blByb3BlcnR5KHByb3BlcnR5KSAvKiYmIGRlc3RpbmF0aW9uW3Byb3BlcnR5XSAhPT0gbnVsbCovKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZXN0aW5hdGlvbltwcm9wZXJ0eV0gaW5zdGFuY2VvZiBPYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld09iamVjdFtwcm9wZXJ0eV0gPSBMYW5nVXRpbHMubWVyZ2VPYmplY3RzUmVjdXJzaXZlKGRlc3RpbmF0aW9uW3Byb3BlcnR5XSwge30pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3T2JqZWN0W3Byb3BlcnR5XSA9IGRlc3RpbmF0aW9uW3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3T2JqZWN0O1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMub2JqZWN0VmFsdWVzID0gZnVuY3Rpb24gb2JqZWN0VmFsdWVzKG9iamVjdCkge1xuICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiBvYmplY3QpIGlmIChvYmplY3QuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2gob2JqZWN0W3Byb3BlcnR5XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfTtcblxuICAgIExhbmdVdGlscy50cmltTGVmdCA9IGZ1bmN0aW9uIHRyaW1MZWZ0KHN0cmluZywgY2hhcmxpc3QpIHtcbiAgICAgICAgaWYgKGNoYXJsaXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNoYXJsaXN0ID0gXCJcXHNcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UobmV3IFJlZ0V4cChcIl5bXCIgKyBjaGFybGlzdCArIFwiXStcIiksIFwiXCIpO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMudHJpbVJpZ2h0ID0gZnVuY3Rpb24gdHJpbVJpZ2h0KHN0cmluZywgY2hhcmxpc3QpIHtcbiAgICAgICAgaWYgKGNoYXJsaXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNoYXJsaXN0ID0gXCJcXHNcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UobmV3IFJlZ0V4cChcIltcIiArIGNoYXJsaXN0ICsgXCJdKyRcIiksIFwiXCIpO1xuICAgIH07XG5cbiAgICBMYW5nVXRpbHMudHJpbSA9IGZ1bmN0aW9uIHRyaW0oc3RyaW5nLCBjaGFybGlzdCkge1xuICAgICAgICByZXR1cm4gTGFuZ1V0aWxzLnRyaW1MZWZ0KExhbmdVdGlscy50cmltUmlnaHQoc3RyaW5nLCBjaGFybGlzdCksIGNoYXJsaXN0KTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIExhbmdVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IExhbmdVdGlscztcblxuTGFuZ1V0aWxzLnNsdWdUYWJsZSA9IFt7IHJlOiAvW1xceEMwLVxceEM2XS9nLCBjaDogJ0EnIH0sIHsgcmU6IC9bXFx4RTAtXFx4RTZdL2csIGNoOiAnYScgfSwgeyByZTogL1tcXHhDOC1cXHhDQl0vZywgY2g6ICdFJyB9LCB7IHJlOiAvW1xceEU4LVxceEVCXS9nLCBjaDogJ2UnIH0sIHsgcmU6IC9bXFx4Q0MtXFx4Q0ZdL2csIGNoOiAnSScgfSwgeyByZTogL1tcXHhFQy1cXHhFRl0vZywgY2g6ICdpJyB9LCB7IHJlOiAvW1xceEQyLVxceEQ2XS9nLCBjaDogJ08nIH0sIHsgcmU6IC9bXFx4RjItXFx4RjZdL2csIGNoOiAnbycgfSwgeyByZTogL1tcXHhEOS1cXHhEQ10vZywgY2g6ICdVJyB9LCB7IHJlOiAvW1xceEY5LVxceEZDXS9nLCBjaDogJ3UnIH0sIHsgcmU6IC9bXFx4QzctXFx4RTddL2csIGNoOiAnYycgfSwgeyByZTogL1tcXHhEMV0vZywgY2g6ICdOJyB9LCB7IHJlOiAvW1xceEYxXS9nLCBjaDogJ24nIH1dO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20vPi5cbiAqXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9odHRwUmVzb3VyY2VzTWFuYWdlciA9IHJlcXVpcmUoJy4uL2h0dHAvUmVzb3VyY2VzTWFuYWdlcicpO1xuXG52YXIgX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2h0dHBSZXNvdXJjZXNNYW5hZ2VyKTtcblxuLyoqXG4gKlxuICogVXRpbHMgdG8gY29tcHV0ZSBwYXNzd29yZCBzdHJlbmd0aFxuICpcbiAqL1xuXG52YXIgUGFzc1V0aWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQYXNzVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBQYXNzVXRpbHMpO1xuICAgIH1cblxuICAgIFBhc3NVdGlscy5nZXRTdGF0ZSA9IGZ1bmN0aW9uIGdldFN0YXRlKCkge1xuICAgICAgICB2YXIgcGFzc1ZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAwIHx8IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gJycgOiBhcmd1bWVudHNbMF07XG4gICAgICAgIHZhciBjb25maXJtVmFsdWUgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyAnJyA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgdmFyIGNydFN0YXRlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8geyB2YWxpZDogZmFsc2UgfSA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIG9uQ2hhbmdlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAzIHx8IGFyZ3VtZW50c1szXSA9PT0gdW5kZWZpbmVkID8gZnVuY3Rpb24gKHN0YXR1cykge30gOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdmFyIHN0YXRlID0ge1xuICAgICAgICAgICAgdmFsaWQ6IHRydWUsXG4gICAgICAgICAgICBwYXNzRXJyb3JUZXh0OiBudWxsLFxuICAgICAgICAgICAgcGFzc0hpbnRUZXh0OiBudWxsLFxuICAgICAgICAgICAgY29uZmlybUVycm9yVGV4dDogbnVsbFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIXBhc3NWYWx1ZSAmJiAhY29uZmlybVZhbHVlKSB7XG4gICAgICAgICAgICBzdGF0ZS52YWxpZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUGFzc1V0aWxzLmNoZWNrUGFzc3dvcmRTdHJlbmd0aChwYXNzVmFsdWUsIGZ1bmN0aW9uICh2YWxpZCwgbWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIHN0YXRlLnZhbGlkID0gdmFsaWQ7XG4gICAgICAgICAgICAgICAgaWYgKCF2YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZS5wYXNzRXJyb3JUZXh0ID0gbWVzc2FnZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzdGF0ZS5wYXNzSGludFRleHQgPSBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFjb25maXJtVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZS52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHN0YXRlLmNvbmZpcm1FcnJvclRleHQgPSBnbG9iYWwucHlkaW8uTWVzc2FnZUhhc2hbNjIxXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29uZmlybVZhbHVlICE9PSBwYXNzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZS52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHN0YXRlLmNvbmZpcm1FcnJvclRleHQgPSBnbG9iYWwucHlkaW8uTWVzc2FnZUhhc2hbMjM4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoY3J0U3RhdGUudmFsaWQgIT09IHN0YXRlLnZhbGlkKSB7XG4gICAgICAgICAgICBvbkNoYW5nZShzdGF0ZS52YWxpZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH07XG5cbiAgICBQYXNzVXRpbHMuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIGdldE9wdGlvbnMoKSB7XG4gICAgICAgIGlmIChQYXNzVXRpbHMuT3B0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIFBhc3NVdGlscy5PcHRpb25zO1xuICAgICAgICB9XG4gICAgICAgIFBhc3NVdGlscy5PcHRpb25zID0ge1xuICAgICAgICAgICAgcHlkaW9NZXNzYWdlczogWzM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCAzODQsIDM4NV0sXG4gICAgICAgICAgICBtZXNzYWdlczogW1wiVW5zYWZlIHBhc3N3b3JkIHdvcmQhXCIsIFwiVG9vIHNob3J0XCIsIFwiVmVyeSB3ZWFrXCIsIFwiV2Vha1wiLCBcIk1lZGl1bVwiLCBcIlN0cm9uZ1wiLCBcIlZlcnkgc3Ryb25nXCJdLFxuICAgICAgICAgICAgY29sb3JzOiBbXCIjZjAwXCIsIFwiIzk5OVwiLCBcIiNDNzBGMEZcIiwgXCIjQzcwRjBGXCIsIFwiI0ZGODQzMlwiLCBcIiMyNzlEMDBcIiwgXCIjMjc5RDAwXCJdLFxuICAgICAgICAgICAgc2NvcmVzOiBbMTAsIDE1LCAzMCwgNDBdLFxuICAgICAgICAgICAgY29tbW9uOiBbXCJwYXNzd29yZFwiLCBcIjEyMzQ1NlwiLCBcIjEyM1wiLCBcIjEyMzRcIiwgXCJteXBhc3NcIiwgXCJwYXNzXCIsIFwibGV0bWVpblwiLCBcInF3ZXJ0eVwiLCBcIm1vbmtleVwiLCBcImFzZGZnaFwiLCBcInp4Y3ZiblwiLCBcInBhc3NcIl0sXG4gICAgICAgICAgICBtaW5jaGFyOiA4XG4gICAgICAgIH07XG4gICAgICAgIHZhciBweWRpb01pbiA9IHBhcnNlSW50KGdsb2JhbC5weWRpby5nZXRQbHVnaW5Db25maWdzKFwiY29yZS5hdXRoXCIpLmdldChcIlBBU1NXT1JEX01JTkxFTkdUSFwiKSk7XG4gICAgICAgIGlmIChweWRpb01pbikge1xuICAgICAgICAgICAgUGFzc1V0aWxzLk9wdGlvbnMubWluY2hhciA9IHB5ZGlvTWluO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQYXNzVXRpbHMuT3B0aW9ucztcbiAgICB9O1xuXG4gICAgUGFzc1V0aWxzLmNoZWNrUGFzc3dvcmRTdHJlbmd0aCA9IGZ1bmN0aW9uIGNoZWNrUGFzc3dvcmRTdHJlbmd0aCh2YWx1ZSwgY2FsbGJhY2spIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBQYXNzUG9saWN5TGliID0gX2h0dHBSZXNvdXJjZXNNYW5hZ2VyMlsnZGVmYXVsdCddLnJlcXVpcmVMaWIoXCJQYXNzd29yZFBvbGljeVwiLCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAoUGFzc1BvbGljeUxpYiAmJiBQYXNzUG9saWN5TGliLkNoZWNrZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgQ2hlY2tlciA9IFBhc3NQb2xpY3lMaWIuQ2hlY2tlcjtcblxuICAgICAgICAgICAgICAgIGlmIChDaGVja2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIENoZWNrZXIuY2hlY2tQYXNzd29yZFN0cmVuZ3RoKHZhbHVlLCBjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIC8vIFVwZGF0ZSB3aXRoIFB5ZGlvIG9wdGlvbnNcbiAgICAgICAgdmFyIG9wdGlvbnMgPSBQYXNzVXRpbHMuZ2V0T3B0aW9ucygpO1xuICAgICAgICBpZiAob3B0aW9ucy5taW5jaGFyICYmIHZhbHVlLmxlbmd0aCA8IG9wdGlvbnMubWluY2hhcikge1xuICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UsIGdsb2JhbC5weWRpby5NZXNzYWdlSGFzaFszODBdKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd3JhcHBlZENhbGxiYWNrID0gZnVuY3Rpb24gd3JhcHBlZENhbGxiYWNrKG1zZ0lkLCBwZXJjZW50KSB7XG4gICAgICAgICAgICB2YXIgcyA9IG9wdGlvbnMubWVzc2FnZXNbbXNnSWRdO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBzID0gZ2xvYmFsLnB5ZGlvLk1lc3NhZ2VIYXNoW29wdGlvbnMucHlkaW9NZXNzYWdlc1ttc2dJZF1dO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgIGNhbGxiYWNrKHBlcmNlbnQgPiAxLCBzKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHN0cmVuZ3RoID0gUGFzc1V0aWxzLmdldFBhc3N3b3JkU2NvcmUodmFsdWUsIG9wdGlvbnMubWluY2hhcik7XG4gICAgICAgIGlmIChzdHJlbmd0aCA9PSAtMjAwKSB7XG4gICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soMCwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoc3RyZW5ndGggPCAwICYmIHN0cmVuZ3RoID4gLTE5OSkge1xuICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjaygxLCAxMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzdHJlbmd0aCA8PSBvcHRpb25zLnNjb3Jlc1swXSkge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soMiwgMTApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdHJlbmd0aCA+IG9wdGlvbnMuc2NvcmVzWzBdICYmIHN0cmVuZ3RoIDw9IG9wdGlvbnMuc2NvcmVzWzFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVkQ2FsbGJhY2soMywgMjUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmVuZ3RoID4gb3B0aW9ucy5zY29yZXNbMV0gJiYgc3RyZW5ndGggPD0gb3B0aW9ucy5zY29yZXNbMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjayg0LCA1NSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RyZW5ndGggPiBvcHRpb25zLnNjb3Jlc1syXSAmJiBzdHJlbmd0aCA8PSBvcHRpb25zLnNjb3Jlc1szXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd3JhcHBlZENhbGxiYWNrKDUsIDgwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZWRDYWxsYmFjayg2LCA5OCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgUGFzc1V0aWxzLmdldFBhc3N3b3JkU2NvcmUgPSBmdW5jdGlvbiBnZXRQYXNzd29yZFNjb3JlKHZhbHVlLCBtaW5jaGFyKSB7XG5cbiAgICAgICAgdmFyIHN0cmVuZ3RoID0gMDtcbiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA8IG1pbmNoYXIpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggLSAxMDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID49IG1pbmNoYXIgJiYgdmFsdWUubGVuZ3RoIDw9IG1pbmNoYXIgKyAyKSB7XG4gICAgICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDY7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPj0gbWluY2hhciArIDMgJiYgdmFsdWUubGVuZ3RoIDw9IG1pbmNoYXIgKyA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAxMjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID49IG1pbmNoYXIgKyA1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMTg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLm1hdGNoKC9bYS16XS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goL1tBLVpdLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA1O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvXFxkKy8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLyguKlswLTldLipbMC05XS4qWzAtOV0pLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA3O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvLlshLEAjJCVeJio/X35dLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyA1O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvKC4qWyEsQCMkJV4mKj9ffl0uKlshLEAjJCVeJio/X35dKS8pKSB7XG4gICAgICAgICAgICBzdHJlbmd0aCA9IHN0cmVuZ3RoICsgNztcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUubWF0Y2goLyhbYS16XS4qW0EtWl0pfChbQS1aXS4qW2Etel0pLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAyO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvKFthLXpBLVpdKS8pICYmIHZhbHVlLm1hdGNoKC8oWzAtOV0pLykpIHtcbiAgICAgICAgICAgIHN0cmVuZ3RoID0gc3RyZW5ndGggKyAzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZS5tYXRjaCgvKFthLXpBLVowLTldLipbISxAIyQlXiYqP19+XSl8KFshLEAjJCVeJio/X35dLipbYS16QS1aMC05XSkvKSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSBzdHJlbmd0aCArIDM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbW1vbiA9IFtcInBhc3N3b3JkXCIsIFwiMTIzNDU2XCIsIFwiMTIzXCIsIFwiMTIzNFwiLCBcIm15cGFzc1wiLCBcInBhc3NcIiwgXCJsZXRtZWluXCIsIFwicXdlcnR5XCIsIFwibW9ua2V5XCIsIFwiYXNkZmdoXCIsIFwienhjdmJuXCIsIFwicGFzc1wiXTtcbiAgICAgICAgaWYgKGNvbW1vbi5pbmRleE9mKHZhbHVlLnRvTG93ZXJDYXNlKCkpICE9PSAtMSkge1xuICAgICAgICAgICAgc3RyZW5ndGggPSAtMjAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJlbmd0aDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFBhc3NVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFBhc3NVdGlscztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgbWFuaXB1bGF0aW5nIGZpbGUvZm9sZGVycyBwYXRoZXNcbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBQYXRoVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBhdGhVdGlscygpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFBhdGhVdGlscyk7XG4gICAgfVxuXG4gICAgUGF0aFV0aWxzLmdldEJhc2VuYW1lID0gZnVuY3Rpb24gZ2V0QmFzZW5hbWUoZmlsZU5hbWUpIHtcbiAgICAgICAgaWYgKGZpbGVOYW1lID09IG51bGwpIHJldHVybiBudWxsO1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gXCIvXCI7XG4gICAgICAgIGlmIChmaWxlTmFtZS5pbmRleE9mKFwiXFxcXFwiKSAhPSAtMSkgc2VwYXJhdG9yID0gXCJcXFxcXCI7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZS5zdWJzdHIoZmlsZU5hbWUubGFzdEluZGV4T2Yoc2VwYXJhdG9yKSArIDEsIGZpbGVOYW1lLmxlbmd0aCk7XG4gICAgfTtcblxuICAgIFBhdGhVdGlscy5nZXREaXJuYW1lID0gZnVuY3Rpb24gZ2V0RGlybmFtZShmaWxlTmFtZSkge1xuICAgICAgICByZXR1cm4gZmlsZU5hbWUuc3Vic3RyKDAsIGZpbGVOYW1lLmxhc3RJbmRleE9mKFwiL1wiKSk7XG4gICAgfTtcblxuICAgIFBhdGhVdGlscy5nZXRBanhwTWltZVR5cGUgPSBmdW5jdGlvbiBnZXRBanhwTWltZVR5cGUoaXRlbSkge1xuICAgICAgICBpZiAoIWl0ZW0pIHJldHVybiBcIlwiO1xuICAgICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0KCdhanhwX21pbWUnKSB8fCBQYXRoVXRpbHMuZ2V0RmlsZUV4dGVuc2lvbihpdGVtLmdldCgnZmlsZW5hbWUnKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXRlbS5nZXRNZXRhZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0TWV0YWRhdGEoKS5nZXQoJ2FqeHBfbWltZScpIHx8IFBhdGhVdGlscy5nZXRGaWxlRXh0ZW5zaW9uKGl0ZW0uZ2V0UGF0aCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtLmdldEF0dHJpYnV0ZSgnYWp4cF9taW1lJykgfHwgUGF0aFV0aWxzLmdldEZpbGVFeHRlbnNpb24oaXRlbS5nZXRBdHRyaWJ1dGUoJ2ZpbGVuYW1lJykpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIFBhdGhVdGlscy5nZXRGaWxlRXh0ZW5zaW9uID0gZnVuY3Rpb24gZ2V0RmlsZUV4dGVuc2lvbihmaWxlTmFtZSkge1xuICAgICAgICBpZiAoIWZpbGVOYW1lIHx8IGZpbGVOYW1lID09IFwiXCIpIHJldHVybiBcIlwiO1xuICAgICAgICB2YXIgc3BsaXQgPSBQYXRoVXRpbHMuZ2V0QmFzZW5hbWUoZmlsZU5hbWUpLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmIChzcGxpdC5sZW5ndGggPiAxKSByZXR1cm4gc3BsaXRbc3BsaXQubGVuZ3RoIC0gMV0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH07XG5cbiAgICBQYXRoVXRpbHMucm91bmRGaWxlU2l6ZSA9IGZ1bmN0aW9uIHJvdW5kRmlsZVNpemUoZmlsZXNpemUpIHtcbiAgICAgICAgdmFyIHNpemVfdW5pdCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IFwib1wiIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIGlmIChmaWxlc2l6ZSA+PSAxMDczNzQxODI0KSB7XG4gICAgICAgICAgICBmaWxlc2l6ZSA9IE1hdGgucm91bmQoZmlsZXNpemUgLyAxMDczNzQxODI0ICogMTAwKSAvIDEwMCArIFwiIEdcIiArIHNpemVfdW5pdDtcbiAgICAgICAgfSBlbHNlIGlmIChmaWxlc2l6ZSA+PSAxMDQ4NTc2KSB7XG4gICAgICAgICAgICBmaWxlc2l6ZSA9IE1hdGgucm91bmQoZmlsZXNpemUgLyAxMDQ4NTc2ICogMTAwKSAvIDEwMCArIFwiIE1cIiArIHNpemVfdW5pdDtcbiAgICAgICAgfSBlbHNlIGlmIChmaWxlc2l6ZSA+PSAxMDI0KSB7XG4gICAgICAgICAgICBmaWxlc2l6ZSA9IE1hdGgucm91bmQoZmlsZXNpemUgLyAxMDI0ICogMTAwKSAvIDEwMCArIFwiIEtcIiArIHNpemVfdW5pdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVzaXplID0gZmlsZXNpemUgKyBcIiBcIiArIHNpemVfdW5pdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmlsZXNpemU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGRhdGVPYmplY3QgRGF0ZVxuICAgICAqIEBwYXJhbSBmb3JtYXQgU3RyaW5nXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG5cbiAgICBQYXRoVXRpbHMuZm9ybWF0TW9kaWZEYXRlID0gZnVuY3Rpb24gZm9ybWF0TW9kaWZEYXRlKGRhdGVPYmplY3QsIGZvcm1hdCkge1xuICAgICAgICBpZiAoIWZvcm1hdCAmJiB3aW5kb3cgJiYgd2luZG93LnB5ZGlvICYmIHB5ZGlvLk1lc3NhZ2VIYXNoKSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBweWRpby5NZXNzYWdlSGFzaFtcImRhdGVfZm9ybWF0XCJdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZm9ybWF0KSByZXR1cm4gJ25vIGZvcm1hdCc7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiZFwiLCBkYXRlT2JqZWN0LmdldERhdGUoKSA8IDEwID8gJzAnICsgZGF0ZU9iamVjdC5nZXREYXRlKCkgOiBkYXRlT2JqZWN0LmdldERhdGUoKSk7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiRFwiLCBkYXRlT2JqZWN0LmdldERheSgpKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJZXCIsIGRhdGVPYmplY3QuZ2V0RnVsbFllYXIoKSk7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwieVwiLCBkYXRlT2JqZWN0LmdldFllYXIoKSk7XG4gICAgICAgIHZhciBtb250aCA9IGRhdGVPYmplY3QuZ2V0TW9udGgoKSArIDE7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwibVwiLCBtb250aCA8IDEwID8gJzAnICsgbW9udGggOiBtb250aCk7XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFwiSFwiLCAoZGF0ZU9iamVjdC5nZXRIb3VycygpIDwgMTAgPyAnMCcgOiAnJykgKyBkYXRlT2JqZWN0LmdldEhvdXJzKCkpO1xuICAgICAgICAvLyBTdXBwb3J0IDEyIGhvdXIgZm9ybWF0IGNvbXBhdGliaWxpdHlcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJoXCIsIGRhdGVPYmplY3QuZ2V0SG91cnMoKSAlIDEyIHx8IDEyKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJwXCIsIGRhdGVPYmplY3QuZ2V0SG91cnMoKSA8IDEyID8gXCJhbVwiIDogXCJwbVwiKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJQXCIsIGRhdGVPYmplY3QuZ2V0SG91cnMoKSA8IDEyID8gXCJBTVwiIDogXCJQTVwiKTtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoXCJpXCIsIChkYXRlT2JqZWN0LmdldE1pbnV0ZXMoKSA8IDEwID8gJzAnIDogJycpICsgZGF0ZU9iamVjdC5nZXRNaW51dGVzKCkpO1xuICAgICAgICBmb3JtYXQgPSBmb3JtYXQucmVwbGFjZShcInNcIiwgKGRhdGVPYmplY3QuZ2V0U2Vjb25kcygpIDwgMTAgPyAnMCcgOiAnJykgKyBkYXRlT2JqZWN0LmdldFNlY29uZHMoKSk7XG4gICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfTtcblxuICAgIHJldHVybiBQYXRoVXRpbHM7XG59KSgpO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IFBhdGhVdGlscztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1tcImRlZmF1bHRcIl07XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cblwidXNlIHN0cmljdFwiO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgUGVyaW9kaWNhbEV4ZWN1dGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBQZXJpb2RpY2FsRXhlY3V0ZXIoY2FsbGJhY2ssIGZyZXF1ZW5jeSkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUGVyaW9kaWNhbEV4ZWN1dGVyKTtcblxuICAgICAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgIHRoaXMuZnJlcXVlbmN5ID0gZnJlcXVlbmN5O1xuICAgICAgICB0aGlzLmN1cnJlbnRseUV4ZWN1dGluZyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMucmVnaXN0ZXJDYWxsYmFjaygpO1xuICAgIH1cblxuICAgIFBlcmlvZGljYWxFeGVjdXRlci5wcm90b3R5cGUucmVnaXN0ZXJDYWxsYmFjayA9IGZ1bmN0aW9uIHJlZ2lzdGVyQ2FsbGJhY2soKSB7XG4gICAgICAgIHRoaXMudGltZXIgPSBzZXRJbnRlcnZhbCh0aGlzLm9uVGltZXJFdmVudC5iaW5kKHRoaXMpLCB0aGlzLmZyZXF1ZW5jeSAqIDEwMDApO1xuICAgIH07XG5cbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbiBleGVjdXRlKCkge1xuICAgICAgICB0aGlzLmNhbGxiYWNrKHRoaXMpO1xuICAgIH07XG5cbiAgICBQZXJpb2RpY2FsRXhlY3V0ZXIucHJvdG90eXBlLnN0b3AgPSBmdW5jdGlvbiBzdG9wKCkge1xuICAgICAgICBpZiAoIXRoaXMudGltZXIpIHJldHVybjtcbiAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnRpbWVyKTtcbiAgICAgICAgdGhpcy50aW1lciA9IG51bGw7XG4gICAgfTtcblxuICAgIFBlcmlvZGljYWxFeGVjdXRlci5wcm90b3R5cGUub25UaW1lckV2ZW50ID0gZnVuY3Rpb24gb25UaW1lckV2ZW50KCkge1xuICAgICAgICBpZiAoIXRoaXMuY3VycmVudGx5RXhlY3V0aW5nKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRseUV4ZWN1dGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gUGVyaW9kaWNhbEV4ZWN1dGVyO1xufSkoKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBQZXJpb2RpY2FsRXhlY3V0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuIiwiLypcbiAqIENvcHlyaWdodCAyMDA3LTIwMTcgQ2hhcmxlcyBkdSBKZXUgLSBBYnN0cml1bSBTQVMgPHRlYW0gKGF0KSBweWQuaW8+XG4gKiBUaGlzIGZpbGUgaXMgcGFydCBvZiBQeWRpby5cbiAqXG4gKiBQeWRpbyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4gKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4gKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFB5ZGlvIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIFB5ZGlvLiAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICpcbiAqIFRoZSBsYXRlc3QgY29kZSBjYW4gYmUgZm91bmQgYXQgPGh0dHBzOi8vcHlkaW8uY29tLz4uXG4gKlxuICovXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfd2lja2VkR29vZFhwYXRoID0gcmVxdWlyZSgnd2lja2VkLWdvb2QteHBhdGgnKTtcblxudmFyIF93aWNrZWRHb29kWHBhdGgyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfd2lja2VkR29vZFhwYXRoKTtcblxuX3dpY2tlZEdvb2RYcGF0aDJbJ2RlZmF1bHQnXS5pbnN0YWxsKCk7XG4vKipcbiAqIFV0aWxpdGFyeSBjbGFzcyBmb3IgbWFuaXB1bGF0aW5nIFhNTFxuICovXG5cbnZhciBYTUxVdGlscyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gWE1MVXRpbHMoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBYTUxVdGlscyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgZmlyc3QgWG1sTm9kZSB0aGF0IG1hdGNoZXMgdGhlIFhQYXRoIGV4cHJlc3Npb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZWxlbWVudCB7RWxlbWVudCB8IERvY3VtZW50fSByb290IGVsZW1lbnQgZm9yIHRoZSBzZWFyY2hcbiAgICAgKiBAcGFyYW0gcXVlcnkge1N0cmluZ30gWFBhdGggcXVlcnlcbiAgICAgKiBAcmV0dXJuIHtFbGVtZW50fSBmaXJzdCBtYXRjaGluZyBlbGVtZW50XG4gICAgICogQHNpZ25hdHVyZSBmdW5jdGlvbihlbGVtZW50LCBxdWVyeSlcbiAgICAgKi9cblxuICAgIFhNTFV0aWxzLlhQYXRoU2VsZWN0U2luZ2xlTm9kZSA9IGZ1bmN0aW9uIFhQYXRoU2VsZWN0U2luZ2xlTm9kZShlbGVtZW50LCBxdWVyeSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRbJ3NlbGVjdFNpbmdsZU5vZGUnXSAmJiB0eXBlb2YgZWxlbWVudC5zZWxlY3RTaW5nbGVOb2RlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gZWxlbWVudC5zZWxlY3RTaW5nbGVOb2RlKHF1ZXJ5KTtcbiAgICAgICAgICAgICAgICBpZiAocmVzKSByZXR1cm4gcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgICAgIGlmICghWE1MVXRpbHMuX194cGUgJiYgd2luZG93LlhQYXRoRXZhbHVhdG9yKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIFhNTFV0aWxzLl9feHBlID0gbmV3IFhQYXRoRXZhbHVhdG9yKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFYTUxVdGlscy5fX3hwZSkge1xuICAgICAgICAgICAgcXVlcnkgPSBkb2N1bWVudC5jcmVhdGVFeHByZXNzaW9uKHF1ZXJ5LCBudWxsKTtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBxdWVyeS5ldmFsdWF0ZShlbGVtZW50LCA3LCBudWxsKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQuc25hcHNob3RMZW5ndGggPyByZXN1bHQuc25hcHNob3RJdGVtKDApIDogbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB4cGUgPSBYTUxVdGlscy5fX3hwZTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIHhwZS5ldmFsdWF0ZShxdWVyeSwgZWxlbWVudCwgeHBlLmNyZWF0ZU5TUmVzb2x2ZXIoZWxlbWVudCksIFhQYXRoUmVzdWx0LkZJUlNUX09SREVSRURfTk9ERV9UWVBFLCBudWxsKS5zaW5nbGVOb2RlVmFsdWU7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VsZWN0U2luZ2xlTm9kZTogcXVlcnk6IFwiICsgcXVlcnkgKyBcIiwgZWxlbWVudDogXCIgKyBlbGVtZW50ICsgXCIsIGVycm9yOiBcIiArIGVycik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyBhIGxpc3Qgb2Ygbm9kZXMgbWF0Y2hpbmcgdGhlIFhQYXRoIGV4cHJlc3Npb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZWxlbWVudCB7RWxlbWVudCB8IERvY3VtZW50fSByb290IGVsZW1lbnQgZm9yIHRoZSBzZWFyY2hcbiAgICAgKiBAcGFyYW0gcXVlcnkge1N0cmluZ30gWFBhdGggcXVlcnlcbiAgICAgKiBAcmV0dXJuIHtFbGVtZW50W119IExpc3Qgb2YgbWF0Y2hpbmcgZWxlbWVudHNcbiAgICAgKiBAc2lnbmF0dXJlIGZ1bmN0aW9uKGVsZW1lbnQsIHF1ZXJ5KVxuICAgICAqL1xuXG4gICAgWE1MVXRpbHMuWFBhdGhTZWxlY3ROb2RlcyA9IGZ1bmN0aW9uIFhQYXRoU2VsZWN0Tm9kZXMoZWxlbWVudCwgcXVlcnkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZWxlbWVudC5zZWxlY3ROb2RlcyA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQub3duZXJEb2N1bWVudCAmJiBlbGVtZW50Lm93bmVyRG9jdW1lbnQuc2V0UHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQub3duZXJEb2N1bWVudC5zZXRQcm9wZXJ0eShcIlNlbGVjdGlvbkxhbmd1YWdlXCIsIFwiWFBhdGhcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZWxlbWVudC5zZXRQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRQcm9wZXJ0eShcIlNlbGVjdGlvbkxhbmd1YWdlXCIsIFwiWFBhdGhcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIHZhciByZXMgPSBBcnJheS5mcm9tKGVsZW1lbnQuc2VsZWN0Tm9kZXMocXVlcnkpKTtcbiAgICAgICAgICAgICAgICBpZiAocmVzKSByZXR1cm4gcmVzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgICAgIHZhciB4cGUgPSBYTUxVdGlscy5fX3hwZTtcblxuICAgICAgICBpZiAoIXhwZSAmJiB3aW5kb3cuWFBhdGhFdmFsdWF0b3IpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgWE1MVXRpbHMuX194cGUgPSB4cGUgPSBuZXcgWFBhdGhFdmFsdWF0b3IoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCxcbiAgICAgICAgICAgIG5vZGVzID0gW10sXG4gICAgICAgICAgICBpO1xuICAgICAgICBpZiAoIVhNTFV0aWxzLl9feHBlKSB7XG4gICAgICAgICAgICBxdWVyeSA9IGRvY3VtZW50LmNyZWF0ZUV4cHJlc3Npb24ocXVlcnksIG51bGwpO1xuICAgICAgICAgICAgcmVzdWx0ID0gcXVlcnkuZXZhbHVhdGUoZWxlbWVudCwgNywgbnVsbCk7XG4gICAgICAgICAgICBub2RlcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5zbmFwc2hvdExlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKEVsZW1lbnQuZXh0ZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzW2ldID0gRWxlbWVudC5leHRlbmQocmVzdWx0LnNuYXBzaG90SXRlbShpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZXNbaV0gPSByZXN1bHQuc25hcHNob3RJdGVtKGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXN1bHQgPSB4cGUuZXZhbHVhdGUocXVlcnksIGVsZW1lbnQsIHhwZS5jcmVhdGVOU1Jlc29sdmVyKGVsZW1lbnQpLCBYUGF0aFJlc3VsdC5PUkRFUkVEX05PREVfU05BUFNIT1RfVFlQRSwgbnVsbCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VsZWN0Tm9kZXM6IHF1ZXJ5OiBcIiArIHF1ZXJ5ICsgXCIsIGVsZW1lbnQ6IFwiICsgZWxlbWVudCArIFwiLCBlcnJvcjogXCIgKyBlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJlc3VsdC5zbmFwc2hvdExlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBub2Rlc1tpXSA9IHJlc3VsdC5zbmFwc2hvdEl0ZW0oaSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNlbGVjdHMgdGhlIGZpcnN0IFhtbE5vZGUgdGhhdCBtYXRjaGVzIHRoZSBYUGF0aCBleHByZXNzaW9uIGFuZCByZXR1cm5zIHRoZSB0ZXh0IGNvbnRlbnQgb2YgdGhlIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IHtFbGVtZW50fERvY3VtZW50fSByb290IGVsZW1lbnQgZm9yIHRoZSBzZWFyY2hcbiAgICAgKiBAcGFyYW0gcXVlcnkge1N0cmluZ30gIFhQYXRoIHF1ZXJ5XG4gICAgICogQHJldHVybiB7U3RyaW5nfSB0aGUgam9pbmVkIHRleHQgY29udGVudCBvZiB0aGUgZm91bmQgZWxlbWVudCBvciBudWxsIGlmIG5vdCBhcHByb3ByaWF0ZS5cbiAgICAgKiBAc2lnbmF0dXJlIGZ1bmN0aW9uKGVsZW1lbnQsIHF1ZXJ5KVxuICAgICAqL1xuXG4gICAgWE1MVXRpbHMuWFBhdGhHZXRTaW5nbGVOb2RlVGV4dCA9IGZ1bmN0aW9uIFhQYXRoR2V0U2luZ2xlTm9kZVRleHQoZWxlbWVudCwgcXVlcnkpIHtcbiAgICAgICAgdmFyIG5vZGUgPSBYTUxVdGlscy5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoZWxlbWVudCwgcXVlcnkpO1xuICAgICAgICByZXR1cm4gWE1MVXRpbHMuZ2V0RG9tTm9kZVRleHQobm9kZSk7XG4gICAgfTtcblxuICAgIFhNTFV0aWxzLmdldERvbU5vZGVUZXh0ID0gZnVuY3Rpb24gZ2V0RG9tTm9kZVRleHQobm9kZSkge1xuICAgICAgICB2YXIgaW5jbHVkZUNEYXRhID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgaWYgKCFub2RlIHx8ICFub2RlLm5vZGVUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAobm9kZS5ub2RlVHlwZSkge1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIC8vIE5PREVfRUxFTUVOVFxuICAgICAgICAgICAgICAgIHZhciBpLFxuICAgICAgICAgICAgICAgICAgICBhID0gW10sXG4gICAgICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZS5jaGlsZE5vZGVzLFxuICAgICAgICAgICAgICAgICAgICBsZW5ndGggPSBub2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGFbaV0gPSBYTUxVdGlscy5nZXREb21Ob2RlVGV4dChub2Rlc1tpXSwgaW5jbHVkZUNEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYS5qb2luKFwiXCIpO1xuXG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgLy8gTk9ERV9BVFRSSUJVVEVcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZS52YWx1ZTtcblxuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIC8vIE5PREVfVEVYVFxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlLm5vZGVWYWx1ZTtcblxuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIC8vIENEQVRBXG4gICAgICAgICAgICAgICAgaWYgKGluY2x1ZGVDRGF0YSkgcmV0dXJuIG5vZGUubm9kZVZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB4bWxTdHJcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cblxuICAgIFhNTFV0aWxzLnBhcnNlWG1sID0gZnVuY3Rpb24gcGFyc2VYbWwoeG1sU3RyKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuRE9NUGFyc2VyICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgd2luZG93LkRPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyh4bWxTdHIsIFwidGV4dC94bWxcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuQWN0aXZlWE9iamVjdCAhPSBcInVuZGVmaW5lZFwiICYmIG5ldyB3aW5kb3cuQWN0aXZlWE9iamVjdChcIk1TWE1MMi5ET01Eb2N1bWVudC42LjBcIikpIHtcbiAgICAgICAgICAgIHZhciB4bWxEb2MgPSBuZXcgd2luZG93LkFjdGl2ZVhPYmplY3QoXCJNU1hNTDIuRE9NRG9jdW1lbnQuNi4wXCIpO1xuICAgICAgICAgICAgeG1sRG9jLnZhbGlkYXRlT25QYXJzZSA9IGZhbHNlO1xuICAgICAgICAgICAgeG1sRG9jLmFzeW5jID0gZmFsc2U7XG4gICAgICAgICAgICB4bWxEb2MubG9hZFhNTCh4bWxTdHIpO1xuICAgICAgICAgICAgeG1sRG9jLnNldFByb3BlcnR5KCdTZWxlY3Rpb25MYW5ndWFnZScsICdYUGF0aCcpO1xuICAgICAgICAgICAgcmV0dXJuIHhtbERvYztcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBwYXJzZSBYTUwgc3RyaW5nJyk7XG4gICAgfTtcblxuICAgIHJldHVybiBYTUxVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFhNTFV0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iLCIvKlxuICogQ29weXJpZ2h0IDIwMDctMjAxNyBDaGFybGVzIGR1IEpldSAtIEFic3RyaXVtIFNBUyA8dGVhbSAoYXQpIHB5ZC5pbz5cbiAqIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIFB5ZGlvLlxuICpcbiAqIFB5ZGlvIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogUHlkaW8gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG4gKiBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggUHlkaW8uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gKlxuICogVGhlIGxhdGVzdCBjb2RlIGNhbiBiZSBmb3VuZCBhdCA8aHR0cHM6Ly9weWRpby5jb20+LlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9sYW5nT2JzZXJ2YWJsZSA9IHJlcXVpcmUoJy4vbGFuZy9PYnNlcnZhYmxlJyk7XG5cbnZhciBfbGFuZ09ic2VydmFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGFuZ09ic2VydmFibGUpO1xuXG52YXIgX2xhbmdMb2dnZXIgPSByZXF1aXJlKCcuL2xhbmcvTG9nZ2VyJyk7XG5cbnZhciBfbGFuZ0xvZ2dlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9sYW5nTG9nZ2VyKTtcblxudmFyIF9odHRwUHlkaW9BcGkgPSByZXF1aXJlKCcuL2h0dHAvUHlkaW9BcGknKTtcblxudmFyIF9odHRwUHlkaW9BcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfaHR0cFB5ZGlvQXBpKTtcblxudmFyIF9tb2RlbFJlZ2lzdHJ5ID0gcmVxdWlyZSgnLi9tb2RlbC9SZWdpc3RyeScpO1xuXG52YXIgX21vZGVsUmVnaXN0cnkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxSZWdpc3RyeSk7XG5cbnZhciBfbW9kZWxBanhwTm9kZSA9IHJlcXVpcmUoJy4vbW9kZWwvQWp4cE5vZGUnKTtcblxudmFyIF9tb2RlbEFqeHBOb2RlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21vZGVsQWp4cE5vZGUpO1xuXG52YXIgX21vZGVsUHlkaW9EYXRhTW9kZWwgPSByZXF1aXJlKCcuL21vZGVsL1B5ZGlvRGF0YU1vZGVsJyk7XG5cbnZhciBfbW9kZWxQeWRpb0RhdGFNb2RlbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbFB5ZGlvRGF0YU1vZGVsKTtcblxudmFyIF9tb2RlbFJlbW90ZU5vZGVQcm92aWRlciA9IHJlcXVpcmUoJy4vbW9kZWwvUmVtb3RlTm9kZVByb3ZpZGVyJyk7XG5cbnZhciBfbW9kZWxSZW1vdGVOb2RlUHJvdmlkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbW9kZWxSZW1vdGVOb2RlUHJvdmlkZXIpO1xuXG52YXIgX21vZGVsUmVwb3NpdG9yeSA9IHJlcXVpcmUoJy4vbW9kZWwvUmVwb3NpdG9yeScpO1xuXG52YXIgX21vZGVsUmVwb3NpdG9yeTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbFJlcG9zaXRvcnkpO1xuXG52YXIgX21vZGVsQ29udHJvbGxlciA9IHJlcXVpcmUoJy4vbW9kZWwvQ29udHJvbGxlcicpO1xuXG52YXIgX21vZGVsQ29udHJvbGxlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9tb2RlbENvbnRyb2xsZXIpO1xuXG52YXIgX3V0aWxYTUxVdGlscyA9IHJlcXVpcmUoJy4vdXRpbC9YTUxVdGlscycpO1xuXG52YXIgX3V0aWxYTUxVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsWE1MVXRpbHMpO1xuXG52YXIgX3V0aWxQYXRoVXRpbHMgPSByZXF1aXJlKCcuL3V0aWwvUGF0aFV0aWxzJyk7XG5cbnZhciBfdXRpbFBhdGhVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF91dGlsUGF0aFV0aWxzKTtcblxudmFyIF91dGlsTGFuZ1V0aWxzID0gcmVxdWlyZSgnLi91dGlsL0xhbmdVdGlscycpO1xuXG52YXIgX3V0aWxMYW5nVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdXRpbExhbmdVdGlscyk7XG5cbnZhciBfdXRpbEFjdGl2aXR5TW9uaXRvciA9IHJlcXVpcmUoJy4vdXRpbC9BY3Rpdml0eU1vbml0b3InKTtcblxudmFyIF91dGlsQWN0aXZpdHlNb25pdG9yMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxBY3Rpdml0eU1vbml0b3IpO1xuXG4vKipcbiAqIFRoaXMgaXMgdGhlIG1haW4gY2xhc3MgZm9yIGxhdW5jaGluZyB0aGUgd2hvbGUgZnJhbWV3b3JrLFxuICogd2l0aCBvciB3aXRob3V0IGEgVUkuXG4gKiBJdCBjYW4gYmUgbGF1bmNoZWQgYnkgUHlkaW9Cb290c3RyYXAgb3IgZGlyZWN0bHkgYnkgZ2l2aW5nIHRoZSByaWdodCBwYXJhbWV0ZXJzLlxuICovXG5cbnZhciBQeWRpbyA9IChmdW5jdGlvbiAoX09ic2VydmFibGUpIHtcbiAgICBfaW5oZXJpdHMoUHlkaW8sIF9PYnNlcnZhYmxlKTtcblxuICAgIC8qKlxuICAgICAqIFB5ZGlvIENvbnN0cnVjdG9yIHRha2VzIGEgTWFwIG9mIHN0YXJ0IHBhcmFtZXRlcnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGFyYW1ldGVycyB7TWFwfVxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gUHlkaW8ocGFyYW1ldGVycykge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHlkaW8pO1xuXG4gICAgICAgIF9PYnNlcnZhYmxlLmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuUGFyYW1ldGVycyA9IHBhcmFtZXRlcnM7XG4gICAgICAgIHRoaXMuX2luaXRMb2FkUmVwID0gcGFyYW1ldGVycy5nZXQoJ2luaXRMb2FkUmVwJykgfHwgbnVsbDtcbiAgICAgICAgdGhpcy51c2Vyc0VuYWJsZWQgPSBwYXJhbWV0ZXJzLmdldCgndXNlcnNFbmFibGVkJykgfHwgbnVsbDtcbiAgICAgICAgdGhpcy5jdXJyZW50TGFuZ3VhZ2UgPSBwYXJhbWV0ZXJzLmdldCgnY3VycmVudExhbmd1YWdlJykgfHwgbnVsbDtcbiAgICAgICAgdGhpcy5hcHBUaXRsZSA9IFwiUHlkaW9cIjtcbiAgICAgICAgaWYgKHRoaXMuUGFyYW1ldGVycy5oYXMoXCJjdXN0b21Xb3JkaW5nXCIpKSB7XG4gICAgICAgICAgICB0aGlzLmFwcFRpdGxlID0gdGhpcy5QYXJhbWV0ZXJzLmdldChcImN1c3RvbVdvcmRpbmdcIikudGl0bGUgfHwgXCJQeWRpb1wiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlciA9IG51bGw7XG4gICAgICAgIHRoaXMuTWVzc2FnZUhhc2ggPSB7fTtcbiAgICAgICAgaWYgKHdpbmRvdy5NZXNzYWdlSGFzaCkgdGhpcy5NZXNzYWdlSGFzaCA9IHdpbmRvdy5NZXNzYWdlSGFzaDtcbiAgICAgICAgdGhpcy5BcGlDbGllbnQgPSBfaHR0cFB5ZGlvQXBpMlsnZGVmYXVsdCddLmdldENsaWVudCgpO1xuICAgICAgICB0aGlzLkFwaUNsaWVudC5zZXRQeWRpb09iamVjdCh0aGlzKTtcbiAgICAgICAgdGhpcy5BY3Rpdml0eU1vbml0b3IgPSBuZXcgX3V0aWxBY3Rpdml0eU1vbml0b3IyWydkZWZhdWx0J10odGhpcyk7XG4gICAgICAgIHRoaXMuUmVnaXN0cnkgPSBuZXcgX21vZGVsUmVnaXN0cnkyWydkZWZhdWx0J10odGhpcyk7XG4gICAgICAgIHRoaXMuX3Jvb3ROb2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKFwiL1wiLCBcIlJvb3RcIik7XG4gICAgICAgIHRoaXMuX2RhdGFNb2RlbCA9IHRoaXMuX2NvbnRleHRIb2xkZXIgPSBuZXcgX21vZGVsUHlkaW9EYXRhTW9kZWwyWydkZWZhdWx0J10oZmFsc2UpO1xuICAgICAgICB0aGlzLl9kYXRhTW9kZWwuc2V0QWp4cE5vZGVQcm92aWRlcihuZXcgX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyMlsnZGVmYXVsdCddKCkpO1xuICAgICAgICB0aGlzLl9kYXRhTW9kZWwuc2V0Um9vdE5vZGUodGhpcy5fcm9vdE5vZGUpO1xuICAgICAgICAvLyBNdXN0IGhhcHBlbiBBRlRFUiBkYXRhbW9kZWwgaW5pdGl6YXRpb24uXG4gICAgICAgIHRoaXMuQ29udHJvbGxlciA9IG5ldyBfbW9kZWxDb250cm9sbGVyMlsnZGVmYXVsdCddKHRoaXMpO1xuICAgIH1cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5maXJlID0gZnVuY3Rpb24gZmlyZShldmVudE5hbWUsIGRhdGEpIHtcbiAgICAgICAgdGhpcy5ub3RpZnkoZXZlbnROYW1lLCBkYXRhKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1VzZXJ8bnVsbH0gdXNlck9iamVjdFxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnVwZGF0ZVVzZXIgPSBmdW5jdGlvbiB1cGRhdGVVc2VyKHVzZXJPYmplY3QpIHtcbiAgICAgICAgdmFyIHNraXBFdmVudCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IGZhbHNlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICAgIHRoaXMudXNlciA9IHVzZXJPYmplY3Q7XG4gICAgICAgIGlmICghc2tpcEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeSgndXNlcl9sb2dnZWQnLCB1c2VyT2JqZWN0KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtudWxsfFVzZXJ9XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0VXNlciA9IGZ1bmN0aW9uIGdldFVzZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVzZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZnJlc2ggdXNlci9wcmVmZXJlbmNlcyByZWdpc3RyeSBwYXJ0XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUucmVmcmVzaFVzZXJEYXRhID0gZnVuY3Rpb24gcmVmcmVzaFVzZXJEYXRhKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAgIHRoaXMub2JzZXJ2ZU9uY2UoXCJyZWdpc3RyeV9wYXJ0X2xvYWRlZFwiLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudCAhPT0gXCJ1c2VyL3ByZWZlcmVuY2VzXCIpIHJldHVybjtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZVVzZXIoX3RoaXMuUmVnaXN0cnkucGFyc2VVc2VyKCksIGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuUmVnaXN0cnkubG9hZChcInVzZXIvcHJlZmVyZW5jZXNcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlYWwgaW5pdGlhbGlzYXRpb24gc2VxdWVuY2UuIFdpbGwgVHJpZ2dlciB0aGUgd2hvbGUgR1VJIGJ1aWxkaW5nLlxuICAgICAqIEV2ZW50IGFqYXhwbG9yZXI6bG9hZGVkIGlzIGZpcmVkIGF0IHRoZSBlbmQuXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdGhpcy5QYXJhbWV0ZXJzLmhhcygnU0VDVVJFX1RPS0VOJykpIHtcbiAgICAgICAgICAgIF9odHRwUHlkaW9BcGkyWydkZWZhdWx0J10uZ2V0Q2xpZW50KCkuZ2V0Qm9vdENvbmYoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluaXQoKTtcbiAgICAgICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vYnNlcnZlKFwicmVnaXN0cnlfbG9hZGVkXCIsIGZ1bmN0aW9uICgpIHtcblxuICAgICAgICAgICAgX3RoaXMyLlJlZ2lzdHJ5LnJlZnJlc2hFeHRlbnNpb25zUmVnaXN0cnkoKTtcbiAgICAgICAgICAgIF90aGlzMi51cGRhdGVVc2VyKF90aGlzMi5SZWdpc3RyeS5wYXJzZVVzZXIoKSwgZmFsc2UpO1xuICAgICAgICAgICAgaWYgKF90aGlzMi51c2VyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcElkID0gX3RoaXMyLnVzZXIuZ2V0QWN0aXZlUmVwb3NpdG9yeSgpO1xuICAgICAgICAgICAgICAgIHZhciByZXBMaXN0ID0gX3RoaXMyLnVzZXIuZ2V0UmVwb3NpdG9yaWVzTGlzdCgpO1xuICAgICAgICAgICAgICAgIHZhciByZXBvc2l0b3J5T2JqZWN0ID0gcmVwTGlzdC5nZXQocmVwSWQpO1xuICAgICAgICAgICAgICAgIGlmIChyZXBvc2l0b3J5T2JqZWN0KSByZXBvc2l0b3J5T2JqZWN0LmxvYWRSZXNvdXJjZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfdGhpczIuVUkuZ3VpTG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMyLlVJLnJlZnJlc2hUZW1wbGF0ZVBhcnRzKCk7XG4gICAgICAgICAgICAgICAgX3RoaXMyLlJlZ2lzdHJ5LnJlZnJlc2hFeHRlbnNpb25zUmVnaXN0cnkoKTtcbiAgICAgICAgICAgICAgICBfdGhpczIuQ29udHJvbGxlci5sb2FkQWN0aW9uc0Zyb21SZWdpc3RyeShfdGhpczIuZ2V0WG1sUmVnaXN0cnkoKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIF90aGlzMi5vYnNlcnZlKFwiZ3VpX2xvYWRlZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5VSS5yZWZyZXNoVGVtcGxhdGVQYXJ0cygpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIuUmVnaXN0cnkucmVmcmVzaEV4dGVuc2lvbnNSZWdpc3RyeSgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIuQ29udHJvbGxlci5sb2FkQWN0aW9uc0Zyb21SZWdpc3RyeShfdGhpczIuZ2V0WG1sUmVnaXN0cnkoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpczIubG9hZEFjdGl2ZVJlcG9zaXRvcnkoKTtcbiAgICAgICAgICAgIGlmIChfdGhpczIuUGFyYW1ldGVycy5oYXMoXCJVU0VSX0dVSV9BQ1RJT05cIikpIHtcbiAgICAgICAgICAgICAgICAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IF90aGlzMi5QYXJhbWV0ZXJzLmdldChcIlVTRVJfR1VJX0FDVElPTlwiKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLlBhcmFtZXRlcnNbJ2RlbGV0ZSddKFwiVVNFUl9HVUlfQUNUSU9OXCIpO1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzMi5Db250cm9sbGVyLmZpcmVBY3Rpb24oYSk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDEwMDApO1xuICAgICAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBzdGFydGVyRnVuYyA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgICAgICAgUmVzb3VyY2VzTWFuYWdlci5sb2FkQ2xhc3Nlc0FuZEFwcGx5KFtcIlJlYWN0XCIsIFwiUHlkaW9SZWFjdFVJXCJdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMzLlVJID0gbmV3IHdpbmRvdy5QeWRpb1JlYWN0VUkuQnVpbGRlcihfdGhpczMpO1xuICAgICAgICAgICAgICAgIF90aGlzMy5VSS5pbml0VGVtcGxhdGVzKCk7XG4gICAgICAgICAgICAgICAgX3RoaXMzLmZpcmUoXCJyZWdpc3RyeV9sb2FkZWRcIiwgX3RoaXMzLlJlZ2lzdHJ5LmdldFhNTCgpKTtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMzLmZpcmUoJ2xvYWRlZCcpO1xuICAgICAgICAgICAgICAgIH0sIDIwMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSkuYmluZCh0aGlzKTtcblxuICAgICAgICBpZiAodGhpcy5QYXJhbWV0ZXJzLmdldChcIlBSRUxPQURFRF9SRUdJU1RSWVwiKSkge1xuXG4gICAgICAgICAgICB0aGlzLlJlZ2lzdHJ5LmxvYWRGcm9tU3RyaW5nKHRoaXMuUGFyYW1ldGVycy5nZXQoXCJQUkVMT0FERURfUkVHSVNUUllcIikpO1xuICAgICAgICAgICAgdGhpcy5QYXJhbWV0ZXJzWydkZWxldGUnXShcIlBSRUxPQURFRF9SRUdJU1RSWVwiKTtcbiAgICAgICAgICAgIHN0YXJ0ZXJGdW5jKCk7XG4gICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgIHRoaXMubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBudWxsLCBzdGFydGVyRnVuYyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9ic2VydmUoXCJzZXJ2ZXJfbWVzc2FnZVwiLCBmdW5jdGlvbiAoeG1sKSB7XG4gICAgICAgICAgICB2YXIgcmVsb2FkID0gX3V0aWxYTUxVdGlsczJbJ2RlZmF1bHQnXS5YUGF0aFNlbGVjdFNpbmdsZU5vZGUoeG1sLCBcInRyZWUvcmVxdWlyZV9yZWdpc3RyeV9yZWxvYWRcIik7XG4gICAgICAgICAgICBpZiAocmVsb2FkKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlbG9hZC5nZXRBdHRyaWJ1dGUoXCJyZXBvc2l0b3J5SWRcIikgIT0gX3RoaXMyLnJlcG9zaXRvcnlJZCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBudWxsLCBudWxsLCByZWxvYWQuZ2V0QXR0cmlidXRlKFwicmVwb3NpdG9yeUlkXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMyLnJlcG9zaXRvcnlJZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTG9hZHMgdGhlIFhNTCBSZWdpc3RyeSwgYW4gaW1hZ2Ugb2YgdGhlIGFwcGxpY2F0aW9uIGluIGl0cyBjdXJyZW50IHN0YXRlXG4gICAgICogc2VudCBieSB0aGUgc2VydmVyLlxuICAgICAqIEBwYXJhbSBzeW5jIEJvb2xlYW4gV2hldGhlciB0byBzZW5kIHN5bmNocm9ub3VzbHkgb3Igbm90LlxuICAgICAqIEBwYXJhbSB4UGF0aCBTdHJpbmcgQW4gWFBhdGggdG8gbG9hZCBvbmx5IGEgc3VicGFydCBvZiB0aGUgcmVnaXN0cnlcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkWG1sUmVnaXN0cnkgPSBmdW5jdGlvbiBsb2FkWG1sUmVnaXN0cnkoc3luYykge1xuICAgICAgICB2YXIgeFBhdGggPSBhcmd1bWVudHMubGVuZ3RoIDw9IDEgfHwgYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuICAgICAgICB2YXIgY29tcGxldGVGdW5jID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyIHx8IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIHRhcmdldFJlcG9zaXRvcnlJZCA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMyB8fCBhcmd1bWVudHNbM10gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbM107XG5cbiAgICAgICAgdGhpcy5SZWdpc3RyeS5sb2FkKHhQYXRoLCBjb21wbGV0ZUZ1bmMsIHRhcmdldFJlcG9zaXRvcnlJZCA9PT0gbnVsbCA/IE1hdGgucmFuZG9tKCkgOiB0YXJnZXRSZXBvc2l0b3J5SWQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIFhNTCBSZWdpc3RyeVxuICAgICAqIEByZXR1cm5zIERvY3VtZW50XG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0WG1sUmVnaXN0cnkgPSBmdW5jdGlvbiBnZXRYbWxSZWdpc3RyeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuUmVnaXN0cnkuZ2V0WE1MKCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZpbmQgdGhlIGN1cnJlbnQgcmVwb3NpdG9yeSAoZnJvbSB0aGUgY3VycmVudCB1c2VyKSBhbmQgbG9hZCBpdC5cbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5sb2FkQWN0aXZlUmVwb3NpdG9yeSA9IGZ1bmN0aW9uIGxvYWRBY3RpdmVSZXBvc2l0b3J5KCkge1xuICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICB2YXIgcmVwb3NpdG9yeU9iamVjdCA9IG5ldyBfbW9kZWxSZXBvc2l0b3J5MlsnZGVmYXVsdCddKG51bGwpO1xuICAgICAgICBpZiAodGhpcy51c2VyID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmxvYWRSZXBvc2l0b3J5KHJlcG9zaXRvcnlPYmplY3QpO1xuICAgICAgICAgICAgdGhpcy5maXJlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCB7IGxpc3Q6IGZhbHNlLCBhY3RpdmU6IGZhbHNlIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlcElkID0gdGhpcy51c2VyLmdldEFjdGl2ZVJlcG9zaXRvcnkoKTtcbiAgICAgICAgdmFyIHJlcExpc3QgPSB0aGlzLnVzZXIuZ2V0UmVwb3NpdG9yaWVzTGlzdCgpO1xuICAgICAgICByZXBvc2l0b3J5T2JqZWN0ID0gcmVwTGlzdC5nZXQocmVwSWQpO1xuXG4gICAgICAgIGlmICghcmVwb3NpdG9yeU9iamVjdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMudXNlci5sb2NrKSB7XG4gICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXM0LkNvbnRyb2xsZXIubG9hZEFjdGlvbnNGcm9tUmVnaXN0cnkoX3RoaXM0LmdldFhtbFJlZ2lzdHJ5KCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbG9jayA9IF90aGlzNC51c2VyLmxvY2suc3BsaXQoXCIsXCIpLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzNC5Db250cm9sbGVyLmZpcmVBY3Rpb24obG9jayk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDUwKTtcbiAgICAgICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbGVydChcIk5vIGFjdGl2ZSByZXBvc2l0b3J5IGZvdW5kIGZvciB1c2VyIVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVzZXIuZ2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIpICYmIHRoaXMudXNlci5nZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIikgIT0gXCItMVwiKSB7XG5cbiAgICAgICAgICAgIHRoaXMuX2luaXRMb2FkUmVwID0gdGhpcy51c2VyLmdldFByZWZlcmVuY2UoXCJwZW5kaW5nX2ZvbGRlclwiKTtcbiAgICAgICAgICAgIHRoaXMudXNlci5zZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIiwgXCItMVwiKTtcbiAgICAgICAgICAgIHRoaXMudXNlci5zYXZlUHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sb2FkUmVwb3NpdG9yeShyZXBvc2l0b3J5T2JqZWN0KTtcbiAgICAgICAgdGhpcy5maXJlKFwicmVwb3NpdG9yeV9saXN0X3JlZnJlc2hlZFwiLCB7IGxpc3Q6IHJlcExpc3QsIGFjdGl2ZTogcmVwSWQgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlZnJlc2ggdGhlIHJlcG9zaXRvcmllcyBsaXN0IGZvciB0aGUgY3VycmVudCB1c2VyXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUucmVsb2FkUmVwb3NpdG9yaWVzTGlzdCA9IGZ1bmN0aW9uIHJlbG9hZFJlcG9zaXRvcmllc0xpc3QoKSB7XG4gICAgICAgIHZhciBfdGhpczUgPSB0aGlzO1xuXG4gICAgICAgIGlmICghdGhpcy51c2VyKSByZXR1cm47XG4gICAgICAgIHRoaXMub2JzZXJ2ZU9uY2UoXCJyZWdpc3RyeV9wYXJ0X2xvYWRlZFwiLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgaWYgKGRhdGEgIT0gXCJ1c2VyL3JlcG9zaXRvcmllc1wiKSByZXR1cm47XG4gICAgICAgICAgICBfdGhpczUudXBkYXRlVXNlcihfdGhpczUuUmVnaXN0cnkucGFyc2VVc2VyKCkpO1xuICAgICAgICAgICAgX3RoaXM1LmZpcmUoXCJyZXBvc2l0b3J5X2xpc3RfcmVmcmVzaGVkXCIsIHtcbiAgICAgICAgICAgICAgICBsaXN0OiBfdGhpczUudXNlci5nZXRSZXBvc2l0b3JpZXNMaXN0KCksXG4gICAgICAgICAgICAgICAgYWN0aXZlOiBfdGhpczUudXNlci5nZXRBY3RpdmVSZXBvc2l0b3J5KClcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sb2FkWG1sUmVnaXN0cnkoZmFsc2UsIFwidXNlci9yZXBvc2l0b3JpZXNcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBSZXBvc2l0b3J5IGluc3RhbmNlXG4gICAgICogQHBhcmFtIHJlcG9zaXRvcnkgUmVwb3NpdG9yeVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmxvYWRSZXBvc2l0b3J5ID0gZnVuY3Rpb24gbG9hZFJlcG9zaXRvcnkocmVwb3NpdG9yeSkge1xuICAgICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgICBpZiAodGhpcy5yZXBvc2l0b3J5SWQgIT0gbnVsbCAmJiB0aGlzLnJlcG9zaXRvcnlJZCA9PSByZXBvc2l0b3J5LmdldElkKCkpIHtcbiAgICAgICAgICAgIF9sYW5nTG9nZ2VyMlsnZGVmYXVsdCddLmRlYnVnKCdSZXBvc2l0b3J5IGFscmVhZHkgbG9hZGVkLCBkbyBub3RoaW5nJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRTZWxlY3RlZE5vZGVzKFtdKTtcbiAgICAgICAgaWYgKHJlcG9zaXRvcnkgPT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgICAgIHJlcG9zaXRvcnkubG9hZFJlc291cmNlcygpO1xuICAgICAgICB2YXIgcmVwb3NpdG9yeUlkID0gcmVwb3NpdG9yeS5nZXRJZCgpO1xuICAgICAgICB2YXIgbmV3SWNvbiA9IHJlcG9zaXRvcnkuZ2V0SWNvbigpO1xuXG4gICAgICAgIHZhciBwcm92aWRlckRlZiA9IHJlcG9zaXRvcnkuZ2V0Tm9kZVByb3ZpZGVyRGVmKCk7XG4gICAgICAgIHZhciByb290Tm9kZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHByb3ZpZGVyRGVmICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBwcm92aWRlciA9IGV2YWwoJ25ldyAnICsgcHJvdmlkZXJEZWYubmFtZSArICcoKScpO1xuICAgICAgICAgICAgaWYgKHByb3ZpZGVyRGVmLm9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBwcm92aWRlci5pbml0UHJvdmlkZXIocHJvdmlkZXJEZWYub3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnNldEFqeHBOb2RlUHJvdmlkZXIocHJvdmlkZXIpO1xuICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10oXCIvXCIsIGZhbHNlLCByZXBvc2l0b3J5LmdldExhYmVsKCksIG5ld0ljb24sIHByb3ZpZGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKFwiL1wiLCBmYWxzZSwgcmVwb3NpdG9yeS5nZXRMYWJlbCgpLCBuZXdJY29uKTtcbiAgICAgICAgICAgIC8vIERlZmF1bHRcbiAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0QWp4cE5vZGVQcm92aWRlcihuZXcgX21vZGVsUmVtb3RlTm9kZVByb3ZpZGVyMlsnZGVmYXVsdCddKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGluaXRMb2FkUmVwID0gdGhpcy5faW5pdExvYWRSZXAgJiYgdGhpcy5faW5pdExvYWRSZXAgIT09ICcvJyA/IHRoaXMuX2luaXRMb2FkUmVwLnZhbHVlT2YoKSA6IG51bGw7XG4gICAgICAgIHZhciBmaXJzdExvYWRPYnMgPSBmdW5jdGlvbiBmaXJzdExvYWRPYnMoKSB7fTtcbiAgICAgICAgaWYgKGluaXRMb2FkUmVwKSB7XG4gICAgICAgICAgICBmaXJzdExvYWRPYnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXM2LmdvVG8oaW5pdExvYWRSZXApO1xuICAgICAgICAgICAgICAgIF90aGlzNi5faW5pdExvYWRSZXAgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0Um9vdE5vZGUocm9vdE5vZGUpO1xuICAgICAgICByb290Tm9kZS5vYnNlcnZlT25jZSgnZmlyc3RfbG9hZCcsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLm5vdGlmeSgnY29udGV4dF9jaGFuZ2VkJywgcm9vdE5vZGUpO1xuICAgICAgICAgICAgZmlyc3RMb2FkT2JzKCk7XG4gICAgICAgIH0pLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLnJlcG9zaXRvcnlJZCA9IHJlcG9zaXRvcnlJZDtcbiAgICAgICAgcm9vdE5vZGUubG9hZCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXF1aXJlIGEgY29udGV4dCBjaGFuZ2UgdG8gdGhlIGdpdmVuIHBhdGhcbiAgICAgKiBAcGFyYW0gbm9kZU9yUGF0aCBBanhwTm9kZXxTdHJpbmcgQSBub2RlIG9yIGEgcGF0aFxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdvVG8gPSBmdW5jdGlvbiBnb1RvKG5vZGVPclBhdGgpIHtcbiAgICAgICAgdmFyIGdvdG9Ob2RlID0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgcGF0aCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHR5cGVvZiBub2RlT3JQYXRoID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHBhdGggPSBub2RlT3JQYXRoO1xuICAgICAgICAgICAgZ290b05vZGUgPSBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10obm9kZU9yUGF0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnb3RvTm9kZSA9IG5vZGVPclBhdGg7XG4gICAgICAgICAgICBwYXRoID0gZ290b05vZGUuZ2V0UGF0aCgpO1xuICAgICAgICAgICAgaWYgKG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5oYXMoXCJyZXBvc2l0b3J5X2lkXCIpICYmIG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5nZXQoXCJyZXBvc2l0b3J5X2lkXCIpICE9IHRoaXMucmVwb3NpdG9yeUlkICYmIG5vZGVPclBhdGguZ2V0QWp4cE1pbWUoKSAhPSBcInJlcG9zaXRvcnlcIiAmJiBub2RlT3JQYXRoLmdldEFqeHBNaW1lKCkgIT0gXCJyZXBvc2l0b3J5X2VkaXRhYmxlXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXNlci5zZXRQcmVmZXJlbmNlKFwicGVuZGluZ19mb2xkZXJcIiwgbm9kZU9yUGF0aC5nZXRQYXRoKCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IG5vZGVPclBhdGguZ2V0UGF0aCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXJSZXBvc2l0b3J5Q2hhbmdlKG5vZGVPclBhdGguZ2V0TWV0YWRhdGEoKS5nZXQoXCJyZXBvc2l0b3J5X2lkXCIpKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX3JlcG9zaXRvcnlDdXJyZW50bHlTd2l0Y2hpbmcgJiYgdGhpcy51c2VyKSB7XG4gICAgICAgICAgICB0aGlzLnVzZXIuc2V0UHJlZmVyZW5jZShcInBlbmRpbmdfZm9sZGVyXCIsIGdvdG9Ob2RlLmdldFBhdGgoKSk7XG4gICAgICAgICAgICB0aGlzLl9pbml0TG9hZFJlcCA9IGdvdG9Ob2RlLmdldFBhdGgoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Q29udGV4dE5vZGUoKTtcbiAgICAgICAgaWYgKGN1cnJlbnQgJiYgY3VycmVudC5nZXRQYXRoKCkgPT0gcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoID09PSBcIlwiIHx8IHBhdGggPT09IFwiL1wiKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250ZXh0SG9sZGVyLnJlcXVpcmVDb250ZXh0Q2hhbmdlKHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Um9vdE5vZGUoKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnb3RvTm9kZSA9IGdvdG9Ob2RlLmZpbmRJbkFyYm8odGhpcy5fY29udGV4dEhvbGRlci5nZXRSb290Tm9kZSgpKTtcbiAgICAgICAgICAgIGlmIChnb3RvTm9kZSkge1xuICAgICAgICAgICAgICAgIC8vIE5vZGUgaXMgYWxyZWFkeSBoZXJlXG4gICAgICAgICAgICAgICAgaWYgKCFnb3RvTm9kZS5pc0Jyb3dzYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIuc2V0UGVuZGluZ1NlbGVjdGlvbihfdXRpbFBhdGhVdGlsczJbJ2RlZmF1bHQnXS5nZXRCYXNlbmFtZShwYXRoKSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoZ290b05vZGUuZ2V0UGFyZW50KCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIucmVxdWlyZUNvbnRleHRDaGFuZ2UoZ290b05vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgb24gc2VydmVyIGlmIGl0IGRvZXMgZXhpc3QsIHRoZW4gbG9hZFxuICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRleHRIb2xkZXIubG9hZFBhdGhJbmZvQXN5bmMocGF0aCwgKGZ1bmN0aW9uIChmb3VuZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmb3VuZE5vZGUuaXNCcm93c2FibGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRQZW5kaW5nU2VsZWN0aW9uKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldEJhc2VuYW1lKHBhdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdvdG9Ob2RlID0gbmV3IF9tb2RlbEFqeHBOb2RlMlsnZGVmYXVsdCddKF91dGlsUGF0aFV0aWxzMlsnZGVmYXVsdCddLmdldERpcm5hbWUocGF0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ290b05vZGUgPSBmb3VuZE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5yZXF1aXJlQ29udGV4dENoYW5nZShnb3RvTm9kZSk7XG4gICAgICAgICAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlIHRoZSByZXBvc2l0b3J5IG9mIHRoZSBjdXJyZW50IHVzZXIgYW5kIHJlbG9hZCBsaXN0IGFuZCBjdXJyZW50LlxuICAgICAqIEBwYXJhbSByZXBvc2l0b3J5SWQgU3RyaW5nIElkIG9mIHRoZSBuZXcgcmVwb3NpdG9yeVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLnRyaWdnZXJSZXBvc2l0b3J5Q2hhbmdlID0gZnVuY3Rpb24gdHJpZ2dlclJlcG9zaXRvcnlDaGFuZ2UocmVwb3NpdG9yeUlkLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgICB0aGlzLmZpcmUoXCJ0cmlnZ2VyX3JlcG9zaXRvcnlfc3dpdGNoXCIpO1xuICAgICAgICB0aGlzLl9yZXBvc2l0b3J5Q3VycmVudGx5U3dpdGNoaW5nID0gdHJ1ZTtcbiAgICAgICAgdmFyIG9uQ29tcGxldGUgPSBmdW5jdGlvbiBvbkNvbXBsZXRlKHRyYW5zcG9ydCkge1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydC5yZXNwb25zZVhNTCkge1xuICAgICAgICAgICAgICAgIF90aGlzNy5BcGlDbGllbnQucGFyc2VYbWxNZXNzYWdlKHRyYW5zcG9ydC5yZXNwb25zZVhNTCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpczcubG9hZFhtbFJlZ2lzdHJ5KGZhbHNlLCBudWxsLCBudWxsLCByZXBvc2l0b3J5SWQpO1xuICAgICAgICAgICAgX3RoaXM3LnJlcG9zaXRvcnlJZCA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT0gXCJmdW5jdGlvblwiKSBjYWxsYmFjaygpO1xuICAgICAgICAgICAgX3RoaXM3Ll9yZXBvc2l0b3J5Q3VycmVudGx5U3dpdGNoaW5nID0gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHJvb3QgPSB0aGlzLl9jb250ZXh0SG9sZGVyLmdldFJvb3ROb2RlKCk7XG4gICAgICAgIGlmIChyb290KSB7XG4gICAgICAgICAgICByb290LmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5BcGlDbGllbnQuc3dpdGNoUmVwb3NpdG9yeShyZXBvc2l0b3J5SWQsIG9uQ29tcGxldGUpO1xuICAgIH07XG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0UGx1Z2luQ29uZmlncyA9IGZ1bmN0aW9uIGdldFBsdWdpbkNvbmZpZ3MocGx1Z2luUXVlcnkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuUmVnaXN0cnkuZ2V0UGx1Z2luQ29uZmlncyhwbHVnaW5RdWVyeSk7XG4gICAgfTtcblxuICAgIFB5ZGlvLnByb3RvdHlwZS5saXN0TGFuZ3VhZ2VzV2l0aENhbGxiYWNrID0gZnVuY3Rpb24gbGlzdExhbmd1YWdlc1dpdGhDYWxsYmFjayhjYWxsYmFjaykge1xuICAgICAgICB2YXIgbGFuZ3MgPSB0aGlzLlBhcmFtZXRlcnMuZ2V0KFwiYXZhaWxhYmxlTGFuZ3VhZ2VzXCIpIHx8IHsgXCJlblwiOiBcIkRlZmF1bHRcIiB9O1xuICAgICAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudExhbmd1YWdlO1xuICAgICAgICBPYmplY3Qua2V5cyhsYW5ncykuc29ydCgpLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBjYWxsYmFjayhrZXksIGxhbmdzW2tleV0sIGN1cnJlbnQgPT09IGtleSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWxvYWQgYWxsIG1lc3NhZ2VzIGZyb20gc2VydmVyIGFuZCB0cmlnZ2VyIHVwZGF0ZUkxOG5UYWdzXG4gICAgICogQHBhcmFtIG5ld0xhbmd1YWdlIFN0cmluZ1xuICAgICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvblxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmxvYWRJMThOTWVzc2FnZXMgPSBmdW5jdGlvbiBsb2FkSTE4Tk1lc3NhZ2VzKG5ld0xhbmd1YWdlKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPD0gMSB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IG51bGwgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgdGhpcy5BcGlDbGllbnQuc3dpdGNoTGFuZ3VhZ2UobmV3TGFuZ3VhZ2UsIChmdW5jdGlvbiAodHJhbnNwb3J0KSB7XG4gICAgICAgICAgICBpZiAodHJhbnNwb3J0LnJlc3BvbnNlSlNPTikge1xuICAgICAgICAgICAgICAgIHRoaXMuTWVzc2FnZUhhc2ggPSB0cmFuc3BvcnQucmVzcG9uc2VKU09OO1xuICAgICAgICAgICAgICAgIGlmICh3aW5kb3cgJiYgd2luZG93Lk1lc3NhZ2VIYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5NZXNzYWdlSGFzaCA9IHRoaXMuTWVzc2FnZUhhc2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLk1lc3NhZ2VIYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLk1lc3NhZ2VIYXNoLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuTWVzc2FnZUhhc2hba2V5XSA9IHRoaXMuTWVzc2FnZUhhc2hba2V5XS5yZXBsYWNlKFwiXFxcXG5cIiwgXCJcXG5cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5Db250cm9sbGVyLnJlZnJlc2hHdWlBY3Rpb25zSTE4bigpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZFhtbFJlZ2lzdHJ5KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ29udGV4dFJlZnJlc2goKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRMYW5ndWFnZSA9IG5ld0xhbmd1YWdlO1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuYmluZCh0aGlzKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgbWFpbiBjb250cm9sbGVyXG4gICAgICogQHJldHVybnMgQWN0aW9uTWFuYWdlclxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmdldENvbnRyb2xsZXIgPSBmdW5jdGlvbiBnZXRDb250cm9sbGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5Db250cm9sbGVyO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBEaXNwbGF5IGFuIGluZm9ybWF0aW9uIG9yIGVycm9yIG1lc3NhZ2UgdG8gdGhlIHVzZXJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZVR5cGUgU3RyaW5nIEVSUk9SIG9yIFNVQ0NFU1NcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBTdHJpbmcgdGhlIG1lc3NhZ2VcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5kaXNwbGF5TWVzc2FnZSA9IGZ1bmN0aW9uIGRpc3BsYXlNZXNzYWdlKG1lc3NhZ2VUeXBlLCBtZXNzYWdlKSB7XG4gICAgICAgIHZhciB1cmxzID0gX3V0aWxMYW5nVXRpbHMyWydkZWZhdWx0J10ucGFyc2VVcmwobWVzc2FnZSk7XG4gICAgICAgIGlmICh1cmxzLmxlbmd0aCAmJiB0aGlzLnVzZXIgJiYgdGhpcy51c2VyLnJlcG9zaXRvcmllcykge1xuICAgICAgICAgICAgdXJscy5mb3JFYWNoKChmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwbyA9IHRoaXMudXNlci5yZXBvc2l0b3JpZXMuZ2V0KG1hdGNoLmhvc3QpO1xuICAgICAgICAgICAgICAgIGlmICghcmVwbykgcmV0dXJuO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBtZXNzYWdlLnJlcGxhY2UobWF0Y2gudXJsLCByZXBvLmxhYmVsICsgXCI6XCIgKyBtYXRjaC5wYXRoICsgbWF0Y2guZmlsZSk7XG4gICAgICAgICAgICB9KS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVzc2FnZVR5cGUgPT0gJ0VSUk9SJykgX2xhbmdMb2dnZXIyWydkZWZhdWx0J10uZXJyb3IobWVzc2FnZSk7ZWxzZSBfbGFuZ0xvZ2dlcjJbJ2RlZmF1bHQnXS5sb2cobWVzc2FnZSk7XG4gICAgICAgIGlmICh0aGlzLlVJKSB7XG4gICAgICAgICAgICB0aGlzLlVJLmRpc3BsYXlNZXNzYWdlKG1lc3NhZ2VUeXBlLCBtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAqXG4gICAgICogICAgICAgICAgUFJPWFkgTUVUSE9EUyBGT1IgREFUQU1PREVMXG4gICAgICpcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIHVwZGF0aW5nIHRoZSBkYXRhbW9kZWwgY29udGV4dFxuICAgICAqIEBwYXJhbSBhanhwQ29udGV4dE5vZGUgQWp4cE5vZGVcbiAgICAgKiBAcGFyYW0gYWp4cFNlbGVjdGVkTm9kZXMgQWp4cE5vZGVbXVxuICAgICAqIEBwYXJhbSBzZWxlY3Rpb25Tb3VyY2UgU3RyaW5nXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUudXBkYXRlQ29udGV4dERhdGEgPSBmdW5jdGlvbiB1cGRhdGVDb250ZXh0RGF0YShhanhwQ29udGV4dE5vZGUsIGFqeHBTZWxlY3RlZE5vZGVzLCBzZWxlY3Rpb25Tb3VyY2UpIHtcbiAgICAgICAgaWYgKGFqeHBDb250ZXh0Tm9kZSkge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5yZXF1aXJlQ29udGV4dENoYW5nZShhanhwQ29udGV4dE5vZGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhanhwU2VsZWN0ZWROb2Rlcykge1xuICAgICAgICAgICAgdGhpcy5fY29udGV4dEhvbGRlci5zZXRTZWxlY3RlZE5vZGVzKGFqeHBTZWxlY3RlZE5vZGVzLCBzZWxlY3Rpb25Tb3VyY2UpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBEYXRhTW9kZWxcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRDb250ZXh0SG9sZGVyID0gZnVuY3Rpb24gZ2V0Q29udGV4dEhvbGRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBOb2RlXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZ2V0Q29udGV4dE5vZGUgPSBmdW5jdGlvbiBnZXRDb250ZXh0Tm9kZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXIuZ2V0Q29udGV4dE5vZGUoKSB8fCBuZXcgX21vZGVsQWp4cE5vZGUyWydkZWZhdWx0J10oXCJcIik7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEFqeHBEYXRhTW9kZWxcbiAgICAgKi9cblxuICAgIFB5ZGlvLnByb3RvdHlwZS5nZXRVc2VyU2VsZWN0aW9uID0gZnVuY3Rpb24gZ2V0VXNlclNlbGVjdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnRleHRIb2xkZXI7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFjY2Vzc29yIGZvciBkYXRhbW9kZWwucmVxdWlyZUNvbnRleHRDaGFuZ2UoKVxuICAgICAqL1xuXG4gICAgUHlkaW8ucHJvdG90eXBlLmZpcmVDb250ZXh0UmVmcmVzaCA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0UmVmcmVzaCgpIHtcbiAgICAgICAgdGhpcy5nZXRDb250ZXh0SG9sZGVyKCkucmVxdWlyZUNvbnRleHRDaGFuZ2UodGhpcy5nZXRDb250ZXh0Tm9kZSgpLCB0cnVlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIGRhdGFtb2RlbC5yZXF1aXJlQ29udGV4dENoYW5nZSgpXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZmlyZU5vZGVSZWZyZXNoID0gZnVuY3Rpb24gZmlyZU5vZGVSZWZyZXNoKG5vZGVQYXRoT3JOb2RlLCBjb21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuZ2V0Q29udGV4dEhvbGRlcigpLnJlcXVpcmVOb2RlUmVsb2FkKG5vZGVQYXRoT3JOb2RlLCBjb21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWNjZXNzb3IgZm9yIGRhdGFtb2RlbC5yZXF1aXJlQ29udGV4dENoYW5nZSgpXG4gICAgICovXG5cbiAgICBQeWRpby5wcm90b3R5cGUuZmlyZUNvbnRleHRVcCA9IGZ1bmN0aW9uIGZpcmVDb250ZXh0VXAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdldENvbnRleHROb2RlKCkuaXNSb290KCkpIHJldHVybjtcbiAgICAgICAgdGhpcy51cGRhdGVDb250ZXh0RGF0YSh0aGlzLmdldENvbnRleHROb2RlKCkuZ2V0UGFyZW50KCkpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQcm94eSB0byBSZXNvdXJjZXNNYW5hZ2VyLnJlcXVpcmVMaWIgZm9yIGVhc2Ugb2Ygd3JpdGluZ1xuICAgICAqIEBwYXJhbSBtb2R1bGVcbiAgICAgKiBAcGFyYW0gcHJvbWlzZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuXG4gICAgUHlkaW8ucmVxdWlyZUxpYiA9IGZ1bmN0aW9uIHJlcXVpcmVMaWIobW9kdWxlKSB7XG4gICAgICAgIHZhciBwcm9taXNlID0gYXJndW1lbnRzLmxlbmd0aCA8PSAxIHx8IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMV07XG5cbiAgICAgICAgcmV0dXJuIHJlcXVpcmUoJ3B5ZGlvL2h0dHAvcmVzb3VyY2VzLW1hbmFnZXInKS5yZXF1aXJlTGliKG1vZHVsZSwgcHJvbWlzZSk7XG4gICAgfTtcblxuICAgIHJldHVybiBQeWRpbztcbn0pKF9sYW5nT2JzZXJ2YWJsZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFB5ZGlvO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4iXX0=