(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("canvas")); else if(typeof define === 'function' && define.amd) define(["canvas"], factory); else if(typeof exports === 'object') exports["ImglyKit"] = factory(require("canvas")); else root["ImglyKit"] = factory(root["canvas"]); })(this, function(__WEBPACK_EXTERNAL_MODULE_52__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { /*! * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _libRenderImage = __webpack_require__(1); var _libRenderImage2 = _interopRequireDefault(_libRenderImage); var _libImageExporter = __webpack_require__(2); var _libImageExporter2 = _interopRequireDefault(_libImageExporter); var _libVersionChecker = __webpack_require__(3); var _libVersionChecker2 = _interopRequireDefault(_libVersionChecker); var _constants = __webpack_require__(4); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var VERSION = '2.0.0-2'; /** * @class * @param {Object} options * @param {Image} [options.image] - The source image * @param {HTMLElement} [options.container] - Specifies where the UI should be * added to. If none is given, the UI * will automatically be disabled. * @param {Boolean} [options.ui.enabled=true] - Enables or disables the UI * @param {Boolean} [options.renderOnWindowResize] - Specifies whether the canvas * should re-render itself when * the window is being resized. * @param {String} [options.assetsUrl='assets'] - The base path for all external assets. * @param {String} [options.renderer='webgl'] - The renderer identifier. Can either * be 'webgl' or 'canvas'. */ var ImglyKit = (function () { function ImglyKit(options) { _classCallCheck(this, ImglyKit); // `options` is required if (typeof options === 'undefined') { throw new Error('No options given.'); } // Set default options options = _libUtils2['default'].defaults(options, { assetsUrl: 'assets', container: null, renderOnWindowResize: false, versionCheck: true }); options.ui = options.ui || {}; options.ui = _libUtils2['default'].defaults(options.ui, { enabled: true }); if (typeof options.image === 'undefined' && !options.ui.enabled) { throw new Error('`options.image` needs to be set when UI is disabled.'); } /** * @type {Object} * @private */ this._options = options; /** * The stack of {@link Operation} instances that will be used * to render the final Image * @type {Array.} */ this.operationsStack = []; /** * The registered UI types that can be selected via the `ui` option * @type {Object.} * @private */ this._registeredUIs = {}; // Register the default UIs this._registerUIs(); /** * The registered operations * @type {Object.} */ this._registeredOperations = {}; // Register the default operations this._registerOperations(); if (typeof window !== 'undefined' && this._options.versionCheck) { this._versionChecker = new _libVersionChecker2['default'](VERSION); } if (this._options.ui.enabled) { this._initUI(); if (this._options.renderOnWindowResize) { this._handleWindowResize(); } } } _createClass(ImglyKit, [{ key: 'render', /** * Renders the image * @param {ImglyKit.RenderType} [renderType=ImglyKit.RenderType.DATAURL] - The output type * @param {ImglyKit.ImageFormat} [imageFormat=ImglyKit.ImageFormat.PNG] - The output image format * @param {string} [dimensions] - The final dimensions of the image * @param {Number} [quality] - The image quality, between 0 and 1 * @return {Promise} */ value: function render(renderType, imageFormat, dimensions, quality) { var _this = this; var settings = _libImageExporter2['default'].validateSettings(renderType, imageFormat); renderType = settings.renderType; imageFormat = settings.imageFormat; // Create a RenderImage var renderImage = new _libRenderImage2['default'](this._options.image, this.operationsStack, dimensions, this._options.renderer); // Set all operations to dirty, since we have another webgl renderer for (var i = 0; i < this.operationsStack.length; i++) { var operation = this.operationsStack[i]; if (!operation) { continue; } operation.dirty = true; } // Initiate image rendering return renderImage.render().then(function () { var canvas = renderImage.getRenderer().getCanvas(); return _libImageExporter2['default']['export'](_this._options.image, canvas, renderType, imageFormat, quality); }); } }, { key: 'reset', /** * Resets all custom and selected operations */ value: function reset() {} }, { key: 'getAssetPath', /** * Returns the asset path for the given filename * @param {String} asset * @return {String} */ value: function getAssetPath(asset) { var isBrowser = typeof window !== 'undefined'; if (isBrowser) { /* istanbul ignore next */ return this._options.assetsUrl + '/' + asset; } else { var path = __webpack_require__(51); return path.resolve(this._options.assetsUrl, asset); } } }, { key: '_handleWindowResize', /** * If `options.renderOnWindowResize` is set to true, this function * will re-render the canvas with a slight delay so that it won't * cause lagging of the resize * @private */ value: function _handleWindowResize() { var _this2 = this; var timer = null; window.addEventListener('resize', function () { if (timer !== null) { clearTimeout(timer); } timer = setTimeout(function () { timer = null; _this2.ui.render(); }, 300); }); } }, { key: '_registerUIs', /** * Registers all default UIs * @private */ value: function _registerUIs() { this.registerUI(ImglyKit.NightUI); } }, { key: '_registerOperations', /** * Registers all default operations * @private */ value: function _registerOperations() { for (var operationName in ImglyKit.Operations) { this.registerOperation(ImglyKit.Operations[operationName]); } } }, { key: 'registerOperation', /** * Registers the given operation * @param {ImglyKit.Operation} operation - The operation class */ value: function registerOperation(operation) { this._registeredOperations[operation.prototype.identifier] = operation; if (this.ui) { this.ui.addOperation(operation); } } }, { key: 'registerUI', /** * Registers the given UI * @param {UI} ui */ value: function registerUI(ui) { this._registeredUIs[ui.prototype.identifier] = ui; } }, { key: '_initUI', /** * Initializes the UI * @private */ /* istanbul ignore next */ value: function _initUI() { var UI; if (this._options.ui.enabled === true) { // Select the first UI by default UI = _libUtils2['default'].values(this._registeredUIs)[0]; } if (!UI) { return; } /** * @type {ImglyKit.UI} */ this.ui = new UI(this, this._options); } }, { key: 'getOperationFromStack', /** * Returns the Operation instance with the given identifier, * if it exists * @param {String} identifier * @returns {Operation} */ value: function getOperationFromStack(identifier) { var operation = this.operationsStack.filter(function (operation) { return operation.identifier === identifier; })[0]; return operation; } }, { key: 'run', /** * Runs the UI, if present */ value: function run() { if (typeof this.ui !== 'undefined') { this.ui.run(); } } }, { key: 'registeredOperations', get: function () { return this._registeredOperations; } }]); return ImglyKit; })(); /** * The current version of the SDK * @name ImglyKit.version * @internal Keep in sync with package.json */ ImglyKit.version = VERSION; // Exposed classes ImglyKit.RenderImage = _libRenderImage2['default']; ImglyKit.Color = __webpack_require__(6); ImglyKit.Filter = __webpack_require__(7); ImglyKit.Operation = __webpack_require__(8); ImglyKit.Operations = {}; ImglyKit.Operations.Filters = __webpack_require__(9); ImglyKit.Operations.Crop = __webpack_require__(10); ImglyKit.Operations.Rotation = __webpack_require__(11); ImglyKit.Operations.Saturation = __webpack_require__(12); ImglyKit.Operations.Contrast = __webpack_require__(13); ImglyKit.Operations.Brightness = __webpack_require__(14); ImglyKit.Operations.Flip = __webpack_require__(15); ImglyKit.Operations.TiltShift = __webpack_require__(16); ImglyKit.Operations.RadialBlur = __webpack_require__(17); ImglyKit.Operations.Text = __webpack_require__(18); ImglyKit.Operations.Stickers = __webpack_require__(19); ImglyKit.Operations.Frames = __webpack_require__(20); ImglyKit.Filters = {}; ImglyKit.Filters.A15 = __webpack_require__(21); ImglyKit.Filters.Breeze = __webpack_require__(22); ImglyKit.Filters.BW = __webpack_require__(23); ImglyKit.Filters.BWHard = __webpack_require__(24); ImglyKit.Filters.Celsius = __webpack_require__(25); ImglyKit.Filters.Chest = __webpack_require__(26); ImglyKit.Filters.Fixie = __webpack_require__(27); ImglyKit.Filters.Food = __webpack_require__(28); ImglyKit.Filters.Fridge = __webpack_require__(29); ImglyKit.Filters.Front = __webpack_require__(30); ImglyKit.Filters.Glam = __webpack_require__(31); ImglyKit.Filters.Gobblin = __webpack_require__(32); ImglyKit.Filters.K1 = __webpack_require__(33); ImglyKit.Filters.K2 = __webpack_require__(34); ImglyKit.Filters.K6 = __webpack_require__(35); ImglyKit.Filters.KDynamic = __webpack_require__(36); ImglyKit.Filters.Lenin = __webpack_require__(37); ImglyKit.Filters.Lomo = __webpack_require__(38); ImglyKit.Filters.Mellow = __webpack_require__(39); ImglyKit.Filters.Morning = __webpack_require__(40); ImglyKit.Filters.Orchid = __webpack_require__(41); ImglyKit.Filters.Pola = __webpack_require__(42); ImglyKit.Filters.Pola669 = __webpack_require__(43); ImglyKit.Filters.Quozi = __webpack_require__(44); ImglyKit.Filters.Semired = __webpack_require__(45); ImglyKit.Filters.Sunny = __webpack_require__(46); ImglyKit.Filters.Texas = __webpack_require__(47); ImglyKit.Filters.X400 = __webpack_require__(48); // Exposed constants ImglyKit.RenderType = _constants.RenderType; ImglyKit.ImageFormat = _constants.ImageFormat; ImglyKit.Vector2 = __webpack_require__(49); // UI ImglyKit.NightUI = __webpack_require__(50); exports['default'] = ImglyKit; module.exports = exports['default']; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _imageDimensions = __webpack_require__(53); var _imageDimensions2 = _interopRequireDefault(_imageDimensions); var _mathVector2 = __webpack_require__(49); var _mathVector22 = _interopRequireDefault(_mathVector2); var _renderersCanvasRenderer = __webpack_require__(54); var _renderersCanvasRenderer2 = _interopRequireDefault(_renderersCanvasRenderer); var _renderersWebglRenderer = __webpack_require__(55); var _renderersWebglRenderer2 = _interopRequireDefault(_renderersWebglRenderer); /** * Handles the image rendering process * @class * @alias ImglyKit.RenderImage * @param {Image} image * @param {Array.} operationsStack * @param {string} dimensions * @param {string} preferredRenderer * @private */ var RenderImage = (function () { function RenderImage(image, operationsStack, dimensions, preferredRenderer) { _classCallCheck(this, RenderImage); /** * @type {Object} * @private */ this._options = { preferredRenderer: preferredRenderer }; /** * @type {Boolean} * @private * @default false */ this._webglEnabled = false; /** * @type {Renderer} * @private */ this._renderer = null; /** * @type {Image} * @private */ this._image = image; /** * @type {Array.} * @private */ this._stack = operationsStack; /** * @type {ImglyKit.ImageDimensions} * @private */ this._dimensions = new _imageDimensions2['default'](dimensions); /** * @type {Vector2} * @private */ this._initialDimensions = new _mathVector22['default'](this._image.width, this._image.height); this._initRenderer(); } _createClass(RenderImage, [{ key: '_initRenderer', /** * Creates a renderer (canvas or webgl, depending on support) * @return {Promise} * @private */ value: function _initRenderer() { /* istanbul ignore if */ if (_renderersWebglRenderer2['default'].isSupported() && this._options.preferredRenderer !== 'canvas') { this._renderer = new _renderersWebglRenderer2['default'](this._initialDimensions); this._webglEnabled = true; } else if (_renderersCanvasRenderer2['default'].isSupported()) { this._renderer = new _renderersCanvasRenderer2['default'](this._initialDimensions); this._webglEnabled = false; } /* istanbul ignore if */ if (this._renderer === null) { throw new Error('Neither Canvas nor WebGL renderer are supported.'); } this._renderer.drawImage(this._image); } }, { key: 'render', /** * Renders the image * @return {Promise} */ value: function render() { var _this = this; var stack = this.sanitizedStack; var validationPromises = []; for (var i = 0; i < stack.length; i++) { var operation = stack[i]; validationPromises.push(operation.validateSettings()); } return Promise.all(validationPromises).then(function () { var promises = []; for (var i = 0; i < stack.length; i++) { var operation = stack[i]; promises.push(operation.render(_this._renderer)); } return Promise.all(promises); }).then(function () { return _this._renderer.renderFinal(); }).then(function () { var initialSize = _this._renderer.getSize(); var finalDimensions = _this._dimensions.calculateFinalDimensions(initialSize); if (finalDimensions.equals(initialSize)) { // No need to resize return; } return _this._renderer.resizeTo(finalDimensions); }); } }, { key: 'getRenderer', /** * Returns the renderer * @return {Renderer} */ value: function getRenderer() { return this._renderer; } }, { key: 'sanitizedStack', /** * Returns the operations stack without falsy values * @type {Array.} */ get: function () { var sanitizedStack = []; for (var i = 0; i < this._stack.length; i++) { var operation = this._stack[i]; if (!operation) continue; sanitizedStack.push(operation); } return sanitizedStack; } }]); return RenderImage; })(); exports['default'] = RenderImage; module.exports = exports['default']; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process) {/* global Image */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _constants = __webpack_require__(4); var _exifRestorer = __webpack_require__(56); var _exifRestorer2 = _interopRequireDefault(_exifRestorer); var _utils = __webpack_require__(5); var _utils2 = _interopRequireDefault(_utils); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); /** * @class * @alias ImglyKit.ImageExporter * @private */ var ImageExporter = (function () { function ImageExporter() { _classCallCheck(this, ImageExporter); } _createClass(ImageExporter, null, [{ key: 'validateSettings', value: function validateSettings(renderType, imageFormat) { var settings = { renderType: renderType, imageFormat: imageFormat }; // Validate RenderType if (typeof settings.renderType !== 'undefined' && settings.renderType !== null && _utils2['default'].values(_constants.RenderType).indexOf(settings.renderType) === -1) { throw new Error('Invalid render type: ' + settings.renderType); } else if (typeof renderType === 'undefined') { settings.renderType = _constants.RenderType.DATAURL; } // Validate ImageFormat if (typeof settings.imageFormat !== 'undefined' && settings.imageFormat !== null && _utils2['default'].values(_constants.ImageFormat).indexOf(settings.imageFormat) === -1) { throw new Error('Invalid image format: ' + settings.imageFormat); } else if (typeof imageFormat === 'undefined') { settings.imageFormat = _constants.ImageFormat.PNG; } // Render type 'buffer' only available in node if (settings.renderType === _constants.RenderType.BUFFER && typeof process === 'undefined') { throw new Error('Render type \'buffer\' is only available when using node.js'); } return settings; } }, { key: 'export', /** * Exports the image from the given canvas with the given options * @param {Image} image * @param {Canvas} canvas * @param {ImglyKit.RenderType} renderType * @param {ImglyKit.ImageFormat} imageFormat * @param {Number} quality = 0.8 * @return {Promise} */ value: function _export(image, canvas, renderType, imageFormat) { var quality = arguments[4] === undefined ? 0.8 : arguments[4]; return new _vendorPromise2['default'](function (resolve, reject) { var result = undefined; if (renderType === _constants.RenderType.IMAGE || renderType === _constants.RenderType.DATAURL) { if (typeof window === 'undefined') { // Quality not supported in node environment / node-canvas result = canvas.toDataURL(imageFormat); } else { result = canvas.toDataURL(imageFormat, quality); } // When image's `src` attribute is a jpeg data url, we can restore // the exif information var jpegMatch = /^data:image\/jpeg/i; if (image.src.match(jpegMatch) && result.match(jpegMatch)) { result = _exifRestorer2['default'].restore(image.src, result); } } if (renderType === _constants.RenderType.IMAGE) { var outputImage = undefined; /* istanbul ignore else */ if (typeof window === 'undefined') { // Not a browser environment var CanvasImage = __webpack_require__(52).Image; outputImage = new CanvasImage(); } else { outputImage = new Image(); } outputImage.src = result; resolve(outputImage); } else if (renderType === _constants.RenderType.DATAURL) { resolve(result); } else if (renderType === _constants.RenderType.BUFFER) { resolve(canvas.toBuffer()); } else if (renderType === _constants.RenderType.MSBLOB) { resolve(canvas.msToBlob()); } else if (renderType === _constants.RenderType.BLOB) { canvas.toBlob(function (blob) { resolve(blob); }, imageFormat, quality); } }); } }]); return ImageExporter; })(); exports['default'] = ImageExporter; module.exports = exports['default']; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(74))) /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var VERSION_CHECK_FN = 'imglySDKVersionCallback'; var VERSION_CHECK_URL = 'http://sdk.img.ly/version.json?sdk=html5&jsoncallback=' + VERSION_CHECK_FN; var VersionChecker = (function () { function VersionChecker(version) { _classCallCheck(this, VersionChecker); this._version = version; this._check(); } _createClass(VersionChecker, [{ key: '_check', /** * Checks if this version of the SDK is outdated * @private */ value: function _check() { var self = this; window[VERSION_CHECK_FN] = function (response) { if (response.outdated) { console.warn('imgly-sdk-html5: Your version ' + self._version + ' is outdated.'); console.warn('imgly-sdk-html5: Current version is ' + response.version + '.'); } }; var script = document.createElement('script'); script.src = VERSION_CHECK_URL + '&version=' + this._version; script.async = true; document.getElementsByTagName('head')[0].appendChild(script); } }]); return VersionChecker; })(); exports['default'] = VersionChecker; module.exports = exports['default']; /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * The available render types * @enum {string} * @alias ImglyKit.RenderType */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var RenderType = { IMAGE: 'image', DATAURL: 'data-url', BUFFER: 'buffer', BLOB: 'blob', MSBLOB: 'ms-blob' }; exports.RenderType = RenderType; /** * The available output image formats * @enum {string} * @alias ImglyKit.ImageFormat */ var ImageFormat = { PNG: 'image/png', JPEG: 'image/jpeg' }; exports.ImageFormat = ImageFormat; /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { /* global HTMLElement */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _mathVector2 = __webpack_require__(49); var _mathVector22 = _interopRequireDefault(_mathVector2); /** * Provides utility functions for internal use * @class * @alias ImglyKit.Utils * @private */ var Utils = (function () { function Utils() { _classCallCheck(this, Utils); } _createClass(Utils, null, [{ key: 'isArray', /** * Checks if the given object is an Array * @param {Object} object * @return {Boolean} */ value: function isArray(object) { return Object.prototype.toString.call(object) === '[object Array]'; } }, { key: 'select', /** * Returns the items selected by the given selector * @param {Array} items * @param {ImglyKit~Selector} selector - The selector * @return {Array} The selected items */ value: function select(items) { var selector = arguments[1] === undefined ? null : arguments[1]; if (selector === null) { return items; } // Turn string parameter into an array if (typeof selector === 'string') { selector = selector.split(',').map(function (identifier) { return identifier.trim(); }); } // Turn array parameter into an object with `only` if (Utils.isArray(selector)) { selector = { only: selector }; } if (typeof selector.only !== 'undefined') { if (typeof selector.only === 'string') { selector.only = selector.only.split(',').map(function (identifier) { return identifier.trim(); }); } // Select only the given identifiers return items.filter(function (item) { return selector.only.indexOf(item) !== -1; }); } else if (typeof selector.except !== 'undefined') { if (typeof selector.except === 'string') { selector.except = selector.except.split(',').map(function (identifier) { return identifier.trim(); }); } // Select all but the given identifiers return items.filter(function (item) { return selector.except.indexOf(item) === -1; }); } throw new Error('Utils#select failed to filter items.'); } }, { key: 'values', /** * Returns the given object's values as an array * @param {Object} object * @returns {Array<*>} */ value: function values(object) { var values = []; for (var key in object) { values.push(object[key]); } return values; } }, { key: 'isDOMElement', /** * Checks if the given object is a DOM element * @param {Object} o * @return {Boolean} */ /* istanbul ignore next */ value: function isDOMElement(o) { return typeof HTMLElement === 'object' ? o instanceof HTMLElement : o && typeof o === 'object' && o !== null && o.nodeType === 1 && typeof o.nodeName === 'string'; } }, { key: 'getEventPosition', /** * Gets the x and y position for the given event. * @param {Event} e * @return {Vector2} */ value: function getEventPosition(e) { var x = e.pageX; var y = e.pageY; if (e.type.indexOf('touch') !== -1) { x = e.touches[0].pageX; y = e.touches[0].pageY; } return new _mathVector22['default'](x, y); } }, { key: 'resizeVectorToFit', /** * Resizes the given vector to fit inside the given max size while maintaining * the aspect ratio * @param {Vector2} vector * @param {Vector2} max * @return {Vector2} */ value: function resizeVectorToFit(vector, max) { var scale = Math.min(max.x / vector.x, max.y / vector.y); var newSize = vector.clone().multiply(scale); return newSize; } }, { key: 'defaults', /** * Assigns own enumerable properties of source object(s) to the destination * object for all destination properties that resolve to undefined. Once a * property is set, additional values of the same property are ignored. * @param {Object} object * @param {Object} ...sources * @return {Object} */ value: function defaults(object) { for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { sources[_key - 1] = arguments[_key]; } // Shallow clone var newObject = {}; for (var key in object) { newObject[key] = object[key]; } // Clone sources for (var i = 0; i < sources.length; i++) { var source = sources[i]; for (var key in source) { if (typeof newObject[key] === 'undefined') { newObject[key] = source[key]; } } } return newObject; } }, { key: 'extend', /** * Assigns own enumerable properties of source object(s) to the destination * object. Subsequent sources overwrite property assignments of previous * sources. * @param {Object} object * @param {Object} ...sources * @return {Object} */ value: function extend(object) { for (var _len2 = arguments.length, sources = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { sources[_key2 - 1] = arguments[_key2]; } // Shallow clone var newObject = {}; for (var key in object) { newObject[key] = object[key]; } // Extend sources for (var i = 0; i < sources.length; i++) { var source = sources[i]; for (var key in source) { newObject[key] = source[key]; } } return newObject; } }, { key: 'fetch', /** * Gets the property value at `path` of `object` * @param {Object} object * @param {String} key * @param {?} [defaultValue] * @return {?} */ value: function fetch(object, path, defaultValue) { // Replace indexes with property accessors path = path.replace(/\[(\w+)\]/g, '.$1'); // Strip leading dot (when path begins with [0] for example) path = path.replace(/^\./, ''); var pathSegments = path.split('.'); for (var i = 0; i < pathSegments.length; i++) { var segment = pathSegments[i]; object = object[segment]; if (!object) { break; } } if (typeof object === 'undefined') { object = defaultValue; } return object; } }]); return Utils; })(); exports['default'] = Utils; module.exports = exports['default']; /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Represents a color * @class * @alias ImglyKit.Color * @param {Number} r * @param {Number} g * @param {Number} b * @param {Number} [a] * @private */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Color = (function () { function Color(r, g, b, a) { _classCallCheck(this, Color); if (typeof a === 'undefined') { a = 1; } this.r = r; this.g = g; this.b = b; this.a = a; } _createClass(Color, [{ key: 'toRGBA', /** * Returns an rgba() representation of this color * @return {String} */ value: function toRGBA() { var colors = [Math.round(this.r * 255), Math.round(this.g * 255), Math.round(this.b * 255), this.a]; return 'rgba(' + colors.join(',') + ')'; } }, { key: 'toHex', /** * Returns a hex representation of this color * @return {String} */ value: function toHex() { var components = [this._componentToHex(Math.round(this.r * 255)), this._componentToHex(Math.round(this.g * 255)), this._componentToHex(Math.round(this.b * 255))]; return '#' + components.join(''); } }, { key: 'toGLColor', /** * Returns an array with 4 values (0...1) * @return {Array.} */ value: function toGLColor() { return [this.r, this.g, this.b, this.a]; } }, { key: 'toRGBGLColor', /** * Returns an array with 3 values (0...1) * @return {Array.} */ value: function toRGBGLColor() { return [this.r, this.g, this.b]; } }, { key: 'toHSV', /** * Converts the RGB value to HSV * @return {Array.} */ value: function toHSV() { var max = Math.max(this.r, this.g, this.b); var min = Math.min(this.r, this.g, this.b); var h = undefined; var s = undefined; var v = max; var d = max - min; s = max === 0 ? 0 : d / max; if (max === min) { h = 0 // achromatic ; } else { switch (max) { case this.r: h = (this.g - this.b) / d + (this.g < this.b ? 6 : 0); break; case this.g: h = (this.b - this.r) / d + 2; break; case this.b: h = (this.r - this.g) / d + 4; break; } h /= 6; } return [h, s, v]; } }, { key: 'fromHSV', /** * Sets the RGB values of this color to match the given HSV values * @param {Number} h * @param {Number} s * @param {Number} v */ value: function fromHSV(h, s, v) { var r = this.r; var g = this.g; var b = this.b; var i = Math.floor(h * 6); var f = h * 6 - i; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } this.r = r; this.g = g; this.b = b; } }, { key: 'clone', /** * Returns a clone of the current color * @return {Color} */ value: function clone() { return new Color(this.r, this.g, this.b, this.a); } }, { key: '_componentToHex', /** * Returns the given number as hex * @param {Number} component * @return {String} * @private */ value: function _componentToHex(component) { var hex = component.toString(16); return hex.length === 1 ? '0' + hex : hex; } }, { key: 'toString', /** * Returns the string representation of this color * @returns {String} */ value: function toString() { return 'Color(' + this.r + ', ' + this.g + ', ' + this.b + ', ' + this.a + ')'; } }]); return Color; })(); exports['default'] = Color; module.exports = exports['default']; /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { /* jshint unused: false */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Base class for filters. Extendable via {@link ImglyKit.Filter#extend} * @class * @alias ImglyKit.Filter */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Filter = (function () { function Filter() { _classCallCheck(this, Filter); } _createClass(Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { /* istanbul ignore next */ throw new Error('Filter#render is abstract and not implemented in inherited class.'); } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return null; } }]); return Filter; })(); /** * To create an {@link ImglyKit.Filter} class of your own, call this * method and provide instance properties and functions. * @function */ Filter.extend = __webpack_require__(58); // Exposed classes Filter.PrimitivesStack = __webpack_require__(59); Filter.Primitives = {}; Filter.Primitives.Saturation = __webpack_require__(60); Filter.Primitives.LookupTable = __webpack_require__(61); Filter.Primitives.ToneCurve = __webpack_require__(62); Filter.Primitives.SoftColorOverlay = __webpack_require__(63); Filter.Primitives.Desaturation = __webpack_require__(64); Filter.Primitives.X400 = __webpack_require__(65); Filter.Primitives.Grayscale = __webpack_require__(66); Filter.Primitives.Contrast = __webpack_require__(67); Filter.Primitives.Glow = __webpack_require__(68); Filter.Primitives.Gobblin = __webpack_require__(69); Filter.Primitives.Brightness = __webpack_require__(70); exports['default'] = Filter; module.exports = exports['default']; /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { /* jshint unused:false */ /* jshint -W083 */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); /** * To create an {@link ImglyKit.Operation} class of your own, call this * method and provide instance properties and functions. * @function */ var _libExtend = __webpack_require__(58); var _libExtend2 = _interopRequireDefault(_libExtend); /** * Base class for Operations. Extendable via {@link ImglyKit.Operation#extend}. * @class * @alias ImglyKit.Operation */ var Operation = (function (_EventEmitter) { function Operation(kit, options) { _classCallCheck(this, Operation); _get(Object.getPrototypeOf(Operation.prototype), 'constructor', this).call(this); this._kit = kit; this.availableOptions = _libUtils2['default'].extend(this.availableOptions || {}, { numberFormat: { type: 'string', 'default': 'relative', available: ['absolute', 'relative'] } }); this._dirty = true; this._glslPrograms = {}; this._uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0; var v = c === 'x' ? r : r & 3 | 8; return v.toString(16); }); this._initOptions(options || {}); } _inherits(Operation, _EventEmitter); _createClass(Operation, [{ key: 'validateSettings', /** * Checks whether this Operation can be applied the way it is configured * @return {Promise} */ value: function validateSettings() { var _this = this; var identifier = this.identifier; return new _vendorPromise2['default'](function (resolve, reject) { // Check for required options for (var optionName in _this.availableOptions) { var optionConfig = _this.availableOptions[optionName]; if (optionConfig.required && typeof _this._options[optionName] === 'undefined') { return reject(new Error('Operation `' + identifier + '`: Option `' + optionName + '` is required.')); } } resolve(); }); } }, { key: 'render', /** * Applies this operation * @param {Renderer} renderer * @return {Promise} * @abstract */ value: function render(renderer) { var renderFn = undefined; if (renderer.identifier === 'webgl') { /* istanbul ignore next */ renderFn = this._renderWebGL.bind(this); } else { renderFn = this._renderCanvas.bind(this); } // Handle caching if (this._dirty) { renderFn(renderer); renderer.cache(this._uuid); this._dirty = false; } else { renderer.drawCached(this._uuid); } } }, { key: '_renderWebGL', /** * Applies this operation using WebGL * @return {WebGLRenderer} renderer * @private */ /* istanbul ignore next */ value: function _renderWebGL() { throw new Error('Operation#_renderWebGL is abstract and not implemented in inherited class.'); } }, { key: '_renderCanvas', /** * Applies this operation using Canvas2D * @return {CanvasRenderer} renderer * @private */ value: function _renderCanvas() { throw new Error('Operation#_renderCanvas is abstract and not implemented in inherited class.'); } }, { key: '_initOptions', /** * Goes through the available options, sets _options defaults * @param {Object} userOptions * @private */ value: function _initOptions(userOptions) { this._options = {}; // Set defaults, create getters and setters var optionName, option, capitalized; var self = this; for (optionName in this.availableOptions) { capitalized = optionName.charAt(0).toUpperCase() + optionName.slice(1); option = this.availableOptions[optionName]; // Create setter and getter var fn = function fn(optionName, option) { self['set' + capitalized] = function (value) { self._setOption(optionName, value); }; // Default getter self['get' + capitalized] = function () { return self._getOption(optionName); }; }; fn(optionName, option); // Set default if available if (typeof option['default'] !== 'undefined') { this['set' + capitalized](option['default']); } } // Overwrite options with the ones given by user for (optionName in userOptions) { // Check if option is available if (typeof this.availableOptions[optionName] === 'undefined') { throw new Error('Invalid option: ' + optionName); } // Call setter capitalized = optionName.charAt(0).toUpperCase() + optionName.slice(1); this['set' + capitalized](userOptions[optionName]); } } }, { key: 'set', /** * Sets the given options * @param {Object} options */ value: function set(options) { for (var optionName in options) { this._setOption(optionName, options[optionName], false); } this.emit('update'); } }, { key: '_getOption', /** * Returns the value for the given option * @param {String} optionName * @return {*} * @private */ value: function _getOption(optionName) { return this._options[optionName]; } }, { key: '_setOption', /** * Sets the value for the given option, validates it * @param {String} optionName * @param {*} value * @param {Boolean} update * @private */ value: function _setOption(optionName, value) { var update = arguments[2] === undefined ? true : arguments[2]; var optionConfig = this.availableOptions[optionName]; var identifier = this.identifier; if (typeof optionConfig.setter !== 'undefined') { value = optionConfig.setter.call(this, value); } if (typeof optionConfig.validation !== 'undefined') { optionConfig.validation(value); } switch (optionConfig.type) { // String options case 'string': if (typeof value !== 'string') { throw new Error('Operation `' + identifier + '`: Option `' + optionName + '` has to be a string.'); } // String value restrictions var available = optionConfig.available; if (typeof available !== 'undefined' && available.indexOf(value) === -1) { throw new Error('Operation `' + identifier + '`: Invalid value for `' + optionName + '` (valid values are: ' + optionConfig.available.join(', ') + ')'); } this._options[optionName] = value; break; // Number options case 'number': if (typeof value !== 'number') { throw new Error('Operation `' + identifier + '`: Option `' + optionName + '` has to be a number.'); } this._options[optionName] = value; break; // Boolean options case 'boolean': if (typeof value !== 'boolean') { throw new Error('Operation `' + identifier + '`: Option `' + optionName + '` has to be a boolean.'); } this._options[optionName] = value; break; // Vector2 options case 'vector2': if (!(value instanceof _libMathVector22['default'])) { throw new Error('Operation `' + identifier + '`: Option `' + optionName + '` has to be an instance of ImglyKit.Vector2.'); } this._options[optionName] = value.clone(); break; // Color options case 'color': if (!(value instanceof _libColor2['default'])) { throw new Error('Operation `' + identifier + '`: Option `' + optionName + '` has to be an instance of ImglyKit.Color.'); } this._options[optionName] = value; break; // Object options case 'object': this._options[optionName] = value; break; } this._dirty = true; if (update) { this.emit('update'); } } }, { key: 'getNewDimensions', /** * Gets the new dimensions * @param {Renderer} renderer * @param {Vector2} [dimensions] * @return {Vector2} * @private */ value: function getNewDimensions(renderer, dimensions) { var canvas = renderer.getCanvas(); dimensions = dimensions || new _libMathVector22['default'](canvas.width, canvas.height); return dimensions; } }, { key: 'dirty', /** * Sets this operation to dirty, so that it will re-render next time * @param {Boolean} dirty = true */ set: function (dirty) { this._dirty = dirty; }, /** * Returns the dirty state * @type {Boolean} */ get: function () { return this._dirty; } }]); return Operation; })(_libEventEmitter2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ Operation.prototype.identifier = null; Operation.extend = _libExtend2['default']; exports['default'] = Operation; module.exports = exports['default']; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _filtersIdentityFilter = __webpack_require__(71); var _filtersIdentityFilter2 = _interopRequireDefault(_filtersIdentityFilter); /** * An operation that can apply a selected filter * * @class * @alias ImglyKit.Operations.FiltersOperation * @extends ImglyKit.Operation */ var FiltersOperation = (function (_Operation) { function FiltersOperation() { _classCallCheck(this, FiltersOperation); if (_Operation != null) { _Operation.apply(this, arguments); } } _inherits(FiltersOperation, _Operation); _createClass(FiltersOperation, [{ key: '_renderWebGL', /** * Renders the filter using WebGL * @param {WebGLRenderer} renderer * @override */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { this._render(renderer); } }, { key: '_renderCanvas', /** * Renders the filter using Canvas2D * @param {CanvasRenderer} renderer * @override */ value: function _renderCanvas(renderer) { this._render(renderer); } }, { key: '_render', /** * Renders the filter (all renderers supported) * @param {Renderer} renderer * @private */ value: function _render(renderer) { this._selectedFilter.render(renderer); } }]); return FiltersOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ FiltersOperation.prototype.identifier = 'filters'; /** * Specifies the available options for this operation * @type {Object} */ FiltersOperation.prototype.availableOptions = { filter: { type: 'object', 'default': _filtersIdentityFilter2['default'], setter: function setter(Filter) { this._selectedFilter = new Filter(); return Filter; } } }; exports['default'] = FiltersOperation; module.exports = exports['default']; /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); /** * An operation that can crop out a part of the image * * @class * @alias ImglyKit.Operations.CropOperation * @extends ImglyKit.Operation */ var CropOperation = (function (_Operation) { function CropOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, CropOperation); _get(Object.getPrototypeOf(CropOperation.prototype), 'constructor', this).apply(this, args); /** * The fragment shader used for this operation */ this.fragmentShader = '\n precision mediump float;\n uniform sampler2D u_image;\n varying vec2 v_texCoord;\n uniform vec2 u_cropStart;\n uniform vec2 u_cropEnd;\n\n void main() {\n vec2 size = u_cropEnd - u_cropStart;\n gl_FragColor = texture2D(u_image, v_texCoord * size + u_cropStart);\n }\n '; } _inherits(CropOperation, _Operation); _createClass(CropOperation, [{ key: '_renderWebGL', /** * Rotates and crops the image using WebGL * @param {WebGLRenderer} renderer * @override * @private */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var start = this._options.start.clone(); var end = this._options.end.clone(); if (this._options.numberFormat === 'absolute') { start.divide(canvasSize); end.divide(canvasSize); } // 0..1 > 1..0 on y-axis var originalStartY = start.y; start.y = 1 - end.y; end.y = 1 - originalStartY; // The new size var newDimensions = this.getNewDimensions(renderer); // Resize the canvas canvas.width = newDimensions.x; canvas.height = newDimensions.y; // Run the cropping shader renderer.runShader(null, this.fragmentShader, { uniforms: { u_cropStart: { type: '2f', value: [start.x, start.y] }, u_cropEnd: { type: '2f', value: [end.x, end.y] } } }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas * @param {CanvasRenderer} renderer * @override * @private */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var dimensions = new _libMathVector22['default'](canvas.width, canvas.height); var newDimensions = this.getNewDimensions(renderer); // Create a temporary canvas to draw to var newCanvas = renderer.createCanvas(); newCanvas.width = newDimensions.x; newCanvas.height = newDimensions.y; var newContext = newCanvas.getContext('2d'); // The upper left corner of the cropped area on the original image var startPosition = this._options.start.clone(); if (this._options.numberFormat === 'relative') { startPosition.multiply(dimensions); } // Draw the source canvas onto the new one newContext.drawImage(canvas, startPosition.x, startPosition.y, // source x, y newDimensions.x, newDimensions.y, // source dimensions 0, 0, // destination x, y newDimensions.x, newDimensions.y // destination dimensions ); // Set the new canvas renderer.setCanvas(newCanvas); } }, { key: 'getNewDimensions', /** * Gets the new dimensions * @param {Renderer} renderer * @param {Vector2} [dimensions] * @return {Vector2} */ value: function getNewDimensions(renderer, dimensions) { var canvas = renderer.getCanvas(); dimensions = dimensions || new _libMathVector22['default'](canvas.width, canvas.height); var newDimensions = this._options.end.clone().subtract(this._options.start); if (this._options.numberFormat === 'relative') { newDimensions.multiply(dimensions); } return newDimensions; } }]); return CropOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ CropOperation.prototype.identifier = 'crop'; /** * Specifies the available options for this operation * @type {Object} */ CropOperation.prototype.availableOptions = { start: { type: 'vector2', required: true, 'default': new _libMathVector22['default'](0, 0) }, end: { type: 'vector2', required: true, 'default': new _libMathVector22['default'](1, 1) } }; exports['default'] = CropOperation; module.exports = exports['default']; /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); /** * An operation that can crop out a part of the image and rotates it * * @class * @alias ImglyKit.Operations.RotationOperation * @extends ImglyKit.Operation */ var RotationOperation = (function (_Operation) { function RotationOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, RotationOperation); _get(Object.getPrototypeOf(RotationOperation.prototype), 'constructor', this).apply(this, args); /** * The fragment shader used for this operation */ this.vertexShader = '\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n varying vec2 v_texCoord;\n uniform mat3 u_matrix;\n\n void main() {\n gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);\n v_texCoord = a_texCoord;\n }\n '; } _inherits(RotationOperation, _Operation); _createClass(RotationOperation, [{ key: '_renderWebGL', /** * Rotates the image using WebGL * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var canvas = renderer.getCanvas(); var actualDegrees = this._options.degrees % 360; // If we're not rotating by 180 degrees, we need to resize the canvas // and the texture if (actualDegrees % 180 !== 0) { var newDimensions = this.getNewDimensions(renderer); // Resize the canvas canvas.width = newDimensions.x; canvas.height = newDimensions.y; } // Build the rotation matrix var radians = actualDegrees * (Math.PI / 180); var c = Math.cos(radians); var s = Math.sin(radians); var rotationMatrix = [c, -s, 0, s, c, 0, 0, 0, 1]; // Run the shader renderer.runShader(this.vertexShader, null, { uniforms: { u_matrix: { type: 'mat3fv', value: rotationMatrix } } }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var actualDegrees = this._options.degrees % 360; var newDimensions = this.getNewDimensions(renderer); // Create a rotated canvas var newCanvas = renderer.createCanvas(); newCanvas.width = newDimensions.x; newCanvas.height = newDimensions.y; var newContext = newCanvas.getContext('2d'); newContext.save(); // Translate the canvas newContext.translate(newCanvas.width / 2, newCanvas.height / 2); // Rotate the canvas newContext.rotate(actualDegrees * (Math.PI / 180)); // Create a temporary canvas so that we can draw the image // with the applied transformation var tempCanvas = renderer.cloneCanvas(); newContext.drawImage(tempCanvas, -canvas.width / 2, -canvas.height / 2); // Restore old transformation newContext.restore(); renderer.setCanvas(newCanvas); } }, { key: 'getNewDimensions', /** * Gets the new dimensions * @param {Renderer} renderer * @param {Vector2} [dimensions] * @return {Vector2} */ value: function getNewDimensions(renderer, dimensions) { var canvas = renderer.getCanvas(); dimensions = dimensions || new _libMathVector22['default'](canvas.width, canvas.height); var actualDegrees = this._options.degrees % 360; if (actualDegrees % 180 !== 0) { var tempX = dimensions.x; dimensions.x = dimensions.y; dimensions.y = tempX; } return dimensions; } }]); return RotationOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ RotationOperation.prototype.identifier = 'rotation'; /** * Specifies the available options for this operation * @type {Object} */ RotationOperation.prototype.availableOptions = { degrees: { type: 'number', 'default': 0, validation: function validation(value) { if (value % 90 !== 0) { throw new Error('RotationOperation: `rotation` has to be a multiple of 90.'); } } } }; exports['default'] = RotationOperation; module.exports = exports['default']; /***/ }, /* 12 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _filtersPrimitivesStack = __webpack_require__(59); var _filtersPrimitivesStack2 = _interopRequireDefault(_filtersPrimitivesStack); var _filtersPrimitivesSaturation = __webpack_require__(60); var _filtersPrimitivesSaturation2 = _interopRequireDefault(_filtersPrimitivesSaturation); /** * @class * @alias ImglyKit.Operations.SaturationOperation * @extends ImglyKit.Operation */ var SaturationOperation = (function (_Operation) { function SaturationOperation() { _classCallCheck(this, SaturationOperation); if (_Operation != null) { _Operation.apply(this, arguments); } } _inherits(SaturationOperation, _Operation); _createClass(SaturationOperation, [{ key: '_renderWebGL', /** * Renders the saturation using WebGL * @param {WebGLRenderer} renderer * @override */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { this._render(renderer); } }, { key: '_renderCanvas', /** * Renders the saturation using Canvas2D * @param {CanvasRenderer} renderer * @override */ value: function _renderCanvas(renderer) { this._render(renderer); } }, { key: '_render', /** * Renders the saturation (all renderers supported) * @param {Renderer} renderer * @private */ value: function _render(renderer) { if (!this._stack) { this._stack = new _filtersPrimitivesStack2['default'](); this._primitive = new _filtersPrimitivesSaturation2['default']({ saturation: this._options.saturation }); this._stack.add(this._primitive); } // @TODO // Primitives should have the same option logic as operations - which // should allow us to do `this._primitive.setSaturation` this._primitive.options.saturation = this._options.saturation; this._stack.render(renderer); } }]); return SaturationOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ SaturationOperation.prototype.identifier = 'saturation'; /** * Specifies the available options for this operation * @type {Object} */ SaturationOperation.prototype.availableOptions = { saturation: { type: 'number', 'default': 1 } }; exports['default'] = SaturationOperation; module.exports = exports['default']; /***/ }, /* 13 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _filtersPrimitivesStack = __webpack_require__(59); var _filtersPrimitivesStack2 = _interopRequireDefault(_filtersPrimitivesStack); var _filtersPrimitivesContrast = __webpack_require__(67); var _filtersPrimitivesContrast2 = _interopRequireDefault(_filtersPrimitivesContrast); /** * @class * @alias ImglyKit.Operations.ContrastOperation * @extends ImglyKit.Operation */ var ContrastOperation = (function (_Operation) { function ContrastOperation() { _classCallCheck(this, ContrastOperation); if (_Operation != null) { _Operation.apply(this, arguments); } } _inherits(ContrastOperation, _Operation); _createClass(ContrastOperation, [{ key: '_renderWebGL', /** * Renders the contrast using WebGL * @param {WebGLRenderer} renderer * @override */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { this._render(renderer); } }, { key: '_renderCanvas', /** * Renders the contrast using Canvas2D * @param {CanvasRenderer} renderer * @override */ value: function _renderCanvas(renderer) { this._render(renderer); } }, { key: '_render', /** * Renders the contrast (all renderers supported) * @param {Renderer} renderer * @private */ value: function _render(renderer) { if (!this._stack) { this._stack = new _filtersPrimitivesStack2['default'](); this._primitive = new _filtersPrimitivesContrast2['default']({ contrast: this._options.contrast }); this._stack.add(this._primitive); } // @TODO // Primitives should have the same option logic as operations - which // should allow us to do `this._primitive.setContrast` this._primitive.options.contrast = this._options.contrast; this._stack.render(renderer); } }]); return ContrastOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ ContrastOperation.prototype.identifier = 'contrast'; /** * Specifies the available options for this operation * @type {Object} */ ContrastOperation.prototype.availableOptions = { contrast: { type: 'number', 'default': 1 } }; exports['default'] = ContrastOperation; module.exports = exports['default']; /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _filtersPrimitivesStack = __webpack_require__(59); var _filtersPrimitivesStack2 = _interopRequireDefault(_filtersPrimitivesStack); var _filtersPrimitivesBrightness = __webpack_require__(70); var _filtersPrimitivesBrightness2 = _interopRequireDefault(_filtersPrimitivesBrightness); /** * @class * @alias ImglyKit.Operations.BrightnessOperation * @extends ImglyKit.Operation */ var BrightnessOperation = (function (_Operation) { function BrightnessOperation() { _classCallCheck(this, BrightnessOperation); if (_Operation != null) { _Operation.apply(this, arguments); } } _inherits(BrightnessOperation, _Operation); _createClass(BrightnessOperation, [{ key: '_renderWebGL', /** * Renders the brightness using WebGL * @param {WebGLRenderer} renderer * @override */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { this._render(renderer); } }, { key: '_renderCanvas', /** * Renders the brightness using Canvas2D * @param {CanvasRenderer} renderer * @override */ value: function _renderCanvas(renderer) { this._render(renderer); } }, { key: '_render', /** * Renders the brightness (all renderers supported) * @param {Renderer} renderer * @private */ value: function _render(renderer) { if (!this._stack) { this._stack = new _filtersPrimitivesStack2['default'](); this._primitive = new _filtersPrimitivesBrightness2['default']({ brightness: this._options.brightness }); this._stack.add(this._primitive); } // @TODO // Primitives should have the same option logic as operations - which // should allow us to do `this._primitive.setBrightness` this._primitive.options.brightness = this._options.brightness; this._stack.render(renderer); } }]); return BrightnessOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ BrightnessOperation.prototype.identifier = 'brightness'; /** * Specifies the available options for this operation * @type {Object} */ BrightnessOperation.prototype.availableOptions = { brightness: { type: 'number', 'default': 0 } }; exports['default'] = BrightnessOperation; module.exports = exports['default']; /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); /** * An operation that can flip the canvas * * @class * @alias ImglyKit.Operations.FlipOperation * @extends ImglyKit.Operation */ var FlipOperation = (function (_Operation) { function FlipOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, FlipOperation); _get(Object.getPrototypeOf(FlipOperation.prototype), 'constructor', this).apply(this, args); /** * The fragment shader used for this operation */ this.fragmentShader = '\n precision mediump float;\n uniform sampler2D u_image;\n varying vec2 v_texCoord;\n uniform bool u_flipVertical;\n uniform bool u_flipHorizontal;\n\n void main() {\n vec2 texCoord = vec2(v_texCoord);\n if (u_flipVertical) {\n texCoord.y = 1.0 - texCoord.y;\n }\n if (u_flipHorizontal) {\n texCoord.x = 1.0 - texCoord.x;\n }\n gl_FragColor = texture2D(u_image, texCoord);\n }\n '; } _inherits(FlipOperation, _Operation); _createClass(FlipOperation, [{ key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { renderer.runShader(null, this.fragmentShader, { uniforms: { u_flipVertical: { type: 'f', value: this._options.vertical }, u_flipHorizontal: { type: 'f', value: this._options.horizontal } } }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var context = renderer.getContext(); var scaleX = 1, scaleY = 1; var translateX = 0, translateY = 0; if (this._options.horizontal) { scaleX = -1; translateX = canvas.width; } if (this._options.vertical) { scaleY = -1; translateY = canvas.height; } // Save the current state context.save(); // Apply the transformation context.translate(translateX, translateY); context.scale(scaleX, scaleY); // Create a temporary canvas so that we can draw the image // with the applied transformation var tempCanvas = renderer.cloneCanvas(); context.drawImage(tempCanvas, 0, 0); // Restore old transformation context.restore(); } }]); return FlipOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ FlipOperation.prototype.identifier = 'flip'; /** * Specifies the available options for this operation * @type {Object} */ FlipOperation.prototype.availableOptions = { horizontal: { type: 'boolean', 'default': false }, vertical: { type: 'boolean', 'default': false } }; exports['default'] = FlipOperation; module.exports = exports['default']; /***/ }, /* 16 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ('value' in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _vendorStackBlur = __webpack_require__(73); var _vendorStackBlur2 = _interopRequireDefault(_vendorStackBlur); /** * An operation that can crop out a part of the image * * @class * @alias ImglyKit.Operations.TiltShiftOperation * @extends ImglyKit.Operation */ var TiltShiftOperation = (function (_Operation) { function TiltShiftOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, TiltShiftOperation); _get(Object.getPrototypeOf(TiltShiftOperation.prototype), 'constructor', this).apply(this, args); /** * The fragment shader used for this operation * @internal Based on evanw's glfx.js tilt shift shader: * https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js */ this._fragmentShader = '\n precision mediump float;\n uniform sampler2D u_image;\n uniform float blurRadius;\n uniform float gradientRadius;\n uniform vec2 start;\n uniform vec2 end;\n uniform vec2 delta;\n uniform vec2 texSize;\n varying vec2 v_texCoord;\n\n float random(vec3 scale, float seed) {\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n }\n\n void main() {\n vec4 color = vec4(0.0);\n float total = 0.0;\n\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n\n vec2 normal = normalize(vec2(start.y - end.y, end.x - start.x));\n float radius = smoothstep(0.0, 1.0, abs(dot(v_texCoord * texSize - start, normal)) / gradientRadius) * blurRadius;\n for (float t = -30.0; t <= 30.0; t++) {\n float percent = (t + offset - 0.5) / 30.0;\n float weight = 1.0 - abs(percent);\n vec4 sample = texture2D(u_image, v_texCoord + delta * percent * radius / texSize);\n\n sample.rgb *= sample.a;\n\n color += sample * weight;\n total += weight;\n }\n\n gl_FragColor = color / total;\n gl_FragColor.rgb /= gl_FragColor.a + 0.00001;\n }\n '; this._cachedBlurredCanvas = null; this._lastBlurRadius = this._options.blurRadius; this._lastGradientRadius = this._options.gradientRadius; } _inherits(TiltShiftOperation, _Operation); _createClass(TiltShiftOperation, [{ key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var start = this._options.start.clone(); var end = this._options.end.clone(); if (this._options.numberFormat === 'relative') { start.multiply(canvasSize); end.multiply(canvasSize); } start.y = canvasSize.y - start.y; end.y = canvasSize.y - end.y; var delta = end.clone().subtract(start); var d = Math.sqrt(delta.x * delta.x + delta.y * delta.y); var uniforms = { blurRadius: { type: 'f', value: this._options.blurRadius }, gradientRadius: { type: 'f', value: this._options.gradientRadius }, start: { type: '2f', value: [start.x, start.y] }, end: { type: '2f', value: [end.x, end.y] }, delta: { type: '2f', value: [delta.x / d, delta.y / d] }, texSize: { type: '2f', value: [canvas.width, canvas.height] } }; if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: uniforms }); // Update delta for second pass uniforms.delta.value = [-delta.y / d, delta.x / d]; renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: uniforms }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var optionsChanged = this._options.blurRadius !== this._lastBlurRadius || this._options.gradientRadius !== this._lastGradientRadius; var blurryCanvas = undefined; if (optionsChanged || this._cachedBlurredCanvas === null) { // Blur and cache canvas blurryCanvas = this._blurCanvas(renderer); this._cachedBlurredCanvas = blurryCanvas; this._lastBlurRadius = this._options.blurRadius; this._lastGradientRadius = this._options.gradientRadius; } else { // Use cached canvas blurryCanvas = this._cachedBlurredCanvas; } var maskCanvas = this._createMask(renderer); this._applyMask(canvas, blurryCanvas, maskCanvas); } }, { key: '_blurCanvas', /** * Creates a blurred copy of the canvas * @param {CanvasRenderer} renderer * @return {Canvas} * @private */ value: function _blurCanvas(renderer) { var newCanvas = renderer.cloneCanvas(); var blurryContext = newCanvas.getContext('2d'); var blurryImageData = blurryContext.getImageData(0, 0, newCanvas.width, newCanvas.height); _vendorStackBlur2['default'].stackBlurCanvasRGBA(blurryImageData, 0, 0, newCanvas.width, newCanvas.height, this._options.blurRadius); blurryContext.putImageData(blurryImageData, 0, 0); return newCanvas; } }, { key: '_createMask', /** * Creates the mask canvas * @param {CanvasRenderer} renderer * @return {Canvas} * @private */ value: function _createMask(renderer) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var gradientRadius = this._options.gradientRadius; var maskCanvas = renderer.createCanvas(canvas.width, canvas.height); var maskContext = maskCanvas.getContext('2d'); var start = this._options.start.clone(); var end = this._options.end.clone(); if (this._options.numberFormat === 'relative') { start.multiply(canvasSize); end.multiply(canvasSize); } var dist = end.clone().subtract(start); var middle = start.clone().add(dist.clone().divide(2)); var totalDist = Math.sqrt(Math.pow(dist.x, 2) + Math.pow(dist.y, 2)); var factor = dist.clone().divide(totalDist); var gradientStart = middle.clone().add(gradientRadius * factor.y, -gradientRadius * factor.x); var gradientEnd = middle.clone().add(-gradientRadius * factor.y, gradientRadius * factor.x); // Build gradient var gradient = maskContext.createLinearGradient(gradientStart.x, gradientStart.y, gradientEnd.x, gradientEnd.y); gradient.addColorStop(0, '#000000'); gradient.addColorStop(0.5, '#FFFFFF'); gradient.addColorStop(1, '#000000'); // Draw gradient maskContext.fillStyle = gradient; maskContext.fillRect(0, 0, canvas.width, canvas.height); return maskCanvas; } }, { key: '_applyMask', /** * Applies the blur and mask to the input canvas * @param {Canvas} inputCanvas * @param {Canvas} blurryCanvas * @param {Canvas} maskCanvas * @private */ value: function _applyMask(inputCanvas, blurryCanvas, maskCanvas) { var inputContext = inputCanvas.getContext('2d'); var blurryContext = blurryCanvas.getContext('2d'); var maskContext = maskCanvas.getContext('2d'); var inputImageData = inputContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height); var pixels = inputImageData.data; var blurryPixels = blurryContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height).data; var maskPixels = maskContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height).data; for (var i = 0; i < maskPixels.length; i++) { var alpha = maskPixels[i] / 255; pixels[i] = alpha * pixels[i] + (1 - alpha) * blurryPixels[i]; } inputContext.putImageData(inputImageData, 0, 0); } }, { key: 'dirty', /** * Sets the dirty state of this operation * @param {Boolean} dirty * @comment Since blur operations do seperate caching of the * blurred canvas, we need to invalidate the cache when the * dirty state changes. */ set: function (dirty) { _set(Object.getPrototypeOf(TiltShiftOperation.prototype), 'dirty', dirty, this); this._cachedBlurredCanvas = null; }, /** * Returns the dirty state * @type {Boolean} */ get: function () { return _get(Object.getPrototypeOf(TiltShiftOperation.prototype), 'dirty', this); } }]); return TiltShiftOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ TiltShiftOperation.prototype.identifier = 'tilt-shift'; /** * Specifies the available options for this operation * @type {Object} */ TiltShiftOperation.prototype.availableOptions = { start: { type: 'vector2', 'default': new _libMathVector22['default'](0, 0.5) }, end: { type: 'vector2', 'default': new _libMathVector22['default'](1, 0.5) }, blurRadius: { type: 'number', 'default': 30 }, gradientRadius: { type: 'number', 'default': 50 } }; exports['default'] = TiltShiftOperation; module.exports = exports['default']; /***/ }, /* 17 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ('value' in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _vendorStackBlur = __webpack_require__(73); var _vendorStackBlur2 = _interopRequireDefault(_vendorStackBlur); /** * An operation that can crop out a part of the image * * @class * @alias ImglyKit.Operations.RadialBlurOperation * @extends ImglyKit.Operation */ var RadialBlurOperation = (function (_Operation) { function RadialBlurOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, RadialBlurOperation); _get(Object.getPrototypeOf(RadialBlurOperation.prototype), 'constructor', this).apply(this, args); /** * The fragment shader used for this operation * @internal Based on evanw's glfx.js tilt shift shader: * https://github.com/evanw/glfx.js/blob/master/src/filters/blur/tiltshift.js */ this._fragmentShader = '\n precision mediump float;\n uniform sampler2D u_image;\n uniform float blurRadius;\n uniform float gradientRadius;\n uniform vec2 position;\n uniform vec2 delta;\n uniform vec2 texSize;\n varying vec2 v_texCoord;\n\n float random(vec3 scale, float seed) {\n return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);\n }\n\n void main() {\n vec4 color = vec4(0.0);\n float total = 0.0;\n\n float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);\n float radius = smoothstep(0.0, 1.0, abs(distance(v_texCoord * texSize, position)) / (gradientRadius * 2.0)) * blurRadius;\n for (float t = -30.0; t <= 30.0; t++) {\n float percent = (t + offset - 0.5) / 30.0;\n float weight = 1.0 - abs(percent);\n vec4 sample = texture2D(u_image, v_texCoord + delta * percent * radius / texSize);\n\n sample.rgb *= sample.a;\n\n color += sample * weight;\n total += weight;\n }\n\n gl_FragColor = color / total;\n gl_FragColor.rgb /= gl_FragColor.a + 0.00001;\n }\n '; this._cachedBlurredCanvas = null; this._lastBlurRadius = this._options.blurRadius; this._lastGradientRadius = this._options.gradientRadius; } _inherits(RadialBlurOperation, _Operation); _createClass(RadialBlurOperation, [{ key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var position = this._options.position.clone(); position.y = 1 - position.y; if (this._options.numberFormat === 'relative') { position.multiply(canvasSize); } var uniforms = { blurRadius: { type: 'f', value: this._options.blurRadius }, gradientRadius: { type: 'f', value: this._options.gradientRadius }, position: { type: '2f', value: [position.x, position.y] }, texSize: { type: '2f', value: [canvas.width, canvas.height] }, delta: { type: '2f', value: [1, 1] } }; // Setup program if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: uniforms }); // Update delta for second pass uniforms.delta.value = [-1, 1]; renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: uniforms }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var blurRadiusChanged = this._options.blurRadius !== this._lastBlurRadius; var blurryCanvas = undefined; if (blurRadiusChanged || this._cachedBlurredCanvas === null) { // Blur and cache canvas blurryCanvas = this._blurCanvas(renderer); this._cachedBlurredCanvas = blurryCanvas; this._lastBlurRadius = this._options.blurRadius; this._lastGradientRadius = this._options.gradientRadius; } else { // Use cached canvas blurryCanvas = this._cachedBlurredCanvas; } var maskCanvas = this._createMask(renderer); this._applyMask(canvas, blurryCanvas, maskCanvas); } }, { key: '_blurCanvas', /** * Creates a blurred copy of the canvas * @param {CanvasRenderer} renderer * @return {Canvas} * @private */ value: function _blurCanvas(renderer) { var newCanvas = renderer.cloneCanvas(); var blurryContext = newCanvas.getContext('2d'); var blurryImageData = blurryContext.getImageData(0, 0, newCanvas.width, newCanvas.height); _vendorStackBlur2['default'].stackBlurCanvasRGBA(blurryImageData, 0, 0, newCanvas.width, newCanvas.height, this._options.blurRadius); blurryContext.putImageData(blurryImageData, 0, 0); return newCanvas; } }, { key: '_createMask', /** * Creates the mask canvas * @param {CanvasRenderer} renderer * @return {Canvas} * @private */ value: function _createMask(renderer) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var gradientRadius = this._options.gradientRadius; var maskCanvas = renderer.createCanvas(canvas.width, canvas.height); var maskContext = maskCanvas.getContext('2d'); var position = this._options.position.clone(); if (this._options.numberFormat === 'relative') { position.multiply(canvasSize); } // Build gradient var gradient = maskContext.createRadialGradient(position.x, position.y, 0, position.x, position.y, gradientRadius); gradient.addColorStop(0, '#FFFFFF'); gradient.addColorStop(1, '#000000'); // Draw gradient maskContext.fillStyle = gradient; maskContext.fillRect(0, 0, canvas.width, canvas.height); return maskCanvas; } }, { key: '_applyMask', /** * Applies the blur and mask to the input canvas * @param {Canvas} inputCanvas * @param {Canvas} blurryCanvas * @param {Canvas} maskCanvas * @private */ value: function _applyMask(inputCanvas, blurryCanvas, maskCanvas) { var inputContext = inputCanvas.getContext('2d'); var blurryContext = blurryCanvas.getContext('2d'); var maskContext = maskCanvas.getContext('2d'); var inputImageData = inputContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height); var pixels = inputImageData.data; var blurryPixels = blurryContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height).data; var maskPixels = maskContext.getImageData(0, 0, inputCanvas.width, inputCanvas.height).data; var index, alpha; for (var y = 0; y < inputCanvas.height; y++) { for (var x = 0; x < inputCanvas.width; x++) { index = (y * inputCanvas.width + x) * 4; alpha = maskPixels[index] / 255; pixels[index] = alpha * pixels[index] + (1 - alpha) * blurryPixels[index]; pixels[index + 1] = alpha * pixels[index + 1] + (1 - alpha) * blurryPixels[index + 1]; pixels[index + 2] = alpha * pixels[index + 2] + (1 - alpha) * blurryPixels[index + 2]; } } inputContext.putImageData(inputImageData, 0, 0); } }, { key: 'dirty', /** * Sets the dirty state of this operation * @param {Boolean} dirty * @comment Since blur operations do seperate caching of the * blurred canvas, we need to invalidate the cache when the * dirty state changes. */ set: function (dirty) { _set(Object.getPrototypeOf(RadialBlurOperation.prototype), 'dirty', dirty, this); this._cachedBlurredCanvas = null; }, /** * Returns the dirty state * @type {Boolean} */ get: function () { return _get(Object.getPrototypeOf(RadialBlurOperation.prototype), 'dirty', this); } }]); return RadialBlurOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ RadialBlurOperation.prototype.identifier = 'radial-blur'; /** * Specifies the available options for this operation * @type {Object} */ RadialBlurOperation.prototype.availableOptions = { position: { type: 'vector2', 'default': new _libMathVector22['default'](0.5, 0.5) }, gradientRadius: { type: 'number', 'default': 50 }, blurRadius: { type: 'number', 'default': 20 } }; exports['default'] = RadialBlurOperation; module.exports = exports['default']; /***/ }, /* 18 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); /** * An operation that can draw text on the canvas * * @class * @alias ImglyKit.Operations.TextOperation * @extends ImglyKit.Operation */ var TextOperation = (function (_Operation) { function TextOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, TextOperation); _get(Object.getPrototypeOf(TextOperation.prototype), 'constructor', this).apply(this, args); /** * The texture index used for the text * @type {Number} * @private */ this._textureIndex = 1; /** * The fragment shader used for this operation */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform sampler2D u_textImage;\n uniform vec2 u_position;\n uniform vec2 u_size;\n\n void main() {\n vec4 color0 = texture2D(u_image, v_texCoord);\n vec2 relative = (v_texCoord - u_position) / u_size;\n\n if (relative.x >= 0.0 && relative.x <= 1.0 &&\n relative.y >= 0.0 && relative.y <= 1.0) {\n\n vec4 color1 = texture2D(u_textImage, relative);\n\n // GL_SOURCE_ALPHA, GL_ONE_MINUS_SOURCE_ALPHA\n gl_FragColor = color1 + color0 * (1.0 - color1.a);\n\n } else {\n\n gl_FragColor = color0;\n\n }\n }\n '; } _inherits(TextOperation, _Operation); _createClass(TextOperation, [{ key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var textCanvas = this._renderTextCanvas(renderer); var canvas = renderer.getCanvas(); var gl = renderer.getContext(); var position = this._options.position.clone(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var size = new _libMathVector22['default'](textCanvas.width, textCanvas.height).divide(canvasSize); if (this._options.numberFormat === 'absolute') { position.divide(canvasSize); } position.y = 1 - position.y; // Invert y position.y -= size.y; // Fix y // Adjust vertical alignment if (this._options.verticalAlignment === 'center') { position.y += size.y / 2; } else if (this._options.verticalAlignment === 'bottom') { position.y += size.y; } // Adjust horizontal alignment if (this._options.alignment === 'center') { position.x -= size.x / 2; } else if (this._options.alignment === 'right') { position.x -= size.x; } // Upload the texture gl.activeTexture(gl.TEXTURE0 + this._textureIndex); this._texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this._texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); // Set premultiplied alpha gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textCanvas); gl.activeTexture(gl.TEXTURE0); // Execute the shader renderer.runShader(null, this._fragmentShader, { uniforms: { u_textImage: { type: 'i', value: this._textureIndex }, u_position: { type: '2f', value: [position.x, position.y] }, u_size: { type: '2f', value: [size.x, size.y] } } }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer */ value: function _renderCanvas(renderer) { var textCanvas = this._renderTextCanvas(renderer); var canvas = renderer.getCanvas(); var context = renderer.getContext(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var scaledPosition = this._options.position.clone(); if (this._options.numberFormat === 'relative') { scaledPosition.multiply(canvasSize); } // Adjust vertical alignment if (this._options.verticalAlignment === 'center') { scaledPosition.y -= textCanvas.height / 2; } else if (this._options.verticalAlignment === 'bottom') { scaledPosition.y -= textCanvas.height; } // Adjust horizontal alignment if (this._options.alignment === 'center') { scaledPosition.x -= textCanvas.width / 2; } else if (this._options.alignment === 'right') { scaledPosition.x -= textCanvas.width; } context.drawImage(textCanvas, scaledPosition.x, scaledPosition.y); } }, { key: '_renderTextCanvas', /** * Renders the text canvas that will be used as a texture in WebGL * and as an image in canvas * @return {Canvas} * @private */ value: function _renderTextCanvas(renderer) { var line = undefined, lineNum = undefined; var canvas = renderer.createCanvas(); var context = canvas.getContext('2d'); var outputCanvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](outputCanvas.width, outputCanvas.height); var maxWidth = this._options.maxWidth; var actualFontSize = this._options.fontSize * canvasSize.y; var actualLineHeight = this._options.lineHeight * actualFontSize; if (this._options.numberFormat === 'relative') { maxWidth *= renderer.getCanvas().width; } // Apply text options this._applyTextOptions(renderer, context); var boundingBox = new _libMathVector22['default'](); var lines = this._options.text.split('\n'); if (typeof maxWidth !== 'undefined') { // Calculate the bounding box boundingBox.x = maxWidth; lines = this._buildOutputLines(context, maxWidth); } else { for (lineNum = 0; lineNum < lines.length; lineNum++) { line = lines[lineNum]; boundingBox.x = Math.max(boundingBox.x, context.measureText(line).width); } } // Calculate boundingbox height boundingBox.y = actualLineHeight * lines.length; // Resize the canvas canvas.width = boundingBox.x; canvas.height = boundingBox.y; // Get the context again context = canvas.getContext('2d'); // Render background color context.fillStyle = this._options.backgroundColor.toRGBA(); context.fillRect(0, 0, canvas.width, canvas.height); // Apply text options this._applyTextOptions(renderer, context); // Draw lines for (lineNum = 0; lineNum < lines.length; lineNum++) { line = lines[lineNum]; this._drawText(context, line, actualLineHeight * lineNum); } return canvas; } }, { key: '_applyTextOptions', /** * Applies the text options on the given context * @param {Renderer} renderer * @param {RenderingContext2D} context * @private */ value: function _applyTextOptions(renderer, context) { var canvas = renderer.getCanvas(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var actualFontSize = this._options.fontSize * canvasSize.y; context.font = this._options.fontWeight + ' ' + actualFontSize + 'px ' + this._options.fontFamily; context.textBaseline = 'top'; context.textAlign = this._options.alignment; context.fillStyle = this._options.color.toRGBA(); } }, { key: '_buildOutputLines', /** * Iterate over all lines and split them into multiple lines, depending * on the width they need * @param {RenderingContext2d} context * @param {Number} maxWidth * @return {Array.} * @private */ value: function _buildOutputLines(context, maxWidth) { var inputLines = this._options.text.split('\n'); var outputLines = []; var currentChars = []; for (var lineNum = 0; lineNum < inputLines.length; lineNum++) { var inputLine = inputLines[lineNum]; var lineChars = inputLine.split(''); if (lineChars.length === 0) { outputLines.push(''); } for (var charNum = 0; charNum < lineChars.length; charNum++) { var currentChar = lineChars[charNum]; currentChars.push(currentChar); var currentLine = currentChars.join(''); var lineWidth = context.measureText(currentLine).width; if (lineWidth > maxWidth && currentChars.length === 1) { outputLines.push(currentChars[0]); currentChars = []; } else if (lineWidth > maxWidth) { // Remove the last word var lastWord = currentChars.pop(); // Add the line, clear the words outputLines.push(currentChars.join('')); currentChars = []; // Make sure to use the last word for the next line currentChars = [lastWord]; } else if (charNum === lineChars.length - 1) { // Add the line, clear the words outputLines.push(currentChars.join('')); currentChars = []; } } // Line ended, but there's words left if (currentChars.length) { outputLines.push(currentChars.join('')); currentChars = []; } } return outputLines; } }, { key: '_drawText', /** * Draws the given line onto the given context at the given Y position * @param {RenderingContext2D} context * @param {String} text * @param {Number} y * @private */ value: function _drawText(context, text, y) { var canvas = context.canvas; if (this._options.alignment === 'center') { context.fillText(text, canvas.width / 2, y); } else if (this._options.alignment === 'left') { context.fillText(text, 0, y); } else if (this._options.alignment === 'right') { context.fillText(text, canvas.width, y); } } }]); return TextOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ TextOperation.prototype.identifier = 'text'; /** * Specifies the available options for this operation * @type {Object} */ TextOperation.prototype.availableOptions = { fontSize: { type: 'number', 'default': 0.1 }, lineHeight: { type: 'number', 'default': 1.1 }, fontFamily: { type: 'string', 'default': 'Times New Roman' }, fontWeight: { type: 'string', 'default': 'normal' }, alignment: { type: 'string', 'default': 'left', available: ['left', 'center', 'right'] }, verticalAlignment: { type: 'string', 'default': 'top', available: ['top', 'center', 'bottom'] }, color: { type: 'color', 'default': new _libColor2['default'](1, 1, 1, 1) }, backgroundColor: { type: 'color', 'default': new _libColor2['default'](0, 0, 0, 0) }, position: { type: 'vector2', 'default': new _libMathVector22['default'](0, 0) }, text: { type: 'string', required: true }, maxWidth: { type: 'number', 'default': 1 } }; exports['default'] = TextOperation; module.exports = exports['default']; /***/ }, /* 19 */ /***/ function(module, exports, __webpack_require__) { /* global Image */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); /** * An operation that can draw text on the canvas * * @class * @alias ImglyKit.Operations.StickersOperation * @extends ImglyKit.Operation */ var StickersOperation = (function (_Operation) { function StickersOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, StickersOperation); _get(Object.getPrototypeOf(StickersOperation.prototype), 'constructor', this).apply(this, args); /** * The texture index used for the sticker * @type {Number} * @private */ this._textureIndex = 1; /** * The fragment shader used for this operation */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform sampler2D u_stickerImage;\n uniform vec2 u_position;\n uniform vec2 u_size;\n\n void main() {\n vec4 color0 = texture2D(u_image, v_texCoord);\n vec2 relative = (v_texCoord - u_position) / u_size;\n\n if (relative.x >= 0.0 && relative.x <= 1.0 &&\n relative.y >= 0.0 && relative.y <= 1.0) {\n\n vec4 color1 = texture2D(u_stickerImage, relative);\n\n // GL_SOURCE_ALPHA, GL_ONE_MINUS_SOURCE_ALPHA\n gl_FragColor = color1 + color0 * (1.0 - color1.a);\n\n } else {\n\n gl_FragColor = color0;\n\n }\n }\n '; this._loadedStickers = {}; } _inherits(StickersOperation, _Operation); _createClass(StickersOperation, [{ key: 'render', /** * Applies this operation * @param {Renderer} renderer * @return {Promise} * @abstract */ value: function render(renderer) { var self = this; return this._loadSticker().then(function (image) { if (renderer.identifier === 'webgl') { /* istanbul ignore next */ return self._renderWebGL(renderer, image); } else { return self._renderCanvas(renderer, image); } }); } }, { key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer * @param {Image} image * @private */ /* istanbul ignore next */ value: function _renderWebGL(renderer, image) { var canvas = renderer.getCanvas(); var gl = renderer.getContext(); var position = this._options.position.clone(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); if (this._options.numberFormat === 'absolute') { position.divide(canvasSize); } var size = new _libMathVector22['default'](image.width, image.height); if (typeof this._options.size !== 'undefined') { size.copy(this._options.size); if (this._options.numberFormat === 'relative') { size.multiply(canvasSize); } // Calculate image ratio, scale by width var ratio = image.height / image.width; size.y = size.x * ratio; } size.divide(canvasSize); position.y = 1 - position.y; // Invert y position.y -= size.y; // Fix y // Upload the texture gl.activeTexture(gl.TEXTURE0 + this._textureIndex); this._texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this._texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); // Set premultiplied alpha gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.activeTexture(gl.TEXTURE0); // Execute the shader renderer.runShader(null, this._fragmentShader, { uniforms: { u_stickerImage: { type: 'i', value: this._textureIndex }, u_position: { type: '2f', value: [position.x, position.y] }, u_size: { type: '2f', value: [size.x, size.y] } } }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer * @param {Image} image * @private */ value: function _renderCanvas(renderer, image) { var canvas = renderer.getCanvas(); var context = renderer.getContext(); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var scaledPosition = this._options.position.clone(); if (this._options.numberFormat === 'relative') { scaledPosition.multiply(canvasSize); } var size = new _libMathVector22['default'](image.width, image.height); if (typeof this._options.size !== 'undefined') { size.copy(this._options.size); if (this._options.numberFormat === 'relative') { size.multiply(canvasSize); } } context.drawImage(image, 0, 0, image.width, image.height, scaledPosition.x, scaledPosition.y, size.x, size.y); } }, { key: '_loadSticker', /** * Loads the sticker * @return {Promise} * @private */ value: function _loadSticker() { var isBrowser = typeof window !== 'undefined'; if (isBrowser) { return this._loadImageBrowser(this._options.sticker); } else { return this._loadImageNode(this._options.sticker); } } }, { key: '_loadImageBrowser', /** * Loads the given image using the browser's `Image` class * @param {String} fileName * @return {Promise} * @private */ value: function _loadImageBrowser(fileName) { var self = this; return new _vendorPromise2['default'](function (resolve, reject) { // Return preloaded sticker if available if (self._loadedStickers[fileName]) { return resolve(self._loadedStickers[fileName]); } var image = new Image(); image.addEventListener('load', function () { self._loadedStickers[fileName] = image; resolve(image); }); image.addEventListener('error', function () { reject(new Error('Could not load sticker: ' + fileName)); }); image.src = self._kit.getAssetPath(fileName); }); } }, { key: '_loadImageNode', /** * Loads the given image using node.js' `fs` and node-canvas `Image` * @param {String} fileName * @return {Promise} * @private */ value: function _loadImageNode(fileName) { var Canvas = __webpack_require__(52); var fs = __webpack_require__(51); var self = this; var image = new Canvas.Image(); var path = self._kit.getAssetPath(fileName); return new _vendorPromise2['default'](function (resolve, reject) { fs.readFile(path, function (err, buffer) { if (err) return reject(err); image.src = buffer; resolve(image); }); }); } }, { key: 'stickers', /** * The registered stickers * @type {Object.} */ get: function () { return this._stickers; } }]); return StickersOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ StickersOperation.prototype.identifier = 'stickers'; /** * Specifies the available options for this operation * @type {Object} */ StickersOperation.prototype.availableOptions = { sticker: { type: 'string' }, position: { type: 'vector2', 'default': new _libMathVector22['default'](0, 0) }, size: { type: 'vector2', 'default': new _libMathVector22['default'](0, 0) } }; exports['default'] = StickersOperation; module.exports = exports['default']; /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _operation = __webpack_require__(8); var _operation2 = _interopRequireDefault(_operation); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); /** * An operation that can frames on the canvas * * @class * @alias ImglyKit.Operations.FramesOperation * @extends ImglyKit.Operation */ var FramesOperation = (function (_Operation) { function FramesOperation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, FramesOperation); _get(Object.getPrototypeOf(FramesOperation.prototype), 'constructor', this).apply(this, args); /** * The texture index used for the frame * @type {Number} * @private */ this._textureIndex = 1; /** * The fragment shader used for this operation */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform sampler2D u_frameImage;\n uniform vec4 u_color;\n uniform vec2 u_thickness;\n\n void main() {\n vec4 fragColor = texture2D(u_image, v_texCoord);\n if (v_texCoord.x < u_thickness.x || v_texCoord.x > 1.0 - u_thickness.x ||\n v_texCoord.y < u_thickness.y || v_texCoord.y > 1.0 - u_thickness.y) {\n fragColor = mix(fragColor, u_color, u_color.a);\n }\n\n gl_FragColor = fragColor;\n }\n '; } _inherits(FramesOperation, _Operation); _createClass(FramesOperation, [{ key: '_renderWebGL', /** * Crops this image using WebGL * @param {WebGLRenderer} renderer * @private */ /* istanbul ignore next */ value: function _renderWebGL(renderer) { var canvas = renderer.getCanvas(); var color = this._options.color; var thickness = this._options.thickness * canvas.height; var thicknessVec2 = [thickness / canvas.width, thickness / canvas.height]; var uniforms = { u_color: { type: '4f', value: color.toGLColor() }, u_thickness: { type: '2f', value: thicknessVec2 } }; if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: uniforms }); } }, { key: '_renderCanvas', /** * Crops the image using Canvas2D * @param {CanvasRenderer} renderer * @private */ value: function _renderCanvas(renderer) { var canvas = renderer.getCanvas(); var context = renderer.getContext(); var color = this._options.color; var thickness = this._options.thickness * canvas.height; context.save(); context.beginPath(); context.lineWidth = thickness * 2; context.strokeStyle = color.toRGBA(); context.rect(0, 0, canvas.width, canvas.height); context.stroke(); context.restore(); } }]); return FramesOperation; })(_operation2['default']); /** * A unique string that identifies this operation. Can be used to select * operations. * @type {String} */ FramesOperation.prototype.identifier = 'frames'; /** * Specifies the available options for this operation * @type {Object} */ FramesOperation.prototype.availableOptions = { color: { type: 'color', 'default': new _libColor2['default'](0, 0, 0, 1) }, thickness: { type: 'number', 'default': 0.02 } }; exports['default'] = FramesOperation; module.exports = exports['default']; /***/ }, /* 21 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * A15 Filter * @class * @alias ImglyKit.Filters.A15Filter * @extends {ImglyKit.Filter} */ var A15Filter = (function (_Filter) { function A15Filter() { _classCallCheck(this, A15Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(A15Filter, _Filter); _createClass(A15Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 0.63 })); stack.add(new _filter2['default'].Primitives.Brightness({ brightness: 0.12 })); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 38], [94, 94], [148, 142], [175, 187], [255, 255]], green: [[0, 0], [77, 53], [171, 190], [255, 255]], blue: [[0, 10], [48, 85], [174, 228], [255, 255]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return '15'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'a15'; } }]); return A15Filter; })(_filter2['default']); exports['default'] = A15Filter; module.exports = exports['default']; /***/ }, /* 22 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Breeze Filter * @class * @alias ImglyKit.Filters.BreezeFilter * @extends {ImglyKit.Filter} */ var BreezeFilter = (function (_Filter) { function BreezeFilter() { _classCallCheck(this, BreezeFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(BreezeFilter, _Filter); _createClass(BreezeFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Desaturation stack.add(new _filter2['default'].Primitives.Desaturation({ desaturation: 0.5 })); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [170, 170], [212, 219], [234, 242], [255, 255]], green: [[0, 0], [170, 168], [234, 231], [255, 255]], blue: [[0, 0], [170, 170], [212, 208], [255, 255]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Breeze'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'breeze'; } }]); return BreezeFilter; })(_filter2['default']); exports['default'] = BreezeFilter; module.exports = exports['default']; /***/ }, /* 23 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * BW Filter * @class * @alias ImglyKit.Filters.BWFilter * @extends {ImglyKit.Filter} */ var BWFilter = (function (_Filter) { function BWFilter() { _classCallCheck(this, BWFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(BWFilter, _Filter); _createClass(BWFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Grayscale()); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'B&W'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'bw'; } }]); return BWFilter; })(_filter2['default']); exports['default'] = BWFilter; module.exports = exports['default']; /***/ }, /* 24 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * BWHard Filter * @class * @alias ImglyKit.Filters.BWHardFilter * @extends {ImglyKit.Filter} */ var BWHardFilter = (function (_Filter) { function BWHardFilter() { _classCallCheck(this, BWHardFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(BWHardFilter, _Filter); _createClass(BWHardFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Grayscale()); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 1.5 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return '1920'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'bwhard'; } }]); return BWHardFilter; })(_filter2['default']); exports['default'] = BWHardFilter; module.exports = exports['default']; /***/ }, /* 25 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Celsius Filter * @class * @alias ImglyKit.Filters.CelsiusFilter * @extends {ImglyKit.Filter} */ var CelsiusFilter = (function (_Filter) { function CelsiusFilter() { _classCallCheck(this, CelsiusFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(CelsiusFilter, _Filter); _createClass(CelsiusFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 69], [55, 110], [202, 230], [255, 255]], green: [[0, 44], [89, 93], [185, 141], [255, 189]], blue: [[0, 76], [39, 82], [218, 138], [255, 171]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Celsius'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'celsius'; } }]); return CelsiusFilter; })(_filter2['default']); exports['default'] = CelsiusFilter; module.exports = exports['default']; /***/ }, /* 26 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Chest Filter * @class * @alias ImglyKit.Filters.ChestFilter * @extends {ImglyKit.Filter} */ var ChestFilter = (function (_Filter) { function ChestFilter() { _classCallCheck(this, ChestFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(ChestFilter, _Filter); _createClass(ChestFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [44, 44], [124, 143], [221, 204], [255, 255]], green: [[0, 0], [130, 127], [213, 199], [255, 255]], blue: [[0, 0], [51, 52], [219, 204], [255, 255]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Chest'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'chest'; } }]); return ChestFilter; })(_filter2['default']); exports['default'] = ChestFilter; module.exports = exports['default']; /***/ }, /* 27 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Fixie Filter * @class * @alias ImglyKit.Filters.FixieFilter * @extends {ImglyKit.Filter} */ var FixieFilter = (function (_Filter) { function FixieFilter() { _classCallCheck(this, FixieFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(FixieFilter, _Filter); _createClass(FixieFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [44, 28], [63, 48], [128, 132], [235, 248], [255, 255]], green: [[0, 0], [20, 10], [60, 45], [190, 209], [211, 231], [255, 255]], blue: [[0, 31], [41, 62], [150, 142], [234, 212], [255, 224]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Fixie'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'fixie'; } }]); return FixieFilter; })(_filter2['default']); exports['default'] = FixieFilter; module.exports = exports['default']; /***/ }, /* 28 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Food Filter * @class * @alias ImglyKit.Filters.FoodFilter * @extends {ImglyKit.Filter} */ var FoodFilter = (function (_Filter) { function FoodFilter() { _classCallCheck(this, FoodFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(FoodFilter, _Filter); _createClass(FoodFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 1.35 })); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 1.1 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Food'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'food'; } }]); return FoodFilter; })(_filter2['default']); exports['default'] = FoodFilter; module.exports = exports['default']; /***/ }, /* 29 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Fridge Filter * @class * @alias ImglyKit.Filters.FridgeFilter * @extends {ImglyKit.Filter} */ var FridgeFilter = (function (_Filter) { function FridgeFilter() { _classCallCheck(this, FridgeFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(FridgeFilter, _Filter); _createClass(FridgeFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 9], [21, 11], [45, 24], [255, 220]], green: [[0, 12], [21, 21], [42, 42], [150, 150], [170, 173], [255, 210]], blue: [[0, 28], [43, 72], [128, 185], [255, 220]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Fridge'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'fridge'; } }]); return FridgeFilter; })(_filter2['default']); exports['default'] = FridgeFilter; module.exports = exports['default']; /***/ }, /* 30 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Front Filter * @class * @alias ImglyKit.Filters.FrontFilter * @extends {ImglyKit.Filter} */ var FrontFilter = (function (_Filter) { function FrontFilter() { _classCallCheck(this, FrontFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(FrontFilter, _Filter); _createClass(FrontFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 65], [28, 67], [67, 113], [125, 183], [187, 217], [255, 229]], green: [[0, 52], [42, 59], [104, 134], [169, 209], [255, 240]], blue: [[0, 52], [65, 68], [93, 104], [150, 153], [255, 198]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Front'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'front'; } }]); return FrontFilter; })(_filter2['default']); exports['default'] = FrontFilter; module.exports = exports['default']; /***/ }, /* 31 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Glam Filter * @class * @alias ImglyKit.Filters.GlamFilter * @extends {ImglyKit.Filter} */ var GlamFilter = (function (_Filter) { function GlamFilter() { _classCallCheck(this, GlamFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(GlamFilter, _Filter); _createClass(GlamFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 1.1 })); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [94, 74], [181, 205], [255, 255]], green: [[0, 0], [127, 127], [255, 255]], blue: [[0, 0], [102, 73], [227, 213], [255, 255]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Glam'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'glam'; } }]); return GlamFilter; })(_filter2['default']); exports['default'] = GlamFilter; module.exports = exports['default']; /***/ }, /* 32 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Gobblin Filter * @class * @alias ImglyKit.Filters.GobblinFilter * @extends {ImglyKit.Filter} */ var GobblinFilter = (function (_Filter) { function GobblinFilter() { _classCallCheck(this, GobblinFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(GobblinFilter, _Filter); _createClass(GobblinFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.Gobblin()); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Gobblin'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'gobblin'; } }]); return GobblinFilter; })(_filter2['default']); exports['default'] = GobblinFilter; module.exports = exports['default']; /***/ }, /* 33 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * K1 Filter * @class * @alias ImglyKit.Filters.K1Filter * @extends {ImglyKit.Filter} */ var K1Filter = (function (_Filter) { function K1Filter() { _classCallCheck(this, K1Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(K1Filter, _Filter); _createClass(K1Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [53, 32], [91, 80], [176, 205], [255, 255]] })); // Saturation stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 0.9 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'K1'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'k1'; } }]); return K1Filter; })(_filter2['default']); exports['default'] = K1Filter; module.exports = exports['default']; /***/ }, /* 34 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); /** * K2 Filter * @class * @alias ImglyKit.Filters.K2Filter * @extends {ImglyKit.Filter} */ var K2Filter = (function (_Filter) { function K2Filter() { _classCallCheck(this, K2Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(K2Filter, _Filter); _createClass(K2Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [54, 33], [77, 82], [94, 103], [122, 126], [177, 193], [229, 232], [255, 255]] })); // Soft color overlay stack.add(new _filter2['default'].Primitives.SoftColorOverlay({ color: new _libColor2['default'](40 / 255, 40 / 255, 40 / 255) })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'K2'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'k2'; } }]); return K2Filter; })(_filter2['default']); exports['default'] = K2Filter; module.exports = exports['default']; /***/ }, /* 35 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * K6 Filter * @class * @alias ImglyKit.Filters.K6Filter * @extends {ImglyKit.Filter} */ var K6Filter = (function (_Filter) { function K6Filter() { _classCallCheck(this, K6Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(K6Filter, _Filter); _createClass(K6Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Saturation stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 0.5 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'K6'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'k6'; } }]); return K6Filter; })(_filter2['default']); exports['default'] = K6Filter; module.exports = exports['default']; /***/ }, /* 36 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * KDynamic Filter * @class * @alias ImglyKit.Filters.KDynamicFilter * @extends {ImglyKit.Filter} */ var KDynamicFilter = (function (_Filter) { function KDynamicFilter() { _classCallCheck(this, KDynamicFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(KDynamicFilter, _Filter); _createClass(KDynamicFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [17, 27], [46, 69], [90, 112], [156, 200], [203, 243], [255, 255]] })); // Saturation stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 0.7 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'KDynamic'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'kdynamic'; } }]); return KDynamicFilter; })(_filter2['default']); exports['default'] = KDynamicFilter; module.exports = exports['default']; /***/ }, /* 37 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Lenin Filter * @class * @alias ImglyKit.Filters.LeninFilter * @extends {ImglyKit.Filter} */ var LeninFilter = (function (_Filter) { function LeninFilter() { _classCallCheck(this, LeninFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(LeninFilter, _Filter); _createClass(LeninFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Desaturation stack.add(new _filter2['default'].Primitives.Desaturation({ desaturation: 0.4 })); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 20], [40, 20], [106, 111], [129, 153], [190, 223], [255, 255]], green: [[0, 20], [40, 20], [62, 41], [106, 108], [132, 159], [203, 237], [255, 255]], blue: [[0, 40], [40, 40], [73, 60], [133, 160], [191, 297], [203, 237], [237, 239], [255, 255]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Lenin'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'lenin'; } }]); return LeninFilter; })(_filter2['default']); exports['default'] = LeninFilter; module.exports = exports['default']; /***/ }, /* 38 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Lomo Filter * @class * @alias ImglyKit.Filters.LomoFilter * @extends {ImglyKit.Filter} */ var LomoFilter = (function (_Filter) { function LomoFilter() { _classCallCheck(this, LomoFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(LomoFilter, _Filter); _createClass(LomoFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [87, 20], [131, 156], [183, 205], [255, 200]] })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Lomo'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'lomo'; } }]); return LomoFilter; })(_filter2['default']); exports['default'] = LomoFilter; module.exports = exports['default']; /***/ }, /* 39 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Mellow Filter * @class * @alias ImglyKit.Filters.MellowFilter * @extends {ImglyKit.Filter} */ var MellowFilter = (function (_Filter) { function MellowFilter() { _classCallCheck(this, MellowFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(MellowFilter, _Filter); _createClass(MellowFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [41, 84], [87, 134], [255, 255]], green: [[0, 0], [255, 216]], blue: [[0, 0], [255, 131]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Mellow'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'mellow'; } }]); return MellowFilter; })(_filter2['default']); exports['default'] = MellowFilter; module.exports = exports['default']; /***/ }, /* 40 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Morning Filter * @class * @alias ImglyKit.Filters.MorningFilter * @extends {ImglyKit.Filter} */ var MorningFilter = (function (_Filter) { function MorningFilter() { _classCallCheck(this, MorningFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(MorningFilter, _Filter); _createClass(MorningFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 40], [255, 230]], green: [[0, 10], [255, 225]], blue: [[0, 20], [255, 181]] } })); stack.add(new _filter2['default'].Primitives.Glow()); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Morning'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'morning'; } }]); return MorningFilter; })(_filter2['default']); exports['default'] = MorningFilter; module.exports = exports['default']; /***/ }, /* 41 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Orchid Filter * @class * @alias ImglyKit.Filters.OrchidFilter * @extends {ImglyKit.Filter} */ var OrchidFilter = (function (_Filter) { function OrchidFilter() { _classCallCheck(this, OrchidFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(OrchidFilter, _Filter); _createClass(OrchidFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [115, 130], [195, 215], [255, 255]], green: [[0, 0], [148, 153], [172, 215], [255, 255]], blue: [[0, 46], [58, 75], [178, 205], [255, 255]] } })); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [117, 151], [189, 217], [255, 255]] })); // Desaturation stack.add(new _filter2['default'].Primitives.Desaturation({ desaturation: 0.65 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Orchid'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'orchid'; } }]); return OrchidFilter; })(_filter2['default']); exports['default'] = OrchidFilter; module.exports = exports['default']; /***/ }, /* 42 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Pola Filter * @class * @alias ImglyKit.Filters.PolaFilter * @extends {ImglyKit.Filter} */ var PolaFilter = (function (_Filter) { function PolaFilter() { _classCallCheck(this, PolaFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(PolaFilter, _Filter); _createClass(PolaFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [94, 74], [181, 205], [255, 255]], green: [[0, 0], [34, 34], [99, 76], [176, 190], [255, 255]], blue: [[0, 0], [102, 73], [227, 213], [255, 255]] } })); stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 0.8 })); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 1.5 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Pola SX'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'pola'; } }]); return PolaFilter; })(_filter2['default']); exports['default'] = PolaFilter; module.exports = exports['default']; /***/ }, /* 43 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Pola669 Filter * @class * @alias ImglyKit.Filters.Pola669Filter * @extends {ImglyKit.Filter} */ var Pola669Filter = (function (_Filter) { function Pola669Filter() { _classCallCheck(this, Pola669Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(Pola669Filter, _Filter); _createClass(Pola669Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [56, 18], [196, 209], [255, 255]], green: [[0, 38], [71, 84], [255, 255]], blue: [[0, 0], [131, 133], [204, 211], [255, 255]] } })); stack.add(new _filter2['default'].Primitives.Saturation({ saturation: 0.8 })); stack.add(new _filter2['default'].Primitives.Contrast({ contrast: 1.5 })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Pola 669'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'pola669'; } }]); return Pola669Filter; })(_filter2['default']); exports['default'] = Pola669Filter; module.exports = exports['default']; /***/ }, /* 44 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Quozi Filter * @class * @alias ImglyKit.Filters.QuoziFilter * @extends {ImglyKit.Filter} */ var QuoziFilter = (function (_Filter) { function QuoziFilter() { _classCallCheck(this, QuoziFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(QuoziFilter, _Filter); _createClass(QuoziFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); // Desaturation stack.add(new _filter2['default'].Primitives.Desaturation({ desaturation: 0.65 })); // Tone curve stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 50], [40, 78], [118, 170], [181, 211], [255, 255]], green: [[0, 27], [28, 45], [109, 157], [157, 195], [179, 208], [206, 212], [255, 240]], blue: [[0, 50], [12, 55], [46, 103], [103, 162], [194, 182], [241, 201], [255, 219]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Quozi'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'quozi'; } }]); return QuoziFilter; })(_filter2['default']); exports['default'] = QuoziFilter; module.exports = exports['default']; /***/ }, /* 45 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Semired Filter * @class * @alias ImglyKit.Filters.SemiredFilter * @extends {ImglyKit.Filter} */ var SemiredFilter = (function (_Filter) { function SemiredFilter() { _classCallCheck(this, SemiredFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(SemiredFilter, _Filter); _createClass(SemiredFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 129], [75, 153], [181, 227], [255, 255]], green: [[0, 8], [111, 85], [212, 158], [255, 226]], blue: [[0, 5], [75, 22], [193, 90], [255, 229]] } })); stack.add(new _filter2['default'].Primitives.Glow()); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Semi Red'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'semired'; } }]); return SemiredFilter; })(_filter2['default']); exports['default'] = SemiredFilter; module.exports = exports['default']; /***/ }, /* 46 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Sunny Filter * @class * @alias ImglyKit.Filters.SunnyFilter * @extends {ImglyKit.Filter} */ var SunnyFilter = (function (_Filter) { function SunnyFilter() { _classCallCheck(this, SunnyFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(SunnyFilter, _Filter); _createClass(SunnyFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 0], [62, 82], [141, 154], [255, 255]], green: [[0, 39], [56, 96], [192, 176], [255, 255]], blue: [[0, 0], [174, 99], [255, 235]] } })); stack.add(new _filter2['default'].Primitives.ToneCurve({ controlPoints: [[0, 0], [55, 20], [158, 191], [255, 255]] })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Sunny'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'sunny'; } }]); return SunnyFilter; })(_filter2['default']); exports['default'] = SunnyFilter; module.exports = exports['default']; /***/ }, /* 47 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Texas Filter * @class * @alias ImglyKit.Filters.TexasFilter * @extends {ImglyKit.Filter} */ var TexasFilter = (function (_Filter) { function TexasFilter() { _classCallCheck(this, TexasFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(TexasFilter, _Filter); _createClass(TexasFilter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.ToneCurve({ rgbControlPoints: { red: [[0, 72], [89, 99], [176, 212], [255, 237]], green: [[0, 49], [255, 192]], blue: [[0, 72], [255, 151]] } })); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Texas'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'texas'; } }]); return TexasFilter; })(_filter2['default']); exports['default'] = TexasFilter; module.exports = exports['default']; /***/ }, /* 48 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * X400 Filter * @class * @alias ImglyKit.Filters.X400Filter * @extends {ImglyKit.Filter} */ var X400Filter = (function (_Filter) { function X400Filter() { _classCallCheck(this, X400Filter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(X400Filter, _Filter); _createClass(X400Filter, [{ key: 'render', /** * Renders the filter * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { var stack = new _filter2['default'].PrimitivesStack(); stack.add(new _filter2['default'].Primitives.X400()); stack.render(renderer); } }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'X400'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'x400'; } }]); return X400Filter; })(_filter2['default']); exports['default'] = X400Filter; module.exports = exports['default']; /***/ }, /* 49 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Represents a 2-dimensional vector while providing math functions to * modify / clone the vector. Fully chainable. * @class * @alias ImglyKit.Vector2 * @param {number} x * @param {number} y * @private */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Vector2 = (function () { function Vector2(x, y) { _classCallCheck(this, Vector2); this.x = x; this.y = y; if (typeof this.x === 'undefined') { this.x = 0; } if (typeof this.y === 'undefined') { this.y = 0; } } _createClass(Vector2, [{ key: 'set', /** * Sets the given values * @param {number} x * @param {number} y * @return {Vector2} */ value: function set(x, y) { this.x = x; this.y = y; return this; } }, { key: 'clone', /** * Creates a clone of this vector * @return {Vector2} */ value: function clone() { return new Vector2(this.x, this.y); } }, { key: 'copy', /** * Copies the values of the given vector * @param {Vector2} other * @return {Vector2} */ value: function copy(other) { this.x = other.x; this.y = other.y; return this; } }, { key: 'clamp', /** * Clamps this vector with the given Vector2 / number * @param {(number|Vector2)} minimum * @param {(number|Vector2)} maximum * @return {Vector2} */ value: function clamp(minimum, maximum) { var minimumSet = minimum !== null && typeof minimum !== 'undefined'; var maximumSet = maximum !== null && typeof maximum !== 'undefined'; /* istanbul ignore else */ if (!(minimum instanceof Vector2) && minimumSet) { minimum = new Vector2(minimum, minimum); } /* istanbul ignore else */ if (!(maximum instanceof Vector2) && maximumSet) { maximum = new Vector2(maximum, maximum); } if (minimumSet) { this.x = Math.max(minimum.x, this.x); this.y = Math.max(minimum.y, this.y); } if (maximumSet) { this.x = Math.min(maximum.x, this.x); this.y = Math.min(maximum.y, this.y); } return this; } }, { key: 'divide', /** * Divides this vector by the given Vector2 / number * @param {(number|Vector2)} divisor * @param {number} [y] * @return {Vector2} */ value: function divide(divisor, y) { if (divisor instanceof Vector2) { this.x /= divisor.x; this.y /= divisor.y; } else { this.x /= divisor; this.y /= typeof y === 'undefined' ? divisor : y; } return this; } }, { key: 'subtract', /** * Subtracts the given Vector2 / number from this vector * @param {(number|Vector2)} subtrahend * @param {number} [y] * @return {Vector2} */ value: function subtract(subtrahend, y) { if (subtrahend instanceof Vector2) { this.x -= subtrahend.x; this.y -= subtrahend.y; } else { this.x -= subtrahend; this.y -= typeof y === 'undefined' ? subtrahend : y; } return this; } }, { key: 'multiply', /** * Multiplies the given Vector2 / number with this vector * @param {(number|Vector2)} subtrahend * @param {number} [y] * @return {Vector2} */ value: function multiply(factor, y) { if (factor instanceof Vector2) { this.x *= factor.x; this.y *= factor.y; } else { this.x *= factor; this.y *= typeof y === 'undefined' ? factor : y; } return this; } }, { key: 'add', /** * Adds the given Vector2 / numbers to this vector * @param {(number|Vector2)} addend * @param {number} [y] */ value: function add(addend, y) { if (addend instanceof Vector2) { this.x += addend.x; this.y += addend.y; } else { this.x += addend; this.y += typeof y === 'undefined' ? addend : y; } return this; } }, { key: 'equals', /** * Checks whether the x and y value are the same as the given ones * @param {(number|Vector2)} vec * @param {number} y * @return {boolean} */ value: function equals(vec, y) { if (vec instanceof Vector2) { return vec.x === this.x && vec.y === this.y; } else { return vec === this.x && y === this.y; } } }, { key: 'flip', /** * Flips the x and y values of this vector * @return {Vector2} */ value: function flip() { var tempX = this.x; this.x = this.y; this.y = tempX; return this; } }, { key: 'toString', /** * Returns a string representation of this vector * @return {String} */ value: function toString() { return 'Vector2({ x: ' + this.x + ', y: ' + this.y + ' })'; } }]); return Vector2; })(); exports['default'] = Vector2; module.exports = exports['default']; /***/ }, /* 50 */ /***/ function(module, exports, __webpack_require__) { /* global FileReader, Image, __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _baseUi = __webpack_require__(75); var _baseUi2 = _interopRequireDefault(_baseUi); var _libCanvas = __webpack_require__(76); var _libCanvas2 = _interopRequireDefault(_libCanvas); var _libFileLoader = __webpack_require__(77); var _libFileLoader2 = _interopRequireDefault(_libFileLoader); var _libWebcamHandler = __webpack_require__(78); var _libWebcamHandler2 = _interopRequireDefault(_libWebcamHandler); var _libTopControls = __webpack_require__(79); var _libTopControls2 = _interopRequireDefault(_libTopControls); var _libScrollbar = __webpack_require__(80); var _libScrollbar2 = _interopRequireDefault(_libScrollbar); var _constants = __webpack_require__(4); var NightUI = (function (_UI) { function NightUI() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, NightUI); _get(Object.getPrototypeOf(NightUI.prototype), 'constructor', this).apply(this, args); this._operationsMap = {}; this._template = function(it /**/) { var out='
'+( it.helpers.translate('generic.loading') )+'...
';if(!it.options.ui.hideHeader){out+='
img.ly Photo Editor SDK ';if(it.options.ui.showCloseButton){out+='
';}out+='
';}out+=' ';if(it.renderControls){out+='
';if(it.options.ui.showNewButton){out+='
'+( it.helpers.translate('top-controls.new') )+'
';}out+='
'+( it.helpers.translate('top-controls.undo') )+'
';if(it.options.ui.showExportButton){out+='
'+( it.helpers.translate('top-controls.export') )+'
';}out+='
'+( it.helpers.translate('top-controls.zoom') )+': 100%
';}out+='
';if(it.renderWebcam){out+='
';}out+=' ';if(!(it.renderSplashScreen || it.renderWebcam)){out+='
';}out+=' ';if(it.renderSplashScreen){out+='
';if(it.options.ui.showUploadButton){out+='
'+( it.helpers.translate('splash.upload.headline') )+'
'+( it.helpers.translate('splash.upload.description') )+'
';}out+=' ';if(it.options.ui.showUploadButton && it.options.ui.showWebcamButton){out+='
'+( it.helpers.translate('splash.or') )+'
';}out+=' ';if(it.options.ui.showWebcamButton){out+='
'+( it.helpers.translate('splash.webcam.headline') )+'
'+( it.helpers.translate('splash.webcam.description') )+'
';}out+='
';}out+='
';if(it.renderWebcam){out+='
';}out+=' ';if(it.renderControls){out+='
    '; for (var identifier in it.controls) { out+=' '; var control = it.controls[identifier]; out+='
  • '+(it.helpers.translate('operations.' + control.identifier))+'
  • '; } out+='
';}out+='
';return out; }; this._registeredControls = {}; this._history = []; // The `Night` UI has a fixed operation order this._preferredOperationOrder = [ // First, all operations that affect the image dimensions 'rotation', 'crop', 'flip', // Then color operations (first filters, then fine-tuning) 'filters', 'contrast', 'brightness', 'saturation', // Then post-processing 'radial-blur', 'tilt-shift', 'frames', 'stickers', 'text']; this._paused = false; this._options.ui = _libUtils2['default'].defaults(this._options.ui, { showNewButton: !this._options.image, showUploadButton: true, showWebcamButton: true, showHeader: true, showCloseButton: false, showExportButton: false, language: 'en', 'export': {} }); this._options.ui['export'] = _libUtils2['default'].defaults(this._options.ui['export'], { type: _constants.ImageFormat.JPEG, quality: 0.8 }); } _inherits(NightUI, _UI); _createClass(NightUI, [{ key: 'run', /** * Prepares the UI for use */ value: function run() { this._registerControls(); this._registerLanguages(); this._loadLanguage(); _get(Object.getPrototypeOf(NightUI.prototype), 'run', this).call(this); var container = this._options.container; this._controlsContainer = container.querySelector('.imglykit-controls'); this._canvasControlsContainer = container.querySelector('.imglykit-canvas-controls'); this._overviewControlsContainer = container.querySelector('.imglykit-controls-overview'); this._loadingOverlay = container.querySelector('.imglykit-loadingOverlay'); this._loadingSpan = container.querySelector('.imglykit-loadingOverlay span'); this._handleOverview(); if (this._options.image) { this._initCanvas(); } if (this.context.renderSplashScreen) { this._initFileLoader(); if (this._options.ui.showWebcamButton) { this._handleWebcamButton(); } } if (this.context.renderWebcam) { this._initWebcam(); } this._initTopControls(); this._initControls(); if (this._options.image) { this.showZoom(); } if (this._options.ui.showCloseButton) { this._handleCloseButton(); } if (this._topControls) { this._topControls.updateExportButton(); } } }, { key: '_loadLanguage', value: function _loadLanguage() { this._language = this._languages[this._options.ui.language]; if (!this._language) { var availableLanguages = Object.keys(this._languages).join(', '); throw new Error('Unknown language \'' + this._options.ui.language + '\'. Available languages are: ' + availableLanguages); } } }, { key: '_initWebcam', /** * Initializes the webcam * @private */ value: function _initWebcam() { this._webcam = new _libWebcamHandler2['default'](this._kit, this); this._webcam.on('image', this._onWebcamImageTaken.bind(this)); } }, { key: '_onWebcamImageTaken', value: function _onWebcamImageTaken(image) { this._options.ui.startWithWebcam = false; this._setImage(image); } }, { key: '_handleWebcamButton', /** * Handles the webcam button * @private */ value: function _handleWebcamButton() { var _this = this; var container = this._options.container; var webcamButton = container.querySelector('.imglykit-splash-row--camera'); webcamButton.addEventListener('click', function () { _this._options.ui.startWithWebcam = true; _this.run(); }); } }, { key: '_initFileLoader', /** * Initializes the file loader * @private */ value: function _initFileLoader() { this._fileLoader = new _libFileLoader2['default'](this._kit, this); this._fileLoader.on('file', this._onFileLoaded.bind(this)); } }, { key: '_onFileLoaded', /** * Gets called when the user loaded a file using the FileLoader * @param {File} file * @private */ value: function _onFileLoaded(file) { var _this2 = this; var reader = new FileReader(); reader.onload = (function () { return function (e) { var data = e.target.result; var image = new Image(); image.addEventListener('load', function () { _this2._setImage(image); }); image.src = data; }; })(file); reader.readAsDataURL(file); } }, { key: '_setImage', /** * Sets the image option and starts rendering * @param {Image} image * @private */ value: function _setImage(image) { this._options.image = image; this.run(); } }, { key: '_initTopControls', /** * Initializes the top controls * @private */ value: function _initTopControls() { var _this3 = this; if (!this.context.renderControls) return; this._topControls = new _libTopControls2['default'](this._kit, this); this._topControls.run(); this._topControls.on('new', function () { _this3._options.image = null; _this3.run(); }); this._topControls.on('undo', function () { _this3.undo(); }); this._topControls.on('export', function () { _this3['export'](); }); // Pass zoom in event this._topControls.on('zoom-in', function () { _this3._canvas.zoomIn().then(function () { if (_this3._currentControl) { _this3._currentControl.onZoom(); } }); }); // Pass zoom out event this._topControls.on('zoom-out', function () { _this3._canvas.zoomOut().then(function () { if (_this3._currentControl) { _this3._currentControl.onZoom(); } }); }); } }, { key: '_initCanvas', /** * Inititializes the canvas * @private */ value: function _initCanvas() { var _this4 = this; this._canvas = new _libCanvas2['default'](this._kit, this, this._options); this._canvas.run(); this._canvas.on('zoom', function () { _this4._topControls.updateZoomLevel(); }); } }, { key: 'selectOperations', /** * Selects the enabled operations * @param {ImglyKit.Selector} */ value: function selectOperations(selector) { _get(Object.getPrototypeOf(NightUI.prototype), 'selectOperations', this).call(this, selector); } }, { key: 'getOrCreateOperation', /** * Returns or creates an instance of the operation with the given identifier * @param {String} identifier */ value: function getOrCreateOperation(identifier) { var _kit = this._kit; var operationsStack = _kit.operationsStack; var registeredOperations = _kit.registeredOperations; var Operation = registeredOperations[identifier]; if (typeof this._operationsMap[identifier] === 'undefined') { // Create operation var operationInstance = new Operation(this._kit); this._operationsMap[identifier] = operationInstance; // Find index in preferred operation order var index = this._preferredOperationOrder.indexOf(identifier); if (index === -1) { index = this._preferredOperationOrder.length; } operationsStack[index] = operationInstance; return operationInstance; } else { return this._operationsMap[identifier]; } } }, { key: 'removeOperation', /** * Removes the operation with the given identifier from the stack * @param {String} identifier */ value: function removeOperation(identifier) { if (!this._operationsMap[identifier]) return; var operation = this._operationsMap[identifier]; delete this._operationsMap[identifier]; var index = this._kit.operationsStack.indexOf(operation); this._kit.operationsStack.splice(index, 1); } }, { key: '_registerControls', /** * Registers all default operation controls * @private */ value: function _registerControls() { this.registerControl('filters', 'filters', __webpack_require__(81)); this.registerControl('rotation', 'rotation', __webpack_require__(82)); this.registerControl('flip', 'flip', __webpack_require__(83)); this.registerControl('brightness', 'brightness', __webpack_require__(84)); this.registerControl('contrast', 'contrast', __webpack_require__(85)); this.registerControl('saturation', 'saturation', __webpack_require__(86)); this.registerControl('crop', 'crop', __webpack_require__(87)); this.registerControl('radial-blur', 'radial-blur', __webpack_require__(88)); this.registerControl('tilt-shift', 'tilt-shift', __webpack_require__(89)); this.registerControl('frames', 'frames', __webpack_require__(90)); this.registerControl('stickers', 'stickers', __webpack_require__(91)); this.registerControl('text', 'text', __webpack_require__(92)); } }, { key: '_registerLanguages', /** * Register all default languages * @private */ value: function _registerLanguages() { this.registerLanguage('en', __webpack_require__(94)); this.registerLanguage('de', __webpack_require__(95)); } }, { key: '_handleOverview', /** * Handles the overview button click events * @private */ value: function _handleOverview() { var _this5 = this; if (!this.context.renderControls) return; var itemsList = this._overviewControlsContainer.querySelector('ul'); if (!itemsList.parentNode === this._overviewControlsContainer) { return; } var listItems = [].filter.call(itemsList.querySelectorAll('li'), function (el) { return el.parentNode === itemsList; }); var _loop = function (i) { var listItem = listItems[i]; var identifier = listItem.dataset.identifier; listItem.addEventListener('click', function () { _this5.switchToControl(identifier); }); }; // Add click events to all items for (var i = 0; i < listItems.length; i++) { _loop(i); } } }, { key: '_enableControls', /** * Enables the overview controls * @private */ value: function _enableControls() { var itemsList = this._overviewControlsContainer.querySelector('ul'); if (!itemsList.parentNode === this._overviewControlsContainer) { return; } var listItems = [].filter.call(itemsList.querySelectorAll('li'), function (el) { return el.parentNode === itemsList; }); // Add click events to all items for (var i = 0; i < listItems.length; i++) { var listItem = listItems[i]; listItem.removeAttribute('data-disabled'); } } }, { key: 'switchToControl', /** * Gets called when an overview button has been clicked * @private */ value: function switchToControl(identifier) { if (this.context.controlsDisabled) return; this._overviewControlsContainer.style.display = 'none'; this._scrollbar.remove(); if (this._currentControl) { this._currentControl.leave(); } this._currentControl = this._registeredControls[identifier]; this._currentControl.enter(); this._currentControl.once('back', this._switchToOverview.bind(this)); } }, { key: '_switchToOverview', /** * Switches back to the overview controls * @private */ value: function _switchToOverview() { if (this._currentControl) { this._currentControl.leave(); } this._currentControl = null; this._overviewControlsContainer.style.display = ''; this._initScrollbar(); } }, { key: 'registerControl', /** * Registers the controls for an operation * @param {String} identifier * @param {String} operationIdentifier * @param {Control} ControlClass */ value: function registerControl(identifier, operationIdentifier, ControlClass) { if (!this.isOperationSelected(operationIdentifier)) return; var instance = new ControlClass(this._kit, this); this._registeredControls[identifier] = instance; } }, { key: '_initControls', /** * Initializes the registered controls * @private */ value: function _initControls() { for (var identifier in this._registeredControls) { var control = this._registeredControls[identifier]; control.setContainers(this._controlsContainer, this._canvasControlsContainer); control.init(); } this._initScrollbar(); } }, { key: '_initScrollbar', /** * Initializes the custom scrollbar * @private */ value: function _initScrollbar() { if (!this.context.renderControls) return; var container = this._controlsContainer.querySelector('.imglykit-controls-list').parentNode; this._scrollbar = new _libScrollbar2['default'](container); } }, { key: '_handleCloseButton', /** * Handles the click event on the close button, emits a `close` event * when clicking * @private */ value: function _handleCloseButton() { var _this6 = this; var closeButton = this._options.container.querySelector('.imglykit-close-button'); closeButton.addEventListener('click', function (e) { e.preventDefault(); _this6.emit('close'); }); } }, { key: 'render', /** * Re-renders the canvas */ value: function render() { if (this._canvas) { this._canvas.render(); } } }, { key: 'pause', /** * Pauses the UI. Operation updates will not cause a re-rendering * of the canvas. */ value: function pause() { this._paused = true; } }, { key: 'resume', /** * Resumes the UI and re-renders the canvas * @param {Boolean} rerender = true */ value: function resume() { var rerender = arguments[0] === undefined ? true : arguments[0]; this._paused = false; if (rerender) { this.render(); } } }, { key: 'addHistory', /** * Adds the given operation and options to the history stack * @param {Operation} operation * @param {Object.} options * @param {Boolean} existent */ value: function addHistory(operation, options, existent) { this._history.push({ operation: operation, options: options, existent: existent }); this._topControls.updateUndoButton(); } }, { key: 'hideZoom', /** * Hides the zoom control */ value: function hideZoom() { this._topControls.hideZoom(); } }, { key: 'showZoom', /** * Hides the zoom control */ value: function showZoom() { this._topControls.showZoom(); } }, { key: 'undo', /** * Takes the last history item and applies its options */ value: function undo() { var lastItem = this._history.pop(); if (lastItem) { var operation = lastItem.operation; var existent = lastItem.existent; var options = lastItem.options; if (!existent) { this.removeOperation(operation.identifier); } else { operation = this.getOrCreateOperation(operation.identifier); operation.set(options); } this.canvas.zoomToFit(true); } this._topControls.updateUndoButton(); } }, { key: 'export', /** * Exports the current image with the default settings */ value: function _export() { var _this7 = this; this.displayLoadingMessage(this.translate('generic.exporting') + '...'); var renderType = _constants.RenderType.DATAURL; // Check if msToBlob is available var canvas = document.createElement('canvas'); if (typeof canvas.msToBlob !== 'undefined') { renderType = _constants.RenderType.MSBLOB; } setTimeout(function () { _this7._kit.render(renderType, _this7._options.ui['export'].type, _this7._options.ui['export'].dimensions, _this7._options.ui['export'].quality).then(function (data) { switch (renderType) { case _constants.RenderType.DATAURL: var link = document.createElement('a'); var extension = _this7._options.ui['export'].type.split('/').pop(); link.download = 'imglykit-export.' + extension; link.href = data; document.body.appendChild(link); link.click(); // Cleanup the DOM document.body.removeChild(link); break; case _constants.RenderType.MSBLOB: navigator.msSaveBlob(data, 'imglykit-export.png'); break; } _this7.hideLoadingMessage(); }); }, 1000); } }, { key: 'displayLoadingMessage', /** * Displays the given message inside the loading overlay * @param {String} message */ value: function displayLoadingMessage(message) { this._loadingSpan.innerText = message; this._loadingOverlay.style.display = 'block'; } }, { key: 'hideLoadingMessage', /** * Hides the loading message */ value: function hideLoadingMessage() { this._loadingOverlay.style.display = 'none'; } }, { key: 'identifier', /** * A unique string that represents this UI * @type {String} */ get: function () { return 'night'; } }, { key: 'operations', /** * An object containing all active operations * @type {Object.} */ get: function () { return this._operationsMap; } }, { key: 'controls', /** * An object containing all registered controls * @type {Object.} */ get: function () { return this._registeredControls; } }, { key: 'context', /** * The data that is passed to the template renderer * @type {Object} */ get: function () { var context = _get(Object.getPrototypeOf(NightUI.prototype), 'context', this); context.controls = this._registeredControls; context.renderSplashScreen = !this._options.image && !this._options.ui.startWithWebcam; context.renderControls = !!this._options.image; context.renderWebcam = this._options.ui.startWithWebcam; return context; } }, { key: 'history', /** * The undo history * @type {Array.} */ get: function () { return this._history; } }, { key: 'fileLoader', /** * The file loader * @type {FileLoader} */ get: function () { return this._fileLoader; } }]); return NightUI; })(_baseUi2['default']); NightUI.Control = __webpack_require__(93); exports['default'] = NightUI; module.exports = exports['default']; /***/ }, /* 51 */ /***/ function(module, exports, __webpack_require__) { /***/ }, /* 52 */ /***/ function(module, exports, __webpack_require__) { module.exports = __WEBPACK_EXTERNAL_MODULE_52__; /***/ }, /* 53 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Parses the dimensions string and provides calculation functions * @class * @alias ImglyKit.ImageDimensions * @param {string} dimensions * @private */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var ImageDimensions = (function () { function ImageDimensions(dimensions) { _classCallCheck(this, ImageDimensions); /** * The available dimension modifiers * @type {Object} * @private */ this._modifiers = { FIXED: '!' }; /** * @type {string} * @private */ this._dimensionsString = dimensions; /** * An object that represents the parsed dimensions string * @type {Object} */ this._rules = this._parse(); this._validateRules(); } _createClass(ImageDimensions, [{ key: '_parse', /** * Parses the dimensions string * @private */ value: function _parse() { if (typeof this._dimensionsString === 'undefined' || this._dimensionsString === null) { return null; } var match = this._dimensionsString.match(/^([0-9]+)?x([0-9]+)?([\!])?$/i); if (!match) { throw new Error('Invalid size option: ' + this._dimensionsString); } return { x: isNaN(match[1]) ? null : parseInt(match[1], 10), y: isNaN(match[2]) ? null : parseInt(match[2], 10), modifier: match[3] }; } }, { key: '_validateRules', /** * Validates the rules * @private */ value: function _validateRules() { if (this._rules === null) return; var xAvailable = this._rules.x !== null; var yAvailable = this._rules.y !== null; if (this._rules.modifier === this._modifiers.FIXED && !(xAvailable && yAvailable)) { throw new Error('Both `x` and `y` have to be set when using the fixed (!) modifier.'); } if (!xAvailable && !yAvailable) { throw new Error('Neither `x` nor `y` are given.'); } } }, { key: 'calculateFinalDimensions', /** * Calculates the final dimensions using the dimensions string and the * given initial dimensions * @param {Vector2} initialDimensions * @return {Vector2} */ value: function calculateFinalDimensions(initialDimensions) { var dimensions = initialDimensions.clone(), ratio; if (this._rules === null) return dimensions; /* istanbul ignore else */ if (this._rules.modifier === this._modifiers.FIXED) { // Fixed dimensions dimensions.set(this._rules.x, this._rules.y); } else if (this._rules.x !== null && this._rules.y !== null) { // Both x and y given, resize to fit ratio = Math.min(this._rules.x / dimensions.x, this._rules.y / dimensions.y); dimensions.multiply(ratio); } else if (this._rules.x !== null) { // Fixed x, y by ratio ratio = initialDimensions.y / initialDimensions.x; dimensions.x = this._rules.x; dimensions.y = dimensions.x * ratio; } else if (this._rules.y !== null) { // Fixed y, x by ratio ratio = initialDimensions.x / initialDimensions.y; dimensions.y = this._rules.y; dimensions.x = dimensions.y * ratio; } return dimensions; } }]); return ImageDimensions; })(); exports['default'] = ImageDimensions; module.exports = exports['default']; /***/ }, /* 54 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _renderer = __webpack_require__(96); var _renderer2 = _interopRequireDefault(_renderer); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); /** * @class * @alias ImglyKit.CanvasRenderer * @extends {ImglyKit.Renderer} * @private */ var CanvasRenderer = (function (_Renderer) { function CanvasRenderer() { _classCallCheck(this, CanvasRenderer); if (_Renderer != null) { _Renderer.apply(this, arguments); } } _inherits(CanvasRenderer, _Renderer); _createClass(CanvasRenderer, [{ key: 'cache', /** * Caches the current canvas content for the given identifier * @param {String} identifier */ value: function cache(identifier) { this._cache[identifier] = { data: this._context.getImageData(0, 0, this._canvas.width, this._canvas.height), size: new _libMathVector22['default'](this._canvas.width, this._canvas.height) }; } }, { key: 'drawCached', /** * Draws the stored texture / image data for the given identifier * @param {String} identifier */ value: function drawCached(identifier) { var _cache$identifier = this._cache[identifier]; var data = _cache$identifier.data; var size = _cache$identifier.size; this._canvas.width = size.x; this._canvas.height = size.y; this._context.putImageData(data, 0, 0); } }, { key: '_getContext', /** * Gets the rendering context from the Canva * @return {RenderingContext} * @abstract */ value: function _getContext() { /* istanbul ignore next */ return this._canvas.getContext('2d'); } }, { key: 'drawImage', /** * Draws the given image on the canvas * @param {Image} image * @returns {Promis} */ value: function drawImage(image) { var _this = this; return new _vendorPromise2['default'](function (resolve, reject) { _this._context.drawImage(image, 0, 0, image.width, image.height, 0, 0, _this._canvas.width, _this._canvas.height); resolve(); }); } }, { key: 'resizeTo', /** * Resizes the current canvas picture to the given dimensions * @param {Vector2} dimensions * @return {Promise} */ value: function resizeTo(dimensions) { // Create a temporary canvas to draw to var newCanvas = this.createCanvas(); newCanvas.width = dimensions.x; newCanvas.height = dimensions.y; var newContext = newCanvas.getContext('2d'); // Draw the source canvas onto the new one newContext.drawImage(this._canvas, 0, 0, this._canvas.width, this._canvas.height, 0, 0, newCanvas.width, newCanvas.height); // Set the new canvas and context this.setCanvas(newCanvas); } }, { key: 'cloneCanvas', /** * Returns a cloned version of the current canvas * @return {Canvas} */ value: function cloneCanvas() { var canvas = this.createCanvas(); var context = canvas.getContext('2d'); // Resize the canvas canvas.width = this._canvas.width; canvas.height = this._canvas.height; // Draw the current canvas on the new one context.drawImage(this._canvas, 0, 0); return canvas; } }, { key: 'reset', /** * Resets the renderer * @param {Boolean} resetCache = false * @override */ value: function reset() { var resetCache = arguments[0] === undefined ? false : arguments[0]; if (resetCache) { this._cache = []; } } }], [{ key: 'isSupported', /** * Checks whether this type of renderer is supported in the current environment * @abstract * @returns {boolean} */ value: function isSupported() { var elem = this.prototype.createCanvas(); return !!(elem.getContext && elem.getContext('2d')); } }, { key: 'identifier', /** * A unique string that identifies this renderer * @type {String} */ get: function () { return 'canvas'; } }]); return CanvasRenderer; })(_renderer2['default']); exports['default'] = CanvasRenderer; module.exports = exports['default']; /***/ }, /* 55 */ /***/ function(module, exports, __webpack_require__) { /* global Image */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _renderer = __webpack_require__(96); var _renderer2 = _interopRequireDefault(_renderer); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libExifRestorer = __webpack_require__(56); var _libExifRestorer2 = _interopRequireDefault(_libExifRestorer); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); /** * @class * @alias ImglyKit.WebGLRenderer * @extends {ImglyKit.Renderer} * @private */ var WebGLRenderer = (function (_Renderer) { function WebGLRenderer() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, WebGLRenderer); _get(Object.getPrototypeOf(WebGLRenderer.prototype), 'constructor', this).apply(this, args); this._defaultProgram = this.setupGLSLProgram(); this.reset(); this.id = WebGLRenderer.contextId; WebGLRenderer.contextId++; } _inherits(WebGLRenderer, _Renderer); _createClass(WebGLRenderer, [{ key: 'cache', /** * Caches the current canvas content for the given identifier * @param {String} identifier */ value: function cache(identifier) { var size = new _libMathVector22['default'](this._canvas.width, this._canvas.height); // Re-use FBO and textures var fbo = undefined, texture = undefined, cacheObject = undefined; if (!this._cache[identifier]) { cacheObject = this._createFramebuffer(); } else { cacheObject = this._cache[identifier]; } // Extract FBO and texture fbo = cacheObject.fbo; texture = cacheObject.texture; // Resize output texture var gl = this._context; gl.useProgram(this._defaultProgram); // Resize cached texture gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.x, size.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Render to FBO gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); gl.viewport(0, 0, size.x, size.y); // Use last fbo texture as input gl.bindTexture(gl.TEXTURE_2D, this._lastTexture); gl.drawArrays(gl.TRIANGLES, 0, 6); this._cache[identifier] = { fbo: fbo, texture: texture, size: size }; } }, { key: '_drawCachedFinal', /** * Debugging method to draw a cached texture to the canvas instead * to an FBO * @private */ value: function _drawCachedFinal(identifier) { var _cache$identifier = this._cache[identifier]; var texture = _cache$identifier.texture; var size = _cache$identifier.size; var gl = this._context; gl.useProgram(this._defaultProgram); gl.bindFramebuffer(gl.FRAMEBUFFER, null); // Use the cached texture as input gl.bindTexture(gl.TEXTURE_2D, texture); // Resize the canvas this._canvas.width = size.x; this._canvas.height = size.y; gl.viewport(0, 0, size.x, size.y); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); } }, { key: 'drawCached', /** * Draws the stored texture / image data for the given identifier * @param {String} identifier */ value: function drawCached(identifier) { var _cache$identifier2 = this._cache[identifier]; var texture = _cache$identifier2.texture; var size = _cache$identifier2.size; var fbo = this.getCurrentFramebuffer(); var currentTexture = this.getCurrentTexture(); var gl = this._context; gl.useProgram(this._defaultProgram); // Resize the canvas this._canvas.width = size.x; this._canvas.height = size.y; // Resize all textures for (var i = 0; i < this._textures.length; i++) { var otherTexture = this._textures[i]; gl.bindTexture(gl.TEXTURE_2D, otherTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.x, size.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } // Select the current framebuffer to draw to gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); // Resize the texture we're drawing to gl.bindTexture(gl.TEXTURE_2D, currentTexture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.x, size.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Use the cached texture as input gl.bindTexture(gl.TEXTURE_2D, texture); gl.viewport(0, 0, size.x, size.y); // Clear gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); this.setLastTexture(currentTexture); this.selectNextBuffer(); } }, { key: '_getContext', /** * Gets the rendering context from the Canvas * @return {RenderingContext} * @abstract */ value: function _getContext() { /* istanbul ignore next */ var gl = this._canvas.getContext('webgl', this._contextOptions) || this._canvas.getContext('experimental-webgl', this._contextOptions); gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); this._maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); return gl; } }, { key: 'drawImage', /** * Draws the given image on the canvas * @param {Image} image * @returns {Promise} */ /* istanbul ignore next */ value: function drawImage(image) { var _this = this; return new _vendorPromise2['default'](function (resolve, reject) { var gl = _this._context; gl.useProgram(_this._defaultProgram); // Create the texture var texture = _this.createTexture(); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); _this._inputTexture = texture; _this.setLastTexture(texture); // Set premultiplied alpha gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); // Upload the image into the texture gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); _this._clear(gl); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); resolve(); }); } }, { key: 'prepareImage', /** * Resizes the given image to fit the maximum texture size * @param {Image} * @returns {Promise} * @private */ value: function prepareImage(image) { if (image.width <= this._maxTextureSize && image.height <= this._maxTextureSize) { return _vendorPromise2['default'].resolve(image); } // Calculate new size that fits the graphics card's max texture size var maxSize = new _libMathVector22['default'](this._maxTextureSize, this._maxTextureSize); var size = new _libMathVector22['default'](image.width, image.height); var scale = Math.min(maxSize.x / size.x, maxSize.y / size.y); var newSize = size.clone().multiply(scale); // Create a new canvas to draw the image to var canvas = this.createCanvas(newSize.x, newSize.y); var context = canvas.getContext('2d'); // Draw the resized image context.drawImage(image, 0, 0, size.x, size.y, 0, 0, newSize.x, newSize.y); // Turn into a data url and make an image out of it var data = canvas.toDataURL('image/jpeg'); var jpegMatch = /^data:image\/jpeg/i; if (image.src.match(jpegMatch) && data.match(jpegMatch)) { data = _libExifRestorer2['default'].restore(image.src, data); } return new _vendorPromise2['default'](function (resolve, reject) { var image = new Image(); image.addEventListener('load', function () { resolve(image); }); image.src = data; }); } }, { key: '_clear', /** * Clears the WebGL context * @param {WebGLRenderingContext} gl * @private */ value: function _clear(gl) { gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); } }, { key: 'runProgram', value: function runProgram(program, options) { var gl = this._context; gl.useProgram(program); var fbo = this.getCurrentFramebuffer(); var currentTexture = this.getCurrentTexture(); // Select the current framebuffer gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); gl.viewport(0, 0, this._canvas.width, this._canvas.height); // Resize the texture to canvas size gl.bindTexture(gl.TEXTURE_2D, currentTexture); // Set premultiplied alpha gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._canvas.width, this._canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Make sure we select the current texture gl.bindTexture(gl.TEXTURE_2D, this._lastTexture); // Set the uniforms for (var name in options.uniforms) { var location = gl.getUniformLocation(program, name); var uniform = options.uniforms[name]; switch (uniform.type) { case 'i': case '1i': gl.uniform1i(location, uniform.value); break; case 'f': case '1f': gl.uniform1f(location, uniform.value); break; case '2f': gl.uniform2f(location, uniform.value[0], uniform.value[1]); break; case '3f': gl.uniform3f(location, uniform.value[0], uniform.value[1], uniform.value[2]); break; case '4f': gl.uniform4f(location, uniform.value[0], uniform.value[1], uniform.value[2], uniform.value[3]); break; case '2fv': gl.uniform2fv(location, uniform.value); break; case 'mat3fv': gl.uniformMatrix3fv(location, false, uniform.value); break; default: throw new Error('Unknown uniform type: ' + uniform.type); } } // Clear gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); this.setLastTexture(currentTexture); this.selectNextBuffer(); } }, { key: 'runShader', /** * Runs the given shader * @param {String} [vertexShader] * @param {String} [fragmentShader] */ /* istanbul ignore next */ value: function runShader(vertexShader, fragmentShader, options) { if (typeof options === 'undefined') options = {}; if (typeof options.uniforms === 'undefined') options.uniforms = {}; var program = this.setupGLSLProgram(vertexShader, fragmentShader); this.runProgram(program, options); } }, { key: 'renderFinal', /** * Draws the last used buffer onto the canvas */ /* istanbul ignore next */ value: function renderFinal() { var gl = this._context; var program = this._defaultProgram; gl.useProgram(program); // Don't draw to framebuffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); // Make sure the viewport size is correct gl.viewport(0, 0, this._canvas.width, this._canvas.height); // Select the last texture that has been rendered to gl.bindTexture(gl.TEXTURE_2D, this._lastTexture); // Clear this._clear(gl); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); } }, { key: 'setupGLSLProgram', /** * Sets up a GLSL program. Uses the default vertex and fragment shader * if none are given. * @param {String} [vertexShader] * @param {String} [fragmentShader] * @return {WebGLProgram} */ /* istanbul ignore next */ value: function setupGLSLProgram(vertexShader, fragmentShader) { var gl = this._context; var shaders = []; // Use default vertex shader vertexShader = this._createShader(gl.VERTEX_SHADER, vertexShader || WebGLRenderer.prototype.defaultVertexShader); shaders.push(vertexShader); // Use default fragment shader fragmentShader = this._createShader(gl.FRAGMENT_SHADER, fragmentShader || WebGLRenderer.prototype.defaultFragmentShader); shaders.push(fragmentShader); // Create the program var program = gl.createProgram(); // Attach the shaders for (var i = 0; i < shaders.length; i++) { gl.attachShader(program, shaders[i]); } // Link the program gl.linkProgram(program); // Check linking status var linked = gl.getProgramParameter(program, gl.LINK_STATUS); if (!linked) { var lastError = gl.getProgramInfoLog(program); gl.deleteProgram(program); throw new Error('WebGL program linking error: ' + lastError); } // Lookup texture coordinates location var positionLocation = gl.getAttribLocation(program, 'a_position'); var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord'); // Provide texture coordinates var texCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ // First triangle 0, 0, 1, 0, 0, 1, // Second triangle 0, 1, 1, 0, 1, 1]), gl.STATIC_DRAW); gl.enableVertexAttribArray(texCoordLocation); gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); // Create a buffer for the rectangle positions var buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ // First triangle -1, -1, 1, -1, -1, 1, // Second triangle -1, 1, 1, -1, 1, 1]), gl.STATIC_DRAW); return program; } }, { key: '_createShader', /** * Creates a WebGL shader with the given type and source code * @param {WebGLShaderType} shaderType * @param {String} shaderSource * @return {WebGLShader} * @private */ /* istanbul ignore next */ value: function _createShader(shaderType, shaderSource) { var gl = this._context; // Create the shader and compile it var shader = gl.createShader(shaderType); gl.shaderSource(shader, shaderSource); gl.compileShader(shader); // Check compilation status var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); if (!compiled) { var lastError = gl.getShaderInfoLog(shader); gl.deleteShader(shader); throw new Error('WebGL shader compilation error: ' + lastError); } return shader; } }, { key: 'createTexture', /** * Creates an empty texture * @return {WebGLTexture} */ /* istanbul ignore next */ value: function createTexture() { var gl = this._context; var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); return texture; } }, { key: '_createFramebuffers', /** * Creates two textures and framebuffers that are used for the stack * rendering * @private */ /* istanbul ignore next */ value: function _createFramebuffers() { for (var i = 0; i < 2; i++) { var _createFramebuffer2 = this._createFramebuffer(); var fbo = _createFramebuffer2.fbo; var texture = _createFramebuffer2.texture; this._textures.push(texture); this._framebuffers.push(fbo); } } }, { key: '_createFramebuffer', /** * Creates and returns a frame buffer and texture * @return {Object} * @private */ value: function _createFramebuffer() { var gl = this._context; // Create texture var texture = this.createTexture(); // Set premultiplied alpha gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this._canvas.width, this._canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // Create framebuffer var fbo = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); // Attach the texture gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); return { fbo: fbo, texture: texture }; } }, { key: 'resizeTo', /** * Resizes the current canvas picture to the given dimensions * @param {Vector2} dimensions * @todo Use a downsampling shader for smoother image resizing */ /* istanbul ignore next */ value: function resizeTo(dimensions) { var gl = this._context; // Resize the canvas this._canvas.width = dimensions.x; this._canvas.height = dimensions.y; // Update the viewport dimensions gl.viewport(0, 0, this._canvas.width, this._canvas.height); // Draw the rectangle gl.drawArrays(gl.TRIANGLES, 0, 6); } }, { key: 'getCurrentFramebuffer', /** * Returns the current framebuffer * @return {WebGLFramebuffer} */ value: function getCurrentFramebuffer() { return this._framebuffers[this._bufferIndex % 2]; } }, { key: 'getCurrentTexture', /** * Returns the current texture * @return {WebGLTexture} */ value: function getCurrentTexture() { return this._textures[this._bufferIndex % 2]; } }, { key: 'selectNextBuffer', /** * Increases the buffer index */ value: function selectNextBuffer() { this._bufferIndex++; } }, { key: 'getDefaultProgram', /** * Returns the default program * @return {WebGLProgram} */ value: function getDefaultProgram() { return this._defaultProgram; } }, { key: 'getLastTexture', /** * Returns the last texture that has been drawn to * @return {WebGLTexture} */ value: function getLastTexture() { return this._lastTexture; } }, { key: 'getTextures', /** * Returns all textures * @return {Array.} */ value: function getTextures() { return this._textures; } }, { key: 'setLastTexture', /** * Sets the last texture * @param {WebGLTexture} texture */ value: function setLastTexture(texture) { this._lastTexture = texture; } }, { key: 'reset', /** * Resets the renderer * @param {Boolean} resetCache = false * @override */ value: function reset() { var resetCache = arguments[0] === undefined ? false : arguments[0]; this._lastTexture = null; this._textures = []; this._framebuffers = []; this._bufferIndex = 0; if (resetCache) { this._cache = []; } this._createFramebuffers(); this.setLastTexture(this._inputTexture); } }, { key: '_contextOptions', /** * Returns the context options passed to getContext() * @type {Object} * @private */ get: function () { return { alpha: true, premultipliedAlpha: true }; } }, { key: 'identifier', /** * A unique string that identifies this renderer * @type {String} */ get: function () { return 'webgl'; } }, { key: 'defaultVertexShader', /** * The default vertex shader which just passes the texCoord to the * fragment shader. * @type {String} * @private */ get: function () { var shader = '\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n varying vec2 v_texCoord;\n\n void main() {\n gl_Position = vec4(a_position, 0, 1);\n v_texCoord = a_texCoord;\n }\n '; return shader; } }, { key: 'defaultFragmentShader', /** * The default fragment shader which will just look up the colors from the * texture. * @type {String} * @private */ get: function () { var shader = '\n precision mediump float;\n uniform sampler2D u_image;\n varying vec2 v_texCoord;\n\n void main() {\n gl_FragColor = texture2D(u_image, v_texCoord);\n }\n '; return shader; } }, { key: 'maxTextureSize', get: function () { return this._maxTextureSize; } }], [{ key: 'isSupported', /** * Checks whether this type of renderer is supported in the current environment * @abstract * @returns {boolean} */ value: function isSupported() { if (typeof window === 'undefined') { return false; } var canvas = document.createElement('canvas'); var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); return !!gl; } }]); return WebGLRenderer; })(_renderer2['default']); WebGLRenderer.contextId = 0; exports['default'] = WebGLRenderer; module.exports = exports['default']; /***/ }, /* 56 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com * * Extracted from MinifyJpeg (Copyright (c) 2014 Hiroaki Matoba, MIT License): * https://github.com/hMatoba/MinifyJpeg */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _base64 = __webpack_require__(97); var _base642 = _interopRequireDefault(_base64); var DATA_JPEG_PREFIX = 'data:image/jpeg;base64,'; var ExifRestorer = (function () { function ExifRestorer() { _classCallCheck(this, ExifRestorer); } _createClass(ExifRestorer, null, [{ key: 'restore', value: function restore(originalData, newData) { // Only for jpeg if (!originalData.match(DATA_JPEG_PREFIX)) { return newData; } var rawImage = _base642['default'].decode(originalData.replace(DATA_JPEG_PREFIX, '')); var segments = this._sliceIntoSegments(rawImage); var image = this._exifManipulation(newData, segments); return DATA_JPEG_PREFIX + _base642['default'].encode(image); } }, { key: '_exifManipulation', value: function _exifManipulation(data, segments) { var exifArray = this._getExifArray(segments); var newImageArray = this._insertExif(data, exifArray); var buffer = new Uint8Array(newImageArray); return buffer; } }, { key: '_getExifArray', value: function _getExifArray(segments) { var seg = undefined; for (var i = 0; i < segments.length; i++) { seg = segments[i]; if (seg[0] === 255 && seg[1] === 225) { return seg; } } return []; } }, { key: '_insertExif', value: function _insertExif(data, exifArray) { var imageData = data.replace(DATA_JPEG_PREFIX, ''); var buf = _base642['default'].decode(imageData); var separatePoint = buf.indexOf(255, 3); var mae = buf.slice(0, separatePoint); var ato = buf.slice(separatePoint); var array = mae; array = array.concat(exifArray); array = array.concat(ato); return array; } }, { key: '_sliceIntoSegments', value: function _sliceIntoSegments(data) { var head = 0; var segments = []; while (1) { if (data[head] === 255 && data[head + 1] === 218) { break; } if (data[head] === 255 && data[head + 1] === 216) { head += 2; } else { var _length = data[head + 2] * 256 + data[head + 3]; var endPoint = head + _length + 2; var seg = data.slice(head, endPoint); segments.push(seg); head = endPoint; } if (head > data.length) { break; } } return segments; } }]); return ExifRestorer; })(); exports['default'] = ExifRestorer; module.exports = exports['default']; /***/ }, /* 57 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {/* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var root = typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : null; var p = root.Promise; if (!p) { p = __webpack_require__(99); } exports['default'] = p; module.exports = exports['default']; /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) /***/ }, /* 58 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Helper function to correctly set up the prototype chain * Based on the backbone.js extend function: * https://github.com/jashkenas/backbone/blob/master/backbone.js * @param {Object} prototypeProperties * @param {Object} classProperties * @return {Object} */ 'use strict'; module.exports = function (prototypeProperties, classProperties) { /*jshint validthis:true*/ var parent = this; var child; // The constructor function for the new subclass is either defined by you // (the 'constructor' property in your `extend` definition), or defaulted // by us to simply call the parent's constructor. if (prototypeProperties && prototypeProperties.hasOwnProperty('constructor')) { child = prototypeProperties.constructor; } else { child = function () { return parent.apply(this, arguments); }; } // Add static properties to the constructor function, if supplied. var key; for (key in parent) { child[key] = parent[key]; } if (typeof classProperties !== 'undefined') { for (key in classProperties) { child[key] = classProperties[key]; } } // Set the prototype chain to inherit from `parent`, without calling // `parent`'s constructor function. var Surrogate = function Surrogate() { this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate(); // Add prototype properties (instance properties) to the subclass, // if supplied. if (prototypeProperties) { for (key in prototypeProperties) { child.prototype[key] = prototypeProperties[key]; } } // Set a convenience property in case the parent's prototype is needed // later. child.__super__ = parent.prototype; return child; }; /***/ }, /* 59 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * A helper class that can collect {@link Primitive} instances and render * the stack * @class * @alias ImglyKit.Filter.PrimitivesStack */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var PrimitivesStack = (function () { function PrimitivesStack() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, PrimitivesStack); /** * The stack of {@link ImglyKit.Filter.Primitive} instances * @type {Array} * @private */ this._stack = []; } _createClass(PrimitivesStack, [{ key: "add", /** * Adds the given primitive to the stack * @param {ImglyKit.Filter.Primitive} primitive */ value: function add(primitive) { this._stack.push(primitive); } }, { key: "render", /** * Renders the stack of primitives on the renderer * @param {Renderer} renderer */ value: function render(renderer) { for (var i = 0; i < this._stack.length; i++) { var primitive = this._stack[i]; primitive.render(renderer); } } }]); return PrimitivesStack; })(); exports["default"] = PrimitivesStack; module.exports = exports["default"]; /***/ }, /* 60 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Saturation primitive * @class * @alias ImglyKit.Filter.Primitives.Saturation * @extends {ImglyKit.Filter.Primitive} */ var Saturation = (function (_Primitive) { function Saturation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Saturation); _get(Object.getPrototypeOf(Saturation.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { saturation: 0 }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform float u_saturation;\n\n const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n float luminance = dot(texColor.rgb, luminanceWeighting);\n\n vec3 greyScaleColor = vec3(luminance);\n\n gl_FragColor = vec4(mix(greyScaleColor, texColor.rgb, u_saturation) * texColor.a, texColor.a);\n }\n '; } _inherits(Saturation, _Primitive); _createClass(Saturation, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: { u_saturation: { type: 'f', value: this._options.saturation } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer * @return {Promise} */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var saturation = this._options.saturation; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var luminance = imageData.data[index] * 0.2125 + imageData.data[index + 1] * 0.7154 + imageData.data[index + 2] * 0.0721; imageData.data[index] = luminance * (1 - saturation) + imageData.data[index] * saturation; imageData.data[index + 1] = luminance * (1 - saturation) + imageData.data[index + 1] * saturation; imageData.data[index + 2] = luminance * (1 - saturation) + imageData.data[index + 2] * saturation; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Saturation; })(_primitive2['default']); exports['default'] = Saturation; module.exports = exports['default']; /***/ }, /* 61 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Stores a 256 byte long lookup table in a 2d texture which will be * used to look up the corresponding value for each channel. * @class * @alias ImglyKit.Filter.Primitives.LookupTable * @extends {ImglyKit.Filter.Primitive} */ var LookupTable = (function (_Primitive) { function LookupTable() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, LookupTable); _get(Object.getPrototypeOf(LookupTable.prototype), 'constructor', this).apply(this, args); this._textureIndex = 3; /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform sampler2D u_lookupTable;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n float r = texture2D(u_lookupTable, vec2(texColor.r, 0.0)).r;\n float g = texture2D(u_lookupTable, vec2(texColor.g, 0.0)).g;\n float b = texture2D(u_lookupTable, vec2(texColor.b, 0.0)).b;\n\n gl_FragColor = vec4(vec3(r, g, b) * texColor.a, texColor.a);\n }\n '; } _inherits(LookupTable, _Primitive); _createClass(LookupTable, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { this._updateTexture(renderer); renderer.runShader(null, this._fragmentShader, { uniforms: { u_lookupTable: { type: 'i', value: 3 } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var table = this._options.data; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var r = imageData.data[index]; imageData.data[index] = table[r * 4]; var g = imageData.data[index + 1]; imageData.data[index + 1] = table[1 + g * 4]; var b = imageData.data[index + 2]; imageData.data[index + 2] = table[2 + b * 4]; } } renderer.getContext().putImageData(imageData, 0, 0); } }, { key: '_updateTexture', /** * Updates the lookup table texture (WebGL only) * @private */ /* istanbul ignore next */ value: function _updateTexture(renderer) { var gl = renderer.getContext(); if (typeof this._options.data === 'undefined') { throw new Error('LookupTable: No data specified.'); } var dataTypedArray = new Uint8Array(this._options.data); gl.activeTexture(gl.TEXTURE0 + this._textureIndex); if (!this._texture) { this._texture = gl.createTexture(); } gl.bindTexture(gl.TEXTURE_2D, this._texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, dataTypedArray); gl.activeTexture(gl.TEXTURE0); } }]); return LookupTable; })(_primitive2['default']); exports['default'] = LookupTable; module.exports = exports['default']; /***/ }, /* 62 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _lookupTable = __webpack_require__(61); var _lookupTable2 = _interopRequireDefault(_lookupTable); /** * Tone curve primitive * @class * @alias ImglyKit.Filter.Primitives.ToneCurve * @extends {ImglyKit.Filter.Primitives.LookupTable} */ var ToneCurve = (function (_LookupTable) { function ToneCurve() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, ToneCurve); _get(Object.getPrototypeOf(ToneCurve.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { rgbControlPoints: { red: this._options.controlPoints, green: this._options.controlPoints, blue: this._options.controlPoints } }); if (typeof this._options.rgbControlPoints !== 'undefined') { this._updateLookupTable(); } } _inherits(ToneCurve, _LookupTable); _createClass(ToneCurve, [{ key: '_updateLookupTable', /** * Calculates the lookup table * @private */ value: function _updateLookupTable() { var r = this._calculateSplineCurve(this._options.rgbControlPoints.red); var g = this._calculateSplineCurve(this._options.rgbControlPoints.green); var b = this._calculateSplineCurve(this._options.rgbControlPoints.blue); this._options.data = this._buildLookupTable(r, g, b); } }, { key: '_buildLookupTable', /** * Builds the lookup table * @param {Array} r * @param {Array} g * @param {Array} b * @return {Array} * @private */ value: function _buildLookupTable(r, g, b) { var data = []; for (var i = 0; i < 256; i++) { data.push(Math.min(Math.max(i + r[i], 0), 255)); data.push(Math.min(Math.max(i + g[i], 0), 255)); data.push(Math.min(Math.max(i + b[i], 0), 255)); data.push(255); } return data; } }, { key: '_calculateSplineCurve', /** * Calculates the spline curve data for the given points * @param {Array.>} points * @return {Array.} */ value: function _calculateSplineCurve(points) { points = points.sort(function (a, b) { return a[0] > b[0]; }); var splinePoints = this._getSplineCurve(points); var firstSplinePoint = splinePoints[0]; var i; if (firstSplinePoint[0] > 0) { for (i = 0; i < firstSplinePoint[0]; i++) { splinePoints.unshift([0, 0]); } } var preparedPoints = []; for (i = 0; i < splinePoints.length; i++) { var newPoint = splinePoints[i]; var origPoint = [newPoint[0], newPoint[0]]; var distance = Math.sqrt(Math.pow(origPoint[0] - newPoint[0], 2) + Math.pow(origPoint[1] - newPoint[1], 2)); if (origPoint[1] > newPoint[1]) { distance = -distance; } preparedPoints.push(distance); } return preparedPoints; } }, { key: '_getSplineCurve', value: function _getSplineCurve(points) { var sdA = this._secondDerivative(points); var n = sdA.length; var sd = []; var i; for (i = 0; i < n; i++) { sd[i] = sdA[i]; } var output = []; for (i = 0; i < n - 1; i++) { var cur = points[i]; var next = points[i + 1]; for (var x = cur[0]; x < next[0]; x++) { var t = (x - cur[0]) / (next[0] - cur[0]); var a = 1 - t; var b = t; var h = next[0] - cur[0]; var y = a * cur[1] + b * next[1] + h * h / 6 * ((a * a * a - a) * sd[i] + (b * b * b - b) * sd[i + 1]); if (y > 255) { y = 255; } else if (y < 0) { y = 0; } output.push([x, y]); } } if (output.length === 255) { output.push(points[points.length - 1]); } return output; } }, { key: '_secondDerivative', value: function _secondDerivative(points) { var n = points.length; if (n <= 0 || n === 1) { return null; } var matrix = []; var result = []; var i, k; matrix[0] = [0, 1, 0]; for (i = 1; i < n - 1; i++) { var P1 = points[i - 1]; var P2 = points[i]; var P3 = points[i + 1]; matrix[i] = matrix[i] || []; matrix[i][0] = (P2[0] - P1[0]) / 6; matrix[i][1] = (P3[0] - P1[0]) / 3; matrix[i][2] = (P3[0] - P2[0]) / 6; result[i] = (P3[1] - P2[1]) / (P3[0] - P2[0]) - (P2[1] - P1[1]) / (P2[0] - P1[0]); } result[0] = 0; result[n - 1] = 0; matrix[n - 1] = [0, 1, 0]; // Pass 1 for (i = 1; i < n; i++) { k = matrix[1][0] / matrix[i - 1][1]; matrix[i][1] -= k * matrix[i - 1][2]; matrix[i][0] = 0; result[i] -= k * result[i - 1]; } // Pass 2 for (i = n - 2; i > 0; i--) { k = matrix[i][2] / matrix[i + 1][1]; matrix[i][1] -= k * matrix[i + 1][0]; matrix[i][2] = 0; result[i] -= k * result[i + 1]; } var y2 = []; for (i = 0; i < n; i++) { y2[i] = result[i] / matrix[i][1]; } return y2; } }]); return ToneCurve; })(_lookupTable2['default']); exports['default'] = ToneCurve; module.exports = exports['default']; /***/ }, /* 63 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); /** * SoftColorOverlay primitive * @class * @alias ImglyKit.Filter.Primitives.SoftColorOverlay * @extends {ImglyKit.Filter.Primitive} */ var SoftColorOverlay = (function (_Primitive) { function SoftColorOverlay() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, SoftColorOverlay); _get(Object.getPrototypeOf(SoftColorOverlay.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { color: new _libColor2['default'](1, 1, 1) }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform vec3 u_overlay;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n vec4 overlayVec4 = vec4(u_overlay, texColor.a);\n gl_FragColor = max(overlayVec4 * texColor.a, texColor);\n }\n '; } _inherits(SoftColorOverlay, _Primitive); _createClass(SoftColorOverlay, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader, { uniforms: { u_overlay: { type: '3f', value: this._options.color.toRGBGLColor() } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; imageData.data[index] = Math.max(this._options.color.r, imageData.data[index]); imageData.data[index + 1] = Math.max(this._options.color.g, imageData.data[index + 1]); imageData.data[index + 2] = Math.max(this._options.color.b, imageData.data[index + 2]); } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return SoftColorOverlay; })(_primitive2['default']); exports['default'] = SoftColorOverlay; module.exports = exports['default']; /***/ }, /* 64 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Desaturation primitive * @class * @alias ImglyKit.Filter.Primitives.Desaturation * @extends {ImglyKit.Filter.Primitive} */ var Desaturation = (function (_Primitive) { function Desaturation() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Desaturation); _get(Object.getPrototypeOf(Desaturation.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { desaturation: 1 }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform float u_desaturation;\n\n const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n vec3 grayXfer = vec3(0.3, 0.59, 0.11);\n vec3 gray = vec3(dot(grayXfer, texColor.xyz));\n gl_FragColor = vec4(mix(texColor.xyz, gray, u_desaturation) * texColor.a, texColor.a);\n }\n '; } _inherits(Desaturation, _Primitive); _createClass(Desaturation, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer * @return {Promise} */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader, { uniforms: { u_desaturation: { type: 'f', value: this._options.desaturation } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var desaturation = this._options.desaturation; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var luminance = imageData.data[index] * 0.3 + imageData.data[index + 1] * 0.59 + imageData.data[index + 2] * 0.11; imageData.data[index] = luminance * (1 - desaturation) + imageData.data[index] * desaturation; imageData.data[index + 1] = luminance * (1 - desaturation) + imageData.data[index + 1] * desaturation; imageData.data[index + 2] = luminance * (1 - desaturation) + imageData.data[index + 2] * desaturation; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Desaturation; })(_primitive2['default']); exports['default'] = Desaturation; module.exports = exports['default']; /***/ }, /* 65 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * X400 primitive * @class * @alias ImglyKit.Filter.Primitives.X400 * @extends {ImglyKit.Filter.Primitive} */ var X400 = (function (_Primitive) { function X400() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, X400); _get(Object.getPrototypeOf(X400.prototype), 'constructor', this).apply(this, args); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n float gray = texColor.r * 0.3 + texColor.g * 0.3 + texColor.b * 0.3;\n gray -= 0.2;\n gray = clamp(gray, 0.0, 1.0);\n gray += 0.15;\n gray *= 1.4;\n gl_FragColor = vec4(vec3(gray) * texColor.a, texColor.a);\n }\n '; } _inherits(X400, _Primitive); _createClass(X400, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var gray = imageData.data[index] / 255 * 0.3 + imageData.data[index + 1] / 255 * 0.3 + imageData.data[index + 2] / 255 * 0.3; gray -= 0.2; gray = Math.max(0, Math.min(1, gray)); gray += 0.15; gray *= 1.4; gray *= 255; imageData.data[index] = gray; imageData.data[index + 1] = gray; imageData.data[index + 2] = gray; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return X400; })(_primitive2['default']); exports['default'] = X400; module.exports = exports['default']; /***/ }, /* 66 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Grayscale primitive * @class * @alias ImglyKit.Filter.Primitives.Grayscale * @extends {ImglyKit.Filter.Primitive} */ var Grayscale = (function (_Primitive) { function Grayscale() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Grayscale); _get(Object.getPrototypeOf(Grayscale.prototype), 'constructor', this).apply(this, args); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n vec3 W = vec3(0.2125, 0.7154, 0.0721);\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n float luminance = dot(texColor.rgb, W);\n gl_FragColor = vec4(vec3(luminance) * texColor.a, texColor.a);\n }\n '; } _inherits(Grayscale, _Primitive); _createClass(Grayscale, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer * @return {Promise} */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var luminance = imageData.data[index] * 0.2125 + imageData.data[index + 1] * 0.7154 + imageData.data[index + 2] * 0.0721; imageData.data[index] = luminance; imageData.data[index + 1] = luminance; imageData.data[index + 2] = luminance; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Grayscale; })(_primitive2['default']); exports['default'] = Grayscale; module.exports = exports['default']; /***/ }, /* 67 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Contrast primitive * @class * @alias ImglyKit.Filter.Primitives.Contrast * @extends {ImglyKit.Filter.Primitive} */ var Contrast = (function (_Primitive) { function Contrast() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Contrast); _get(Object.getPrototypeOf(Contrast.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { contrast: 1 }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform float u_contrast;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor = vec4(((texColor.rgb - vec3(0.5)) * u_contrast + vec3(0.5) * texColor.a), texColor.a);\n }\n '; } _inherits(Contrast, _Primitive); _createClass(Contrast, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: { u_contrast: { type: 'f', value: this._options.contrast } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var contrast = this._options.contrast; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; imageData.data[index] = (imageData.data[index] - 127) * contrast + 127; imageData.data[index + 1] = (imageData.data[index + 1] - 127) * contrast + 127; imageData.data[index + 2] = (imageData.data[index + 2] - 127) * contrast + 127; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Contrast; })(_primitive2['default']); exports['default'] = Contrast; module.exports = exports['default']; /***/ }, /* 68 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); /** * Glow primitive * @class * @alias ImglyKit.Filter.Primitives.Glow * @extends {ImglyKit.Filter.Primitive} */ var Glow = (function (_Primitive) { function Glow() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Glow); _get(Object.getPrototypeOf(Glow.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { color: new _libColor2['default'](1, 1, 1) }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n\n uniform vec3 u_color;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n\n vec2 textureCoord = v_texCoord - vec2(0.5, 0.5);\n textureCoord /= 0.75;\n\n float d = 1.0 - dot(textureCoord, textureCoord);\n d = clamp(d, 0.2, 1.0);\n vec3 newColor = texColor.rgb * d * u_color.rgb;\n gl_FragColor = vec4(vec3(newColor) * texColor.a, texColor.a);\n }\n '; } _inherits(Glow, _Primitive); _createClass(Glow, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer * @return {Promise} */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader, { uniforms: { u_color: { type: '3f', value: this._options.color.toRGBGLColor() } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer * @return {Promise} */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var color = this._options.color; var d; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; var x01 = x / canvas.width; var y01 = y / canvas.height; var nx = (x01 - 0.5) / 0.75; var ny = (y01 - 0.5) / 0.75; var scalarX = nx * nx; var scalarY = ny * ny; d = 1 - (scalarX + scalarY); d = Math.min(Math.max(d, 0.1), 1); imageData.data[index] = imageData.data[index] * (d * color.r); imageData.data[index + 1] = imageData.data[index + 1] * (d * color.g); imageData.data[index + 2] = imageData.data[index + 2] * (d * color.b); imageData.data[index + 3] = 255; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Glow; })(_primitive2['default']); exports['default'] = Glow; module.exports = exports['default']; /***/ }, /* 69 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Gobblin primitive * @class * @alias ImglyKit.Filter.Primitives.Gobblin * @extends {ImglyKit.Filter.Primitive} */ var Gobblin = (function (_Primitive) { function Gobblin() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Gobblin); _get(Object.getPrototypeOf(Gobblin.prototype), 'constructor', this).apply(this, args); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n texColor.b = texColor.g * 0.33;\n texColor.r = texColor.r * 0.6;\n texColor.b += texColor.r * 0.33;\n texColor.g = texColor.g * 0.7;\n gl_FragColor = texColor;\n }\n '; } _inherits(Gobblin, _Primitive); _createClass(Gobblin, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer * @return {Promise} */ /* istanbul ignore next */ value: function renderWebGL(renderer) { renderer.runShader(null, this._fragmentShader); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; imageData.data[index + 2] = imageData.data[index + 1] * 0.33; imageData.data[index] = imageData.data[index] * 0.6; imageData.data[index + 2] += imageData.data[index] * 0.33; imageData.data[index + 1] = imageData.data[index + 1] * 0.7; imageData.data[index + 3] = 255; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Gobblin; })(_primitive2['default']); exports['default'] = Gobblin; module.exports = exports['default']; /***/ }, /* 70 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _primitive = __webpack_require__(98); var _primitive2 = _interopRequireDefault(_primitive); /** * Brightness primitive * @class * @alias ImglyKit.Filter.Primitives.Brightness * @extends {ImglyKit.Filter.Primitive} */ var Brightness = (function (_Primitive) { function Brightness() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _classCallCheck(this, Brightness); _get(Object.getPrototypeOf(Brightness.prototype), 'constructor', this).apply(this, args); this._options = _libUtils2['default'].defaults(this._options, { brightness: 1 }); /** * The fragment shader for this primitive * @return {String} * @private */ this._fragmentShader = '\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_image;\n uniform float u_brightness;\n\n void main() {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor = vec4((texColor.rgb + vec3(u_brightness) * texColor.a), texColor.a);;\n }\n '; } _inherits(Brightness, _Primitive); _createClass(Brightness, [{ key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {WebGLRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { if (!this._glslPrograms[renderer.id]) { this._glslPrograms[renderer.id] = renderer.setupGLSLProgram(null, this._fragmentShader); } renderer.runProgram(this._glslPrograms[renderer.id], { uniforms: { u_brightness: { type: 'f', value: this._options.brightness } } }); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { var canvas = renderer.getCanvas(); var imageData = renderer.getContext().getImageData(0, 0, canvas.width, canvas.height); var brightness = this._options.brightness; for (var x = 0; x < canvas.width; x++) { for (var y = 0; y < canvas.height; y++) { var index = (canvas.width * y + x) * 4; imageData.data[index] = imageData.data[index] + brightness * 255; imageData.data[index + 1] = imageData.data[index + 1] + brightness * 255; imageData.data[index + 2] = imageData.data[index + 2] + brightness * 255; } } renderer.getContext().putImageData(imageData, 0, 0); } }]); return Brightness; })(_primitive2['default']); exports['default'] = Brightness; module.exports = exports['default']; /***/ }, /* 71 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _filter = __webpack_require__(7); var _filter2 = _interopRequireDefault(_filter); /** * Identity Filter * @class * @alias ImglyKit.Filters.IdentityFilter * @extends {ImglyKit.Filter} */ var IdentityFilter = (function (_Filter) { function IdentityFilter() { _classCallCheck(this, IdentityFilter); if (_Filter != null) { _Filter.apply(this, arguments); } } _inherits(IdentityFilter, _Filter); _createClass(IdentityFilter, [{ key: 'render', /** * Renders the filter * @return {Promise} */ value: function render() {} }, { key: 'name', /** * The name that is displayed in the UI * @type {String} */ get: function () { return 'Original'; } }], [{ key: 'identifier', /** * A unique string that identifies this operation. Can be used to select * the active filter. * @type {String} */ get: function () { return 'identity'; } }]); return IdentityFilter; })(_filter2['default']); exports['default'] = IdentityFilter; module.exports = exports['default']; // This is the identity filter, it doesn't have any effect. /***/ }, /* 72 */ /***/ function(module, exports, __webpack_require__) { /** * EventEmitter (ES6) from: * https://gist.github.com/bloodyowl/41b1de3388c626796eca */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var DEFAULT_MAX_LISTENERS = 12; function error(message) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } console.error.apply(console, [message].concat(args)); console.trace(); } var EventEmitter = (function () { function EventEmitter() { _classCallCheck(this, EventEmitter); this._maxListeners = DEFAULT_MAX_LISTENERS; this._events = {}; } _createClass(EventEmitter, [{ key: 'on', value: function on(type, listener) { if (typeof listener !== 'function') { throw new TypeError(); } var listeners = this._events[type] || (this._events[type] = []); if (listeners.indexOf(listener) !== -1) { return this; } listeners.push(listener); if (listeners.length > this._maxListeners) { error('possible memory leak, added %i %s listeners,\n use EventEmitter#setMaxListeners(number) if you\n want to increase the limit (%i now)', listeners.length, type, this._maxListeners); } return this; } }, { key: 'once', value: function once(type, listener) { var eventsInstance = this; function onceCallback() { eventsInstance.off(type, onceCallback); listener.apply(null, arguments); } return this.on(type, onceCallback); } }, { key: 'off', value: function off(type) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } if (args.length === 0) { this._events[type] = null; return this; } var listener = args[0]; if (typeof listener !== 'function') { throw new TypeError(); } var listeners = this._events[type]; if (!listeners || !listeners.length) { return this; } var indexOfListener = listeners.indexOf(listener); if (indexOfListener === -1) { return this; } listeners.splice(indexOfListener, 1); return this; } }, { key: 'emit', value: function emit(type) { for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { args[_key3 - 1] = arguments[_key3]; } var listeners = this._events[type]; if (!listeners || !listeners.length) { return false; } listeners.forEach(function (fn) { return fn.apply(null, args); }); return true; } }, { key: 'setMaxListeners', value: function setMaxListeners(newMaxListeners) { if (parseInt(newMaxListeners, 10) !== newMaxListeners) { throw new TypeError(); } this._maxListeners = newMaxListeners; } }]); return EventEmitter; })(); exports['default'] = EventEmitter; module.exports = exports['default']; /***/ }, /* 73 */ /***/ function(module, exports, __webpack_require__) { "use strict"; /*! StackBlur - a fast almost Gaussian Blur For Canvas Version: 0.5 Author: Mario Klingemann Contact: mario@quasimondo.com Website: http://www.quasimondo.com/StackBlurForCanvas Twitter: @quasimondo In case you find this class useful - especially in commercial projects - I am not totally unhappy for a small donation to my PayPal account mario@quasimondo.de Or support me on flattr: https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript Copyright (c) 2010 Mario Klingemann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var mul_table = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259]; var shg_table = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]; function stackBlurCanvasRGBA(imageData, top_x, top_y, width, height, radius) { if (isNaN(radius) || radius < 1) return; radius |= 0; var pixels = imageData.data; var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum, r_out_sum, g_out_sum, b_out_sum, a_out_sum, r_in_sum, g_in_sum, b_in_sum, a_in_sum, pr, pg, pb, pa, rbs; var div = radius + radius + 1; var widthMinus1 = width - 1; var heightMinus1 = height - 1; var radiusPlus1 = radius + 1; var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; var stackStart = new BlurStack(); var stackEnd; var stack = stackStart; for (i = 1; i < div; i++) { stack = stack.next = new BlurStack(); if (i == radiusPlus1) stackEnd = stack; } stack.next = stackStart; var stackIn = null; var stackOut = null; yw = yi = 0; var mul_sum = mul_table[radius]; var shg_sum = shg_table[radius]; for (y = 0; y < height; y++) { r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; a_sum += sumFactor * pa; stack = stackStart; for (i = 0; i < radiusPlus1; i++) { stack.r = pr; stack.g = pg; stack.b = pb; stack.a = pa; stack = stack.next; } for (i = 1; i < radiusPlus1; i++) { p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i); g_sum += (stack.g = pg = pixels[p + 1]) * rbs; b_sum += (stack.b = pb = pixels[p + 2]) * rbs; a_sum += (stack.a = pa = pixels[p + 3]) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; a_in_sum += pa; stack = stack.next; } stackIn = stackStart; stackOut = stackEnd; for (x = 0; x < width; x++) { pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum; if (pa !== 0) { pa = 255 / pa; pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa; pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa; pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa; } else { pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0; } r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; a_sum -= a_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; a_out_sum -= stackIn.a; p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2; r_in_sum += stackIn.r = pixels[p]; g_in_sum += stackIn.g = pixels[p + 1]; b_in_sum += stackIn.b = pixels[p + 2]; a_in_sum += stackIn.a = pixels[p + 3]; r_sum += r_in_sum; g_sum += g_in_sum; b_sum += b_in_sum; a_sum += a_in_sum; stackIn = stackIn.next; r_out_sum += pr = stackOut.r; g_out_sum += pg = stackOut.g; b_out_sum += pb = stackOut.b; a_out_sum += pa = stackOut.a; r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; a_in_sum -= pa; stackOut = stackOut.next; yi += 4; } yw += width; } for (x = 0; x < width; x++) { g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0; yi = x << 2; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; a_sum += sumFactor * pa; stack = stackStart; for (i = 0; i < radiusPlus1; i++) { stack.r = pr; stack.g = pg; stack.b = pb; stack.a = pa; stack = stack.next; } yp = width; for (i = 1; i <= radius; i++) { yi = yp + x << 2; r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i); g_sum += (stack.g = pg = pixels[yi + 1]) * rbs; b_sum += (stack.b = pb = pixels[yi + 2]) * rbs; a_sum += (stack.a = pa = pixels[yi + 3]) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; a_in_sum += pa; stack = stack.next; if (i < heightMinus1) { yp += width; } } yi = x; stackIn = stackStart; stackOut = stackEnd; for (y = 0; y < height; y++) { p = yi << 2; pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum; if (pa > 0) { pa = 255 / pa; pixels[p] = (r_sum * mul_sum >> shg_sum) * pa; pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa; pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa; } else { pixels[p] = pixels[p + 1] = pixels[p + 2] = 0; } r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; a_sum -= a_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; a_out_sum -= stackIn.a; p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2; r_sum += r_in_sum += stackIn.r = pixels[p]; g_sum += g_in_sum += stackIn.g = pixels[p + 1]; b_sum += b_in_sum += stackIn.b = pixels[p + 2]; a_sum += a_in_sum += stackIn.a = pixels[p + 3]; stackIn = stackIn.next; r_out_sum += pr = stackOut.r; g_out_sum += pg = stackOut.g; b_out_sum += pb = stackOut.b; a_out_sum += pa = stackOut.a; r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; a_in_sum -= pa; stackOut = stackOut.next; yi += width; } } } function BlurStack() { this.r = 0; this.g = 0; this.b = 0; this.a = 0; this.next = null; } module.exports = { stackBlurCanvasRGBA: stackBlurCanvasRGBA }; /***/ }, /* 74 */ /***/ function(module, exports, __webpack_require__) { // shim for using process in browser var process = module.exports = {}; var queue = []; var draining = false; function drainQueue() { if (draining) { return; } draining = true; var currentQueue; var len = queue.length; while(len) { currentQueue = queue; queue = []; var i = -1; while (++i < len) { currentQueue[i](); } len = queue.length; } draining = false; } process.nextTick = function (fun) { queue.push(fun); if (!draining) { setTimeout(drainQueue, 0); } }; 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.binding = function (name) { throw new Error('process.binding is not supported'); }; // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; /***/ }, /* 75 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _helpers = __webpack_require__(100); var _helpers2 = _interopRequireDefault(_helpers); var BaseUI = (function (_EventEmitter) { function BaseUI(kit, options) { _classCallCheck(this, BaseUI); _get(Object.getPrototypeOf(BaseUI.prototype), 'constructor', this).call(this); this._kit = kit; this._options = options; this._options.ui = this._options.ui || {}; this._operations = []; this._helpers = new _helpers2['default'](this.kit, this, options); this._languages = {}; this.selectOperations(null); } _inherits(BaseUI, _EventEmitter); _createClass(BaseUI, [{ key: 'run', /** * Prepares the UI for use */ value: function run() { this._attach(); } }, { key: 'registerLanguage', /** * Registers a language * @param {String} identifier * @param {Object} object */ value: function registerLanguage(identifier, object) { this._languages[identifier] = object; } }, { key: 'translate', /** * Returns the translation for `key` * @param {String} key * @return {String} */ value: function translate(key) { return _libUtils2['default'].fetch(this._language, key, 'translation-missing'); } }, { key: '_attach', /** * Renders and attaches the UI HTML * @private */ value: function _attach() { if (this._options.container === null) { throw new Error('BaseUI#attach: No container set.'); } var html = this._render(); this._options.container.innerHTML = html; // Container has to be position: relative this._options.container.style.position = 'relative'; } }, { key: '_render', /** * Renders the template * @private */ value: function _render() { if (typeof this._template === 'undefined') { throw new Error('BaseUI#_render: No template set.'); } return this._template(this.context); } }, { key: 'selectOperations', /** * Selects the enabled operations * @param {ImglyKit.Selector} */ value: function selectOperations(selector) { var registeredOperations = this._kit.registeredOperations; var operationIdentifiers = Object.keys(registeredOperations); var selectedOperations = _libUtils2['default'].select(operationIdentifiers, selector); this._operations = selectedOperations.map(function (identifier) { return registeredOperations[identifier]; }); } }, { key: 'addOperation', /** * Adds the given operation to the available operations * @param {Operation} operation */ value: function addOperation(operation) { this._operations.push(operation); } }, { key: 'isOperationSelected', /** * Checks whether the operation with the given identifier is selected * @param {String} identifier * @returns {Boolean} */ value: function isOperationSelected(identifier) { var operationIdentifiers = this._operations.map(function (operation) { return operation.prototype.identifier; }); return operationIdentifiers.indexOf(identifier) !== -1; } }, { key: 'identifier', /** * A unique string that represents this UI * @type {String} */ get: function () { return null; } }, { key: 'context', /** * The data that is passed to the template renderer * @type {Object} */ get: function () { return { operations: this._operations, helpers: this._helpers, options: this._options }; } }, { key: 'container', /** * The DOM container * @type {DOMElement} */ get: function () { return this._options.container; } }, { key: 'operations', /** * The selected / active operations * @type {Array.} */ get: function () { return this._operations; } }, { key: 'options', /** * The options * @type {Object} */ get: function () { return this._options; } }, { key: 'canvas', /** * The canvas object * @type {Canvas} */ get: function () { return this._canvas; } }, { key: 'helpers', /** * The helpers * @type {Helpers} */ get: function () { return this._helpers; } }, { key: 'image', /** * The image * @type {Image} */ get: function () { return this._options.image; } }]); return BaseUI; })(_libEventEmitter2['default']); exports['default'] = BaseUI; module.exports = exports['default']; /***/ }, /* 76 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _renderersWebglRenderer = __webpack_require__(55); var _renderersWebglRenderer2 = _interopRequireDefault(_renderersWebglRenderer); var _renderersCanvasRenderer = __webpack_require__(54); var _renderersCanvasRenderer2 = _interopRequireDefault(_renderersCanvasRenderer); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _vendorPromise = __webpack_require__(57); var _vendorPromise2 = _interopRequireDefault(_vendorPromise); var Canvas = (function (_EventEmitter) { function Canvas(kit, ui, options) { _classCallCheck(this, Canvas); _get(Object.getPrototypeOf(Canvas.prototype), 'constructor', this).call(this); this._kit = kit; this._ui = ui; this._options = options; var container = this._ui.container; this._canvasContainer = container.querySelector('.imglykit-canvas-container'); this._canvasInnerContainer = container.querySelector('.imglykit-canvas-inner-container'); this._canvas = this._canvasContainer.querySelector('canvas'); this._image = this._options.image; this._roundZoomBy = 0.1; this._isFirstRender = true; // Mouse event callbacks bound to the class context this._dragOnMousedown = this._dragOnMousedown.bind(this); this._dragOnMousemove = this._dragOnMousemove.bind(this); this._dragOnMouseup = this._dragOnMouseup.bind(this); } _inherits(Canvas, _EventEmitter); _createClass(Canvas, [{ key: 'run', /** * Initializes the renderer, sets the zoom level and initially * renders the operations stack */ value: function run() { this._initRenderer(); // Calculate the initial zoom level this._zoomLevel = this._getInitialZoomLevel(); this._initialZoomLevel = this._zoomLevel; this._isInitialZoom = true; this._size = null; this.render(); this._centerCanvas(); this._handleDrag(); } }, { key: 'render', /** * Renders the current operations stack */ value: function render() { var _this = this; this._initialZoomLevel = this._getInitialZoomLevel(); // Reset the zoom level to initial // Some operations change the texture resolution (e.g. rotation) // If we're on initial zoom level, we still want to make the canvas // fit into the container. Find the new initial zoom level and set it. if (this._isInitialZoom) { this.setZoomLevel(this._initialZoomLevel, false); } // Calculate the initial size var imageSize = new _libMathVector22['default'](this._image.width, this._image.height); var initialSize = imageSize.multiply(this._zoomLevel); this._setCanvasSize(initialSize); // Reset framebuffers this._renderer.reset(); // Run the operations stack var stack = this.sanitizedStack; this._updateStackDirtyStates(stack); var validationPromises = []; for (var i = 0; i < stack.length; i++) { var operation = stack[i]; validationPromises.push(operation.validateSettings()); } return _vendorPromise2['default'].all(validationPromises).then(function () { // When using WebGL, resize the image to max texture size if necessary if (_this._isFirstRender && _this._renderer.identifier === 'webgl') { if (_this._image.width > _this._renderer.maxTextureSize || _this._image.height > _this._renderer.maxTextureSize) { _this._ui.displayLoadingMessage('Resizing...'); return new _vendorPromise2['default'](function (resolve, reject) { setTimeout(function () { _this._renderer.prepareImage(_this._image).then(function (image) { _this._ui.hideLoadingMessage(); _this._options.image = image; _this._image = _this._options.image; resolve(); })['catch'](function (e) { reject(e); }); }, 100); }); } } }).then(function () { // On first render, draw the image to the input texture if (_this._isFirstRender || _this._renderer.constructor.identifier === 'canvas') { _this._isFirstRender = false; return _this._renderer.drawImage(_this._image); } }) // Render the operations stack .then(function () { var promises = []; for (var i = 0; i < stack.length; i++) { var operation = stack[i]; promises.push(operation.render(_this._renderer)); } return _vendorPromise2['default'].all(promises); }) // Render the final image .then(function () { return _this._renderer.renderFinal(); }) // Update the margins and boundaries .then(function () { _this._storeCanvasSize(); _this._updateContainerSize(); _this._updateCanvasMargins(); _this._applyBoundaries(); })['catch'](function (e) { console.log(e); }); } }, { key: 'setImage', /** * Sets the image to the given one * @param {Image} image */ value: function setImage(image) { this._image = image; this.reset(); this.render(); this._centerCanvas(); } }, { key: 'zoomIn', /** * Increase zoom level */ value: function zoomIn() { this._isInitialZoom = false; var zoomLevel = Math.round(this._zoomLevel * 100); var roundZoomBy = Math.round(this._roundZoomBy * 100); var initialZoomLevel = Math.round(this._initialZoomLevel * 100); // Round up if needed if (zoomLevel % roundZoomBy !== 0) { zoomLevel = Math.ceil(zoomLevel / roundZoomBy) * roundZoomBy; } else { zoomLevel += roundZoomBy; } zoomLevel = Math.min(initialZoomLevel * 2, zoomLevel); return this.setZoomLevel(zoomLevel / 100); } }, { key: 'zoomOut', /** * Decrease zoom level */ value: function zoomOut() { this._isInitialZoom = false; var zoomLevel = Math.round(this._zoomLevel * 100); var roundZoomBy = Math.round(this._roundZoomBy * 100); var initialZoomLevel = Math.round(this._initialZoomLevel * 100); // Round up if needed if (zoomLevel % roundZoomBy !== 0) { zoomLevel = Math.floor(zoomLevel / roundZoomBy) * roundZoomBy; } else { zoomLevel -= roundZoomBy; } zoomLevel = Math.max(initialZoomLevel, zoomLevel); return this.setZoomLevel(zoomLevel / 100); } }, { key: '_setCanvasSize', /** * Resizes and positions the canvas * @param {Vector2} [size] * @private */ value: function _setCanvasSize(size) { size = size || new _libMathVector22['default'](this._canvas.width, this._canvas.height); this._canvas.width = size.x; this._canvas.height = size.y; this._storeCanvasSize(); this._updateContainerSize(); } }, { key: '_updateContainerSize', /** * Updates the canvas container size * @private */ value: function _updateContainerSize() { var size = this._size; this._canvasInnerContainer.style.width = '' + size.x + 'px'; this._canvasInnerContainer.style.height = '' + size.y + 'px'; } }, { key: '_storeCanvasSize', /** * Remembers the canvas size * @comment This was introduced because the canvas size was not always * correct due to some race conditions. Now that promises work * properly, do we still need this? * @private */ value: function _storeCanvasSize() { this._size = new _libMathVector22['default'](this._canvas.width, this._canvas.height); } }, { key: '_centerCanvas', /** * Centers the canvas inside the container * @private */ value: function _centerCanvas() { var position = this._maxSize.divide(2); this._canvasInnerContainer.style.left = '' + position.x + 'px'; this._canvasInnerContainer.style.top = '' + position.y + 'px'; this._updateCanvasMargins(); } }, { key: '_updateCanvasMargins', /** * Updates the canvas margins so that they are the negative half width * and height of the canvas * @private */ value: function _updateCanvasMargins() { var canvasSize = new _libMathVector22['default'](this._canvas.width, this._canvas.height); var margin = canvasSize.divide(2).multiply(-1); this._canvasInnerContainer.style.marginLeft = '' + margin.x + 'px'; this._canvasInnerContainer.style.marginTop = '' + margin.y + 'px'; } }, { key: 'setZoomLevel', /** * Sets the zoom level, re-renders the canvas and * repositions it * @param {Number} zoomLevel * @param {Boolean} render * @private */ value: function setZoomLevel(zoomLevel) { var _this2 = this; var render = arguments[1] === undefined ? true : arguments[1]; this._zoomLevel = zoomLevel; if (render) { this.setAllOperationsToDirty(); return this.render().then(function () { _this2._updateCanvasMargins(); _this2._applyBoundaries(); _this2.emit('zoom'); }); } else { this._updateCanvasMargins(); this._applyBoundaries(); this.emit('zoom'); } } }, { key: 'setAllOperationsToDirty', /** * Sets all operations to dirty */ value: function setAllOperationsToDirty() { var operationsStack = this._kit.operationsStack; for (var i = 0; i < operationsStack.length; i++) { var operation = operationsStack[i]; if (!operation) continue; operation.dirty = true; } } }, { key: '_getInitialZoomLevel', /** * Gets the initial zoom level so that the image fits the maximum * canvas size * @private */ value: function _getInitialZoomLevel() { var inputSize = new _libMathVector22['default'](this._image.width, this._image.height); var cropOperation = this._ui.operations.crop; var rotationOperation = this._ui.operations.rotation; var cropSize = undefined, croppedSize = undefined, finalSize = undefined, initialSize = undefined; if (cropOperation) { cropSize = cropOperation.getEnd().clone().subtract(cropOperation.getStart()); } else { cropSize = new _libMathVector22['default'](1, 1); } croppedSize = inputSize.clone().multiply(cropSize); // Has the image been rotated? if (rotationOperation && rotationOperation.getDegrees() % 180 !== 0) { var tempX = croppedSize.x; croppedSize.x = croppedSize.y; croppedSize.y = tempX; } finalSize = _libUtils2['default'].resizeVectorToFit(croppedSize, this._maxSize); // Rotate back to be able to find the final size if (rotationOperation && rotationOperation.getDegrees() % 180 !== 0) { var tempX = finalSize.x; finalSize.x = finalSize.y; finalSize.y = tempX; } initialSize = finalSize.clone().divide(cropSize); return initialSize.x / inputSize.x; } }, { key: '_initRenderer', /** * Initializes the renderer * @private */ value: function _initRenderer() { var _this3 = this; if (_renderersWebglRenderer2['default'].isSupported() && this._options.renderer !== 'canvas') { this._renderer = new _renderersWebglRenderer2['default'](null, this._canvas); this._webglEnabled = true; } else if (_renderersCanvasRenderer2['default'].isSupported()) { this._renderer = new _renderersCanvasRenderer2['default'](null, this._canvas); this._webglEnabled = false; } if (this._renderer === null) { throw new Error('Neither Canvas nor WebGL renderer are supported.'); } this._renderer.on('new-canvas', function (canvas) { _this3._setCanvas(canvas); }); } }, { key: '_setCanvas', /** * Replaces the canvas with the given canvas, updates margins etc * @param {DOMElement} canvas * @private */ value: function _setCanvas(canvas) { var canvasParent = this._canvas.parentNode; canvasParent.removeChild(this._canvas); this._canvas = canvas; canvasParent.appendChild(this._canvas); this._updateCanvasMargins(); this._applyBoundaries(); this._updateContainerSize(); } }, { key: '_handleDrag', /** * Handles the dragging * @private */ value: function _handleDrag() { this._canvas.addEventListener('mousedown', this._dragOnMousedown); this._canvas.addEventListener('touchstart', this._dragOnMousedown); } }, { key: '_dragOnMousedown', /** * Gets called when the user started touching / clicking the canvas * @param {Event} e * @private */ value: function _dragOnMousedown(e) { if (e.type === 'mousedown' && e.button !== 0) return; e.preventDefault(); var x = e.pageX; var y = e.pageY; if (e.type === 'touchstart') { x = e.touches[0].pageX; y = e.touches[0].pageY; } var canvasX = parseInt(this._canvasInnerContainer.style.left, 10); var canvasY = parseInt(this._canvasInnerContainer.style.top, 10); document.addEventListener('mousemove', this._dragOnMousemove); document.addEventListener('touchmove', this._dragOnMousemove); document.addEventListener('mouseup', this._dragOnMouseup); document.addEventListener('touchend', this._dragOnMouseup); // Remember initial position this._initialMousePosition = new _libMathVector22['default'](x, y); this._initialCanvasPosition = new _libMathVector22['default'](canvasX, canvasY); } }, { key: '_dragOnMousemove', /** * Gets called when the user drags the canvas * @param {Event} e * @private */ value: function _dragOnMousemove(e) { e.preventDefault(); var x = e.pageX, y = e.pageY; if (e.type === 'touchmove') { x = e.touches[0].pageX; y = e.touches[0].pageY; } var newMousePosition = new _libMathVector22['default'](x, y); var mouseDiff = newMousePosition.clone().subtract(this._initialMousePosition); var newPosition = this._initialCanvasPosition.clone().add(mouseDiff); this._canvasInnerContainer.style.left = '' + newPosition.x + 'px'; this._canvasInnerContainer.style.top = '' + newPosition.y + 'px'; this._applyBoundaries(); } }, { key: '_applyBoundaries', /** * Makes sure the canvas positions are within the boundaries * @private */ value: function _applyBoundaries() { var x = parseInt(this._canvasInnerContainer.style.left, 10); var y = parseInt(this._canvasInnerContainer.style.top, 10); var canvasPosition = new _libMathVector22['default'](x, y); // Boundaries var boundaries = this._boundaries; canvasPosition.x = Math.min(boundaries.max.x, Math.max(boundaries.min.x, canvasPosition.x)); canvasPosition.y = Math.min(boundaries.max.y, Math.max(boundaries.min.y, canvasPosition.y)); this._canvasInnerContainer.style.left = '' + canvasPosition.x + 'px'; this._canvasInnerContainer.style.top = '' + canvasPosition.y + 'px'; } }, { key: '_dragOnMouseup', /** * Gets called when the user stopped dragging the canvsa * @param {Event} e * @private */ value: function _dragOnMouseup(e) { e.preventDefault(); document.removeEventListener('mousemove', this._dragOnMousemove); document.removeEventListener('touchmove', this._dragOnMousemove); document.removeEventListener('mouseup', this._dragOnMouseup); document.removeEventListener('touchend', this._dragOnMouseup); } }, { key: '_updateStackDirtyStates', /** * Find the first dirty operation of the stack and sets all following * operations to dirty * @param {Array.} stack * @private */ value: function _updateStackDirtyStates(stack) { var dirtyFound = false; for (var i = 0; i < stack.length; i++) { var operation = stack[i]; if (!operation) continue; if (operation.dirty) { dirtyFound = true; } if (dirtyFound) { operation.dirty = true; } } } }, { key: 'zoomToFit', /** * Zooms the canvas so that it fits the container * @param {Boolean} render */ value: function zoomToFit() { var render = arguments[0] === undefined ? true : arguments[0]; var initialZoomLevel = this._getInitialZoomLevel(); return this.setZoomLevel(initialZoomLevel, render); } }, { key: 'reset', /** * Resets the renderer */ value: function reset() { this._renderer.reset(true); this._kit.operationsStack = []; this._isFirstRender = true; } }, { key: '_boundaries', /** * The position boundaries for the canvas inside the container * @type {Object.} * @private */ get: function () { var canvasSize = new _libMathVector22['default'](this._canvas.width, this._canvas.height); var maxSize = this._maxSize; var diff = canvasSize.clone().subtract(maxSize).multiply(-1); var boundaries = { min: new _libMathVector22['default'](diff.x, diff.y), max: new _libMathVector22['default'](0, 0) }; if (canvasSize.x < maxSize.x) { boundaries.min.x = diff.x / 2; boundaries.max.x = diff.x / 2; } if (canvasSize.y < maxSize.y) { boundaries.min.y = diff.y / 2; boundaries.max.y = diff.y / 2; } var halfCanvasSize = canvasSize.clone().divide(2); boundaries.min.add(halfCanvasSize); boundaries.max.add(halfCanvasSize); return boundaries; } }, { key: '_maxSize', /** * The maximum canvas size * @private */ get: function () { return new _libMathVector22['default'](this._canvasContainer.offsetWidth, this._canvasContainer.offsetHeight); } }, { key: 'sanitizedStack', /** * Returns the operations stack without falsy values * @type {Array.} */ get: function () { var sanitizedStack = []; for (var i = 0; i < this._kit.operationsStack.length; i++) { var operation = this._kit.operationsStack[i]; if (!operation) continue; sanitizedStack.push(operation); } return sanitizedStack; } }, { key: 'zoomLevel', /** * The current zoom level * @type {Number} */ get: function () { return this._zoomLevel; } }, { key: 'size', /** * The canvas size in pixels * @type {Vector2} */ get: function () { return this._size; } }]); return Canvas; })(_libEventEmitter2['default']); exports['default'] = Canvas; module.exports = exports['default']; // will be redirected to top controls // will be redirected to top controls /***/ }, /* 77 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var FileLoader = (function (_EventEmitter) { function FileLoader(kit, ui) { _classCallCheck(this, FileLoader); _get(Object.getPrototypeOf(FileLoader.prototype), 'constructor', this).call(this); this._kit = kit; this._ui = ui; // http://stackoverflow.com/questions/7110353/html5-dragleave-fired-when-hovering-a-child-element this._dragCounter = 0; this._container = this._ui.container.querySelector('.imglykit-splash-container'); this._onDropAreaDragEnter = this._onDropAreaDragEnter.bind(this); this._onDropAreaDragOver = this._onDropAreaDragOver.bind(this); this._onDropAreaDragLeave = this._onDropAreaDragLeave.bind(this); this._onDropAreaDrop = this._onDropAreaDrop.bind(this); this._onDropAreaClick = this._onDropAreaClick.bind(this); this._onFileInputChange = this._onFileInputChange.bind(this); this._hiddenInputField = this._ui.container.querySelector('.imglykit-upload-hidden-input'); this._hiddenInputField.addEventListener('change', this._onFileInputChange); this._handleDropArea(); if (this._ui.options.image) { this.removeDOM(); } } _inherits(FileLoader, _EventEmitter); _createClass(FileLoader, [{ key: 'openFileDialog', /** * Opens the file dialog */ value: function openFileDialog() { this._hiddenInputField.click(); } }, { key: '_handleDropArea', /** * Finds the drop area, adds event listeners * @private */ value: function _handleDropArea() { this._dropArea = this._container.querySelector('.imglykit-splash-row--upload'); this._dropArea.addEventListener('dragenter', this._onDropAreaDragEnter); this._dropArea.addEventListener('dragover', this._onDropAreaDragOver); this._dropArea.addEventListener('dragleave', this._onDropAreaDragLeave); this._dropArea.addEventListener('drop', this._onDropAreaDrop); this._dropArea.addEventListener('dragdrop', this._onDropAreaDrop); this._dropArea.addEventListener('click', this._onDropAreaClick); } }, { key: '_onDropAreaClick', /** * Gets called when the user clicks on the drop area. Opens the file * dialog by triggering a click on the hidden input field * @param {Event} e * @private */ value: function _onDropAreaClick() { this.openFileDialog(); } }, { key: '_onDropAreaDragEnter', /** * Gets called when the user drags a file over the drop area * @param {Event} e * @private */ value: function _onDropAreaDragEnter(e) { e.preventDefault(); this._dragCounter++; this._dropArea.classList.add('imglykit-splash-active'); } }, { key: '_onDropAreaDragOver', /** * We need to cancel this event to get a drop event * @param {Event} e * @private */ value: function _onDropAreaDragOver(e) { e.preventDefault(); } }, { key: '_onDropAreaDragLeave', /** * Gets called when the user does no longer drag a file over the drop area * @param {Event} e * @private */ value: function _onDropAreaDragLeave(e) { e.preventDefault(); this._dragCounter--; if (this._dragCounter === 0) { this._dropArea.classList.remove('imglykit-splash-active'); } } }, { key: '_onDropAreaDrop', /** * Gets called when the user drops a file on the drop area * @param {Event} e * @private */ value: function _onDropAreaDrop(e) { e.stopPropagation(); e.preventDefault(); e.returnValue = false; this._dropArea.classList.remove('imglykit-splash-active'); if (!e.dataTransfer) return; this._handleFile(e.dataTransfer.files[0]); } }, { key: '_onFileInputChange', /** * Gets called when the user selected a file * @param {Event} e * @private */ value: function _onFileInputChange() { this._handleFile(this._hiddenInputField.files[0]); } }, { key: '_handleFile', /** * Gets called when the user selected a file. Emits a `file` event. * @param {File} file * @private */ value: function _handleFile(file) { this.emit('file', file); } }, { key: 'removeDOM', /** * Removes event listeners and removes the container form the dom */ value: function removeDOM() { this._dropArea.removeEventListener('dragenter', this._onDropAreaDragEnter); this._dropArea.removeEventListener('dragover', this._onDropAreaDragOver); this._dropArea.removeEventListener('dragleave', this._onDropAreaDragLeave); this._dropArea.removeEventListener('drop', this._onDropAreaDrop); this._dropArea.removeEventListener('dragdrop', this._onDropAreaDrop); this._dropArea.removeEventListener('click', this._onDropAreaClick); if (this._container) { this._container.style.display = 'none'; } } }]); return FileLoader; })(_libEventEmitter2['default']); exports['default'] = FileLoader; module.exports = exports['default']; /***/ }, /* 78 */ /***/ function(module, exports, __webpack_require__) { /* global Image */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var WebcamHandler = (function (_EventEmitter) { function WebcamHandler(kit, ui) { _classCallCheck(this, WebcamHandler); _get(Object.getPrototypeOf(WebcamHandler.prototype), 'constructor', this).call(this); this._kit = kit; this._ui = ui; var container = this._ui.container; this._canvasContainer = container.querySelector('.imglykit-canvas-container'); this._video = container.querySelector('.imglykit-webcam-video'); this._webcamButton = container.querySelector('.imglykit-webcam-button'); this._webcamButton.addEventListener('click', this._onWebcamButtonClick.bind(this)); this._initVideoStream(); } _inherits(WebcamHandler, _EventEmitter); _createClass(WebcamHandler, [{ key: '_onWebcamButtonClick', /** * Gets called when the user clicked the shutter button. Draws the current * video frame to a canvas, creates an image from it and emits the `image` * event * @param {Event} e * @private */ value: function _onWebcamButtonClick(e) { var _this = this; e.preventDefault(); var canvas = document.createElement('canvas'); canvas.width = this._video.videoWidth; canvas.height = this._video.videoHeight; var context = canvas.getContext('2d'); context.drawImage(this._video, 0, 0); this._stream.stop(); this._video.pause(); delete this._stream; delete this._video; var image = new Image(); image.addEventListener('load', function () { _this.emit('image', image); }); image.src = canvas.toDataURL('image/png'); } }, { key: '_initVideoStream', /** * Initializes the video stream * @private */ value: function _initVideoStream() { var _this2 = this; var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; if (!getUserMedia) { throw new Error('Webcam feature not supported! :('); } getUserMedia.call(navigator, { video: true }, function (stream) { _this2._stream = stream; _this2._video.onloadedmetadata = _this2._onVideoReady.bind(_this2); _this2._video.src = window.URL.createObjectURL(stream); }, function (err) { throw err; }); } }, { key: '_onVideoReady', value: function _onVideoReady() { this._resizeVideo(); } }, { key: '_resizeVideo', value: function _resizeVideo() { var _video = this._video; var videoWidth = _video.videoWidth; var videoHeight = _video.videoHeight; var size = new _libMathVector22['default'](videoWidth, videoHeight); var maxSize = new _libMathVector22['default'](this._canvasContainer.offsetWidth, this._canvasContainer.offsetHeight); var finalSize = _libUtils2['default'].resizeVectorToFit(size, maxSize); this._video.style.width = '' + finalSize.x + 'px'; this._video.style.height = '' + finalSize.y + 'px'; var diff = maxSize.clone().subtract(finalSize).divide(2); this._video.style.marginLeft = '' + diff.x + 'px'; this._video.style.marginTop = '' + diff.y + 'px'; } }, { key: 'getUserMedia', get: function () { return; } }]); return WebcamHandler; })(_libEventEmitter2['default']); exports['default'] = WebcamHandler; module.exports = exports['default']; /***/ }, /* 79 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var TopControls = (function (_EventEmitter) { function TopControls(kit, ui) { _classCallCheck(this, TopControls); _get(Object.getPrototypeOf(TopControls.prototype), 'constructor', this).call(this); this._kit = kit; this._ui = ui; this.init(); } _inherits(TopControls, _EventEmitter); _createClass(TopControls, [{ key: 'init', /** * Initializes the controls */ value: function init() { this._canvas = this._ui.canvas; } }, { key: 'run', /** * Initializes the controls */ value: function run() { var container = this._ui.container; this._rightControls = container.querySelector('.imglykit-top-controls-right'); this._leftControls = container.querySelector('.imglykit-top-controls-left'); this._undoButton = container.querySelector('.imglykit-undo'); this._zoomIn = container.querySelector('.imglykit-zoom-in'); this._zoomOut = container.querySelector('.imglykit-zoom-out'); this._zoomLevel = container.querySelector('.imglykit-zoom-level-num'); this._newButton = container.querySelector('.imglykit-new'); this._exportButton = container.querySelector('.imglykit-export'); this._handleZoom(); this._handleUndo(); this._handleNew(); this._handleExport(); } }, { key: '_handleZoom', /** * Handles the zoom controls * @private */ value: function _handleZoom() { this._zoomIn.addEventListener('click', this._onZoomInClick.bind(this)); this._zoomOut.addEventListener('click', this._onZoomOutClick.bind(this)); } }, { key: '_handleUndo', /** * Handles the undo control * @private */ value: function _handleUndo() { this._undoButton.addEventListener('click', this._undo.bind(this)); this._undo(); } }, { key: '_handleNew', /** * Handles the new button * @private */ value: function _handleNew() { if (!this._newButton) return; this._newButton.addEventListener('click', this._onNewClick.bind(this)); } }, { key: '_handleExport', /** * Handles the export button * @private */ value: function _handleExport() { if (!this._exportButton) return; this._exportButton.addEventListener('click', this._onExportClick.bind(this)); } }, { key: '_onNewClick', /** * Gets called when the user clicks the new button * @param {Event} e * @private */ value: function _onNewClick(e) { e.preventDefault(); this.emit('new'); } }, { key: '_onExportClick', /** * Gets called when the user clicks the export button * @param {Event} e * @private */ value: function _onExportClick(e) { e.preventDefault(); this.emit('export'); } }, { key: '_undo', /** * Gets called when the user clicks the undo button * @private */ value: function _undo() { this.emit('undo'); } }, { key: 'updateUndoButton', /** * Updates the undo button visible state */ value: function updateUndoButton() { var history = this._ui.history; if (history.length === 0) { this._undoButton.style.display = 'none'; } else { this._undoButton.style.display = 'inline-block'; } } }, { key: 'updateExportButton', /** * Updates the export button visible state */ value: function updateExportButton() { if (!this._exportButton) return; var image = this._ui.image; if (image) { this._exportButton.style.display = 'inline-block'; } else { this._exportButton.style.display = 'none'; } } }, { key: '_onZoomInClick', /** * Gets called when the user clicked the zoom in button * @param {Event} * @private */ value: function _onZoomInClick(e) { e.preventDefault(); this.emit('zoom-in'); this.updateZoomLevel(); } }, { key: '_onZoomOutClick', /** * Gets called when the user clicked the zoom out button * @param {Event} * @private */ value: function _onZoomOutClick(e) { e.preventDefault(); this.emit('zoom-out'); this.updateZoomLevel(); } }, { key: 'showZoom', /** * Shows the zoom control */ value: function showZoom() { this._rightControls.style.display = 'inline-block'; } }, { key: 'hideZoom', /** * Hides the zoom control */ value: function hideZoom() { this._rightControls.style.display = 'none'; } }, { key: 'updateZoomLevel', /** * Updates the zoom level display */ value: function updateZoomLevel() { var zoomLevel = this._canvas.zoomLevel; this._zoomLevel.innerHTML = Math.round(zoomLevel * 100); } }]); return TopControls; })(_libEventEmitter2['default']); exports['default'] = TopControls; module.exports = exports['default']; /***/ }, /* 80 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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 _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var maxScrollbarWidth = 18; /** * Our custom scroll bar */ var Scrollbar = (function () { /** * @param {DOMElement} container */ function Scrollbar(container) { _classCallCheck(this, Scrollbar); this._container = container; this._isDragging = false; this._isHovering = false; this._appendDOM(); this._resizeButton(); this._updateValues(); this._onButtonDown = this._onButtonDown.bind(this); this._onButtonMove = this._onButtonMove.bind(this); this._onButtonUp = this._onButtonUp.bind(this); this._onContainerEnter = this._onContainerEnter.bind(this); this._onContainerLeave = this._onContainerLeave.bind(this); this._onBackgroundClick = this._onBackgroundClick.bind(this); this._container.addEventListener('mouseenter', this._onContainerEnter); this._container.addEventListener('mouseleave', this._onContainerLeave); this._container.addEventListener('mousemove', this._onContainerEnter); this._dom.button.addEventListener('mousedown', this._onButtonDown); this._dom.button.addEventListener('touchstart', this._onButtonDown); this._dom.background.addEventListener('click', this._onBackgroundClick); this._list.addEventListener('scroll', this._onListScroll.bind(this)); this._onListScroll(); } _createClass(Scrollbar, [{ key: '_onBackgroundClick', /** * Gets called when the user clicks the scrollbar background * @param {Event} e * @private */ value: function _onBackgroundClick(e) { e.preventDefault(); if (e.target !== this._dom.background) return; var position = _libUtils2['default'].getEventPosition(e); var backgroundOffset = this._dom.background.getBoundingClientRect(); backgroundOffset = new _libMathVector22['default'](backgroundOffset.left, backgroundOffset.top); var relativePosition = position.clone().subtract(backgroundOffset); relativePosition.x -= this._values.button.width * 0.5; this._setButtonPosition(relativePosition.x); } }, { key: '_onContainerEnter', /** * Gets called when the user enters the list with the mouse * @private */ value: function _onContainerEnter() { this._isHovering = true; this.show(); } }, { key: '_onContainerLeave', /** * Gets called when the user leaves the list with the mouse * @private */ value: function _onContainerLeave() { this._isHovering = false; this.hide(); } }, { key: 'show', /** * Shows the scrollbar */ value: function show() { if (!this._isScrollingNecessary) return; this._dom.background.classList.add('visible'); } }, { key: 'hide', /** * Hides the scrollbar */ value: function hide() { if (this._isDragging) return; this._dom.background.classList.remove('visible'); } }, { key: '_updateValues', /** * Updates the size values * @private */ value: function _updateValues() { this._values = { list: { totalWidth: this._list.scrollWidth, visibleWidth: this._list.offsetWidth, scrollableWidth: this._list.scrollWidth - this._list.offsetWidth }, button: { width: this._dom.button.offsetWidth, scrollableWidth: this._dom.background.offsetWidth - this._dom.button.offsetWidth } }; } }, { key: '_onButtonDown', /** * Gets called when the user starts dragging the button * @param {Event} event * @private */ value: function _onButtonDown(event) { event.preventDefault(); this._isDragging = true; this._initialMousePosition = _libUtils2['default'].getEventPosition(event); this._initialButtonPosition = this._buttonPosition || 0; document.addEventListener('mousemove', this._onButtonMove); document.addEventListener('touchmove', this._onButtonMove); document.addEventListener('mouseup', this._onButtonUp); document.addEventListener('touchend', this._onButtonUp); } }, { key: '_onButtonMove', /** * Gets called when the user drags the button * @param {Event} event * @private */ value: function _onButtonMove(event) { event.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(event); var diff = mousePosition.clone().subtract(this._initialMousePosition); var newButtonPosition = this._initialButtonPosition + diff.x; this._setButtonPosition(newButtonPosition); } }, { key: '_setButtonPosition', /** * Sets the button position to the given value * @param {Number} newButtonPosition * @private */ value: function _setButtonPosition(newButtonPosition) { // Clamp button position newButtonPosition = Math.max(0, newButtonPosition); newButtonPosition = Math.min(newButtonPosition, this._values.button.scrollableWidth); // Set button position this._buttonPosition = newButtonPosition; this._dom.button.style.left = '' + this._buttonPosition + 'px'; // Update list scroll position var progress = newButtonPosition / this._values.button.scrollableWidth; var scrollPosition = this._values.list.scrollableWidth * progress; this._list.scrollLeft = scrollPosition; } }, { key: '_onButtonUp', /** * Gets called when the user releases the button * @private */ value: function _onButtonUp() { this._isDragging = false; document.removeEventListener('mousemove', this._onButtonMove); document.removeEventListener('touchmove', this._onButtonMove); document.removeEventListener('mouseup', this._onButtonUp); document.removeEventListener('touchend', this._onButtonUp); } }, { key: '_onListScroll', /** * Gets called when the user scrolls the list * @private */ value: function _onListScroll() { if (this._isDragging) return; var listScrollWidth = this._list.scrollWidth - this._list.offsetWidth; var listScrollPosition = this._list.scrollLeft; var backgroundScrollWidth = this._dom.background.offsetWidth - this._dom.button.offsetWidth; var progress = listScrollPosition / listScrollWidth; this._buttonPosition = backgroundScrollWidth * progress; this._dom.button.style.left = '' + this._buttonPosition + 'px'; } }, { key: '_resizeButton', /** * Resizes the button to represent the visible size of the container * @private */ value: function _resizeButton() { var listScrollWidth = this._list.scrollWidth; var listWidth = this._list.offsetWidth; this._buttonWidth = listWidth / listScrollWidth * listWidth; this._dom.button.style.width = '' + this._buttonWidth + 'px'; } }, { key: '_appendDOM', /** * Appends the DOM elements to the container * @private */ value: function _appendDOM() { var background = document.createElement('div'); background.classList.add('imglykit-scrollbar-background'); background.style.bottom = '' + maxScrollbarWidth + 'px'; var button = document.createElement('div'); button.classList.add('imglykit-scrollbar-button'); background.appendChild(button); this._container.appendChild(background); // Container should have position: relative this._container.style.position = 'relative'; // Find the list this._list = this._container.querySelector('.imglykit-controls-list'); this._dom = { background: background, button: button }; // Resize the list and the container this._list.style.height = ''; var listHeight = this._list.offsetHeight; listHeight += maxScrollbarWidth; this._container.style.height = '' + listHeight + 'px'; this._list.style.height = '' + listHeight + 'px'; } }, { key: 'remove', /** * Removes the DOM elements and event listeners */ value: function remove() { this._dom.button.removeEventListener('mousedown', this._onButtonDown); this._dom.button.removeEventListener('touchstart', this._onButtonDown); this._dom.background.parentNode.removeChild(this._dom.background); } }, { key: '_isScrollingNecessary', /** * Checks whether scrolling is necessary * @returns {Boolean} * @private */ get: function () { return this._list.scrollWidth > this._list.offsetWidth; } }]); return Scrollbar; })(); exports['default'] = Scrollbar; module.exports = exports['default']; /***/ }, /* 81 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var FiltersControl = (function (_Control) { function FiltersControl() { _classCallCheck(this, FiltersControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(FiltersControl, _Control); _createClass(FiltersControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
    '; for(var identifier in it.filters) { out+=' '; var filter = it.filters[identifier]; out+=' '; var name = filter.prototype.name; out+=' '; var enabled = it.activeFilter.identifier === identifier; out+='
  • '+( name )+'
  • '; } out+='
';return out; }; this._controlsTemplate = controlsTemplate; this._availableFilters = {}; this._filters = {}; this._addDefaultFilters(); // Select all filters per default this.selectFilters(null); } }, { key: '_renderAllControls', /** * Renders the controls * @private * @internal We need to access information from the operation when * rendering, which is why we have to override this function */ value: function _renderAllControls() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } this._operationExistedBefore = !!this._ui.operations.filters; this._operation = this._ui.getOrCreateOperation('filters'); _get(Object.getPrototypeOf(FiltersControl.prototype), '_renderAllControls', this).apply(this, args); } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; this._initialFilter = this._operation.getFilter(); this._defaultFilter = this._operation.availableOptions.filter['default']; var listItems = this._controls.querySelectorAll('li'); this._listItems = Array.prototype.slice.call(listItems); var _loop = function (i) { var listItem = _this._listItems[i]; listItem.addEventListener('click', function () { _this._onListItemClick(listItem); }); }; // Listen to click events for (var i = 0; i < this._listItems.length; i++) { _loop(i); } } }, { key: '_onBack', /** * Gets called when the user hits the back button * @override */ value: function _onBack() { var currentFilter = this._operation.getFilter(); if (currentFilter !== this._initialFilter) { this._ui.addHistory(this._operation, { filter: this._initialFilter }, this._operationExistedBefore); } if (currentFilter === this._defaultFilter) { this._ui.removeOperation('filters'); } this._ui.canvas.render(); } }, { key: '_onListItemClick', /** * Gets called when the user clicked a list item * @private */ value: function _onListItemClick(item) { this._deactivateAllItems(); var identifier = item.dataset.identifier; this._operation.setFilter(this._filters[identifier]); this._ui.canvas.render(); item.classList.add('imglykit-controls-item-active'); } }, { key: '_deactivateAllItems', /** * Deactivates all list items * @private */ value: function _deactivateAllItems() { for (var i = 0; i < this._listItems.length; i++) { var listItem = this._listItems[i]; listItem.classList.remove('imglykit-controls-item-active'); } } }, { key: '_addDefaultFilters', /** * Registers all the known filters * @private */ value: function _addDefaultFilters() { this.addFilter(__webpack_require__(71)); this.addFilter(__webpack_require__(33)); this.addFilter(__webpack_require__(34)); this.addFilter(__webpack_require__(35)); this.addFilter(__webpack_require__(36)); this.addFilter(__webpack_require__(29)); this.addFilter(__webpack_require__(22)); this.addFilter(__webpack_require__(41)); this.addFilter(__webpack_require__(26)); this.addFilter(__webpack_require__(30)); this.addFilter(__webpack_require__(27)); this.addFilter(__webpack_require__(48)); this.addFilter(__webpack_require__(23)); this.addFilter(__webpack_require__(24)); this.addFilter(__webpack_require__(37)); this.addFilter(__webpack_require__(44)); this.addFilter(__webpack_require__(43)); this.addFilter(__webpack_require__(42)); this.addFilter(__webpack_require__(28)); this.addFilter(__webpack_require__(31)); this.addFilter(__webpack_require__(25)); this.addFilter(__webpack_require__(47)); this.addFilter(__webpack_require__(40)); this.addFilter(__webpack_require__(38)); this.addFilter(__webpack_require__(32)); this.addFilter(__webpack_require__(39)); this.addFilter(__webpack_require__(46)); this.addFilter(__webpack_require__(21)); this.addFilter(__webpack_require__(45)); } }, { key: 'addFilter', /** * Registers the given filter * @param {class} filter * @private */ value: function addFilter(filter) { this._availableFilters[filter.identifier] = filter; } }, { key: 'selectFilters', /** * Selects the filters * @param {Selector} selector */ value: function selectFilters(selector) { this._filters = {}; var filterIdentifiers = Object.keys(this._availableFilters); var selectedFilters = _libUtils2['default'].select(filterIdentifiers, selector); for (var i = 0; i < selectedFilters.length; i++) { var identifier = selectedFilters[i]; this._filters[identifier] = this._availableFilters[identifier]; } if (this._active) { this._renderControls(); } } }, { key: 'context', /** * The data that is available to the template * @type {Object} * @override */ get: function () { return { filters: this._filters, activeFilter: this._operation.getFilter() }; } }]); return FiltersControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ FiltersControl.prototype.identifier = 'filters'; exports['default'] = FiltersControl; module.exports = exports['default']; /***/ }, /* 82 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var RotationControl = (function (_Control) { function RotationControl() { _classCallCheck(this, RotationControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(RotationControl, _Control); _createClass(RotationControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
';return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; } }, { key: '_onEnter', /** * Gets called when this control is activated */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations.rotation; this._operation = this._ui.getOrCreateOperation('rotation'); this._cropOperation = this._ui.operations.crop; this._initialZoomLevel = this._ui.canvas.zoomLevel; this._ui.canvas.zoomToFit(false); if (this._cropOperation) { // Store initial settings for 'back' and 'done' buttons this._initialStart = this._cropOperation.getStart().clone(); this._initialEnd = this._cropOperation.getEnd().clone(); // Make sure we see the whole input image this._cropOperation.set({ start: new _libMathVector22['default'](0, 0), end: new _libMathVector22['default'](1, 1) }); } this._initialDegrees = this._operation.getDegrees(); var listItems = this._controls.querySelectorAll('li'); this._listItems = Array.prototype.slice.call(listItems); var _loop = function (i) { var listItem = _this._listItems[i]; listItem.addEventListener('click', function () { _this._onListItemClick(listItem); }); }; // Listen to click events for (var i = 0; i < this._listItems.length; i++) { _loop(i); } // Find the div areas that affect the displayed crop size var prefix = '.imglykit-canvas-crop'; this._cropAreas = { topLeft: this._canvasControls.querySelector('' + prefix + '-top-left'), topCenter: this._canvasControls.querySelector('' + prefix + '-top-center'), centerLeft: this._canvasControls.querySelector('' + prefix + '-center-left'), centerCenter: this._canvasControls.querySelector('' + prefix + '-center-center') }; // Resume the rendering this._ui.canvas.render().then(function () { _this._showCropContainer(); _this._updateCropDOM(); }); } }, { key: '_showCropContainer', /** * Shows the crop container which is hidden initially to avoid flickering * when resizing after the rendering * @private */ value: function _showCropContainer() { var container = this._canvasControls.querySelector('.imglykit-canvas-crop-container'); container.classList.remove('imglykit-canvas-crop-container-hidden'); } }, { key: '_onListItemClick', /** * Gets called when the given item has been clicked * @param {DOMObject} item * @private */ value: function _onListItemClick(item) { var _this2 = this; var degrees = item.dataset.degrees; degrees = parseInt(degrees, 10); var currentDegrees = this._operation.getDegrees(); this._operation.setDegrees(currentDegrees + degrees); this._ui.canvas.zoomToFit().then(function () { _this2._updateCropDOM(); }); } }, { key: 'onZoom', /** * Gets called when the zoom level has been changed while * this control is active */ value: function onZoom() { this._updateCropDOM(); } }, { key: '_updateCropDOM', /** * Updates the cropping divs for the current operation settings * @private */ value: function _updateCropDOM() { var start = undefined, end = undefined; if (this._cropOperation) { start = this._initialStart.clone(); end = this._initialEnd.clone(); } else { start = new _libMathVector22['default'](0, 0); end = new _libMathVector22['default'](1, 1); } var canvasSize = this._ui.canvas.size; var startAbsolute = start.multiply(canvasSize); var endAbsolute = end.multiply(canvasSize); var size = endAbsolute.clone().subtract(startAbsolute); var top = Math.max(1, startAbsolute.y); var left = Math.max(1, startAbsolute.x); var width = Math.max(1, size.x); var height = Math.max(1, size.y); // widths are defined by top left and top center areas this._cropAreas.topLeft.style.width = '' + left + 'px'; this._cropAreas.topCenter.style.width = '' + width + 'px'; // heights are defined by top left and center left areas this._cropAreas.topLeft.style.height = '' + top + 'px'; this._cropAreas.centerLeft.style.height = '' + height + 'px'; } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { var currentDegrees = this._operation.getDegrees(); if (this._initialDegrees !== currentDegrees) { this._ui.addHistory(this._operation, { degrees: this._initialDegrees }, this._operationExistedBefore); } if (currentDegrees === 0) { this._ui.removeOperation('rotation'); } if (this._cropOperation) { this._cropOperation.set({ start: this._initialStart, end: this._initialEnd }); } this._ui.canvas.render(); } }]); return RotationControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ RotationControl.prototype.identifier = 'rotation'; exports['default'] = RotationControl; module.exports = exports['default']; /***/ }, /* 83 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var FlipControl = (function (_Control) { function FlipControl() { _classCallCheck(this, FlipControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(FlipControl, _Control); _createClass(FlipControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
';return out; }; this._controlsTemplate = controlsTemplate; } }, { key: '_onEnter', /** * Gets called when this control is activated */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations.flip; this._operation = this._ui.getOrCreateOperation('flip'); this._initialHorizontal = this._operation.getHorizontal(); this._initialVertical = this._operation.getVertical(); var listItems = this._controls.querySelectorAll('li'); this._listItems = Array.prototype.slice.call(listItems); var _loop = function (i) { var listItem = _this._listItems[i]; listItem.addEventListener('click', function () { _this._onListItemClick(listItem); }); var direction = listItem.dataset.direction; if (direction === 'horizontal' && _this._operation.getHorizontal()) { _this._toggleItem(listItem, true); } else if (direction === 'vertical' && _this._operation.getVertical()) { _this._toggleItem(listItem, true); } }; // Listen to click events for (var i = 0; i < this._listItems.length; i++) { _loop(i); } } }, { key: '_onListItemClick', /** * Gets called when the user clicked a list item * @private */ value: function _onListItemClick(item) { var direction = item.dataset.direction; var active = false; if (direction === 'horizontal') { var currentHorizontal = this._operation.getHorizontal(); this._operation.setHorizontal(!currentHorizontal); this._ui.canvas.render(); active = !currentHorizontal; } else if (direction === 'vertical') { var currentVertical = this._operation.getVertical(); this._operation.setVertical(!currentVertical); this._ui.canvas.render(); active = !currentVertical; } this._toggleItem(item, active); } }, { key: '_toggleItem', /** * Toggles the active state of the given item * @param {DOMElement} item * @param {Boolean} active * @private */ value: function _toggleItem(item, active) { var activeClass = 'imglykit-controls-item-active'; if (active) { item.classList.add(activeClass); } else { item.classList.remove(activeClass); } } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { var currentVertical = this._operation.getVertical(); var currentHorizontal = this._operation.getHorizontal(); if (this._initialVertical !== currentVertical || this._initialHorizontal !== currentHorizontal) { this._ui.addHistory(this._operation, { vertical: this._initialVertical, horizontal: this._initialHorizontal }, this._operationExistedBefore); } if (!currentVertical && !currentHorizontal) { this._ui.removeOperation('flip'); } this._ui.canvas.render(); } }]); return FlipControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ FlipControl.prototype.identifier = 'flip'; exports['default'] = FlipControl; module.exports = exports['default']; /***/ }, /* 84 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libSlider = __webpack_require__(101); var _libSlider2 = _interopRequireDefault(_libSlider); var BrightnessControl = (function (_Control) { function BrightnessControl() { _classCallCheck(this, BrightnessControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(BrightnessControl, _Control); _createClass(BrightnessControl, [{ key: 'init', /** * The entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
'+(it.partials.slider)+'
';return out; }; this._controlsTemplate = controlsTemplate; this._partialTemplates.slider = _libSlider2['default'].template; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { this._operationExistedBefore = !!this._ui.operations.brightness; this._operation = this._ui.getOrCreateOperation('brightness'); // Initially set value var brightness = this._operation.getBrightness(); this._initialBrightness = brightness; var sliderElement = this._controls.querySelector('.imglykit-slider'); this._slider = new _libSlider2['default'](sliderElement, { minValue: -1, maxValue: 1, defaultValue: brightness }); this._slider.on('update', this._onUpdate.bind(this)); this._slider.setValue(this._initialBrightness); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { var currentBrightness = this._operation.getBrightness(); if (this._initialBrightness !== currentBrightness) { this._ui.addHistory(this._operation, { brightness: this._initialBrightness }, this._operationExistedBefore); } if (currentBrightness === 1) { this._ui.removeOperation('brightness'); } this._ui.canvas.render(); } }, { key: '_onUpdate', /** * Gets called when the value has been updated * @override */ value: function _onUpdate(value) { this._operation.setBrightness(value); this._ui.canvas.render(); } }]); return BrightnessControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ BrightnessControl.prototype.identifier = 'brightness'; exports['default'] = BrightnessControl; module.exports = exports['default']; /***/ }, /* 85 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libSlider = __webpack_require__(101); var _libSlider2 = _interopRequireDefault(_libSlider); var ContrastControl = (function (_Control) { function ContrastControl() { _classCallCheck(this, ContrastControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(ContrastControl, _Control); _createClass(ContrastControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
'+(it.partials.slider)+'
';return out; }; this._controlsTemplate = controlsTemplate; this._partialTemplates.slider = _libSlider2['default'].template; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { this._operationExistedBefore = !!this._ui.operations.contrast; this._operation = this._ui.getOrCreateOperation('contrast'); // Initially set value var contrast = this._operation.getContrast(); this._initialContrast = contrast; var sliderElement = this._controls.querySelector('.imglykit-slider'); this._slider = new _libSlider2['default'](sliderElement, { minValue: 0, maxValue: 2, defaultValue: contrast }); this._slider.on('update', this._onUpdate.bind(this)); this._slider.setValue(this._initialContrast); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { var currentContrast = this._operation.getContrast(); if (this._initialContrast !== currentContrast) { this._ui.addHistory(this._operation, { contrast: this._initialContrast }, this._operationExistedBefore); } if (currentContrast === 1) { this._ui.removeOperation('contrast'); } this._ui.canvas.render(); } }, { key: '_onUpdate', /** * Gets called when the value has been updated * @override */ value: function _onUpdate(value) { this._operation.setContrast(value); this._ui.canvas.render(); } }]); return ContrastControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ ContrastControl.prototype.identifier = 'contrast'; exports['default'] = ContrastControl; module.exports = exports['default']; /***/ }, /* 86 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libSlider = __webpack_require__(101); var _libSlider2 = _interopRequireDefault(_libSlider); var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var SaturationControl = (function (_Control) { function SaturationControl() { _classCallCheck(this, SaturationControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(SaturationControl, _Control); _createClass(SaturationControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
'+(it.partials.slider)+'
';return out; }; this._controlsTemplate = controlsTemplate; this._partialTemplates.slider = _libSlider2['default'].template; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { _get(Object.getPrototypeOf(SaturationControl.prototype), '_onEnter', this).call(this); this._operationExistedBefore = !!this._ui.operations.saturation; this._operation = this._ui.getOrCreateOperation('saturation'); // Initially set value var saturation = this._operation.getSaturation(); this._initialSaturation = saturation; var sliderElement = this._controls.querySelector('.imglykit-slider'); this._slider = new _libSlider2['default'](sliderElement, { minValue: 0, maxValue: 2, defaultValue: saturation }); this._slider.on('update', this._onUpdate.bind(this)); this._slider.setValue(this._initialSaturation); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { var currentSaturation = this._operation.getSaturation(); if (this._initialSaturation !== currentSaturation) { this._ui.addHistory(this._operation, { saturation: this._initialSaturation }, this._operationExistedBefore); } if (currentSaturation === 1) { this._ui.removeOperation('saturation'); } this._ui.canvas.render(); } }, { key: '_onUpdate', /** * Gets called when the value has been updated * @override */ value: function _onUpdate(value) { this._operation.setSaturation(value); this._ui.canvas.render(); } }]); return SaturationControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ SaturationControl.prototype.identifier = 'saturation'; exports['default'] = SaturationControl; module.exports = exports['default']; /***/ }, /* 87 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var CropControl = (function (_Control) { function CropControl() { _classCallCheck(this, CropControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(CropControl, _Control); _createClass(CropControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { this._availableRatios = {}; this._ratios = {}; var controlsTemplate = function(it /**/) { var out='
    '; for(var identifier in it.ratios) { out+=' '; var ratio = it.ratios[identifier]; out+=' '; var enabled = ratio.selected; out+='
  • '; } out+='
'+(it.partials.doneButton);return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; // Mouse event callbacks bound to the class context this._onKnobDown = this._onKnobDown.bind(this); this._onKnobDrag = this._onKnobDrag.bind(this); this._onKnobUp = this._onKnobUp.bind(this); this._onCenterDown = this._onCenterDown.bind(this); this._onCenterDrag = this._onCenterDrag.bind(this); this._onCenterUp = this._onCenterUp.bind(this); this._addDefaultRatios(); // Select all ratios per default this.selectRatios(null); } }, { key: 'selectRatios', /** * Selects the ratios * @param {Selector} selector */ value: function selectRatios(selector) { this._ratios = {}; var ratioIdentifiers = Object.keys(this._availableRatios); var selectedRatios = _libUtils2['default'].select(ratioIdentifiers, selector); for (var i = 0; i < selectedRatios.length; i++) { var identifier = selectedRatios[i]; this._ratios[identifier] = this._availableRatios[identifier]; } if (this._active) { this._renderControls(); } } }, { key: '_addDefaultRatios', /** * Adds the default ratios * @private */ value: function _addDefaultRatios() { this.addRatio('custom', '*', true); this.addRatio('square', '1'); this.addRatio('4-3', '1.33'); this.addRatio('16-9', '1.77'); } }, { key: 'addRatio', /** * Adds a ratio with the given identifier * @param {String} identifier * @param {Number} ratio * @param {Boolean} selected */ value: function addRatio(identifier, ratio, selected) { this._availableRatios[identifier] = { ratio: ratio, selected: selected }; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; _get(Object.getPrototypeOf(CropControl.prototype), '_onEnter', this).call(this); this._operationExistedBefore = !!this._ui.operations.crop; this._operation = this._ui.getOrCreateOperation('crop'); this._defaultStart = new _libMathVector22['default'](0.1, 0.1); this._defaultEnd = new _libMathVector22['default'](0.9, 0.9); this._initialOptions = { start: this._operation.getStart(), end: this._operation.getEnd() }; this._start = this._initialOptions.start || this._defaultStart; this._end = this._initialOptions.end || this._defaultEnd; // Minimum size in pixels this._minimumSize = new _libMathVector22['default'](50, 50); this._initialZoomLevel = this._ui.canvas.zoomLevel; this._ui.canvas.zoomToFit(false); var prefix = '.imglykit-canvas-crop'; var container = this._canvasControls; var knobsContainer = container.querySelector('' + prefix + '-knobs'); // Store initial settings for 'back' button this._initialStart = this._operation.getStart().clone(); this._initialEnd = this._operation.getEnd().clone(); // Make sure we see the whole input image this._operation.set({ start: new _libMathVector22['default'](0, 0), end: new _libMathVector22['default'](1, 1) }); // Find all 4 knobs this._knobs = { topLeft: knobsContainer.querySelector('[data-corner=top-left]'), topRight: knobsContainer.querySelector('[data-corner=top-right]'), bottomLeft: knobsContainer.querySelector('[data-corner=bottom-left]'), bottomRight: knobsContainer.querySelector('[data-corner=bottom-right]') }; // Find the div areas that affect the displayed crop size this._areas = { topLeft: this._canvasControls.querySelector('' + prefix + '-top-left'), topCenter: this._canvasControls.querySelector('' + prefix + '-top-center'), centerLeft: this._canvasControls.querySelector('' + prefix + '-center-left'), centerCenter: this._canvasControls.querySelector('' + prefix + '-center-center') }; this._handleControls(); this._handleKnobs(); this._handleCenter(); // Resume the rendering this._ui.canvas.render().then(function () { _this._updateDOM(); }); } }, { key: '_handleControls', /** * Handles the ratio controls * @private */ value: function _handleControls() { var _this2 = this; var listItems = this._controls.querySelectorAll('ul > li'); this._ratioItems = Array.prototype.slice.call(listItems); var _loop = function (i) { var item = _this2._ratioItems[i]; var _item$dataset = item.dataset; var selected = _item$dataset.selected; var ratio = _item$dataset.ratio; var identifier = _item$dataset.identifier; if (typeof selected !== 'undefined' && !_this2._operationExistedBefore) { _this2._setRatio(identifier, ratio, false); _this2._selectRatio(item); } item.addEventListener('click', function (e) { e.preventDefault(); _this2._onRatioClick(item); }); }; for (var i = 0; i < this._ratioItems.length; i++) { _loop(i); } } }, { key: '_onRatioClick', /** * Gets called when the given ratio has been selected * @param {DOMElement} item * @private */ value: function _onRatioClick(item) { this._unselectAllRatios(); this._selectRatio(item); } }, { key: '_unselectAllRatios', /** * Unselects all ratio control items * @private */ value: function _unselectAllRatios() { for (var i = 0; i < this._ratioItems.length; i++) { var item = this._ratioItems[i]; item.classList.remove('imglykit-controls-item-active'); } } }, { key: '_selectRatio', /** * Activates the given ratio control item * @param {DOMElement} item * @private */ value: function _selectRatio(item) { item.classList.add('imglykit-controls-item-active'); var _item$dataset2 = item.dataset; var ratio = _item$dataset2.ratio; var identifier = _item$dataset2.identifier; this._setRatio(identifier, ratio); } }, { key: '_setRatio', /** * Sets the given ratio * @param {String} identifier * @param {String} ratio * @param {Boolean} resize * @private */ value: function _setRatio(identifier, ratio) { var resize = arguments[2] === undefined ? true : arguments[2]; var canvasSize = this._ui.canvas.size; this._selectedRatio = identifier; if (ratio === '*') { this._ratio = null; this._start = new _libMathVector22['default'](0.1, 0.1); this._end = new _libMathVector22['default'](0.9, 0.9); } else { if (ratio === 'original') { this._ratio = canvasSize.x / canvasSize.y; } else { ratio = parseFloat(ratio); this._ratio = ratio; } if (resize) { if (canvasSize.x / canvasSize.y <= this._ratio) { this._start.x = 0.1; this._end.x = 0.9; var height = 1 / canvasSize.y * (canvasSize.x / this._ratio * 0.8); this._start.y = (1 - height) / 2; this._end.y = 1 - this._start.y; } else { this._start.y = 0.1; this._end.y = 0.9; var width = 1 / canvasSize.x * (this._ratio * canvasSize.y * 0.8); this._start.x = (1 - width) / 2; this._end.x = 1 - this._start.x; } } } this._updateDOM(); } }, { key: '_updateDOM', /** * Updates the cropping divs for the current operation settings * @private */ value: function _updateDOM() { var canvasSize = this._ui.canvas.size; var startAbsolute = this._start.clone().multiply(canvasSize); var endAbsolute = this._end.clone().multiply(canvasSize); var size = endAbsolute.clone().subtract(startAbsolute); var top = Math.max(1, startAbsolute.y); var left = Math.max(1, startAbsolute.x); var width = Math.max(1, size.x); var height = Math.max(1, size.y); // widths are defined by top left and top center areas this._areas.topLeft.style.width = '' + left + 'px'; this._areas.topCenter.style.width = '' + width + 'px'; // heights are defined by top left and center left areas this._areas.topLeft.style.height = '' + top + 'px'; this._areas.centerLeft.style.height = '' + height + 'px'; } }, { key: '_handleKnobs', /** * Handles the knob dragging * @private */ value: function _handleKnobs() { var _this3 = this; var _loop2 = function (identifier) { var knob = _this3._knobs[identifier]; knob.addEventListener('mousedown', function (e) { _this3._onKnobDown(e, knob); }); knob.addEventListener('touchstart', function (e) { _this3._onKnobDown(e, knob); }); }; for (var identifier in this._knobs) { _loop2(identifier); } } }, { key: '_onKnobDown', /** * Gets called when the user presses a knob * @param {Event} e * @param {DOMElement} knob * @private */ value: function _onKnobDown(e, knob) { e.preventDefault(); e.stopPropagation(); this._currentKnob = knob; this._initialMousePosition = _libUtils2['default'].getEventPosition(e); // Remember the current values this._startBeforeDrag = this._start.clone(); this._endBeforeDrag = this._end.clone(); document.addEventListener('mousemove', this._onKnobDrag); document.addEventListener('touchmove', this._onKnobDrag); document.addEventListener('mouseup', this._onKnobUp); document.addEventListener('touchend', this._onKnobUp); } }, { key: '_onKnobDrag', /** * Gets called whe the user drags a knob * @param {Event} e * @private */ value: function _onKnobDrag(e) { e.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(e); var mouseDiff = mousePosition.subtract(this._initialMousePosition); var corner = this._currentKnob.dataset.corner; var canvasSize = this._ui.canvas.size; var absoluteStart = this._startBeforeDrag.clone().multiply(canvasSize); var absoluteEnd = this._endBeforeDrag.clone().multiply(canvasSize); var width = undefined, height = undefined, maximum = undefined, minimum = undefined; switch (corner) { case 'top-left': absoluteStart.add(mouseDiff); maximum = absoluteEnd.clone().subtract(this._minimumSize); absoluteStart.clamp(null, maximum); break; case 'top-right': absoluteEnd.x += mouseDiff.x; absoluteStart.y += mouseDiff.y; absoluteEnd.x = Math.max(absoluteStart.x + this._minimumSize.x, absoluteEnd.x); absoluteStart.y = Math.min(absoluteEnd.y - this._minimumSize.y, absoluteStart.y); break; case 'bottom-right': absoluteEnd.add(mouseDiff); minimum = absoluteStart.clone().add(this._minimumSize); absoluteEnd.clamp(minimum); break; case 'bottom-left': absoluteStart.x += mouseDiff.x; absoluteEnd.y += mouseDiff.y; absoluteStart.x = Math.min(absoluteEnd.x - this._minimumSize.x, absoluteStart.x); absoluteEnd.y = Math.max(absoluteStart.y + this._minimumSize.y, absoluteEnd.y); break; } this._start.copy(absoluteStart).divide(canvasSize); this._end.copy(absoluteEnd).divide(canvasSize); this._start.clamp(0, 1); this._end.clamp(0, 1); /** * Calculate boundaries */ if (this._ratio !== null) { switch (corner) { case 'top-left': width = (this._end.x - this._start.x) * canvasSize.x; height = width / this._ratio; this._start.y = this._end.y - height / canvasSize.y; if (this._start.y <= 0) { this._start.y = 0; height = (this._end.y - this._start.y) * canvasSize.y; width = height * this._ratio; this._start.x = this._end.x - width / canvasSize.x; } break; case 'top-right': width = (this._end.x - this._start.x) * canvasSize.x; height = width / this._ratio; this._start.y = this._end.y - height / canvasSize.y; if (this._start.y <= 0) { this._start.y = 0; height = (this._end.y - this._start.y) * canvasSize.y; width = height * this._ratio; this._end.x = this._start.x + width / canvasSize.x; } break; case 'bottom-right': width = (this._end.x - this._start.x) * canvasSize.x; height = width / this._ratio; this._end.y = this._start.y + height / canvasSize.y; // If boundaries are exceeded, calculate width by maximum height if (this._end.y >= 1) { this._end.y = 1; height = (this._end.y - this._start.y) * canvasSize.y; width = height * this._ratio; this._end.x = this._start.x + width / canvasSize.x; } break; case 'bottom-left': width = (this._end.x - this._start.x) * canvasSize.x; height = width / this._ratio; this._end.y = this._start.y + height / canvasSize.y; if (this._end.y >= 1) { this._end.y = 1; height = (this._end.y - this._start.y) * canvasSize.y; width = height * this._ratio; this._start.x = this._end.x - width / canvasSize.x; } break; } } this._updateDOM(); } }, { key: '_onKnobUp', /** * Gets called whe the user releases a knob * @param {Event} e * @private */ value: function _onKnobUp() { this._currentKnob = null; document.removeEventListener('mousemove', this._onKnobDrag); document.removeEventListener('touchmove', this._onKnobDrag); document.removeEventListener('mouseup', this._onKnobUp); document.removeEventListener('touchend', this._onKnobUp); } }, { key: '_handleCenter', /** * Handles the center dragging * @private */ value: function _handleCenter() { this._areas.centerCenter.addEventListener('mousedown', this._onCenterDown); this._areas.centerCenter.addEventListener('touchstart', this._onCenterDown); } }, { key: '_onCenterDown', /** * Gets called when the user presses the center area * @param {Event} e * @private */ value: function _onCenterDown(e) { this._initialMousePosition = _libUtils2['default'].getEventPosition(e); // Remember the current values this._startBeforeDrag = this._start.clone(); this._endBeforeDrag = this._end.clone(); document.addEventListener('mousemove', this._onCenterDrag); document.addEventListener('touchmove', this._onCenterDrag); document.addEventListener('mouseup', this._onCenterUp); document.addEventListener('touchend', this._onCenterUp); } }, { key: '_onCenterDrag', /** * Gets called when the user presses the center area and moves his mouse * @param {Event} e * @private */ value: function _onCenterDrag(e) { var mousePosition = _libUtils2['default'].getEventPosition(e); var mouseDiff = mousePosition.subtract(this._initialMousePosition); var canvasSize = this._ui.canvas.size; // Get the crop size var cropSize = this._endBeforeDrag.clone().subtract(this._startBeforeDrag); var absoluteCropSize = cropSize.clone().multiply(canvasSize); // Get the absolute initial values var absoluteStart = this._startBeforeDrag.clone().multiply(canvasSize); var absoluteEnd = this._endBeforeDrag.clone().multiply(canvasSize); // Add the mouse position difference absoluteStart.add(mouseDiff); // Clamp the value var maxStart = canvasSize.clone().subtract(absoluteCropSize); absoluteStart.clamp(new _libMathVector22['default'](0, 0), maxStart); // End position does not change (relative to start) absoluteEnd.copy(absoluteStart).add(absoluteCropSize); // Set the final values this._start.copy(absoluteStart).divide(canvasSize); this._end.copy(absoluteEnd).divide(canvasSize); this._updateDOM(); } }, { key: '_onCenterUp', /** * Gets called when the user releases the center area * @param {Event} e * @private */ value: function _onCenterUp() { document.removeEventListener('mousemove', this._onCenterDrag); document.removeEventListener('touchmove', this._onCenterDrag); document.removeEventListener('mouseup', this._onCenterUp); document.removeEventListener('touchend', this._onCenterUp); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { this._ui.canvas.setZoomLevel(this._initialZoomLevel, false); if (this._operationExistedBefore) { this._operation.set({ start: this._initialStart, end: this._initialEnd }); } else { this._ui.removeOperation('crop'); } this._ui.canvas.render(); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @protected */ value: function _onDone() { this._operation.set({ start: this._start, end: this._end }); this._ui.canvas.zoomToFit(true); this._ui.addHistory(this._operation, { start: this._initialStart.clone(), end: this._initialEnd.clone() }, this._operationExistedBefore); } }, { key: 'context', /** * The data that is available to the template * @type {Object} * @override */ get: function () { var context = _get(Object.getPrototypeOf(CropControl.prototype), 'context', this); context.ratios = this._ratios; return context; } }, { key: 'selectedRatio', /** * The selected ratio identifier * @type {String} */ get: function () { return this._selectedRatio; } }]); return CropControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ CropControl.prototype.identifier = 'crop'; exports['default'] = CropControl; module.exports = exports['default']; /***/ }, /* 88 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libSimpleSlider = __webpack_require__(102); var _libSimpleSlider2 = _interopRequireDefault(_libSimpleSlider); var RadialBlurControl = (function (_Control) { function RadialBlurControl() { _classCallCheck(this, RadialBlurControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(RadialBlurControl, _Control); _createClass(RadialBlurControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
'+( it.partials.slider)+'
'+( it.partials.doneButton);return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; this._partialTemplates.slider = _libSimpleSlider2['default'].template; this._partialTemplates.slider.additionalContext = { id: 'imglykit-blur-radius-slider' }; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations['radial-blur']; this._operation = this._ui.getOrCreateOperation('radial-blur'); // Remember initial identity state this._initialSettings = { position: this._operation.getPosition().clone(), gradientRadius: this._operation.getGradientRadius(), blurRadius: this._operation.getBlurRadius() }; // Mouse event callbacks bound to the class context this._onPositionKnobDown = this._onPositionKnobDown.bind(this); this._onPositionKnobDrag = this._onPositionKnobDrag.bind(this); this._onPositionKnobUp = this._onPositionKnobUp.bind(this); this._onGradientKnobDown = this._onGradientKnobDown.bind(this); this._onGradientKnobDrag = this._onGradientKnobDrag.bind(this); this._onGradientKnobUp = this._onGradientKnobUp.bind(this); this._positionKnob = this._canvasControls.querySelector('#imglykit-radial-blur-position'); this._gradientKnob = this._canvasControls.querySelector('#imglykit-radial-blur-gradient'); this._circle = this._canvasControls.querySelector('.imglykit-canvas-radial-blur-circle'); this._handleKnobs(); this._initSliders(); this._ui.canvas.render().then(function () { _this._updateDOM(); }); } }, { key: '_initSliders', /** * Initializes the slider controls * @private */ value: function _initSliders() { var blurRadiusSlider = this._controls.querySelector('#imglykit-blur-radius-slider'); this._blurRadiusSlider = new _libSimpleSlider2['default'](blurRadiusSlider, { minValue: 0, maxValue: 40 }); this._blurRadiusSlider.on('update', this._onBlurRadiusUpdate.bind(this)); this._blurRadiusSlider.setValue(this._initialSettings.blurRadius); } }, { key: '_onBlurRadiusUpdate', /** * Gets called when the value of the blur radius slider has been updated * @param {Number} value * @private */ value: function _onBlurRadiusUpdate(value) { this._operation.setBlurRadius(value); this._ui.canvas.render(); this._highlightDoneButton(); } }, { key: '_handleKnobs', /** * Handles the knob dragging * @private */ value: function _handleKnobs() { // Initially set gradient knob position var canvasSize = this._ui.canvas.size; var position = this._operation.getPosition().clone().multiply(canvasSize); this._gradientKnobPosition = position.clone().add(this._initialSettings.gradientRadius, 0); this._positionKnob.addEventListener('mousedown', this._onPositionKnobDown); this._positionKnob.addEventListener('touchstart', this._onPositionKnobDown); this._gradientKnob.addEventListener('mousedown', this._onGradientKnobDown); this._gradientKnob.addEventListener('touchstart', this._onGradientKnobDown); } }, { key: '_onPositionKnobDown', /** * Gets called when the user starts dragging the position knob * @param {Event} e * @private */ value: function _onPositionKnobDown(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialPosition = this._operation.getPosition().clone(); this._gradientKnobDistance = this._gradientKnobPosition.clone().subtract(this._initialPosition.clone().multiply(canvasSize)); document.addEventListener('mousemove', this._onPositionKnobDrag); document.addEventListener('touchmove', this._onPositionKnobDrag); document.addEventListener('mouseup', this._onPositionKnobUp); document.addEventListener('touchend', this._onPositionKnobUp); } }, { key: '_onPositionKnobDrag', /** * Gets called while the user starts drags the position knob * @param {Event} e * @private */ value: function _onPositionKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.subtract(this._initialMousePosition); var newPosition = this._initialPosition.clone().multiply(canvasSize).add(diff); var maxPosition = canvasSize.clone().subtract(this._gradientKnobDistance); newPosition.clamp(new _libMathVector22['default'](0, 0), maxPosition); this._gradientKnobPosition.copy(newPosition).add(this._gradientKnobDistance); // Translate to 0...1 newPosition.divide(canvasSize); this._operation.setPosition(newPosition); this._updateDOM(); this._ui.canvas.render(); } }, { key: '_onPositionKnobUp', /** * Gets called when the user stops dragging the position knob * @param {Event} e * @private */ value: function _onPositionKnobUp(e) { e.preventDefault(); document.removeEventListener('mousemove', this._onPositionKnobDrag); document.removeEventListener('touchmove', this._onPositionKnobDrag); document.removeEventListener('mouseup', this._onPositionKnobUp); document.removeEventListener('touchend', this._onPositionKnobUp); } }, { key: '_onGradientKnobDown', /** * Gets called when the user starts dragging the position knob * @param {Event} e * @private */ value: function _onGradientKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialGradientKnobPosition = this._gradientKnobPosition.clone(); document.addEventListener('mousemove', this._onGradientKnobDrag); document.addEventListener('touchmove', this._onGradientKnobDrag); document.addEventListener('mouseup', this._onGradientKnobUp); document.addEventListener('touchend', this._onGradientKnobUp); } }, { key: '_onGradientKnobDrag', /** * Gets called while the user starts drags the position knob * @param {Event} e * @private */ value: function _onGradientKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.subtract(this._initialMousePosition); // Calculate new gradient knob position this._gradientKnobPosition = this._initialGradientKnobPosition.clone().add(diff); this._gradientKnobPosition.clamp(new _libMathVector22['default'](0, 0), canvasSize); // Calculate distance to position var position = this._operation.getPosition().clone().multiply(canvasSize); var distance = this._gradientKnobPosition.clone().subtract(position); var gradientRadius = Math.sqrt(Math.pow(distance.x, 2) + Math.pow(distance.y, 2)); // Update operation this._operation.setGradientRadius(gradientRadius); this._updateDOM(); this._ui.canvas.render(); } }, { key: '_onGradientKnobUp', /** * Gets called when the user stops dragging the position knob * @param {Event} e * @private */ value: function _onGradientKnobUp(e) { e.preventDefault(); document.removeEventListener('mousemove', this._onGradientKnobDrag); document.removeEventListener('touchmove', this._onGradientKnobDrag); document.removeEventListener('mouseup', this._onGradientKnobUp); document.removeEventListener('touchend', this._onGradientKnobUp); } }, { key: '_updateDOM', /** * Updates the knob * @private */ value: function _updateDOM() { var canvasSize = this._ui.canvas.size; var position = this._operation.getPosition().clone().multiply(canvasSize); this._positionKnob.style.left = '' + position.x + 'px'; this._positionKnob.style.top = '' + position.y + 'px'; this._gradientKnob.style.left = '' + this._gradientKnobPosition.x + 'px'; this._gradientKnob.style.top = '' + this._gradientKnobPosition.y + 'px'; var circleSize = this._operation.getGradientRadius() * 2; this._circle.style.left = '' + position.x + 'px'; this._circle.style.top = '' + position.y + 'px'; this._circle.style.width = '' + circleSize + 'px'; this._circle.style.height = '' + circleSize + 'px'; this._circle.style.marginLeft = '-' + circleSize / 2 + 'px'; this._circle.style.marginTop = '-' + circleSize / 2 + 'px'; } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { if (this._operationExistedBefore) { this._operation.set(this._initialSettings); } else { this._ui.removeOperation('radial-blur'); } this._ui.canvas.render(); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @override */ value: function _onDone() { this._ui.addHistory(this._operation, { position: this._initialSettings.position.clone(), gradientRadius: this._initialSettings.gradientRadius, blurRadius: this._initialSettings.blurRadius }, this._operationExistedBefore); } }]); return RadialBlurControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ RadialBlurControl.prototype.identifier = 'radial-blur'; exports['default'] = RadialBlurControl; module.exports = exports['default']; /***/ }, /* 89 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libSimpleSlider = __webpack_require__(102); var _libSimpleSlider2 = _interopRequireDefault(_libSimpleSlider); var TiltShiftControl = (function (_Control) { function TiltShiftControl() { _classCallCheck(this, TiltShiftControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(TiltShiftControl, _Control); _createClass(TiltShiftControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
';var sliderId = "imglykit-blur-radius-slider";out+=' '+( it.partials.slider)+'
'+( it.partials.doneButton);return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; this._partialTemplates.slider = _libSimpleSlider2['default'].template; this._partialTemplates.slider.additionalContext = { id: 'imglykit-blur-radius-slider' }; this._currentKnob = null; } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations['tilt-shift']; this._operation = this._ui.getOrCreateOperation('tilt-shift'); this._initialSettings = { start: this._operation.getStart().clone(), end: this._operation.getEnd().clone(), gradientRadius: this._operation.getGradientRadius(), blurRadius: this._operation.getBlurRadius() }; // Mouse event callbacks bound to the class context this._onPositionKnobDown = this._onPositionKnobDown.bind(this); this._onPositionKnobDrag = this._onPositionKnobDrag.bind(this); this._onPositionKnobUp = this._onPositionKnobUp.bind(this); this._onGradientKnobDown = this._onGradientKnobDown.bind(this); this._onGradientKnobDrag = this._onGradientKnobDrag.bind(this); this._onGradientKnobUp = this._onGradientKnobUp.bind(this); // Find DOM elements var selector = '.imglykit-canvas-tilt-shift-dot'; this._positionKnob = this._canvasControls.querySelector('' + selector + '[data-option=\'position\']'); this._gradientKnob = this._canvasControls.querySelector('' + selector + '[data-option=\'gradient\']'); this._rect = this._canvasControls.querySelector('.imglykit-canvas-tilt-shift-rect'); // Initialization this._initSliders(); this._ui.canvas.render().then(function () { _this._handleKnobs(); _this._updateDOM(); }); } }, { key: '_initSliders', /** * Initializes the slider controls * @private */ value: function _initSliders() { var blurRadiusSlider = this._controls.querySelector('#imglykit-blur-radius-slider'); this._blurRadiusSlider = new _libSimpleSlider2['default'](blurRadiusSlider, { minValue: 0, maxValue: 40 }); this._blurRadiusSlider.on('update', this._onBlurRadiusUpdate.bind(this)); this._blurRadiusSlider.setValue(this._initialSettings.blurRadius); } }, { key: '_onBlurRadiusUpdate', /** * Gets called when the value of the blur radius slider has been updated * @param {Number} value * @private */ value: function _onBlurRadiusUpdate(value) { this._operation.setBlurRadius(value); this._ui.canvas.render(); this._highlightDoneButton(); } }, { key: '_handleKnobs', /** * Handles the knob dragging * @private */ value: function _handleKnobs() { // Add event listeners this._positionKnob.addEventListener('mousedown', this._onPositionKnobDown); this._positionKnob.addEventListener('touchstart', this._onPositionKnobDown); this._gradientKnob.addEventListener('mousedown', this._onGradientKnobDown); this._gradientKnob.addEventListener('touchstart', this._onGradientKnobDown); var canvasSize = this._ui.canvas.size; var _initialSettings = this._initialSettings; var start = _initialSettings.start; var end = _initialSettings.end; start = start.clone().multiply(canvasSize); end = end.clone().multiply(canvasSize); var dist = end.clone().subtract(start); var middle = start.clone().add(dist.clone().divide(2)); var totalDist = Math.sqrt(Math.pow(dist.x, 2) + Math.pow(dist.y, 2)); var factor = dist.clone().divide(totalDist).divide(2); // Calculate initial knob position (middle of start and end) this._knobPosition = middle.clone(); // Calculate initial gradient knob position var gradientRadius = this._initialSettings.gradientRadius; this._gradientKnobPosition = middle.clone().add(-gradientRadius * factor.y, gradientRadius * factor.x); this._updateStartAndEnd(); this._updateDOM(); this._ui.canvas.render(); } }, { key: '_updateStartAndEnd', /** * Calculate start and end positions using the knob positions * @private */ value: function _updateStartAndEnd() { var canvasSize = this._ui.canvas.size; // Calculate distance between gradient and position knob var diff = this._gradientKnobPosition.clone().subtract(this._knobPosition); var start = this._knobPosition.clone().add(-diff.y, diff.x).divide(canvasSize); var end = this._knobPosition.clone().add(diff.y, -diff.x).divide(canvasSize); this._operation.set({ start: start, end: end }); } }, { key: '_onPositionKnobDown', /** * Gets called when the user starts dragging the position knob * @param {Event} e * @private */ value: function _onPositionKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialPosition = this._knobPosition.clone(); this._initialDistanceToGradientKnob = this._gradientKnobPosition.clone().subtract(this._initialPosition); document.addEventListener('mousemove', this._onPositionKnobDrag); document.addEventListener('touchmove', this._onPositionKnobDrag); document.addEventListener('mouseup', this._onPositionKnobUp); document.addEventListener('touchend', this._onPositionKnobUp); } }, { key: '_onPositionKnobDrag', /** * Gets called when the user drags the position knob * @param {Event} e * @private */ value: function _onPositionKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.subtract(this._initialMousePosition); var newPosition = this._initialPosition.clone().add(diff); this._knobPosition.copy(newPosition); var minPosition = new _libMathVector22['default']().subtract(this._initialDistanceToGradientKnob); minPosition.clamp(new _libMathVector22['default'](0, 0)); var maxPosition = canvasSize.clone().subtract(this._initialDistanceToGradientKnob); maxPosition.clamp(null, canvasSize); this._knobPosition.clamp(minPosition, maxPosition); this._gradientKnobPosition.copy(this._knobPosition).add(this._initialDistanceToGradientKnob); this._updateStartAndEnd(); this._updateDOM(); this._ui.canvas.render(); } }, { key: '_onPositionKnobUp', /** * Gets called when the user stops dragging the position knob * @param {Event} e * @private */ value: function _onPositionKnobUp(e) { e.preventDefault(); document.removeEventListener('mousemove', this._onPositionKnobDrag); document.removeEventListener('touchmove', this._onPositionKnobDrag); document.removeEventListener('mouseup', this._onPositionKnobUp); document.removeEventListener('touchend', this._onPositionKnobUp); } }, { key: '_onGradientKnobDown', /** * Gets called when the user starts dragging the gradient knob * @param {Event} e * @private */ value: function _onGradientKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialGradientKnobPosition = this._gradientKnobPosition.clone(); document.addEventListener('mousemove', this._onGradientKnobDrag); document.addEventListener('touchmove', this._onGradientKnobDrag); document.addEventListener('mouseup', this._onGradientKnobUp); document.addEventListener('touchend', this._onGradientKnobUp); } }, { key: '_onGradientKnobDrag', /** * Gets called when the user drags the gradient knob * @param {Event} e * @private */ value: function _onGradientKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.subtract(this._initialMousePosition); this._gradientKnobPosition.copy(this._initialGradientKnobPosition).add(diff); this._gradientKnobPosition.clamp(new _libMathVector22['default'](0, 0), canvasSize); var distance = this._gradientKnobPosition.clone().subtract(this._knobPosition); var newGradientRadius = 2 * Math.sqrt(Math.pow(distance.x, 2) + Math.pow(distance.y, 2)); this._operation.setGradientRadius(newGradientRadius); this._updateStartAndEnd(); this._updateDOM(); this._ui.canvas.render(); } }, { key: '_onGradientKnobUp', /** * Gets called when the user stops dragging the gradient knob * @param {Event} e * @private */ value: function _onGradientKnobUp(e) { e.preventDefault(); document.removeEventListener('mousemove', this._onGradientKnobDrag); document.removeEventListener('touchmove', this._onGradientKnobDrag); document.removeEventListener('mouseup', this._onGradientKnobUp); document.removeEventListener('touchend', this._onGradientKnobUp); } }, { key: '_updateDOM', /** * Updates the knob * @private */ value: function _updateDOM() { var position = this._knobPosition; this._positionKnob.style.left = '' + position.x + 'px'; this._positionKnob.style.top = '' + position.y + 'px'; var gradientPosition = this._gradientKnobPosition; this._gradientKnob.style.left = '' + gradientPosition.x + 'px'; this._gradientKnob.style.top = '' + gradientPosition.y + 'px'; // Resize rectangle to worst case size var canvasSize = this._ui.canvas.size; var gradientRadius = this._operation.getGradientRadius(); var rectSize = new _libMathVector22['default'](Math.sqrt(Math.pow(canvasSize.x, 2) + Math.pow(canvasSize.y, 2)) * 2, gradientRadius); this._rect.style.width = '' + rectSize.x + 'px'; this._rect.style.height = '' + rectSize.y + 'px'; this._rect.style.marginLeft = '-' + rectSize.x / 2 + 'px'; this._rect.style.marginTop = '-' + rectSize.y / 2 + 'px'; this._rect.style.left = '' + position.x + 'px'; this._rect.style.top = '' + position.y + 'px'; // Rotate rectangle var dist = gradientPosition.clone().subtract(position); var degrees = Math.atan2(dist.x, dist.y) * (180 / Math.PI); this._rect.style.transform = 'rotate(' + (-degrees).toFixed(2) + 'deg)'; } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { if (this._operationExistedBefore) { this._operation.set(this._initialSettings); } else { this._ui.removeOperation('tilt-shift'); } this._ui.canvas.render(); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @override */ value: function _onDone() { this._ui.addHistory(this._operation, { start: this._initialSettings.start.clone(), end: this._initialSettings.end.clone(), blurRadius: this._initialSettings.blurRadius, gradientRadius: this._initialSettings.gradientRadius }, this._operationExistedBefore); } }]); return TiltShiftControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ TiltShiftControl.prototype.identifier = 'tilt-shift'; exports['default'] = TiltShiftControl; module.exports = exports['default']; /***/ }, /* 90 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libSimpleSlider = __webpack_require__(102); var _libSimpleSlider2 = _interopRequireDefault(_libSimpleSlider); var _libColorPicker = __webpack_require__(103); var _libColorPicker2 = _interopRequireDefault(_libColorPicker); var FramesControl = (function (_Control) { function FramesControl() { _classCallCheck(this, FramesControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(FramesControl, _Control); _createClass(FramesControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
'+( it.partials.slider)+'
'+( it.partials.colorPicker)+'
'+( it.partials.doneButton);return out; }; this._controlsTemplate = controlsTemplate; this._partialTemplates.slider = _libSimpleSlider2['default'].template; this._partialTemplates.colorPicker = _libColorPicker2['default'].template; } }, { key: '_renderControls', value: function _renderControls() { this._partialTemplates.colorPicker.additionalContext = { label: this._ui.translate('controls.frames.color') }; _get(Object.getPrototypeOf(FramesControl.prototype), '_renderControls', this).call(this); } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { this._operationExistedBefore = !!this._ui.operations.frames; this._operation = this._ui.getOrCreateOperation('frames'); this._initialOptions = { thickness: this._operation.getThickness(), color: this._operation.getColor() }; this._ui.canvas.render(); // Init slider var sliderElement = this._controls.querySelector('.imglykit-slider'); this._slider = new _libSimpleSlider2['default'](sliderElement, { minValue: 0, maxValue: 0.5 }); this._slider.on('update', this._onThicknessUpdate.bind(this)); this._slider.setValue(this._initialOptions.thickness); // Init colorpicker var colorPickerElement = this._controls.querySelector('.imglykit-color-picker'); this._colorPicker = new _libColorPicker2['default'](this._ui, colorPickerElement); this._colorPicker.on('update', this._onColorUpdate.bind(this)); this._colorPicker.setValue(this._initialOptions.color); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { if (this._operationExistedBefore) { this._operation.set(this._initialOptions); } else { this._ui.removeOperation('frames'); } this._ui.canvas.render(); } }, { key: '_onThicknessUpdate', /** * Gets called when the thickness has been changed * @override */ value: function _onThicknessUpdate(value) { this._operation.setThickness(value); this._ui.canvas.render(); this._highlightDoneButton(); } }, { key: '_onColorUpdate', /** * Gets called when the color has been changed * @override */ value: function _onColorUpdate(value) { this._operation.setColor(value); this._ui.canvas.render(); this._highlightDoneButton(); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @override */ value: function _onDone() { this._ui.addHistory(this._operation, { color: this._initialOptions.color, thickness: this._initialOptions.thickness }, this._operationExistedBefore); } }]); return FramesControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ FramesControl.prototype.identifier = 'frames'; exports['default'] = FramesControl; module.exports = exports['default']; /***/ }, /* 91 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var StickersControl = (function (_Control) { function StickersControl() { _classCallCheck(this, StickersControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(StickersControl, _Control); _createClass(StickersControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
    '; for(var identifier in it.stickers) { out+=' '; var stickerPath = it.stickers[identifier]; out+=' '; var enabled = it.activeSticker === identifier; out+='
  • '; } out+='
'+( it.partials.doneButton );return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; /** * The registered stickers * @type {Object.} */ this._availableStickers = {}; this._stickers = {}; this._addDefaultStickers(); this.selectStickers(null); } }, { key: '_addDefaultStickers', /** * Registers the default stickers * @private */ value: function _addDefaultStickers() { this.addSticker('glasses-nerd', 'stickers/sticker-glasses-nerd.png'); this.addSticker('glasses-normal', 'stickers/sticker-glasses-normal.png'); this.addSticker('glasses-shutter-green', 'stickers/sticker-glasses-shutter-green.png'); this.addSticker('glasses-shutter-yellow', 'stickers/sticker-glasses-shutter-yellow.png'); this.addSticker('glasses-sun', 'stickers/sticker-glasses-sun.png'); this.addSticker('hat-cap', 'stickers/sticker-hat-cap.png'); this.addSticker('hat-cylinder', 'stickers/sticker-hat-cylinder.png'); this.addSticker('hat-party', 'stickers/sticker-hat-party.png'); this.addSticker('hat-sheriff', 'stickers/sticker-hat-sheriff.png'); this.addSticker('heart', 'stickers/sticker-heart.png'); this.addSticker('mustache-long', 'stickers/sticker-mustache-long.png'); this.addSticker('mustache1', 'stickers/sticker-mustache1.png'); this.addSticker('mustache2', 'stickers/sticker-mustache2.png'); this.addSticker('mustache3', 'stickers/sticker-mustache3.png'); this.addSticker('pipe', 'stickers/sticker-pipe.png'); this.addSticker('snowflake', 'stickers/sticker-snowflake.png'); this.addSticker('star', 'stickers/sticker-star.png'); } }, { key: 'addSticker', /** * Registers the sticker with the given identifier and path * @private */ value: function addSticker(identifier, path) { this._availableStickers[identifier] = path; this._stickers[identifier] = this._availableStickers[identifier]; if (this._active) { this._renderControls(); } } }, { key: 'selectStickers', /** * Selects the stickers * @param {Selector} selector */ value: function selectStickers(selector) { this._stickers = {}; var stickerIdentifiers = Object.keys(this._availableStickers); var selectedStickers = _libUtils2['default'].select(stickerIdentifiers, selector); for (var i = 0; i < selectedStickers.length; i++) { var identifier = selectedStickers[i]; this._stickers[identifier] = this._availableStickers[identifier]; } if (this._active) { this._renderControls(); } } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations.stickers; this._operation = this._ui.getOrCreateOperation('stickers'); // Don't render initially this._ui.removeOperation('stickers'); this._initialSettings = { sticker: this._operation.getSticker(), position: this._operation.getPosition().clone(), size: this._operation.getSize().clone() }; var canvasSize = this._ui.canvas.size; this._size = this._initialSettings.size.clone(); this._position = this._initialSettings.position.clone().multiply(canvasSize); // Remember zoom level and zoom to fit the canvas this._initialZoomLevel = this._ui.canvas.zoomLevel; this._ui.canvas.zoomToFit(); // Find DOM elements this._container = this._canvasControls.querySelector('.imglykit-canvas-stickers'); this._stickerImage = this._canvasControls.querySelector('img'); this._stickerImage.addEventListener('load', function () { _this._stickerSize = new _libMathVector22['default'](_this._stickerImage.width, _this._stickerImage.height); _this._onStickerLoad(); }); this._knob = this._canvasControls.querySelector('div.imglykit-knob'); // Mouse event callbacks bound to the class context this._onImageDown = this._onImageDown.bind(this); this._onImageDrag = this._onImageDrag.bind(this); this._onImageUp = this._onImageUp.bind(this); this._onKnobDown = this._onKnobDown.bind(this); this._onKnobDrag = this._onKnobDrag.bind(this); this._onKnobUp = this._onKnobUp.bind(this); this._renderListItems(); this._handleListItems(); this._handleImage(); this._handleKnob(); } }, { key: '_renderListItems', /** * Renders the stickers on the list item canvas elements * @private */ value: function _renderListItems() { var _this2 = this; var canvasItems = this._controls.querySelectorAll('li canvas'); this._canvasItems = Array.prototype.slice.call(canvasItems); var _loop = function (i) { var canvas = _this2._canvasItems[i]; canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; var context = canvas.getContext('2d'); var image = canvas.dataset.image; var imageEl = document.createElement('img'); var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); imageEl.addEventListener('load', function () { var imageSize = new _libMathVector22['default'](imageEl.width, imageEl.height); var newSize = _libUtils2['default'].resizeVectorToFit(imageSize, canvasSize); var offset = canvasSize.clone().divide(2).subtract(newSize.clone().divide(2)); context.drawImage(imageEl, 0, 0, imageSize.x, imageSize.y, offset.x, offset.y, newSize.x, newSize.y); }); imageEl.src = image; }; for (var i = 0; i < this._canvasItems.length; i++) { _loop(i); } } }, { key: '_handleListItems', /** * Handles the list item click events * @private */ value: function _handleListItems() { var _this3 = this; var listItems = this._controls.querySelectorAll('li'); this._listItems = Array.prototype.slice.call(listItems); var _loop2 = function (i) { var listItem = _this3._listItems[i]; var identifier = listItem.dataset.identifier; listItem.addEventListener('click', function () { _this3._onListItemClick(listItem); }); if (!_this3._operationExistedBefore && i === 0 || _this3._operationExistedBefore && _this3._stickers[identifier] === _this3._initialSettings.sticker) { _this3._onListItemClick(listItem, false); } }; // Listen to click events for (var i = 0; i < this._listItems.length; i++) { _loop2(i); } } }, { key: '_applySettings', /** * Resizes and positions the sticker according to the current settings * @private */ value: function _applySettings() { var ratio = this._stickerSize.y / this._stickerSize.x; this._size.y = this._size.x * ratio; this._stickerImage.style.width = '' + this._size.x + 'px'; this._stickerImage.style.height = '' + this._size.y + 'px'; this._container.style.left = '' + this._position.x + 'px'; this._container.style.top = '' + this._position.y + 'px'; } }, { key: '_onBack', /** * Gets called when the user hits the back button * @override */ value: function _onBack() { if (this._operationExistedBefore) { this._operation = this._ui.getOrCreateOperation('stickers'); this._operation.set(this._initialSettings); } else { this._ui.removeOperation('stickers'); } this._ui.canvas.setZoomLevel(this._initialZoomLevel); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @protected */ value: function _onDone() { // Map the position and size options to 0...1 values var canvasSize = this._ui.canvas.size; var position = this._position.clone().divide(canvasSize); var size = this._size.clone().divide(canvasSize); this._ui.canvas.setZoomLevel(this._initialZoomLevel, false); // Create a new operation and render it this._operation = this._ui.getOrCreateOperation('stickers'); this._operation.set({ sticker: this._availableStickers[this._sticker], position: position, size: size }); this._ui.canvas.render(); this._ui.addHistory(this, { sticker: this._initialSettings.sticker, position: this._initialSettings.position.clone(), size: this._initialSettings.size.clone() }, this._operationExistedBefore); } }, { key: '_handleKnob', /** * Handles the knob dragging * @private */ value: function _handleKnob() { this._knob.addEventListener('mousedown', this._onKnobDown); this._knob.addEventListener('touchstart', this._onKnobDown); } }, { key: '_onKnobDown', /** * Gets called when the user clicks the knob * @param {Event} e * @private */ value: function _onKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialSize = this._size.clone(); document.addEventListener('mousemove', this._onKnobDrag); document.addEventListener('touchmove', this._onKnobDrag); document.addEventListener('mouseup', this._onKnobUp); document.addEventListener('touchend', this._onKnobUp); } }, { key: '_onKnobDrag', /** * Gets called when the user drags the knob * @param {Event} e * @private */ value: function _onKnobDrag(e) { e.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.clone().subtract(this._initialMousePosition); var size = this._initialSize.clone(); var ratio = this._stickerImage.height / this._stickerImage.width; size.x += diff.x; size.y = size.x * ratio; this._size.copy(size); this._applySettings(); this._highlightDoneButton(); } }, { key: '_onKnobUp', /** * Gets called when the user releases the knob * @param {Event} e * @private */ value: function _onKnobUp() { document.removeEventListener('mousemove', this._onKnobDrag); document.removeEventListener('touchmove', this._onKnobDrag); document.removeEventListener('mouseup', this._onKnobUp); document.removeEventListener('touchend', this._onKnobUp); } }, { key: '_handleImage', /** * Handles the image dragging * @private */ value: function _handleImage() { this._stickerImage.addEventListener('mousedown', this._onImageDown); this._stickerImage.addEventListener('touchstart', this._onImageDown); } }, { key: '_onImageDown', /** * Gets called when the user clicks the image * @param {Event} e * @private */ value: function _onImageDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialPosition = this._position.clone(); document.addEventListener('mousemove', this._onImageDrag); document.addEventListener('touchmove', this._onImageDrag); document.addEventListener('mouseup', this._onImageUp); document.addEventListener('touchend', this._onImageUp); } }, { key: '_onImageDrag', /** * Gets called when the user drags the image * @param {Event} e * @private */ value: function _onImageDrag(e) { e.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.clone().subtract(this._initialMousePosition); var position = this._initialPosition.clone(); position.add(diff); this._position.copy(position); this._applySettings(); this._highlightDoneButton(); } }, { key: '_onImageUp', /** * Gets called when the user releases the image * @param {Event} e * @private */ value: function _onImageUp() { document.removeEventListener('mousemove', this._onImageDrag); document.removeEventListener('touchmove', this._onImageDrag); document.removeEventListener('mouseup', this._onImageUp); document.removeEventListener('touchend', this._onImageUp); } }, { key: '_onStickerLoad', /** * Gets called as soon as the sticker image has been loaded * @private */ value: function _onStickerLoad() { this._size = new _libMathVector22['default'](this._stickerImage.width, this._stickerImage.height); if (typeof this._position === 'undefined') { this._position = new _libMathVector22['default'](0, 0); } this._applySettings(); } }, { key: '_onListItemClick', /** * Gets called when the user clicked a list item * @private */ value: function _onListItemClick(item) { var manually = arguments[1] === undefined ? true : arguments[1]; this._deactivateAllItems(); var identifier = item.dataset.identifier; var stickerPath = this._availableStickers[identifier]; stickerPath = this._kit.getAssetPath(stickerPath); try { this._stickerImage.attributes.removeNamedItem('style'); } catch (e) {} this._sticker = identifier; this._stickerImage.src = stickerPath; item.classList.add('imglykit-controls-item-active'); if (manually) { this._highlightDoneButton(); } } }, { key: '_deactivateAllItems', /** * Deactivates all list items * @private */ value: function _deactivateAllItems() { for (var i = 0; i < this._listItems.length; i++) { var listItem = this._listItems[i]; listItem.classList.remove('imglykit-controls-item-active'); } } }, { key: 'context', /** * The data that is available to the template * @type {Object} * @override */ get: function () { var context = _get(Object.getPrototypeOf(StickersControl.prototype), 'context', this); context.stickers = this._stickers; return context; } }]); return StickersControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ StickersControl.prototype.identifier = 'stickers'; exports['default'] = StickersControl; module.exports = exports['default']; /***/ }, /* 92 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _control = __webpack_require__(93); var _control2 = _interopRequireDefault(_control); var _libColorPicker = __webpack_require__(103); var _libColorPicker2 = _interopRequireDefault(_libColorPicker); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var TextControl = (function (_Control) { function TextControl() { _classCallCheck(this, TextControl); if (_Control != null) { _Control.apply(this, arguments); } } _inherits(TextControl, _Control); _createClass(TextControl, [{ key: 'init', /** * Entry point for this control */ value: function init() { var controlsTemplate = function(it /**/) { var out='
    ';var arr1=it.fonts;if(arr1){var value,index=-1,l1=arr1.length-1;while(index ';} } out+='
'+( it.partials.fgColorPicker)+'
'+( it.partials.bgColorPicker)+'
'+( it.partials.doneButton);return out; }; this._controlsTemplate = controlsTemplate; var canvasControlsTemplate = function(it /**/) { var out='
';return out; }; this._canvasControlsTemplate = canvasControlsTemplate; this._partialTemplates.fgColorPicker = _libColorPicker2['default'].template; this._partialTemplates.fgColorPicker.additionalContext = { id: 'imglykit-text-foreground-color-picker' }; this._partialTemplates.bgColorPicker = _libColorPicker2['default'].template; this._partialTemplates.bgColorPicker.additionalContext = { id: 'imglykit-text-background-color-picker' }; this._fonts = []; this._addFonts(); } }, { key: '_renderControls', value: function _renderControls() { this._partialTemplates.fgColorPicker.additionalContext.label = this._ui.translate('controls.text.foreground'); this._partialTemplates.bgColorPicker.additionalContext.label = this._ui.translate('controls.text.background'); _get(Object.getPrototypeOf(TextControl.prototype), '_renderControls', this).call(this); } }, { key: '_onEnter', /** * Gets called when this control is activated * @override */ value: function _onEnter() { var _this = this; this._operationExistedBefore = !!this._ui.operations.text; this._operation = this._ui.getOrCreateOperation('text'); // Don't render initially this._ui.removeOperation('text'); var canvasSize = this._ui.canvas.size; this._initialSettings = { lineHeight: this._operation.getLineHeight(), fontSize: this._operation.getFontSize(), fontFamily: this._operation.getFontFamily(), fontWeight: this._operation.getFontWeight(), color: this._operation.getColor(), position: this._operation.getPosition(), text: this._operation.getText() || '', maxWidth: this._operation.getMaxWidth(), backgroundColor: this._operation.getBackgroundColor() }; this._settings = { lineHeight: this._initialSettings.lineHeight, fontSize: this._initialSettings.fontSize, fontFamily: this._initialSettings.fontFamily, fontWeight: this._initialSettings.fontWeight, color: this._initialSettings.color.clone(), position: this._initialSettings.position.clone().multiply(canvasSize), text: this._initialSettings.text, maxWidth: this._initialSettings.maxWidth * canvasSize.x, backgroundColor: this._initialSettings.backgroundColor.clone() }; // Remember zoom level and zoom to fit the canvas this._initialZoomLevel = this._ui.canvas.zoomLevel; this._container = this._canvasControls.querySelector('.imglykit-canvas-text'); this._textarea = this._canvasControls.querySelector('textarea'); this._textarea.focus(); this._moveKnob = this._canvasControls.querySelector('.imglykit-crosshair'); this._resizeKnob = this._canvasControls.querySelector('.imglykit-knob'); // If the text has been edited before, subtract the knob width and padding if (this._operationExistedBefore) { this._settings.position.x -= 2; this._settings.position.y -= 2; } this._onTextareaKeyUp = this._onTextareaKeyUp.bind(this); this._onResizeKnobDown = this._onResizeKnobDown.bind(this); this._onResizeKnobDrag = this._onResizeKnobDrag.bind(this); this._onResizeKnobUp = this._onResizeKnobUp.bind(this); this._onMoveKnobDown = this._onMoveKnobDown.bind(this); this._onMoveKnobDrag = this._onMoveKnobDrag.bind(this); this._onMoveKnobUp = this._onMoveKnobUp.bind(this); this._onForegroundColorUpdate = this._onForegroundColorUpdate.bind(this); this._onBackgroundColorUpdate = this._onBackgroundColorUpdate.bind(this); this._initColorPickers(); this._renderListItems(); this._handleListItems(); this._handleTextarea(); this._handleResizeKnob(); this._handleMoveKnob(); // Resize asynchronously to render a frame setTimeout(function () { _this._resizeTextarea(); }, 1); this._ui.canvas.zoomToFit().then(function () { _this._applySettings(); }); } }, { key: '_initColorPickers', /** * Initializes the color pickers * @private */ value: function _initColorPickers() { var _this2 = this; var foregroundColorPicker = this._controls.querySelector('#imglykit-text-foreground-color-picker'); this._foregroundColorPicker = new _libColorPicker2['default'](this._ui, foregroundColorPicker); this._foregroundColorPicker.setValue(this._operation.getColor()); this._foregroundColorPicker.on('update', this._onForegroundColorUpdate); this._foregroundColorPicker.on('show', function () { _this2._backgroundColorPicker.hide(); }); var backgroundColorPicker = this._controls.querySelector('#imglykit-text-background-color-picker'); this._backgroundColorPicker = new _libColorPicker2['default'](this._ui, backgroundColorPicker); this._backgroundColorPicker.setValue(this._operation.getBackgroundColor()); this._backgroundColorPicker.on('update', this._onBackgroundColorUpdate); this._backgroundColorPicker.on('show', function () { _this2._foregroundColorPicker.hide(); }); } }, { key: '_renderListItems', /** * Renders the text on the list item canvas elements * @private */ value: function _renderListItems() { var canvasItems = this._controls.querySelectorAll('li canvas'); this._canvasItems = Array.prototype.slice.call(canvasItems); for (var i = 0; i < this._canvasItems.length; i++) { var canvas = this._canvasItems[i]; canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; var listItem = canvas.parentNode; var context = canvas.getContext('2d'); var fontFamily = listItem.dataset.name; var fontWeight = listItem.dataset.weight; context.font = '' + fontWeight + ' 30px ' + fontFamily; context.textBaseline = 'middle'; context.textAlign = 'center'; context.fillStyle = 'white'; context.fillText(fontFamily.substr(0, 2), canvas.width / 2, canvas.height / 2); } } }, { key: '_handleListItems', /** * Handles the list item click events * @private */ value: function _handleListItems() { var _this3 = this; var listItems = this._controls.querySelectorAll('li'); this._listItems = Array.prototype.slice.call(listItems); var _loop = function (i) { var listItem = _this3._listItems[i]; var name = listItem.dataset.name; listItem.addEventListener('click', function () { _this3._onListItemClick(listItem); }); if (!_this3._operationExistedBefore && i === 0 || _this3._operationExistedBefore && name === _this3._initialSettings.fontFamily) { _this3._onListItemClick(listItem, false); } }; // Listen to click events for (var i = 0; i < this._listItems.length; i++) { _loop(i); } } }, { key: '_handleTextarea', /** * Handles the text area key events * @private */ value: function _handleTextarea() { this._textarea.addEventListener('keyup', this._onTextareaKeyUp); } }, { key: '_onTextareaKeyUp', /** * Gets called when the user releases a key inside the text area * @private */ value: function _onTextareaKeyUp() { this._resizeTextarea(); this._settings.text = this._textarea.value; this._highlightDoneButton(); } }, { key: '_resizeTextarea', /** * Resizes the text area to fit the text inside of it * @private */ value: function _resizeTextarea() { var scrollTop = this._textarea.scrollTop; if (!scrollTop) { var _scrollHeight = undefined, height = undefined; do { _scrollHeight = this._textarea.scrollHeight; height = this._textarea.offsetHeight; this._textarea.style.height = '' + (height - 5) + 'px'; } while (_scrollHeight && _scrollHeight !== this._textarea.scrollHeight); } var scrollHeight = this._textarea.scrollHeight; this._textarea.style.height = '' + (scrollHeight + 20) + 'px'; } }, { key: '_handleMoveKnob', /** * Handles the move knob dragging * @private */ value: function _handleMoveKnob() { this._moveKnob.addEventListener('mousedown', this._onMoveKnobDown); this._moveKnob.addEventListener('touchstart', this._onMoveKnobDown); } }, { key: '_onMoveKnobDown', /** * Gets called when the user clicks the move knob * @private */ value: function _onMoveKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialPosition = this._settings.position.clone(); document.addEventListener('mousemove', this._onMoveKnobDrag); document.addEventListener('touchmove', this._onMoveKnobDrag); document.addEventListener('mouseup', this._onMoveKnobUp); document.addEventListener('tochend', this._onMoveKnobUp); } }, { key: '_onMoveKnobDrag', /** * Gets called when the user drags the move knob * @private */ value: function _onMoveKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.clone().subtract(this._initialMousePosition); var minPosition = new _libMathVector22['default'](0, 0); var containerSize = new _libMathVector22['default'](this._container.offsetWidth, this._container.offsetHeight); var maxPosition = canvasSize.clone().subtract(containerSize); var position = this._initialPosition.clone().add(diff).clamp(minPosition, maxPosition); this._settings.position = position; this._container.style.left = '' + position.x + 'px'; this._container.style.top = '' + position.y + 'px'; } }, { key: '_onMoveKnobUp', /** * Gets called when the user releases the move knob * @private */ value: function _onMoveKnobUp() { document.removeEventListener('mousemove', this._onMoveKnobDrag); document.removeEventListener('touchmove', this._onMoveKnobDrag); document.removeEventListener('mouseup', this._onMoveKnobUp); document.removeEventListener('touchend', this._onMoveKnobUp); } }, { key: '_handleResizeKnob', /** * Handles the resize knob dragging * @private */ value: function _handleResizeKnob() { this._resizeKnob.addEventListener('mousedown', this._onResizeKnobDown); this._resizeKnob.addEventListener('touchstart', this._onResizeKnobDown); } }, { key: '_onResizeKnobDown', /** * Gets called when the user clicks the resize knob * @param {Event} e * @private */ value: function _onResizeKnobDown(e) { e.preventDefault(); this._initialMousePosition = _libUtils2['default'].getEventPosition(e); this._initialMaxWidth = this._settings.maxWidth; document.addEventListener('mousemove', this._onResizeKnobDrag); document.addEventListener('touchmove', this._onResizeKnobDrag); document.addEventListener('mouseup', this._onResizeKnobUp); document.addEventListener('touchend', this._onResizeKnobUp); } }, { key: '_onResizeKnobDrag', /** * Gets called when the user drags the resize knob * @param {Event} e * @private */ value: function _onResizeKnobDrag(e) { e.preventDefault(); var canvasSize = this._ui.canvas.size; var mousePosition = _libUtils2['default'].getEventPosition(e); var diff = mousePosition.subtract(this._initialMousePosition); var position = this._settings.position.clone(); var maxWidthAllowed = canvasSize.x - position.x; var maxWidth = this._initialMaxWidth + diff.x; maxWidth = Math.max(100, Math.min(maxWidthAllowed, maxWidth)); this._settings.maxWidth = maxWidth; this._textarea.style.width = '' + maxWidth + 'px'; this._resizeTextarea(); } }, { key: '_onResizeKnobUp', /** * Gets called when the user releases the resize knob * @param {Event} e * @private */ value: function _onResizeKnobUp() { document.removeEventListener('mousemove', this._onResizeKnobDrag); document.removeEventListener('touchmove', this._onResizeKnobDrag); document.removeEventListener('mouseup', this._onResizeKnobUp); document.removeEventListener('touchend', this._onResizeKnobUp); } }, { key: '_onForegroundColorUpdate', /** * Gets called when the user selects another color using * the color picker. * @param {Color} value * @private */ value: function _onForegroundColorUpdate(value) { this._settings.color = value; this._applySettings(); this._highlightDoneButton(); } }, { key: '_onBackgroundColorUpdate', /** * Gets called when the user selects another color using * the color picker. * @param {Color} value * @private */ value: function _onBackgroundColorUpdate(value) { this._settings.backgroundColor = value; this._applySettings(); this._highlightDoneButton(); } }, { key: '_applySettings', /** * Styles the textarea to represent the current settings * @private */ value: function _applySettings() { var textarea = this._textarea; var settings = this._settings; var canvasSize = this._ui.canvas.size; var actualFontSize = settings.fontSize * canvasSize.y; this._container.style.left = '' + settings.position.x + 'px'; this._container.style.top = '' + settings.position.y + 'px'; textarea.value = settings.text; textarea.style.fontFamily = settings.fontFamily; textarea.style.fontSize = '' + actualFontSize + 'px'; textarea.style.fontWeight = settings.fontWeight; textarea.style.lineHeight = settings.lineHeight; textarea.style.color = settings.color.toRGBA(); textarea.style.backgroundColor = settings.backgroundColor.toRGBA(); textarea.style.width = '' + settings.maxWidth + 'px'; } }, { key: '_onListItemClick', /** * Gets called when the user clicked a list item * @private */ value: function _onListItemClick(item) { var manually = arguments[1] === undefined ? true : arguments[1]; this._deactivateAllItems(); var _item$dataset = item.dataset; var name = _item$dataset.name; var weight = _item$dataset.weight; this._settings.fontFamily = name; this._settings.fontWeight = weight; this._applySettings(); item.classList.add('imglykit-controls-item-active'); if (manually) { this._highlightDoneButton(); } } }, { key: '_deactivateAllItems', /** * Deactivates all list items * @private */ value: function _deactivateAllItems() { for (var i = 0; i < this._listItems.length; i++) { var listItem = this._listItems[i]; listItem.classList.remove('imglykit-controls-item-active'); } } }, { key: '_addFonts', /** * Adds the default fonts * @private */ value: function _addFonts() { this.addFont('Helvetica', 'normal'); this.addFont('Lucida Grande', 'normal'); this.addFont('Times New Roman', 'normal'); } }, { key: 'addFont', /** * Adds a font with the given name and weight * @param {String} name * @param {String} weight */ value: function addFont(name, weight) { this._fonts.push({ name: name, weight: weight }); } }, { key: '_onDone', /** * Gets called when the done button has been clicked * @override */ value: function _onDone() { var canvasSize = this._ui.canvas.size; var padding = new _libMathVector22['default'](2, 2); var position = this._settings.position.clone().add(padding).divide(canvasSize); this._ui.canvas.setZoomLevel(this._initialZoomLevel, false); this._operation = this._ui.getOrCreateOperation('text'); this._operation.set({ fontSize: this._settings.fontSize, fontFamily: this._settings.fontFamily, fontWeight: this._settings.fontWeight, color: this._settings.color, backgroundColor: this._settings.backgroundColor, position: position, text: this._settings.text, maxWidth: this._settings.maxWidth / canvasSize.x }); this._ui.canvas.render(); this._ui.addHistory(this, { fontFamily: this._initialSettings.fontFamily, fontWeight: this._initialSettings.fontWeight, color: this._initialSettings.color.clone(), backgroundColor: this._initialSettings.backgroundColor.clone(), position: this._initialSettings.position.clone(), text: this._initialSettings.text, maxWidth: this._initialSettings.maxWidth }, this._operationExistedBefore); } }, { key: '_onBack', /** * Gets called when the back button has been clicked * @override */ value: function _onBack() { if (this._operationExistedBefore) { this._operation = this._ui.getOrCreateOperation('text'); this._operation.set(this._initialSettings); } else { this._ui.removeOperation('text'); } this._ui.canvas.setZoomLevel(this._initialZoomLevel); } }, { key: 'context', /** * The data that is available to the template * @type {Object} * @override */ get: function () { var context = _get(Object.getPrototypeOf(TextControl.prototype), 'context', this); context.fonts = this._fonts; return context; } }]); return TextControl; })(_control2['default']); /** * A unique string that identifies this control. * @type {String} */ TextControl.prototype.identifier = 'text'; exports['default'] = TextControl; module.exports = exports['default']; /***/ }, /* 93 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _baseHelpers = __webpack_require__(100); var _baseHelpers2 = _interopRequireDefault(_baseHelpers); var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libScrollbar = __webpack_require__(80); var _libScrollbar2 = _interopRequireDefault(_libScrollbar); /** * To create an {@link ImglyKit.NightUI.Control} class of your own, call * this method and provide instance properties and functions. * @function */ var _libExtend = __webpack_require__(58); var _libExtend2 = _interopRequireDefault(_libExtend); var Control = (function (_EventEmitter) { function Control(kit, ui, operation) { _classCallCheck(this, Control); _get(Object.getPrototypeOf(Control.prototype), 'constructor', this).call(this); this._kit = kit; this._ui = ui; this._operation = operation; this._helpers = new _baseHelpers2['default'](this._kit, this._ui, this._ui.options); this._partialTemplates = { doneButton: function(it /**/) { var out='
';return out; } }; this._template = function(it /**/) { var out='
'+(it.partials.control)+'
';return out; }; this._active = false; this.init(); } _inherits(Control, _EventEmitter); _createClass(Control, [{ key: 'setContainers', /** * Sets the containers that the control will be rendered to * @param {DOMElement} controlsContainer * @param {DOMElement} canvasControlsContainer */ value: function setContainers(controlsContainer, canvasControlsContainer) { this._controlsContainer = controlsContainer; this._canvasControlsContainer = canvasControlsContainer; } }, { key: 'init', /** * The entry point for this control */ value: function init() {} }, { key: '_renderAllControls', /** * Renders the controls * @private */ value: function _renderAllControls() { this._renderControls(); this._renderCanvasControls(); this._initScrollbar(); } }, { key: '_renderControls', /** * Renders the controls * @private */ value: function _renderControls() { if (typeof this._controlsTemplate === 'undefined') { throw new Error('Control#_renderOverviewControls: Control needs to define this._controlsTemplate.'); } // Render the template var html = this._template(this._context); if (typeof this._controls !== 'undefined' && this._controls.parentNode !== null) { this._controls.parentNode.removeChild(this._controls); } // Create a wrapper this._controls = document.createElement('div'); this._controls.innerHTML = html; // Append to DOM this._controlsContainer.appendChild(this._controls); } }, { key: '_renderCanvasControls', /** * Renders the canvas controls * @private */ value: function _renderCanvasControls() { if (typeof this._canvasControlsTemplate === 'undefined') { return; // Canvas controls are optional } // Render the template var html = this._canvasControlsTemplate(this._context); // Create a wrapper this._canvasControls = document.createElement('div'); this._canvasControls.innerHTML = html; // Append to DOM this._canvasControlsContainer.appendChild(this._canvasControls); } }, { key: '_initScrollbar', /** * Initializes the custom scrollbar * @private */ value: function _initScrollbar() { var list = this._controls.querySelector('.imglykit-controls-list'); if (list) { this._scrollbar = new _libScrollbar2['default'](list.parentNode); } } }, { key: '_removeControls', /** * Removes the controls from the DOM * @private */ value: function _removeControls() { this._controls.parentNode.removeChild(this._controls); if (this._canvasControls) { this._canvasControls.parentNode.removeChild(this._canvasControls); } if (this._scrollbar) this._scrollbar.remove(); } }, { key: '_handleBackAndDoneButtons', /** * Handles the back and done buttons * @private */ value: function _handleBackAndDoneButtons() { // Back button this._backButton = this._controls.querySelector('.imglykit-controls-back'); if (this._backButton) { this._backButton.addEventListener('click', this._onBackButtonClick.bind(this)); } // Done button this._doneButton = this._controls.querySelector('.imglykit-controls-done'); if (this._doneButton) { this._doneButton.addEventListener('click', this._onDoneButtonClick.bind(this)); } } }, { key: '_onBackButtonClick', /** * Gets called when the back button has been clicked * @private */ value: function _onBackButtonClick() { this._onBack(); this.emit('back'); } }, { key: '_onDoneButtonClick', /** * Gets called when the done button has been clicked * @private */ value: function _onDoneButtonClick() { this._onDone(); this.emit('back'); } }, { key: '_highlightDoneButton', /** * Highlights the done button * @private */ value: function _highlightDoneButton() { this._doneButton.classList.add('highlighted'); } }, { key: 'enter', /** * Gets called when this control is activated * @internal Used by the SDK, don't override. */ value: function enter() { this._active = true; this._ui.hideZoom(); this._renderAllControls(); this._handleBackAndDoneButtons(); this._enableCanvasControls(); this._onEnter(); } }, { key: 'leave', /** * Gets called when this control is deactivated * @internal Used by the SDK, don't override. */ value: function leave() { this._active = false; this._ui.showZoom(); this._removeControls(); this._disableCanvasControls(); this._onLeave(); } }, { key: '_enableCanvasControls', value: function _enableCanvasControls() { this._canvasControlsContainer.classList.remove('imglykit-canvas-controls-disabled'); } }, { key: '_disableCanvasControls', value: function _disableCanvasControls() { this._canvasControlsContainer.classList.add('imglykit-canvas-controls-disabled'); } }, { key: '_onEnter', // Protected methods /** * Gets called when this control is activated. * @protected */ value: function _onEnter() {} }, { key: '_onLeave', /** * Gets called when this control is deactivated * @protected */ value: function _onLeave() {} }, { key: '_onBack', /** * Gets called when the back button has been clicked * @protected */ value: function _onBack() {} }, { key: '_onDone', /** * Gets called when the done button has been clicked * @protected */ value: function _onDone() {} }, { key: 'onZoom', /** * Gets called when the zoom level has been changed while * this control is active */ value: function onZoom() {} }, { key: '_context', /** * The data that is available to the template * @type {Object} */ get: function () { var context = this.context; context = _libUtils2['default'].extend(context, { helpers: this._helpers, identifier: this.identifier }); // Render partials before rendering control context.partials = {}; for (var _name in this._partialTemplates) { var template = this._partialTemplates[_name]; var partialContext = _libUtils2['default'].extend({}, context, template.additionalContext || {}); context.partials[_name] = template(partialContext); } context.partials.control = this._controlsTemplate(context); return context; } }, { key: 'context', /** * The data that is available to the template * @abstract */ get: function () { return {}; } }]); return Control; })(_libEventEmitter2['default']); /** * A unique string that identifies this control. * @type {String} */ Control.prototype.identifier = null; Control.extend = _libExtend2['default']; exports['default'] = Control; module.exports = exports['default']; /***/ }, /* 94 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "operations": { "brightness": "Brightness", "contrast": "Contrast", "filters": "Filters", "flip": "Flip", "frames": "Frames", "radial-blur": "Radial Blur", "rotation": "Rotation", "saturation": "Saturation", "stickers": "Stickers", "text": "Text", "tilt-shift": "Tilt-Shift", "crop": "Crop" }, "top-controls": { "new": "New", "undo": "Undo", "export": "Export", "zoom": "Zoom" }, "splash": { "upload": { "headline": "Upload a picture", "description": "Click here to upload a picture from your library or just drag and drop" }, "or": "or", "webcam": { "headline": "Take a picture", "description": "Click here to take a picture with your webcam or phone" } }, "generic": { "loading": "Loading", "exporting": "Exporting", "color": "Color" }, "controls": { "frames": { "color": "Color" }, "text": { "foreground": "Foreground", "background": "Background" } } } /***/ }, /* 95 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "operations": { "brightness": "Helligkeit", "contrast": "Kontrast", "filters": "Filter", "flip": "Spiegeln", "frames": "Rahmen", "radial-blur": "Radial Blur", "rotation": "Drehung", "saturation": "Sättigung", "stickers": "Sticker", "text": "Text", "tilt-shift": "Tilt-Shift", "crop": "Zuschneiden" }, "top-controls": { "new": "Neu", "undo": "Rückgängig", "export": "Exportieren", "zoom": "Zoom" }, "splash": { "upload": { "headline": "Bild hochladen", "description": "Klicke hier, um ein Bild hochzuladen oder ziehe eine Bilddatei hier her" }, "or": "oder", "webcam": { "headline": "Foto machen", "description": "Klicke hier, um ein Foto mit deiner Webcam oder deinem Smartphone zu machen" } }, "generic": { "loading": "Laden", "exporting": "Exportiere" }, "controls": { "frames": { "color": "Farbe" }, "text": { "foreground": "Text", "background": "Hintergrund" } } } /***/ }, /* 96 */ /***/ function(module, exports, __webpack_require__) { /*jshint unused:false */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); /** * @class * @alias ImglyKit.Renderer * @param {Vector2} dimensions * @private */ var Renderer = (function (_EventEmitter) { function Renderer(dimensions, canvas) { _classCallCheck(this, Renderer); _get(Object.getPrototypeOf(Renderer.prototype), 'constructor', this).call(this); /** * @type {Canvas} * @private */ this._canvas = canvas || this.createCanvas(); if (!canvas) { this.setSize(dimensions); } /** * @type {RenderingContext} * @private */ this._context = this._getContext(); /** * The texture / image data cache * @type {Object.} */ this._cache = {}; } _inherits(Renderer, _EventEmitter); _createClass(Renderer, [{ key: 'cache', /** * Caches the current canvas content for the given identifier * @param {String} identifier */ value: function cache(identifier) {} }, { key: 'drawCached', /** * Draws the stored texture / image data for the given identifier * @param {String} identifier */ value: function drawCached(identifier) {} }, { key: 'createCanvas', /** * Creates a new canvas * @param {Number} [width] * @param {Number} [height] * @return {Canvas} * @private */ value: function createCanvas(width, height) { var isBrowser = typeof window !== 'undefined'; var canvas; if (isBrowser) { /* istanbul ignore next */ canvas = document.createElement('canvas'); } else { var Canvas = __webpack_require__(52); canvas = new Canvas(); } // Apply width if (typeof width !== 'undefined') { canvas.width = width; } // Apply height if (typeof height !== 'undefined') { canvas.height = height; } return canvas; } }, { key: 'getSize', /** * Returns the current size of the canvas * @return {Vector2} */ value: function getSize() { return new _libMathVector22['default'](this._canvas.width, this._canvas.height); } }, { key: 'setSize', /** * Sets the canvas dimensions * @param {Vector2} dimensions */ value: function setSize(dimensions) { this._canvas.width = dimensions.x; this._canvas.height = dimensions.y; } }, { key: '_getContext', /** * Gets the rendering context from the Canva * @return {RenderingContext} * @abstract */ value: function _getContext() { /* istanbul ignore next */ throw new Error('Renderer#_getContext is abstract and not implemented in inherited class.'); } }, { key: 'resizeTo', /** * Resizes the current canvas picture to the given dimensions * @param {Vector2} dimensions * @return {Promise} * @abstract */ value: function resizeTo(dimensions) { /* istanbul ignore next */ throw new Error('Renderer#resizeTo is abstract and not implemented in inherited class.'); } }, { key: 'drawImage', /** * Draws the given image on the canvas * @param {Image} image * @abstract */ value: function drawImage(image) { /* istanbul ignore next */ throw new Error('Renderer#drawImage is abstract and not implemented in inherited class.'); } }, { key: 'renderFinal', /** * Gets called after the stack has been rendered * @param {Image} image */ value: function renderFinal() {} }, { key: 'getCanvas', /** * Returns the canvas * @return {Canvas} */ value: function getCanvas() { return this._canvas; } }, { key: 'getContext', /** * Returns the context * @return {RenderingContext} */ value: function getContext() { return this._context; } }, { key: 'setCanvas', /** * Sets the current canvas to the given one * @param {Canvas} canvas */ value: function setCanvas(canvas) { this._canvas = canvas; this._context = this._getContext(); this.emit('new-canvas', this._canvas); } }, { key: 'setContext', /** * Sets the current context to the given one * @param {RenderingContext2D} context */ value: function setContext(context) { this._context = context; } }, { key: 'reset', /** * Resets the renderer * @param {Boolean} resetCache = false */ value: function reset() { var resetCache = arguments[0] === undefined ? false : arguments[0]; } }, { key: 'identifier', /** * A unique string that identifies this renderer * @type {String} */ get: function () { return null; } }], [{ key: 'isSupported', /** * Checks whether this type of renderer is supported in the current environment * @abstract * @returns {boolean} */ value: function isSupported() { /* istanbul ignore next */ throw new Error('Renderer#isSupported is abstract and not implemented in inherited class.'); } }]); return Renderer; })(_libEventEmitter2['default']); exports['default'] = Renderer; module.exports = exports['default']; /***/ }, /* 97 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com * * Extracted from MinifyJpeg (Copyright (c) 2014 Hiroaki Matoba, MIT License): * https://github.com/hMatoba/MinifyJpeg */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; exports['default'] = { encode: function encode(input) { var output = '', chr1 = undefined, chr2 = undefined, chr3 = '', enc1 = undefined, enc2 = undefined, enc3 = undefined, enc4 = '', i = 0; do { chr1 = input[i++]; chr2 = input[i++]; chr3 = input[i++]; enc1 = chr1 >> 2; enc2 = (chr1 & 3) << 4 | chr2 >> 4; enc3 = (chr2 & 15) << 2 | chr3 >> 6; enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + KEY_STR.charAt(enc1) + KEY_STR.charAt(enc2) + KEY_STR.charAt(enc3) + KEY_STR.charAt(enc4); chr1 = chr2 = chr3 = ''; enc1 = enc2 = enc3 = enc4 = ''; } while (i < input.length); return output; }, decode: function decode(input) { var chr1 = undefined, chr2 = undefined, chr3 = '', enc1 = undefined, enc2 = undefined, enc3 = undefined, enc4 = '', i = 0, buf = []; // remove all characters that are not A-Z, a-z, 0-9, +, /, or = var base64test = /[^A-Za-z0-9\+\/\=]/g; if (base64test.exec(input)) { throw new Error('There were invalid base64 characters in the input text.\n' + 'Valid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\n' + 'Expect errors in decoding.'); } input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); do { enc1 = KEY_STR.indexOf(input.charAt(i++)); enc2 = KEY_STR.indexOf(input.charAt(i++)); enc3 = KEY_STR.indexOf(input.charAt(i++)); enc4 = KEY_STR.indexOf(input.charAt(i++)); chr1 = enc1 << 2 | enc2 >> 4; chr2 = (enc2 & 15) << 4 | enc3 >> 2; chr3 = (enc3 & 3) << 6 | enc4; buf.push(chr1); if (enc3 !== 64) { buf.push(chr2); } if (enc4 !== 64) { buf.push(chr3); } chr1 = chr2 = chr3 = ''; enc1 = enc2 = enc3 = enc4 = ''; } while (i < input.length); return buf; } }; module.exports = exports['default']; /***/ }, /* 98 */ /***/ function(module, exports, __webpack_require__) { /* jshint unused: false */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ /** * Base class for primitives. Extendable via {@link ImglyKit.Filter.Primitive#extend} * @class * @alias ImglyKit.Filter.Primitive */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Primitive = (function () { function Primitive(options) { _classCallCheck(this, Primitive); options = options || {}; this._glslPrograms = {}; this._options = options; } _createClass(Primitive, [{ key: 'render', /** * Renders the primitive * @param {Renderer} renderer * @return {Promise} */ value: function render(renderer) { if (renderer.identifier === 'webgl') { this.renderWebGL(renderer); } else { this.renderCanvas(renderer); } } }, { key: 'renderWebGL', /** * Renders the primitive (WebGL) * @param {CanvasRenderer} renderer */ /* istanbul ignore next */ value: function renderWebGL(renderer) { /* istanbul ignore next */ throw new Error('Primitive#renderWebGL is abstract and not implemented in inherited class.'); } }, { key: 'renderCanvas', /** * Renders the primitive (Canvas2D) * @param {CanvasRenderer} renderer */ value: function renderCanvas(renderer) { /* istanbul ignore next */ throw new Error('Primitive#renderCanvas is abstract and not implemented in inherited class.'); } }, { key: 'options', get: function () { return this._options; } }]); return Primitive; })(); exports['default'] = Primitive; module.exports = exports['default']; /***/ }, /* 99 */ /***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, setImmediate) {/*! * Native Promise Only * v0.8.0-a (c) Kyle Simpson * MIT License: http://getify.mit-license.org * @license */ "use strict"; (function UMD(name, context, definition) { // special form of UMD for polyfilling across evironments context[name] = context[name] || definition(); if (typeof module != "undefined" && module.exports) { module.exports = context[name]; } else if (true) { !(__WEBPACK_AMD_DEFINE_RESULT__ = function $AMD$() { return context[name]; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } })("Promise", typeof global != "undefined" ? global : undefined, function DEF() { /*jshint validthis:true */ "use strict"; var builtInProp, cycle, scheduling_queue, ToString = Object.prototype.toString, timer = typeof setImmediate != "undefined" ? function timer(fn) { return setImmediate(fn); } : setTimeout; // dammit, IE8. try { Object.defineProperty({}, "x", {}); builtInProp = function builtInProp(obj, name, val, config) { return Object.defineProperty(obj, name, { value: val, writable: true, configurable: config !== false }); }; } catch (err) { builtInProp = function builtInProp(obj, name, val) { obj[name] = val; return obj; }; } // Note: using a queue instead of array for efficiency scheduling_queue = (function Queue() { var first, last, item; function Item(fn, self) { this.fn = fn; this.self = self; this.next = void 0; } return { add: function add(fn, self) { item = new Item(fn, self); if (last) { last.next = item; } else { first = item; } last = item; item = void 0; }, drain: function drain() { var f = first; first = last = cycle = void 0; while (f) { f.fn.call(f.self); f = f.next; } } }; })(); function schedule(fn, self) { scheduling_queue.add(fn, self); if (!cycle) { cycle = timer(scheduling_queue.drain); } } // promise duck typing function isThenable(o) { var _then, o_type = typeof o; if (o != null && (o_type == "object" || o_type == "function")) { _then = o.then; } return typeof _then == "function" ? _then : false; } function notify() { for (var i = 0; i < this.chain.length; i++) { notifyIsolated(this, this.state === 1 ? this.chain[i].success : this.chain[i].failure, this.chain[i]); } this.chain.length = 0; } // NOTE: This is a separate function to isolate // the `try..catch` so that other code can be // optimized better function notifyIsolated(self, cb, chain) { var ret, _then; try { if (cb === false) { chain.reject(self.msg); } else { if (cb === true) { ret = self.msg; } else { ret = cb.call(void 0, self.msg); } if (ret === chain.promise) { chain.reject(TypeError("Promise-chain cycle")); } else if (_then = isThenable(ret)) { _then.call(ret, chain.resolve, chain.reject); } else { chain.resolve(ret); } } } catch (err) { chain.reject(err); } } function resolve(msg) { var _then, self = this; // already triggered? if (self.triggered) { return; } self.triggered = true; // unwrap if (self.def) { self = self.def; } try { if (_then = isThenable(msg)) { schedule(function () { var def_wrapper = new MakeDefWrapper(self); try { _then.call(msg, function $resolve$() { resolve.apply(def_wrapper, arguments); }, function $reject$() { reject.apply(def_wrapper, arguments); }); } catch (err) { reject.call(def_wrapper, err); } }); } else { self.msg = msg; self.state = 1; if (self.chain.length > 0) { schedule(notify, self); } } } catch (err) { reject.call(new MakeDefWrapper(self), err); } } function reject(msg) { var self = this; // already triggered? if (self.triggered) { return; } self.triggered = true; // unwrap if (self.def) { self = self.def; } self.msg = msg; self.state = 2; if (self.chain.length > 0) { schedule(notify, self); } } function iteratePromises(Constructor, arr, resolver, rejecter) { for (var idx = 0; idx < arr.length; idx++) { (function IIFE(idx) { Constructor.resolve(arr[idx]).then(function $resolver$(msg) { resolver(idx, msg); }, rejecter); })(idx); } } function MakeDefWrapper(self) { this.def = self; this.triggered = false; } function MakeDef(self) { this.promise = self; this.state = 0; this.triggered = false; this.chain = []; this.msg = void 0; } function Promise(executor) { if (typeof executor != "function") { throw TypeError("Not a function"); } if (this.__NPO__ !== 0) { throw TypeError("Not a promise"); } // instance shadowing the inherited "brand" // to signal an already "initialized" promise this.__NPO__ = 1; var def = new MakeDef(this); this["then"] = function then(success, failure) { var o = { success: typeof success == "function" ? success : true, failure: typeof failure == "function" ? failure : false }; // Note: `then(..)` itself can be borrowed to be used against // a different promise constructor for making the chained promise, // by substituting a different `this` binding. o.promise = new this.constructor(function extractChain(resolve, reject) { if (typeof resolve != "function" || typeof reject != "function") { throw TypeError("Not a function"); } o.resolve = resolve; o.reject = reject; }); def.chain.push(o); if (def.state !== 0) { schedule(notify, def); } return o.promise; }; this["catch"] = function $catch$(failure) { return this.then(void 0, failure); }; try { executor.call(void 0, function publicResolve(msg) { resolve.call(def, msg); }, function publicReject(msg) { reject.call(def, msg); }); } catch (err) { reject.call(def, err); } } var PromisePrototype = builtInProp({}, "constructor", Promise, /*configurable=*/false); // Note: Android 4 cannot use `Object.defineProperty(..)` here Promise.prototype = PromisePrototype; // built-in "brand" to signal an "uninitialized" promise builtInProp(PromisePrototype, "__NPO__", 0, /*configurable=*/false); builtInProp(Promise, "resolve", function Promise$resolve(msg) { var Constructor = this; // spec mandated checks // note: best "isPromise" check that's practical for now if (msg && typeof msg == "object" && msg.__NPO__ === 1) { return msg; } return new Constructor(function executor(resolve, reject) { if (typeof resolve != "function" || typeof reject != "function") { throw TypeError("Not a function"); } resolve(msg); }); }); builtInProp(Promise, "reject", function Promise$reject(msg) { return new this(function executor(resolve, reject) { if (typeof resolve != "function" || typeof reject != "function") { throw TypeError("Not a function"); } reject(msg); }); }); builtInProp(Promise, "all", function Promise$all(arr) { var Constructor = this; // spec mandated checks if (ToString.call(arr) != "[object Array]") { return Constructor.reject(TypeError("Not an array")); } if (arr.length === 0) { return Constructor.resolve([]); } return new Constructor(function executor(resolve, reject) { if (typeof resolve != "function" || typeof reject != "function") { throw TypeError("Not a function"); } var len = arr.length, msgs = Array(len), count = 0; iteratePromises(Constructor, arr, function resolver(idx, msg) { msgs[idx] = msg; if (++count === len) { resolve(msgs); } }, reject); }); }); builtInProp(Promise, "race", function Promise$race(arr) { var Constructor = this; // spec mandated checks if (ToString.call(arr) != "[object Array]") { return Constructor.reject(TypeError("Not an array")); } return new Constructor(function executor(resolve, reject) { if (typeof resolve != "function" || typeof reject != "function") { throw TypeError("Not a function"); } iteratePromises(Constructor, arr, function resolver(idx, msg) { resolve(msg); }, reject); }); }); return Promise; }); /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(104).setImmediate)) /***/ }, /* 100 */ /***/ function(module, exports, __webpack_require__) { /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var Helpers = (function () { function Helpers(kit, ui, options) { _classCallCheck(this, Helpers); this._kit = kit; this._ui = ui; this._options = options; } _createClass(Helpers, [{ key: 'assetPath', value: function assetPath(asset) { var path = this._options.assetsUrl + '/' + asset; var assetPathResolver = this._ui.options.ui.assetPathResolver; if (typeof assetPathResolver !== 'undefined') { path = assetPathResolver(path); } return path; } }, { key: 'translate', value: function translate(key) { return this._ui.translate(key); } }]); return Helpers; })(); exports['default'] = Helpers; module.exports = exports['default']; /***/ }, /* 101 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 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) subClass.__proto__ = superClass; } var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var Slider = (function (_EventEmitter) { function Slider(element, options) { _classCallCheck(this, Slider); _get(Object.getPrototypeOf(Slider.prototype), 'constructor', this).call(this); this._element = element; this._options = _libUtils2['default'].defaults(options, { minValue: 0, maxValue: 1, defaultValue: 0 }); this._value = this._options.defaultValue; this._sliderElement = this._element.querySelector('.imglykit-slider-slider'); this._dotElement = this._element.querySelector('.imglykit-slider-dot'); this._centerDotElement = this._element.querySelector('.imglykit-slider-center-dot'); this._fillElement = this._element.querySelector('.imglykit-slider-fill'); this._backgroundElement = this._element.querySelector('.imglykit-slider-background'); // Mouse event callbacks bound to class context this._onMouseDown = this._onMouseDown.bind(this); this._onMouseMove = this._onMouseMove.bind(this); this._onMouseUp = this._onMouseUp.bind(this); this._onCenterDotClick = this._onCenterDotClick.bind(this); this._onBackgroundClick = this._onBackgroundClick.bind(this); this._backgroundElement.addEventListener('click', this._onBackgroundClick); this._fillElement.addEventListener('click', this._onBackgroundClick); this._handleDot(); } _inherits(Slider, _EventEmitter); _createClass(Slider, [{ key: 'setValue', /** * Sets the given value * @param {Number} value */ value: function setValue(value) { this._value = value; var _options = this._options; var maxValue = _options.maxValue; var minValue = _options.minValue; // Calculate the X position var valueRange = maxValue - minValue; var percentage = (value - minValue) / valueRange; var sliderWidth = this._sliderElement.offsetWidth; this._setX(sliderWidth * percentage); } }, { key: '_setX', /** * Sets the slider position to the given X value and resizes * the fill div * @private */ value: function _setX(x) { this._xPosition = x; this._dotElement.style.left = '' + x + 'px'; // X position relative to center to simplify calculations var halfSliderWidth = this._sliderElement.offsetWidth / 2; var relativeX = x - halfSliderWidth; // Update style this._fillElement.style.width = '' + Math.abs(relativeX) + 'px'; if (relativeX < 0) { this._fillElement.style.left = halfSliderWidth - Math.abs(relativeX) + 'px'; } else { this._fillElement.style.left = halfSliderWidth + 'px'; } } }, { key: '_handleDot', /** * Handles the dot dragging * @private */ value: function _handleDot() { this._dotElement.addEventListener('mousedown', this._onMouseDown); this._dotElement.addEventListener('touchstart', this._onMouseDown); if (this._centerDotElement) { this._centerDotElement.addEventListener('click', this._onCenterDotClick); } } }, { key: '_onCenterDotClick', /** * Gets called when the user clicks the center button. Resets to default * settings. * @private */ value: function _onCenterDotClick() { this.setValue(this._options.defaultValue); this.emit('update', this._value); } }, { key: '_onBackgroundClick', /** * Gets called when the user clicks on the slider background * @param {Event} e * @private */ value: function _onBackgroundClick(e) { var position = _libUtils2['default'].getEventPosition(e); var sliderOffset = this._sliderElement.getBoundingClientRect(); sliderOffset = new _libMathVector22['default'](sliderOffset.left, sliderOffset.y); var relativePosition = position.clone().subtract(sliderOffset); this._setX(relativePosition.x); this._updateValue(); } }, { key: '_onMouseDown', /** * Gets called when the user presses a mouse button on the slider dot * @private */ value: function _onMouseDown(e) { if (e.type === 'mousedown' && e.button !== 0) return; e.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(e); document.addEventListener('mousemove', this._onMouseMove); document.addEventListener('touchmove', this._onMouseMove); document.addEventListener('mouseup', this._onMouseUp); document.addEventListener('touchend', this._onMouseUp); // Remember initial position var dotPosition = this._dotElement.getBoundingClientRect(); var sliderPosition = this._sliderElement.getBoundingClientRect(); this._initialSliderX = dotPosition.left - sliderPosition.left; this._initialMousePosition = mousePosition; } }, { key: '_onMouseMove', /** * Gets called when the user drags the mouse * @private */ value: function _onMouseMove(e) { e.preventDefault(); var mousePosition = _libUtils2['default'].getEventPosition(e); var mouseDiff = mousePosition.subtract(this._initialMousePosition); // Add half width of the dot for negative margin compensation var halfDotWidth = this._dotElement.offsetWidth * 0.5; var newSliderX = this._initialSliderX + mouseDiff.x + halfDotWidth; // X boundaries var sliderWidth = this._sliderElement.offsetWidth; newSliderX = Math.max(0, Math.min(newSliderX, sliderWidth)); this._setX(newSliderX); this._updateValue(); } }, { key: '_updateValue', /** * Updates the value using the slider position * @private */ value: function _updateValue() { var sliderWidth = this._sliderElement.offsetWidth; // Calculate the new value var _options2 = this._options; var minValue = _options2.minValue; var maxValue = _options2.maxValue; var percentage = this._xPosition / sliderWidth; var value = minValue + (maxValue - minValue) * percentage; this.emit('update', value); } }, { key: '_onMouseUp', /** * Gets called when the user does not press the mouse button anymore * @private */ value: function _onMouseUp() { document.removeEventListener('mousemove', this._onMouseMove); document.removeEventListener('touchmove', this._onMouseMove); document.removeEventListener('mouseup', this._onMouseUp); document.removeEventListener('touchend', this._onMouseUp); } }], [{ key: 'template', /** * The partial template string * @type {String} */ get: function () { return function(it /**/) { var out='
';return out; }; } }]); return Slider; })(_libEventEmitter2['default']); exports['default'] = Slider; module.exports = exports['default']; /***/ }, /* 102 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 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) subClass.__proto__ = superClass; } var _slider = __webpack_require__(101); var _slider2 = _interopRequireDefault(_slider); var SimpleSlider = (function (_Slider) { function SimpleSlider() { _classCallCheck(this, SimpleSlider); if (_Slider != null) { _Slider.apply(this, arguments); } } _inherits(SimpleSlider, _Slider); _createClass(SimpleSlider, [{ key: '_setX', /** * Sets the slider position to the given X value and resizes * the fill div * @private */ value: function _setX(x) { this._xPosition = x; this._dotElement.style.left = '' + x + 'px'; this._fillElement.style.width = '' + x + 'px'; } }], [{ key: 'template', /** * The partial template string * @type {String} */ get: function () { return function(it /**/) { var out='
';return out; }; } }]); return SimpleSlider; })(_slider2['default']); exports['default'] = SimpleSlider; module.exports = exports['default']; /***/ }, /* 103 */ /***/ function(module, exports, __webpack_require__) { /* global __DOTJS_TEMPLATE, Image */ /* * Photo Editor SDK - photoeditorsdk.com * Copyright (c) 2013-2015 9elements GmbH * * Released under Attribution-NonCommercial 3.0 Unported * http://creativecommons.org/licenses/by-nc/3.0/ * * For commercial use, please contact us at contact@9elements.com */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } } 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) subClass.__proto__ = superClass; } var _libEventEmitter = __webpack_require__(72); var _libEventEmitter2 = _interopRequireDefault(_libEventEmitter); var _libUtils = __webpack_require__(5); var _libUtils2 = _interopRequireDefault(_libUtils); var _libColor = __webpack_require__(6); var _libColor2 = _interopRequireDefault(_libColor); var _libMathVector2 = __webpack_require__(49); var _libMathVector22 = _interopRequireDefault(_libMathVector2); var ColorPicker = (function (_EventEmitter) { function ColorPicker(ui, element) { _classCallCheck(this, ColorPicker); _get(Object.getPrototypeOf(ColorPicker.prototype), 'constructor', this).call(this); this._ui = ui; this._element = element; this._visible = false; this._loaded = false; this._overlay = this._element.querySelector('.imglykit-color-picker-overlay'); this._currentColorCanvas = this._element.querySelector('.imglykit-color-picker-color'); this._alphaCanvas = this._element.querySelector('canvas.imglykit-color-picker-alpha'); this._alphaKnob = this._element.querySelector('.imglykit-color-picker-alpha-container .imglykit-transparent-knob'); this._hueCanvas = this._element.querySelector('canvas.imglykit-color-picker-hue'); this._hueKnob = this._element.querySelector('.imglykit-color-picker-hue-container .imglykit-transparent-knob'); this._saturationCanvas = this._element.querySelector('canvas.imglykit-color-picker-saturation'); this._saturationKnob = this._element.querySelector('.imglykit-color-picker-saturation-container .imglykit-transparent-knob'); this._transparencyImage = new Image(); this._transparencyImage.src = ui.helpers.assetPath('ui/night/transparency.png'); this._transparencyImage.addEventListener('load', this._onTransparencyImageLoad.bind(this)); this._onAlphaCanvasDown = this._onAlphaCanvasDown.bind(this); this._onAlphaCanvasDrag = this._onAlphaCanvasDrag.bind(this); this._onAlphaCanvasUp = this._onAlphaCanvasUp.bind(this); this._onHueCanvasDown = this._onHueCanvasDown.bind(this); this._onHueCanvasDrag = this._onHueCanvasDrag.bind(this); this._onHueCanvasUp = this._onHueCanvasUp.bind(this); this._onSaturationCanvasDown = this._onSaturationCanvasDown.bind(this); this._onSaturationCanvasDrag = this._onSaturationCanvasDrag.bind(this); this._onSaturationCanvasUp = this._onSaturationCanvasUp.bind(this); this._onElementClick = this._onElementClick.bind(this); this._handleToggle(); this._handleAlphaKnob(); this._handleHueKnob(); this._handleSaturationKnob(); } _inherits(ColorPicker, _EventEmitter); _createClass(ColorPicker, [{ key: '_onTransparencyImageLoad', value: function _onTransparencyImageLoad() { this._loaded = true; this._render(); } }, { key: '_handleToggle', /** * Handles the toggling of the overlay * @private */ value: function _handleToggle() { this._element.addEventListener('click', this._onElementClick); } }, { key: '_onElementClick', /** * Gets called when the element has been clicked * @param {Event} e * @private */ value: function _onElementClick(e) { if (e.target === this._element || e.target === this._currentColorCanvas) { if (this._visible) { this.hide(); this.emit('hide'); } else { this.show(); this.emit('show'); } } } }, { key: 'hide', /** * Hides the color picker */ value: function hide() { this._overlay.classList.remove('imglykit-visible'); this._visible = false; } }, { key: 'show', /** * Shows the color picker */ value: function show() { this._overlay.classList.add('imglykit-visible'); this._visible = true; } }, { key: 'setValue', /** * Sets the given value * @param {Number} value */ value: function setValue(value) { this._value = value.clone(); var _value$toHSV = this._value.toHSV(); var _value$toHSV2 = _slicedToArray(_value$toHSV, 3); var h = _value$toHSV2[0]; var s = _value$toHSV2[1]; var v = _value$toHSV2[2]; this._hsvColor = { h: h, s: s, v: v }; this._positionKnobs(); this._render(); } }, { key: '_positionKnobs', /** * Updates the knob positions to represent the current HSV color * @private */ value: function _positionKnobs() { this._positionAlphaKnob(); this._positionHueKnob(); this._positionSaturationKnob(); } }, { key: '_positionAlphaKnob', /** * Positions the alpha knob according to the current alpha value * @private */ value: function _positionAlphaKnob() { var canvas = this._alphaCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var left = this._value.a * canvasSize.x; this._alphaKnob.style.left = '' + left + 'px'; } }, { key: '_positionHueKnob', /** * Positions the hue knob according to the current hue value * @private */ value: function _positionHueKnob() { var canvas = this._hueCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var top = this._hsvColor.h * canvasSize.y; this._hueKnob.style.top = '' + top + 'px'; } }, { key: '_positionSaturationKnob', /** * Positions the saturation knob according to the current saturation value * @private */ value: function _positionSaturationKnob() { var canvas = this._saturationCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var left = this._hsvColor.s * canvasSize.x; this._saturationKnob.style.left = '' + left + 'px'; var top = (1 - this._hsvColor.v) * canvasSize.y; this._saturationKnob.style.top = '' + top + 'px'; } }, { key: '_render', /** * Updates and renders all controls to represent the current value * @private */ value: function _render() { if (!this._loaded) return; this._renderCurrentColor(); this._renderAlpha(); this._renderHue(); this._renderSaturation(); } }, { key: '_renderCurrentColor', /** * Renders the currently selected color on the controls canvas * @private */ value: function _renderCurrentColor() { var canvas = this._currentColorCanvas; var context = canvas.getContext('2d'); var pattern = context.createPattern(this._transparencyImage, 'repeat'); context.rect(0, 0, canvas.width, canvas.height); context.fillStyle = pattern; context.fill(); context.fillStyle = this._value.toRGBA(); context.fill(); } }, { key: '_renderAlpha', /** * Renders the transparency canvas with the current color * @private */ value: function _renderAlpha() { var canvas = this._alphaCanvas; var context = canvas.getContext('2d'); var pattern = context.createPattern(this._transparencyImage, 'repeat'); context.rect(0, 0, canvas.width, canvas.height); context.fillStyle = pattern; context.fill(); var gradient = context.createLinearGradient(0, 0, canvas.width, canvas.height); var color = this._value.clone(); color.a = 0; gradient.addColorStop(0, color.toRGBA()); gradient.addColorStop(1, this._value.toHex()); context.fillStyle = gradient; context.fill(); } }, { key: '_renderHue', /** * Renders the hue canvas * @private */ value: function _renderHue() { var canvas = this._hueCanvas; var context = canvas.getContext('2d'); var color = new _libColor2['default'](); for (var y = 0; y < canvas.height; y++) { var ratio = y / canvas.height; color.fromHSV(ratio, 1, 1); context.strokeStyle = color.toRGBA(); context.beginPath(); context.moveTo(0, y); context.lineTo(canvas.width, y); context.stroke(); } } }, { key: '_renderSaturation', /** * Renders the saturation canvas * @private */ value: function _renderSaturation() { var canvas = this._saturationCanvas; var context = canvas.getContext('2d'); var imageData = context.getImageData(0, 0, canvas.width, canvas.height); var color = new _libColor2['default'](1, 0, 0, 1); for (var y = 0; y < canvas.height; y++) { var value = (canvas.height - y) / canvas.height; for (var x = 0; x < canvas.width; x++) { var saturation = x / canvas.width; color.fromHSV(this._hsvColor.h, saturation, value); var r = color.r; var g = color.g; var b = color.b; var a = color.a; var index = (y * canvas.width + x) * 4; imageData.data[index] = r * 255; imageData.data[index + 1] = g * 255; imageData.data[index + 2] = b * 255; imageData.data[index + 3] = a * 255; } } context.putImageData(imageData, 0, 0); } }, { key: '_handleAlphaKnob', /** * Handles the dragging of the alpha knob * @private */ value: function _handleAlphaKnob() { this._alphaCanvas.addEventListener('mousedown', this._onAlphaCanvasDown); this._alphaCanvas.addEventListener('touchstart', this._onAlphaCanvasDown); } }, { key: '_onAlphaCanvasDown', /** * Gets called when the user clicks the alpha knob * @param {Event} e * @private */ value: function _onAlphaCanvasDown(e) { e.preventDefault(); this._onAlphaCanvasDrag(e); document.addEventListener('mousemove', this._onAlphaCanvasDrag); document.addEventListener('touchmove', this._onAlphaCanvasDrag); document.addEventListener('mouseup', this._onAlphaCanvasUp); document.addEventListener('touchend', this._onAlphaCanvasUp); } }, { key: '_onAlphaCanvasDrag', /** * Gets called when the user drags the alpha knob * @param {Event} e * @private */ value: function _onAlphaCanvasDrag(e) { e.preventDefault(); // Calculate relative mouse position on canvas var canvas = this._alphaCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); var mousePosition = _libUtils2['default'].getEventPosition(e); var _canvas$getBoundingClientRect = canvas.getBoundingClientRect(); var left = _canvas$getBoundingClientRect.left; var top = _canvas$getBoundingClientRect.top; var offset = new _libMathVector22['default'](left, top); var relativePosition = mousePosition.subtract(offset); relativePosition.clamp(new _libMathVector22['default'](0, 0), canvasSize); // Update knob css positioning this._alphaKnob.style.left = '' + relativePosition.x + 'px'; // Update alpha value this._value.a = relativePosition.x / canvasSize.x; this._updateColor(); } }, { key: '_onAlphaCanvasUp', /** * Gets called when the user stops dragging the alpha knob * @param {Event} e * @private */ value: function _onAlphaCanvasUp() { document.removeEventListener('mousemove', this._onAlphaCanvasDrag); document.removeEventListener('touchmove', this._onAlphaCanvasDrag); document.removeEventListener('mouseup', this._onAlphaCanvasUp); document.removeEventListener('touchend', this._onAlphaCanvasUp); } }, { key: '_handleHueKnob', /** * Handles the dragging of the hue knob * @private */ value: function _handleHueKnob() { this._hueCanvas.addEventListener('mousedown', this._onHueCanvasDown); this._hueCanvas.addEventListener('touchstart', this._onHueCanvasDown); } }, { key: '_onHueCanvasDown', /** * Gets called when the user clicks the canvas knob * @param {Event} e * @private */ value: function _onHueCanvasDown(e) { e.preventDefault(); this._onHueCanvasDrag(e); document.addEventListener('mousemove', this._onHueCanvasDrag); document.addEventListener('touchmove', this._onHueCanvasDrag); document.addEventListener('mouseup', this._onHueCanvasUp); document.addEventListener('touchend', this._onHueCanvasUp); } }, { key: '_onHueCanvasDrag', /** * Gets called when the user drags the hue knob * @param {Event} e * @private */ value: function _onHueCanvasDrag(e) { e.preventDefault(); var canvas = this._hueCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); // Calculate relative mouse position on canvas var mousePosition = _libUtils2['default'].getEventPosition(e); var _canvas$getBoundingClientRect2 = canvas.getBoundingClientRect(); var left = _canvas$getBoundingClientRect2.left; var top = _canvas$getBoundingClientRect2.top; var offset = new _libMathVector22['default'](left, top); var relativePosition = mousePosition.subtract(offset); relativePosition.clamp(new _libMathVector22['default'](0, 0), canvasSize); // Update saturaiton knob css positioning this._hueKnob.style.top = '' + relativePosition.y + 'px'; // Update saturation and value relativePosition.divide(canvasSize); this._hsvColor.h = relativePosition.y; this._updateColor(); } }, { key: '_onHueCanvasUp', /** * Gets called when the user stops dragging the alpha knob * @param {Event} e * @private */ value: function _onHueCanvasUp() { document.removeEventListener('mousemove', this._onHueCanvasDrag); document.removeEventListener('touchmove', this._onHueCanvasDrag); document.removeEventListener('mouseup', this._onHueCanvasUp); document.removeEventListener('touchend', this._onHueCanvasUp); } }, { key: '_handleSaturationKnob', /** * Handles the dragging of the saturation knob * @private */ value: function _handleSaturationKnob() { this._saturationCanvas.addEventListener('mousedown', this._onSaturationCanvasDown); this._saturationCanvas.addEventListener('touchstart', this._onSaturationCanvasDown); } }, { key: '_onSaturationCanvasDown', /** * Gets called when the user clicks the saturation canvas * @param {Event} e * @private */ value: function _onSaturationCanvasDown(e) { e.preventDefault(); this._onSaturationCanvasDrag(e); document.addEventListener('mousemove', this._onSaturationCanvasDrag); document.addEventListener('touchmove', this._onSaturationCanvasDrag); document.addEventListener('mouseup', this._onSaturationCanvasUp); document.addEventListener('touchend', this._onSaturationCanvasUp); } }, { key: '_onSaturationCanvasDrag', /** * Gets called when the user drags the saturation knob * @param {Event} e * @private */ value: function _onSaturationCanvasDrag(e) { e.preventDefault(); var canvas = this._saturationCanvas; var canvasSize = new _libMathVector22['default'](canvas.width, canvas.height); // Calculate relative mouse position on canvas var mousePosition = _libUtils2['default'].getEventPosition(e); var _canvas$getBoundingClientRect3 = canvas.getBoundingClientRect(); var left = _canvas$getBoundingClientRect3.left; var top = _canvas$getBoundingClientRect3.top; var offset = new _libMathVector22['default'](left, top); var relativePosition = mousePosition.subtract(offset); relativePosition.clamp(0, canvas.width); // Update saturaiton knob css positioning this._saturationKnob.style.left = '' + relativePosition.x + 'px'; this._saturationKnob.style.top = '' + relativePosition.y + 'px'; // Update saturation and value relativePosition.divide(canvasSize); this._hsvColor.s = relativePosition.x; this._hsvColor.v = 1 - relativePosition.y; this._updateColor(); } }, { key: '_onSaturationCanvasUp', /** * Gets called when the user stops dragging the saturation knob * @param {Event} e * @private */ value: function _onSaturationCanvasUp() { document.removeEventListener('mousemove', this._onSaturationCanvasDrag); document.removeEventListener('touchmove', this._onSaturationCanvasDrag); document.removeEventListener('mouseup', this._onSaturationCanvasUp); document.removeEventListener('touchend', this._onSaturationCanvasUp); } }, { key: '_updateColor', /** * Updates the attached color, emits the `update` event and triggers * a render * @private */ value: function _updateColor() { this._value.fromHSV(this._hsvColor.h, this._hsvColor.s, this._hsvColor.v); this.emit('update', this._value); this._render(); } }], [{ key: 'template', /** * The partial template string * @type {String} */ get: function () { return function(it /**/) { var out='
'+((typeof it.label === "undefined"?'':it.label))+'
';return out; }; } }]); return ColorPicker; })(_libEventEmitter2['default']); exports['default'] = ColorPicker; module.exports = exports['default']; /***/ }, /* 104 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(105).nextTick; var apply = Function.prototype.apply; var slice = Array.prototype.slice; var immediateIds = {}; var nextImmediateId = 0; // DOM APIs, for completeness exports.setTimeout = function() { return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); }; exports.setInterval = function() { return new Timeout(apply.call(setInterval, window, arguments), clearInterval); }; exports.clearTimeout = exports.clearInterval = function(timeout) { timeout.close(); }; function Timeout(id, clearFn) { this._id = id; this._clearFn = clearFn; } Timeout.prototype.unref = Timeout.prototype.ref = function() {}; Timeout.prototype.close = function() { this._clearFn.call(window, this._id); }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { clearTimeout(item._idleTimeoutId); item._idleTimeout = msecs; }; exports.unenroll = function(item) { clearTimeout(item._idleTimeoutId); item._idleTimeout = -1; }; exports._unrefActive = exports.active = function(item) { clearTimeout(item._idleTimeoutId); var msecs = item._idleTimeout; if (msecs >= 0) { item._idleTimeoutId = setTimeout(function onTimeout() { if (item._onTimeout) item._onTimeout(); }, msecs); } }; // That's not how node.js implements it but the exposed api is the same. exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { var id = nextImmediateId++; var args = arguments.length < 2 ? false : slice.call(arguments, 1); immediateIds[id] = true; nextTick(function onNextTick() { if (immediateIds[id]) { // fn.call() is faster so we optimize for the common use-case // @see http://jsperf.com/call-apply-segu if (args) { fn.apply(null, args); } else { fn.call(null); } // Prevent ids from leaking exports.clearImmediate(id); } }); return id; }; exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { delete immediateIds[id]; }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(104).setImmediate, __webpack_require__(104).clearImmediate)) /***/ }, /* 105 */ /***/ function(module, exports, __webpack_require__) { // shim for using process in browser var process = module.exports = {}; var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = setTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { currentQueue[queueIndex].run(); } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; clearTimeout(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) { setTimeout(drainQueue, 0); } }; // 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.binding = function (name) { throw new Error('process.binding is not supported'); }; // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; /***/ } /******/ ]) }); ; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCBjYzYwMGU3Njk2NGJlMjJkYzliNyIsIndlYnBhY2s6Ly8vLi9pbWdseWtpdC5qcyIsIndlYnBhY2s6Ly8vLi9saWIvcmVuZGVyLWltYWdlLmpzIiwid2VicGFjazovLy8uL2xpYi9pbWFnZS1leHBvcnRlci5qcyIsIndlYnBhY2s6Ly8vLi9saWIvdmVyc2lvbi1jaGVja2VyLmpzIiwid2VicGFjazovLy8uL2NvbnN0YW50cy5qcyIsIndlYnBhY2s6Ly8vLi9saWIvdXRpbHMuanMiLCJ3ZWJwYWNrOi8vLy4vbGliL2NvbG9yLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzLW9wZXJhdGlvbi5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2Nyb3Atb3BlcmF0aW9uLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvcm90YXRpb24tb3BlcmF0aW9uLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvc2F0dXJhdGlvbi1vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9jb250cmFzdC1vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9icmlnaHRuZXNzLW9wZXJhdGlvbi5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZsaXAtb3BlcmF0aW9uLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvdGlsdC1zaGlmdC1vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9yYWRpYWwtYmx1ci1vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy90ZXh0LW9wZXJhdGlvbi5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL3N0aWNrZXJzLW9wZXJhdGlvbi5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZyYW1lcy1vcGVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2ExNS1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2JyZWV6ZS1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2J3LWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvYndoYXJkLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvY2Vsc2l1cy1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2NoZXN0LWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvZml4aWUtZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9mb29kLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvZnJpZGdlLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvZnJvbnQtZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9nbGFtLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvZ29iYmxpbi1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2sxLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvazItZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9rNi1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2tkeW5hbWljLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvbGVuaW4tZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9sb21vLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvbWVsbG93LWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvbW9ybmluZy1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL29yY2hpZC1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL3BvbGEtZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9wb2xhNjY5LWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcXVvemktZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9zZW1pcmVkLWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvc3VubnktZmlsdGVyLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy90ZXhhcy1maWx0ZXIuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL3g0MDAtZmlsdGVyLmpzIiwid2VicGFjazovLy8uL2xpYi9tYXRoL3ZlY3RvcjIuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvdWkuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiY2FudmFzXCIiLCJ3ZWJwYWNrOi8vLy4vbGliL2ltYWdlLWRpbWVuc2lvbnMuanMiLCJ3ZWJwYWNrOi8vLy4vcmVuZGVyZXJzL2NhbnZhcy1yZW5kZXJlci5qcyIsIndlYnBhY2s6Ly8vLi9yZW5kZXJlcnMvd2ViZ2wtcmVuZGVyZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbGliL2V4aWYtcmVzdG9yZXIuanMiLCJ3ZWJwYWNrOi8vLy4vdmVuZG9yL3Byb21pc2UuanMiLCJ3ZWJwYWNrOi8vLy4vbGliL2V4dGVuZC5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy1zdGFjay5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9zYXR1cmF0aW9uLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL2xvb2t1cC10YWJsZS5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy90b25lLWN1cnZlLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL3NvZnQtY29sb3Itb3ZlcmxheS5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9kZXNhdHVyYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMveDQwMC5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9ncmF5c2NhbGUuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvY29udHJhc3QuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvZ2xvdy5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9nb2JibGluLmpzIiwid2VicGFjazovLy8uL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL2JyaWdodG5lc3MuanMiLCJ3ZWJwYWNrOi8vLy4vb3BlcmF0aW9ucy9maWx0ZXJzL2lkZW50aXR5LWZpbHRlci5qcyIsIndlYnBhY2s6Ly8vLi9saWIvZXZlbnQtZW1pdHRlci5qcyIsIndlYnBhY2s6Ly8vLi92ZW5kb3Ivc3RhY2stYmx1ci5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL34vbm9kZS1saWJzLWJyb3dzZXIvfi9wcm9jZXNzL2Jyb3dzZXIuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvYmFzZS91aS5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9saWIvY2FudmFzLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2xpYi9maWxlLWxvYWRlci5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9saWIvd2ViY2FtLWhhbmRsZXIuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvbGliL3RvcC1jb250cm9scy5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9saWIvc2Nyb2xsYmFyLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL2ZpbHRlcnMtY29udHJvbC5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9jb250cm9scy9yb3RhdGlvbi1jb250cm9sLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL2ZsaXAtY29udHJvbC5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9jb250cm9scy9icmlnaHRuZXNzLWNvbnRyb2wuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvY29udHJvbHMvY29udHJhc3QtY29udHJvbC5qcyIsIndlYnBhY2s6Ly8vLi91aS9uaWdodC9jb250cm9scy9zYXR1cmF0aW9uLWNvbnRyb2wuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvY29udHJvbHMvY3JvcC1jb250cm9sLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL3JhZGlhbC1ibHVyLWNvbnRyb2wuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvY29udHJvbHMvdGlsdC1zaGlmdC1jb250cm9sLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL2ZyYW1lcy1jb250cm9sLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL3N0aWNrZXJzLWNvbnRyb2wuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvY29udHJvbHMvdGV4dC1jb250cm9sLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2NvbnRyb2xzL2NvbnRyb2wuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvbGFuZy9lbi5qc29uIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2xhbmcvZGUuanNvbiIsIndlYnBhY2s6Ly8vLi9yZW5kZXJlcnMvcmVuZGVyZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbGliL2Jhc2U2NC5qcyIsIndlYnBhY2s6Ly8vLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9wcmltaXRpdmUuanMiLCJ3ZWJwYWNrOi8vLy4vdmVuZG9yL25hdGl2ZS1wcm9taXNlLW9ubHkuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvYmFzZS9oZWxwZXJzLmpzIiwid2VicGFjazovLy8uL3VpL25pZ2h0L2xpYi9zbGlkZXIuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvbGliL3NpbXBsZS1zbGlkZXIuanMiLCJ3ZWJwYWNrOi8vLy4vdWkvbmlnaHQvbGliL2NvbG9yLXBpY2tlci5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL34vbm9kZS1saWJzLWJyb3dzZXIvfi90aW1lcnMtYnJvd3NlcmlmeS9tYWluLmpzIiwid2VicGFjazovLy8od2VicGFjaykvfi9ub2RlLWxpYnMtYnJvd3Nlci9+L3RpbWVycy1icm93c2VyaWZ5L34vcHJvY2Vzcy9icm93c2VyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxPO0FDVkE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsdUJBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7OztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEVBQUM7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QUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQU87O0FBRVA7QUFDQTtBQUNBLFFBQU87O0FBRVA7QUFDQTtBQUNBLFFBQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBUztBQUNULFFBQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBUztBQUNULFFBQU87QUFDUDtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7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O0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBRzs7QUFFSDtBQUNBLEVBQUM7O0FBRUQ7QUFDQSxxQzs7Ozs7O0FDN0hBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxjQUFhLFlBQVk7QUFDekI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsZ0JBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnQkFBZSxpQkFBaUI7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWEsV0FBVztBQUN4Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7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QUFRO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBUztBQUNULFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXFCLDRCQUE0QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxXQUFXO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtB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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBUztBQUNUO0FBQ0E7QUFDQSxVQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckIsZ0JBQWUsV0FBVztBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFD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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsU0FBUztBQUN4QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxzQkFBcUIsNkJBQTZCO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxVQUFTOztBQUVUO0FBQ0E7O0FBRUEsc0JBQXFCLDhCQUE4QjtBQUNuRDtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXFCLDRCQUE0QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNB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O0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFxQiw4QkFBOEI7QUFDbkQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXFCLDRCQUE0QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXFCLDRCQUE0QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7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QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGVBQWM7QUFDZDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsUUFBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZEQUE0RCwyQ0FBMkM7QUFDdkc7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFHO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7O0FBRUg7QUFDQSxFQUFDOztBQUVEO0FBQ0EscUM7Ozs7OzttQ0NyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBLEVBQUM7QUFDRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7O0FBRUg7QUFDQTtBQUNBLDZCQUE0QixTQUFTO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFPO0FBQ1A7QUFDQSxJQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW1CLHVCQUF1QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBTztBQUNQO0FBQ0E7QUFDQSxVQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBUztBQUNUO0FBQ0EsVUFBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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OztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHlCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNCQUFxQixtQkFBbUI7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHNCQUFxQixtQkFBbUI7QUFDeEM7QUFDQSx3QkFBdUIsa0JBQWtCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWUsTUFBTTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxnQkFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGdCQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLGVBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHczQkFBdTNCO0FBQ3YzQjtBQUNBO0FBQ0EsSUFBRzs7QUFFSDtBQUNBLEVBQUM7O0FBRUQ7QUFDQSxxQzs7Ozs7O0FDbm1CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTJDLGlCQUFpQjs7QUFFNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHOzs7Ozs7O0FDM0VBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF1QixzQkFBc0I7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBcUI7QUFDckI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLDZCQUE0QixVQUFVIiwiZmlsZSI6ImltZ2x5a2l0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwiY2FudmFzXCIpKTtcblx0ZWxzZSBpZih0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpXG5cdFx0ZGVmaW5lKFtcImNhbnZhc1wiXSwgZmFjdG9yeSk7XG5cdGVsc2UgaWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKVxuXHRcdGV4cG9ydHNbXCJJbWdseUtpdFwiXSA9IGZhY3RvcnkocmVxdWlyZShcImNhbnZhc1wiKSk7XG5cdGVsc2Vcblx0XHRyb290W1wiSW1nbHlLaXRcIl0gPSBmYWN0b3J5KHJvb3RbXCJjYW52YXNcIl0pO1xufSkodGhpcywgZnVuY3Rpb24oX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV81Ml9fKSB7XG5yZXR1cm4gXG5cblxuLyoqIFdFQlBBQ0sgRk9PVEVSICoqXG4gKiogd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uXG4gKiovIiwiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pXG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG5cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGV4cG9ydHM6IHt9LFxuIFx0XHRcdGlkOiBtb2R1bGVJZCxcbiBcdFx0XHRsb2FkZWQ6IGZhbHNlXG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmxvYWRlZCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oMCk7XG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiB3ZWJwYWNrL2Jvb3RzdHJhcCBjYzYwMGU3Njk2NGJlMjJkYzliN1xuICoqLyIsIi8qIVxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9saWJSZW5kZXJJbWFnZSA9IHJlcXVpcmUoJy4vbGliL3JlbmRlci1pbWFnZScpO1xuXG52YXIgX2xpYlJlbmRlckltYWdlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlJlbmRlckltYWdlKTtcblxudmFyIF9saWJJbWFnZUV4cG9ydGVyID0gcmVxdWlyZSgnLi9saWIvaW1hZ2UtZXhwb3J0ZXInKTtcblxudmFyIF9saWJJbWFnZUV4cG9ydGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkltYWdlRXhwb3J0ZXIpO1xuXG52YXIgX2xpYlZlcnNpb25DaGVja2VyID0gcmVxdWlyZSgnLi9saWIvdmVyc2lvbi1jaGVja2VyJyk7XG5cbnZhciBfbGliVmVyc2lvbkNoZWNrZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVmVyc2lvbkNoZWNrZXIpO1xuXG52YXIgX2NvbnN0YW50cyA9IHJlcXVpcmUoJy4vY29uc3RhbnRzJyk7XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIFZFUlNJT04gPSAnMi4wLjAtMic7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHBhcmFtIHtJbWFnZX0gW29wdGlvbnMuaW1hZ2VdIC0gVGhlIHNvdXJjZSBpbWFnZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gW29wdGlvbnMuY29udGFpbmVyXSAtIFNwZWNpZmllcyB3aGVyZSB0aGUgVUkgc2hvdWxkIGJlXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZGVkIHRvLiBJZiBub25lIGlzIGdpdmVuLCB0aGUgVUlcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIGRpc2FibGVkLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy51aS5lbmFibGVkPXRydWVdIC0gRW5hYmxlcyBvciBkaXNhYmxlcyB0aGUgVUlcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMucmVuZGVyT25XaW5kb3dSZXNpemVdIC0gU3BlY2lmaWVzIHdoZXRoZXIgdGhlIGNhbnZhc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkIHJlLXJlbmRlciBpdHNlbGYgd2hlblxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIHdpbmRvdyBpcyBiZWluZyByZXNpemVkLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFzc2V0c1VybD0nYXNzZXRzJ10gLSBUaGUgYmFzZSBwYXRoIGZvciBhbGwgZXh0ZXJuYWwgYXNzZXRzLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnJlbmRlcmVyPSd3ZWJnbCddIC0gVGhlIHJlbmRlcmVyIGlkZW50aWZpZXIuIENhbiBlaXRoZXJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZSAnd2ViZ2wnIG9yICdjYW52YXMnLlxuICovXG5cbnZhciBJbWdseUtpdCA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEltZ2x5S2l0KG9wdGlvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSW1nbHlLaXQpO1xuXG4gICAgLy8gYG9wdGlvbnNgIGlzIHJlcXVpcmVkXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBvcHRpb25zIGdpdmVuLicpO1xuICAgIH1cblxuICAgIC8vIFNldCBkZWZhdWx0IG9wdGlvbnNcbiAgICBvcHRpb25zID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmRlZmF1bHRzKG9wdGlvbnMsIHtcbiAgICAgIGFzc2V0c1VybDogJ2Fzc2V0cycsXG4gICAgICBjb250YWluZXI6IG51bGwsXG4gICAgICByZW5kZXJPbldpbmRvd1Jlc2l6ZTogZmFsc2UsXG4gICAgICB2ZXJzaW9uQ2hlY2s6IHRydWVcbiAgICB9KTtcbiAgICBvcHRpb25zLnVpID0gb3B0aW9ucy51aSB8fCB7fTtcbiAgICBvcHRpb25zLnVpID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmRlZmF1bHRzKG9wdGlvbnMudWksIHtcbiAgICAgIGVuYWJsZWQ6IHRydWVcbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5pbWFnZSA9PT0gJ3VuZGVmaW5lZCcgJiYgIW9wdGlvbnMudWkuZW5hYmxlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdgb3B0aW9ucy5pbWFnZWAgbmVlZHMgdG8gYmUgc2V0IHdoZW4gVUkgaXMgZGlzYWJsZWQuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YWNrIG9mIHtAbGluayBPcGVyYXRpb259IGluc3RhbmNlcyB0aGF0IHdpbGwgYmUgdXNlZFxuICAgICAqIHRvIHJlbmRlciB0aGUgZmluYWwgSW1hZ2VcbiAgICAgKiBAdHlwZSB7QXJyYXkuPEltZ2x5S2l0Lk9wZXJhdGlvbj59XG4gICAgICovXG4gICAgdGhpcy5vcGVyYXRpb25zU3RhY2sgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWdpc3RlcmVkIFVJIHR5cGVzIHRoYXQgY2FuIGJlIHNlbGVjdGVkIHZpYSB0aGUgYHVpYCBvcHRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0LjxTdHJpbmcsIFVJPn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX3JlZ2lzdGVyZWRVSXMgPSB7fTtcblxuICAgIC8vIFJlZ2lzdGVyIHRoZSBkZWZhdWx0IFVJc1xuICAgIHRoaXMuX3JlZ2lzdGVyVUlzKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVnaXN0ZXJlZCBvcGVyYXRpb25zXG4gICAgICogQHR5cGUge09iamVjdC48U3RyaW5nLCBJbWdseUtpdC5PcGVyYXRpb24+fVxuICAgICAqL1xuICAgIHRoaXMuX3JlZ2lzdGVyZWRPcGVyYXRpb25zID0ge307XG5cbiAgICAvLyBSZWdpc3RlciB0aGUgZGVmYXVsdCBvcGVyYXRpb25zXG4gICAgdGhpcy5fcmVnaXN0ZXJPcGVyYXRpb25zKCk7XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5fb3B0aW9ucy52ZXJzaW9uQ2hlY2spIHtcbiAgICAgIHRoaXMuX3ZlcnNpb25DaGVja2VyID0gbmV3IF9saWJWZXJzaW9uQ2hlY2tlcjJbJ2RlZmF1bHQnXShWRVJTSU9OKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fb3B0aW9ucy51aS5lbmFibGVkKSB7XG4gICAgICB0aGlzLl9pbml0VUkoKTtcbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLnJlbmRlck9uV2luZG93UmVzaXplKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZVdpbmRvd1Jlc2l6ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhJbWdseUtpdCwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgaW1hZ2VcbiAgICAgKiBAcGFyYW0gIHtJbWdseUtpdC5SZW5kZXJUeXBlfSBbcmVuZGVyVHlwZT1JbWdseUtpdC5SZW5kZXJUeXBlLkRBVEFVUkxdIC0gVGhlIG91dHB1dCB0eXBlXG4gICAgICogQHBhcmFtICB7SW1nbHlLaXQuSW1hZ2VGb3JtYXR9IFtpbWFnZUZvcm1hdD1JbWdseUtpdC5JbWFnZUZvcm1hdC5QTkddIC0gVGhlIG91dHB1dCBpbWFnZSBmb3JtYXRcbiAgICAgKiBAcGFyYW0gIHtzdHJpbmd9IFtkaW1lbnNpb25zXSAtIFRoZSBmaW5hbCBkaW1lbnNpb25zIG9mIHRoZSBpbWFnZVxuICAgICAqIEBwYXJhbSAge051bWJlcn0gW3F1YWxpdHldIC0gVGhlIGltYWdlIHF1YWxpdHksIGJldHdlZW4gMCBhbmQgMVxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJUeXBlLCBpbWFnZUZvcm1hdCwgZGltZW5zaW9ucywgcXVhbGl0eSkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgdmFyIHNldHRpbmdzID0gX2xpYkltYWdlRXhwb3J0ZXIyWydkZWZhdWx0J10udmFsaWRhdGVTZXR0aW5ncyhyZW5kZXJUeXBlLCBpbWFnZUZvcm1hdCk7XG5cbiAgICAgIHJlbmRlclR5cGUgPSBzZXR0aW5ncy5yZW5kZXJUeXBlO1xuICAgICAgaW1hZ2VGb3JtYXQgPSBzZXR0aW5ncy5pbWFnZUZvcm1hdDtcblxuICAgICAgLy8gQ3JlYXRlIGEgUmVuZGVySW1hZ2VcbiAgICAgIHZhciByZW5kZXJJbWFnZSA9IG5ldyBfbGliUmVuZGVySW1hZ2UyWydkZWZhdWx0J10odGhpcy5fb3B0aW9ucy5pbWFnZSwgdGhpcy5vcGVyYXRpb25zU3RhY2ssIGRpbWVuc2lvbnMsIHRoaXMuX29wdGlvbnMucmVuZGVyZXIpO1xuXG4gICAgICAvLyBTZXQgYWxsIG9wZXJhdGlvbnMgdG8gZGlydHksIHNpbmNlIHdlIGhhdmUgYW5vdGhlciB3ZWJnbCByZW5kZXJlclxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm9wZXJhdGlvbnNTdGFjay5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3BlcmF0aW9uID0gdGhpcy5vcGVyYXRpb25zU3RhY2tbaV07XG4gICAgICAgIGlmICghb3BlcmF0aW9uKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgb3BlcmF0aW9uLmRpcnR5ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gSW5pdGlhdGUgaW1hZ2UgcmVuZGVyaW5nXG4gICAgICByZXR1cm4gcmVuZGVySW1hZ2UucmVuZGVyKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYW52YXMgPSByZW5kZXJJbWFnZS5nZXRSZW5kZXJlcigpLmdldENhbnZhcygpO1xuICAgICAgICByZXR1cm4gX2xpYkltYWdlRXhwb3J0ZXIyWydkZWZhdWx0J11bJ2V4cG9ydCddKF90aGlzLl9vcHRpb25zLmltYWdlLCBjYW52YXMsIHJlbmRlclR5cGUsIGltYWdlRm9ybWF0LCBxdWFsaXR5KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Jlc2V0JyxcblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyBhbGwgY3VzdG9tIGFuZCBzZWxlY3RlZCBvcGVyYXRpb25zXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlc2V0KCkge31cbiAgfSwge1xuICAgIGtleTogJ2dldEFzc2V0UGF0aCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBhc3NldCBwYXRoIGZvciB0aGUgZ2l2ZW4gZmlsZW5hbWVcbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IGFzc2V0XG4gICAgICogQHJldHVybiB7U3RyaW5nfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRBc3NldFBhdGgoYXNzZXQpIHtcbiAgICAgIHZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJztcbiAgICAgIGlmIChpc0Jyb3dzZXIpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuYXNzZXRzVXJsICsgJy8nICsgYXNzZXQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTtcbiAgICAgICAgcmV0dXJuIHBhdGgucmVzb2x2ZSh0aGlzLl9vcHRpb25zLmFzc2V0c1VybCwgYXNzZXQpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVXaW5kb3dSZXNpemUnLFxuXG4gICAgLyoqXG4gICAgICogSWYgYG9wdGlvbnMucmVuZGVyT25XaW5kb3dSZXNpemVgIGlzIHNldCB0byB0cnVlLCB0aGlzIGZ1bmN0aW9uXG4gICAgICogd2lsbCByZS1yZW5kZXIgdGhlIGNhbnZhcyB3aXRoIGEgc2xpZ2h0IGRlbGF5IHNvIHRoYXQgaXQgd29uJ3RcbiAgICAgKiBjYXVzZSBsYWdnaW5nIG9mIHRoZSByZXNpemVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlV2luZG93UmVzaXplKCkge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIHZhciB0aW1lciA9IG51bGw7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGltZXIgIT09IG51bGwpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB0aW1lciA9IG51bGw7XG4gICAgICAgICAgX3RoaXMyLnVpLnJlbmRlcigpO1xuICAgICAgICB9LCAzMDApO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlZ2lzdGVyVUlzJyxcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbGwgZGVmYXVsdCBVSXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVnaXN0ZXJVSXMoKSB7XG4gICAgICB0aGlzLnJlZ2lzdGVyVUkoSW1nbHlLaXQuTmlnaHRVSSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlZ2lzdGVyT3BlcmF0aW9ucycsXG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYWxsIGRlZmF1bHQgb3BlcmF0aW9uc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZWdpc3Rlck9wZXJhdGlvbnMoKSB7XG4gICAgICBmb3IgKHZhciBvcGVyYXRpb25OYW1lIGluIEltZ2x5S2l0Lk9wZXJhdGlvbnMpIHtcbiAgICAgICAgdGhpcy5yZWdpc3Rlck9wZXJhdGlvbihJbWdseUtpdC5PcGVyYXRpb25zW29wZXJhdGlvbk5hbWVdKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZWdpc3Rlck9wZXJhdGlvbicsXG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgdGhlIGdpdmVuIG9wZXJhdGlvblxuICAgICAqIEBwYXJhbSB7SW1nbHlLaXQuT3BlcmF0aW9ufSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGNsYXNzXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlZ2lzdGVyT3BlcmF0aW9uKG9wZXJhdGlvbikge1xuICAgICAgdGhpcy5fcmVnaXN0ZXJlZE9wZXJhdGlvbnNbb3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyXSA9IG9wZXJhdGlvbjtcbiAgICAgIGlmICh0aGlzLnVpKSB7XG4gICAgICAgIHRoaXMudWkuYWRkT3BlcmF0aW9uKG9wZXJhdGlvbik7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVnaXN0ZXJVSScsXG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgdGhlIGdpdmVuIFVJXG4gICAgICogQHBhcmFtIHtVSX0gdWlcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVnaXN0ZXJVSSh1aSkge1xuICAgICAgdGhpcy5fcmVnaXN0ZXJlZFVJc1t1aS5wcm90b3R5cGUuaWRlbnRpZmllcl0gPSB1aTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW5pdFVJJyxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBVSVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRVSSgpIHtcbiAgICAgIHZhciBVSTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudWkuZW5hYmxlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAvLyBTZWxlY3QgdGhlIGZpcnN0IFVJIGJ5IGRlZmF1bHRcbiAgICAgICAgVUkgPSBfbGliVXRpbHMyWydkZWZhdWx0J10udmFsdWVzKHRoaXMuX3JlZ2lzdGVyZWRVSXMpWzBdO1xuICAgICAgfVxuXG4gICAgICBpZiAoIVVJKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLyoqXG4gICAgICAgKiBAdHlwZSB7SW1nbHlLaXQuVUl9XG4gICAgICAgKi9cbiAgICAgIHRoaXMudWkgPSBuZXcgVUkodGhpcywgdGhpcy5fb3B0aW9ucyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0T3BlcmF0aW9uRnJvbVN0YWNrJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIE9wZXJhdGlvbiBpbnN0YW5jZSB3aXRoIHRoZSBnaXZlbiBpZGVudGlmaWVyLFxuICAgICAqIGlmIGl0IGV4aXN0c1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICogQHJldHVybnMge09wZXJhdGlvbn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0T3BlcmF0aW9uRnJvbVN0YWNrKGlkZW50aWZpZXIpIHtcbiAgICAgIHZhciBvcGVyYXRpb24gPSB0aGlzLm9wZXJhdGlvbnNTdGFjay5maWx0ZXIoZnVuY3Rpb24gKG9wZXJhdGlvbikge1xuICAgICAgICByZXR1cm4gb3BlcmF0aW9uLmlkZW50aWZpZXIgPT09IGlkZW50aWZpZXI7XG4gICAgICB9KVswXTtcbiAgICAgIHJldHVybiBvcGVyYXRpb247XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncnVuJyxcblxuICAgIC8qKlxuICAgICAqIFJ1bnMgdGhlIFVJLCBpZiBwcmVzZW50XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJ1bigpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy51aSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhpcy51aS5ydW4oKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZWdpc3RlcmVkT3BlcmF0aW9ucycsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVnaXN0ZXJlZE9wZXJhdGlvbnM7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEltZ2x5S2l0O1xufSkoKTtcblxuLyoqXG4gKiBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBTREtcbiAqIEBuYW1lIEltZ2x5S2l0LnZlcnNpb25cbiAqIEBpbnRlcm5hbCBLZWVwIGluIHN5bmMgd2l0aCBwYWNrYWdlLmpzb25cbiAqL1xuSW1nbHlLaXQudmVyc2lvbiA9IFZFUlNJT047XG5cbi8vIEV4cG9zZWQgY2xhc3Nlc1xuSW1nbHlLaXQuUmVuZGVySW1hZ2UgPSBfbGliUmVuZGVySW1hZ2UyWydkZWZhdWx0J107XG5JbWdseUtpdC5Db2xvciA9IHJlcXVpcmUoJy4vbGliL2NvbG9yJyk7XG5JbWdseUtpdC5GaWx0ZXIgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9maWx0ZXInKTtcbkltZ2x5S2l0Lk9wZXJhdGlvbiA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9vcGVyYXRpb24nKTtcbkltZ2x5S2l0Lk9wZXJhdGlvbnMgPSB7fTtcbkltZ2x5S2l0Lk9wZXJhdGlvbnMuRmlsdGVycyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzLW9wZXJhdGlvbicpO1xuSW1nbHlLaXQuT3BlcmF0aW9ucy5Dcm9wID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2Nyb3Atb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLlJvdGF0aW9uID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL3JvdGF0aW9uLW9wZXJhdGlvbicpO1xuSW1nbHlLaXQuT3BlcmF0aW9ucy5TYXR1cmF0aW9uID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL3NhdHVyYXRpb24tb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLkNvbnRyYXN0ID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2NvbnRyYXN0LW9wZXJhdGlvbicpO1xuSW1nbHlLaXQuT3BlcmF0aW9ucy5CcmlnaHRuZXNzID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2JyaWdodG5lc3Mtb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLkZsaXAgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmxpcC1vcGVyYXRpb24nKTtcbkltZ2x5S2l0Lk9wZXJhdGlvbnMuVGlsdFNoaWZ0ID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL3RpbHQtc2hpZnQtb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLlJhZGlhbEJsdXIgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvcmFkaWFsLWJsdXItb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLlRleHQgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvdGV4dC1vcGVyYXRpb24nKTtcbkltZ2x5S2l0Lk9wZXJhdGlvbnMuU3RpY2tlcnMgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvc3RpY2tlcnMtb3BlcmF0aW9uJyk7XG5JbWdseUtpdC5PcGVyYXRpb25zLkZyYW1lcyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9mcmFtZXMtb3BlcmF0aW9uJyk7XG5cbkltZ2x5S2l0LkZpbHRlcnMgPSB7fTtcbkltZ2x5S2l0LkZpbHRlcnMuQTE1ID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvYTE1LWZpbHRlcicpO1xuSW1nbHlLaXQuRmlsdGVycy5CcmVlemUgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9icmVlemUtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkJXID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvYnctZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkJXSGFyZCA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL2J3aGFyZC1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuQ2Vsc2l1cyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL2NlbHNpdXMtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkNoZXN0ID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvY2hlc3QtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkZpeGllID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvZml4aWUtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkZvb2QgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9mb29kLWZpbHRlcicpO1xuSW1nbHlLaXQuRmlsdGVycy5GcmlkZ2UgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9mcmlkZ2UtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkZyb250ID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvZnJvbnQtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLkdsYW0gPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9nbGFtLWZpbHRlcicpO1xuSW1nbHlLaXQuRmlsdGVycy5Hb2JibGluID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvZ29iYmxpbi1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuSzEgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9rMS1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuSzIgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9rMi1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuSzYgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9rNi1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuS0R5bmFtaWMgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9rZHluYW1pYy1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuTGVuaW4gPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9sZW5pbi1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuTG9tbyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL2xvbW8tZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLk1lbGxvdyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL21lbGxvdy1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuTW9ybmluZyA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL21vcm5pbmctZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLk9yY2hpZCA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL29yY2hpZC1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuUG9sYSA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL3BvbGEtZmlsdGVyJyk7XG5JbWdseUtpdC5GaWx0ZXJzLlBvbGE2NjkgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9wb2xhNjY5LWZpbHRlcicpO1xuSW1nbHlLaXQuRmlsdGVycy5RdW96aSA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL3F1b3ppLWZpbHRlcicpO1xuSW1nbHlLaXQuRmlsdGVycy5TZW1pcmVkID0gcmVxdWlyZSgnLi9vcGVyYXRpb25zL2ZpbHRlcnMvc2VtaXJlZC1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuU3VubnkgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy9zdW5ueS1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuVGV4YXMgPSByZXF1aXJlKCcuL29wZXJhdGlvbnMvZmlsdGVycy90ZXhhcy1maWx0ZXInKTtcbkltZ2x5S2l0LkZpbHRlcnMuWDQwMCA9IHJlcXVpcmUoJy4vb3BlcmF0aW9ucy9maWx0ZXJzL3g0MDAtZmlsdGVyJyk7XG5cbi8vIEV4cG9zZWQgY29uc3RhbnRzXG5JbWdseUtpdC5SZW5kZXJUeXBlID0gX2NvbnN0YW50cy5SZW5kZXJUeXBlO1xuSW1nbHlLaXQuSW1hZ2VGb3JtYXQgPSBfY29uc3RhbnRzLkltYWdlRm9ybWF0O1xuSW1nbHlLaXQuVmVjdG9yMiA9IHJlcXVpcmUoJy4vbGliL21hdGgvdmVjdG9yMicpO1xuXG4vLyBVSVxuSW1nbHlLaXQuTmlnaHRVSSA9IHJlcXVpcmUoJy4vdWkvbmlnaHQvdWknKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gSW1nbHlLaXQ7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vaW1nbHlraXQuanNcbiAqKiBtb2R1bGUgaWQgPSAwXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfaW1hZ2VEaW1lbnNpb25zID0gcmVxdWlyZSgnLi9pbWFnZS1kaW1lbnNpb25zJyk7XG5cbnZhciBfaW1hZ2VEaW1lbnNpb25zMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ltYWdlRGltZW5zaW9ucyk7XG5cbnZhciBfbWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX21hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21hdGhWZWN0b3IyKTtcblxudmFyIF9yZW5kZXJlcnNDYW52YXNSZW5kZXJlciA9IHJlcXVpcmUoJy4uL3JlbmRlcmVycy9jYW52YXMtcmVuZGVyZXInKTtcblxudmFyIF9yZW5kZXJlcnNDYW52YXNSZW5kZXJlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZW5kZXJlcnNDYW52YXNSZW5kZXJlcik7XG5cbnZhciBfcmVuZGVyZXJzV2ViZ2xSZW5kZXJlciA9IHJlcXVpcmUoJy4uL3JlbmRlcmVycy93ZWJnbC1yZW5kZXJlcicpO1xuXG52YXIgX3JlbmRlcmVyc1dlYmdsUmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVuZGVyZXJzV2ViZ2xSZW5kZXJlcik7XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgaW1hZ2UgcmVuZGVyaW5nIHByb2Nlc3NcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LlJlbmRlckltYWdlXG4gKiBAcGFyYW0ge0ltYWdlfSBpbWFnZVxuICogQHBhcmFtIHtBcnJheS48SW1nbHlLaXQuT3BlcmF0aW9uPn0gb3BlcmF0aW9uc1N0YWNrXG4gKiBAcGFyYW0ge3N0cmluZ30gZGltZW5zaW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IHByZWZlcnJlZFJlbmRlcmVyXG4gKiBAcHJpdmF0ZVxuICovXG5cbnZhciBSZW5kZXJJbWFnZSA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIFJlbmRlckltYWdlKGltYWdlLCBvcGVyYXRpb25zU3RhY2ssIGRpbWVuc2lvbnMsIHByZWZlcnJlZFJlbmRlcmVyKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFJlbmRlckltYWdlKTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9vcHRpb25zID0ge1xuICAgICAgcHJlZmVycmVkUmVuZGVyZXI6IHByZWZlcnJlZFJlbmRlcmVyXG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgKi9cbiAgICB0aGlzLl93ZWJnbEVuYWJsZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtSZW5kZXJlcn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX3JlbmRlcmVyID0gbnVsbDtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtJbWFnZX1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2ltYWdlID0gaW1hZ2U7XG5cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7QXJyYXkuPEltZ2x5S2l0Lk9wZXJhdGlvbj59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9zdGFjayA9IG9wZXJhdGlvbnNTdGFjaztcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtJbWdseUtpdC5JbWFnZURpbWVuc2lvbnN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9kaW1lbnNpb25zID0gbmV3IF9pbWFnZURpbWVuc2lvbnMyWydkZWZhdWx0J10oZGltZW5zaW9ucyk7XG5cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7VmVjdG9yMn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2luaXRpYWxEaW1lbnNpb25zID0gbmV3IF9tYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9pbWFnZS53aWR0aCwgdGhpcy5faW1hZ2UuaGVpZ2h0KTtcblxuICAgIHRoaXMuX2luaXRSZW5kZXJlcigpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKFJlbmRlckltYWdlLCBbe1xuICAgIGtleTogJ19pbml0UmVuZGVyZXInLFxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHJlbmRlcmVyIChjYW52YXMgb3Igd2ViZ2wsIGRlcGVuZGluZyBvbiBzdXBwb3J0KVxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRSZW5kZXJlcigpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKF9yZW5kZXJlcnNXZWJnbFJlbmRlcmVyMlsnZGVmYXVsdCddLmlzU3VwcG9ydGVkKCkgJiYgdGhpcy5fb3B0aW9ucy5wcmVmZXJyZWRSZW5kZXJlciAhPT0gJ2NhbnZhcycpIHtcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBuZXcgX3JlbmRlcmVyc1dlYmdsUmVuZGVyZXIyWydkZWZhdWx0J10odGhpcy5faW5pdGlhbERpbWVuc2lvbnMpO1xuICAgICAgICB0aGlzLl93ZWJnbEVuYWJsZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIyWydkZWZhdWx0J10uaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICB0aGlzLl9yZW5kZXJlciA9IG5ldyBfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIyWydkZWZhdWx0J10odGhpcy5faW5pdGlhbERpbWVuc2lvbnMpO1xuICAgICAgICB0aGlzLl93ZWJnbEVuYWJsZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAodGhpcy5fcmVuZGVyZXIgPT09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOZWl0aGVyIENhbnZhcyBub3IgV2ViR0wgcmVuZGVyZXIgYXJlIHN1cHBvcnRlZC4nKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fcmVuZGVyZXIuZHJhd0ltYWdlKHRoaXMuX2ltYWdlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgaW1hZ2VcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgc3RhY2sgPSB0aGlzLnNhbml0aXplZFN0YWNrO1xuXG4gICAgICB2YXIgdmFsaWRhdGlvblByb21pc2VzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSBzdGFja1tpXTtcbiAgICAgICAgdmFsaWRhdGlvblByb21pc2VzLnB1c2gob3BlcmF0aW9uLnZhbGlkYXRlU2V0dGluZ3MoKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBQcm9taXNlLmFsbCh2YWxpZGF0aW9uUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJvbWlzZXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdGFjay5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBvcGVyYXRpb24gPSBzdGFja1tpXTtcbiAgICAgICAgICBwcm9taXNlcy5wdXNoKG9wZXJhdGlvbi5yZW5kZXIoX3RoaXMuX3JlbmRlcmVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX3RoaXMuX3JlbmRlcmVyLnJlbmRlckZpbmFsKCk7XG4gICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGluaXRpYWxTaXplID0gX3RoaXMuX3JlbmRlcmVyLmdldFNpemUoKTtcbiAgICAgICAgdmFyIGZpbmFsRGltZW5zaW9ucyA9IF90aGlzLl9kaW1lbnNpb25zLmNhbGN1bGF0ZUZpbmFsRGltZW5zaW9ucyhpbml0aWFsU2l6ZSk7XG5cbiAgICAgICAgaWYgKGZpbmFsRGltZW5zaW9ucy5lcXVhbHMoaW5pdGlhbFNpemUpKSB7XG4gICAgICAgICAgLy8gTm8gbmVlZCB0byByZXNpemVcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gX3RoaXMuX3JlbmRlcmVyLnJlc2l6ZVRvKGZpbmFsRGltZW5zaW9ucyk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRSZW5kZXJlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1JlbmRlcmVyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRSZW5kZXJlcigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJlcjtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzYW5pdGl6ZWRTdGFjaycsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBvcGVyYXRpb25zIHN0YWNrIHdpdGhvdXQgZmFsc3kgdmFsdWVzXG4gICAgICogQHR5cGUge0FycmF5LjxPcGVyYXRpb24+fVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHNhbml0aXplZFN0YWNrID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3N0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSB0aGlzLl9zdGFja1tpXTtcbiAgICAgICAgaWYgKCFvcGVyYXRpb24pIGNvbnRpbnVlO1xuICAgICAgICBzYW5pdGl6ZWRTdGFjay5wdXNoKG9wZXJhdGlvbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuaXRpemVkU3RhY2s7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFJlbmRlckltYWdlO1xufSkoKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUmVuZGVySW1hZ2U7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL3JlbmRlci1pbWFnZS5qc1xuICoqIG1vZHVsZSBpZCA9IDFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBJbWFnZSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2NvbnN0YW50cyA9IHJlcXVpcmUoJy4uL2NvbnN0YW50cycpO1xuXG52YXIgX2V4aWZSZXN0b3JlciA9IHJlcXVpcmUoJy4vZXhpZi1yZXN0b3JlcicpO1xuXG52YXIgX2V4aWZSZXN0b3JlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9leGlmUmVzdG9yZXIpO1xuXG52YXIgX3V0aWxzID0gcmVxdWlyZSgnLi91dGlscycpO1xuXG52YXIgX3V0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3V0aWxzKTtcblxudmFyIF92ZW5kb3JQcm9taXNlID0gcmVxdWlyZSgnLi4vdmVuZG9yL3Byb21pc2UnKTtcblxudmFyIF92ZW5kb3JQcm9taXNlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ZlbmRvclByb21pc2UpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkltYWdlRXhwb3J0ZXJcbiAqIEBwcml2YXRlXG4gKi9cblxudmFyIEltYWdlRXhwb3J0ZXIgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBJbWFnZUV4cG9ydGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBJbWFnZUV4cG9ydGVyKTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhJbWFnZUV4cG9ydGVyLCBudWxsLCBbe1xuICAgIGtleTogJ3ZhbGlkYXRlU2V0dGluZ3MnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiB2YWxpZGF0ZVNldHRpbmdzKHJlbmRlclR5cGUsIGltYWdlRm9ybWF0KSB7XG4gICAgICB2YXIgc2V0dGluZ3MgPSB7XG4gICAgICAgIHJlbmRlclR5cGU6IHJlbmRlclR5cGUsXG4gICAgICAgIGltYWdlRm9ybWF0OiBpbWFnZUZvcm1hdFxuICAgICAgfTtcblxuICAgICAgLy8gVmFsaWRhdGUgUmVuZGVyVHlwZVxuICAgICAgaWYgKHR5cGVvZiBzZXR0aW5ncy5yZW5kZXJUeXBlICE9PSAndW5kZWZpbmVkJyAmJiBzZXR0aW5ncy5yZW5kZXJUeXBlICE9PSBudWxsICYmIF91dGlsczJbJ2RlZmF1bHQnXS52YWx1ZXMoX2NvbnN0YW50cy5SZW5kZXJUeXBlKS5pbmRleE9mKHNldHRpbmdzLnJlbmRlclR5cGUpID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcmVuZGVyIHR5cGU6ICcgKyBzZXR0aW5ncy5yZW5kZXJUeXBlKTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlbmRlclR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHNldHRpbmdzLnJlbmRlclR5cGUgPSBfY29uc3RhbnRzLlJlbmRlclR5cGUuREFUQVVSTDtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgSW1hZ2VGb3JtYXRcbiAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MuaW1hZ2VGb3JtYXQgIT09ICd1bmRlZmluZWQnICYmIHNldHRpbmdzLmltYWdlRm9ybWF0ICE9PSBudWxsICYmIF91dGlsczJbJ2RlZmF1bHQnXS52YWx1ZXMoX2NvbnN0YW50cy5JbWFnZUZvcm1hdCkuaW5kZXhPZihzZXR0aW5ncy5pbWFnZUZvcm1hdCkgPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbWFnZSBmb3JtYXQ6ICcgKyBzZXR0aW5ncy5pbWFnZUZvcm1hdCk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbWFnZUZvcm1hdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgc2V0dGluZ3MuaW1hZ2VGb3JtYXQgPSBfY29uc3RhbnRzLkltYWdlRm9ybWF0LlBORztcbiAgICAgIH1cblxuICAgICAgLy8gUmVuZGVyIHR5cGUgJ2J1ZmZlcicgb25seSBhdmFpbGFibGUgaW4gbm9kZVxuICAgICAgaWYgKHNldHRpbmdzLnJlbmRlclR5cGUgPT09IF9jb25zdGFudHMuUmVuZGVyVHlwZS5CVUZGRVIgJiYgdHlwZW9mIHByb2Nlc3MgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVuZGVyIHR5cGUgXFwnYnVmZmVyXFwnIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdXNpbmcgbm9kZS5qcycpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2V0dGluZ3M7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZXhwb3J0JyxcblxuICAgIC8qKlxuICAgICAqIEV4cG9ydHMgdGhlIGltYWdlIGZyb20gdGhlIGdpdmVuIGNhbnZhcyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zXG4gICAgICogQHBhcmFtICB7SW1hZ2V9IGltYWdlXG4gICAgICogQHBhcmFtICB7Q2FudmFzfSBjYW52YXNcbiAgICAgKiBAcGFyYW0gIHtJbWdseUtpdC5SZW5kZXJUeXBlfSByZW5kZXJUeXBlXG4gICAgICogQHBhcmFtICB7SW1nbHlLaXQuSW1hZ2VGb3JtYXR9IGltYWdlRm9ybWF0XG4gICAgICogQHBhcmFtICB7TnVtYmVyfSBxdWFsaXR5ID0gMC44XG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2V4cG9ydChpbWFnZSwgY2FudmFzLCByZW5kZXJUeXBlLCBpbWFnZUZvcm1hdCkge1xuICAgICAgdmFyIHF1YWxpdHkgPSBhcmd1bWVudHNbNF0gPT09IHVuZGVmaW5lZCA/IDAuOCA6IGFyZ3VtZW50c1s0XTtcblxuICAgICAgcmV0dXJuIG5ldyBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChyZW5kZXJUeXBlID09PSBfY29uc3RhbnRzLlJlbmRlclR5cGUuSU1BR0UgfHwgcmVuZGVyVHlwZSA9PT0gX2NvbnN0YW50cy5SZW5kZXJUeXBlLkRBVEFVUkwpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIFF1YWxpdHkgbm90IHN1cHBvcnRlZCBpbiBub2RlIGVudmlyb25tZW50IC8gbm9kZS1jYW52YXNcbiAgICAgICAgICAgIHJlc3VsdCA9IGNhbnZhcy50b0RhdGFVUkwoaW1hZ2VGb3JtYXQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBjYW52YXMudG9EYXRhVVJMKGltYWdlRm9ybWF0LCBxdWFsaXR5KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBXaGVuIGltYWdlJ3MgYHNyY2AgYXR0cmlidXRlIGlzIGEganBlZyBkYXRhIHVybCwgd2UgY2FuIHJlc3RvcmVcbiAgICAgICAgICAvLyB0aGUgZXhpZiBpbmZvcm1hdGlvblxuICAgICAgICAgIHZhciBqcGVnTWF0Y2ggPSAvXmRhdGE6aW1hZ2VcXC9qcGVnL2k7XG4gICAgICAgICAgaWYgKGltYWdlLnNyYy5tYXRjaChqcGVnTWF0Y2gpICYmIHJlc3VsdC5tYXRjaChqcGVnTWF0Y2gpKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBfZXhpZlJlc3RvcmVyMlsnZGVmYXVsdCddLnJlc3RvcmUoaW1hZ2Uuc3JjLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZW5kZXJUeXBlID09PSBfY29uc3RhbnRzLlJlbmRlclR5cGUuSU1BR0UpIHtcbiAgICAgICAgICB2YXIgb3V0cHV0SW1hZ2UgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAgKi9cbiAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIE5vdCBhIGJyb3dzZXIgZW52aXJvbm1lbnRcbiAgICAgICAgICAgIHZhciBDYW52YXNJbWFnZSA9IHJlcXVpcmUoJ2NhbnZhcycpLkltYWdlO1xuICAgICAgICAgICAgb3V0cHV0SW1hZ2UgPSBuZXcgQ2FudmFzSW1hZ2UoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0cHV0SW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBvdXRwdXRJbWFnZS5zcmMgPSByZXN1bHQ7XG4gICAgICAgICAgcmVzb2x2ZShvdXRwdXRJbWFnZSk7XG4gICAgICAgIH0gZWxzZSBpZiAocmVuZGVyVHlwZSA9PT0gX2NvbnN0YW50cy5SZW5kZXJUeXBlLkRBVEFVUkwpIHtcbiAgICAgICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0gZWxzZSBpZiAocmVuZGVyVHlwZSA9PT0gX2NvbnN0YW50cy5SZW5kZXJUeXBlLkJVRkZFUikge1xuICAgICAgICAgIHJlc29sdmUoY2FudmFzLnRvQnVmZmVyKCkpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlbmRlclR5cGUgPT09IF9jb25zdGFudHMuUmVuZGVyVHlwZS5NU0JMT0IpIHtcbiAgICAgICAgICByZXNvbHZlKGNhbnZhcy5tc1RvQmxvYigpKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZW5kZXJUeXBlID09PSBfY29uc3RhbnRzLlJlbmRlclR5cGUuQkxPQikge1xuICAgICAgICAgIGNhbnZhcy50b0Jsb2IoZnVuY3Rpb24gKGJsb2IpIHtcbiAgICAgICAgICAgIHJlc29sdmUoYmxvYik7XG4gICAgICAgICAgfSwgaW1hZ2VGb3JtYXQsIHF1YWxpdHkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gSW1hZ2VFeHBvcnRlcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEltYWdlRXhwb3J0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL2ltYWdlLWV4cG9ydGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgVkVSU0lPTl9DSEVDS19GTiA9ICdpbWdseVNES1ZlcnNpb25DYWxsYmFjayc7XG52YXIgVkVSU0lPTl9DSEVDS19VUkwgPSAnaHR0cDovL3Nkay5pbWcubHkvdmVyc2lvbi5qc29uP3Nkaz1odG1sNSZqc29uY2FsbGJhY2s9JyArIFZFUlNJT05fQ0hFQ0tfRk47XG5cbnZhciBWZXJzaW9uQ2hlY2tlciA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIFZlcnNpb25DaGVja2VyKHZlcnNpb24pIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVmVyc2lvbkNoZWNrZXIpO1xuXG4gICAgdGhpcy5fdmVyc2lvbiA9IHZlcnNpb247XG4gICAgdGhpcy5fY2hlY2soKTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhWZXJzaW9uQ2hlY2tlciwgW3tcbiAgICBrZXk6ICdfY2hlY2snLFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoaXMgdmVyc2lvbiBvZiB0aGUgU0RLIGlzIG91dGRhdGVkXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NoZWNrKCkge1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgd2luZG93W1ZFUlNJT05fQ0hFQ0tfRk5dID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmIChyZXNwb25zZS5vdXRkYXRlZCkge1xuICAgICAgICAgIGNvbnNvbGUud2FybignaW1nbHktc2RrLWh0bWw1OiBZb3VyIHZlcnNpb24gJyArIHNlbGYuX3ZlcnNpb24gKyAnIGlzIG91dGRhdGVkLicpO1xuICAgICAgICAgIGNvbnNvbGUud2FybignaW1nbHktc2RrLWh0bWw1OiBDdXJyZW50IHZlcnNpb24gaXMgJyArIHJlc3BvbnNlLnZlcnNpb24gKyAnLicpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICB2YXIgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgICBzY3JpcHQuc3JjID0gVkVSU0lPTl9DSEVDS19VUkwgKyAnJnZlcnNpb249JyArIHRoaXMuX3ZlcnNpb247XG4gICAgICBzY3JpcHQuYXN5bmMgPSB0cnVlO1xuICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2hlYWQnKVswXS5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBWZXJzaW9uQ2hlY2tlcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFZlcnNpb25DaGVja2VyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL2xpYi92ZXJzaW9uLWNoZWNrZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAzXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuLyoqXG4gKiBUaGUgYXZhaWxhYmxlIHJlbmRlciB0eXBlc1xuICogQGVudW0ge3N0cmluZ31cbiAqIEBhbGlhcyBJbWdseUtpdC5SZW5kZXJUeXBlXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG52YXIgUmVuZGVyVHlwZSA9IHtcbiAgSU1BR0U6ICdpbWFnZScsXG4gIERBVEFVUkw6ICdkYXRhLXVybCcsXG4gIEJVRkZFUjogJ2J1ZmZlcicsXG4gIEJMT0I6ICdibG9iJyxcbiAgTVNCTE9COiAnbXMtYmxvYidcbn07XG5cbmV4cG9ydHMuUmVuZGVyVHlwZSA9IFJlbmRlclR5cGU7XG4vKipcbiAqIFRoZSBhdmFpbGFibGUgb3V0cHV0IGltYWdlIGZvcm1hdHNcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAYWxpYXMgSW1nbHlLaXQuSW1hZ2VGb3JtYXRcbiAqL1xudmFyIEltYWdlRm9ybWF0ID0ge1xuICBQTkc6ICdpbWFnZS9wbmcnLFxuICBKUEVHOiAnaW1hZ2UvanBlZydcbn07XG5leHBvcnRzLkltYWdlRm9ybWF0ID0gSW1hZ2VGb3JtYXQ7XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL2NvbnN0YW50cy5qc1xuICoqIG1vZHVsZSBpZCA9IDRcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBIVE1MRWxlbWVudCAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBfbWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX21hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX21hdGhWZWN0b3IyKTtcblxuLyoqXG4gKiBQcm92aWRlcyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgaW50ZXJuYWwgdXNlXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5VdGlsc1xuICogQHByaXZhdGVcbiAqL1xuXG52YXIgVXRpbHMgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBVdGlscygpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVXRpbHMpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKFV0aWxzLCBudWxsLCBbe1xuICAgIGtleTogJ2lzQXJyYXknLFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSBnaXZlbiBvYmplY3QgaXMgYW4gQXJyYXlcbiAgICAgKiBAcGFyYW0gIHtPYmplY3R9ICBvYmplY3RcbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpc0FycmF5KG9iamVjdCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmplY3QpID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NlbGVjdCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBpdGVtcyBzZWxlY3RlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3JcbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gaXRlbXNcbiAgICAgKiBAcGFyYW0gIHtJbWdseUtpdH5TZWxlY3Rvcn0gc2VsZWN0b3IgLSBUaGUgc2VsZWN0b3JcbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIHNlbGVjdGVkIGl0ZW1zXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNlbGVjdChpdGVtcykge1xuICAgICAgdmFyIHNlbGVjdG9yID0gYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyBudWxsIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICBpZiAoc2VsZWN0b3IgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgICAgfVxuXG4gICAgICAvLyBUdXJuIHN0cmluZyBwYXJhbWV0ZXIgaW50byBhbiBhcnJheVxuICAgICAgaWYgKHR5cGVvZiBzZWxlY3RvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc2VsZWN0b3IgPSBzZWxlY3Rvci5zcGxpdCgnLCcpLm1hcChmdW5jdGlvbiAoaWRlbnRpZmllcikge1xuICAgICAgICAgIHJldHVybiBpZGVudGlmaWVyLnRyaW0oKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFR1cm4gYXJyYXkgcGFyYW1ldGVyIGludG8gYW4gb2JqZWN0IHdpdGggYG9ubHlgXG4gICAgICBpZiAoVXRpbHMuaXNBcnJheShzZWxlY3RvcikpIHtcbiAgICAgICAgc2VsZWN0b3IgPSB7IG9ubHk6IHNlbGVjdG9yIH07XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygc2VsZWN0b3Iub25seSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWxlY3Rvci5vbmx5ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHNlbGVjdG9yLm9ubHkgPSBzZWxlY3Rvci5vbmx5LnNwbGl0KCcsJykubWFwKGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7XG4gICAgICAgICAgICByZXR1cm4gaWRlbnRpZmllci50cmltKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZWxlY3Qgb25seSB0aGUgZ2l2ZW4gaWRlbnRpZmllcnNcbiAgICAgICAgcmV0dXJuIGl0ZW1zLmZpbHRlcihmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgIHJldHVybiBzZWxlY3Rvci5vbmx5LmluZGV4T2YoaXRlbSkgIT09IC0xO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHNlbGVjdG9yLmV4Y2VwdCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWxlY3Rvci5leGNlcHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgc2VsZWN0b3IuZXhjZXB0ID0gc2VsZWN0b3IuZXhjZXB0LnNwbGl0KCcsJykubWFwKGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7XG4gICAgICAgICAgICByZXR1cm4gaWRlbnRpZmllci50cmltKCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZWxlY3QgYWxsIGJ1dCB0aGUgZ2l2ZW4gaWRlbnRpZmllcnNcbiAgICAgICAgcmV0dXJuIGl0ZW1zLmZpbHRlcihmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgIHJldHVybiBzZWxlY3Rvci5leGNlcHQuaW5kZXhPZihpdGVtKSA9PT0gLTE7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1V0aWxzI3NlbGVjdCBmYWlsZWQgdG8gZmlsdGVyIGl0ZW1zLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3ZhbHVlcycsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBnaXZlbiBvYmplY3QncyB2YWx1ZXMgYXMgYW4gYXJyYXlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAgICogQHJldHVybnMge0FycmF5PCo+fVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZXMob2JqZWN0KSB7XG4gICAgICB2YXIgdmFsdWVzID0gW107XG4gICAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgIHZhbHVlcy5wdXNoKG9iamVjdFtrZXldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaXNET01FbGVtZW50JyxcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGEgRE9NIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0gIHtPYmplY3R9ICBvXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpc0RPTUVsZW1lbnQobykge1xuICAgICAgcmV0dXJuIHR5cGVvZiBIVE1MRWxlbWVudCA9PT0gJ29iamVjdCcgPyBvIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgOiBvICYmIHR5cGVvZiBvID09PSAnb2JqZWN0JyAmJiBvICE9PSBudWxsICYmIG8ubm9kZVR5cGUgPT09IDEgJiYgdHlwZW9mIG8ubm9kZU5hbWUgPT09ICdzdHJpbmcnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldEV2ZW50UG9zaXRpb24nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgeCBhbmQgeSBwb3NpdGlvbiBmb3IgdGhlIGdpdmVuIGV2ZW50LlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRFdmVudFBvc2l0aW9uKGUpIHtcbiAgICAgIHZhciB4ID0gZS5wYWdlWDtcbiAgICAgIHZhciB5ID0gZS5wYWdlWTtcbiAgICAgIGlmIChlLnR5cGUuaW5kZXhPZigndG91Y2gnKSAhPT0gLTEpIHtcbiAgICAgICAgeCA9IGUudG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgeSA9IGUudG91Y2hlc1swXS5wYWdlWTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgX21hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHgsIHkpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Jlc2l6ZVZlY3RvclRvRml0JyxcblxuICAgIC8qKlxuICAgICAqIFJlc2l6ZXMgdGhlIGdpdmVuIHZlY3RvciB0byBmaXQgaW5zaWRlIHRoZSBnaXZlbiBtYXggc2l6ZSB3aGlsZSBtYWludGFpbmluZ1xuICAgICAqIHRoZSBhc3BlY3QgcmF0aW9cbiAgICAgKiBAcGFyYW0gIHtWZWN0b3IyfSB2ZWN0b3JcbiAgICAgKiBAcGFyYW0gIHtWZWN0b3IyfSBtYXhcbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZXNpemVWZWN0b3JUb0ZpdCh2ZWN0b3IsIG1heCkge1xuICAgICAgdmFyIHNjYWxlID0gTWF0aC5taW4obWF4LnggLyB2ZWN0b3IueCwgbWF4LnkgLyB2ZWN0b3IueSk7XG4gICAgICB2YXIgbmV3U2l6ZSA9IHZlY3Rvci5jbG9uZSgpLm11bHRpcGx5KHNjYWxlKTtcbiAgICAgIHJldHVybiBuZXdTaXplO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RlZmF1bHRzJyxcblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0KHMpIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdCBmb3IgYWxsIGRlc3RpbmF0aW9uIHByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIHVuZGVmaW5lZC4gT25jZSBhXG4gICAgICogcHJvcGVydHkgaXMgc2V0LCBhZGRpdGlvbmFsIHZhbHVlcyBvZiB0aGUgc2FtZSBwcm9wZXJ0eSBhcmUgaWdub3JlZC5cbiAgICAgKiBAcGFyYW0gIHtPYmplY3R9IG9iamVjdFxuICAgICAqIEBwYXJhbSAge09iamVjdH0gLi4uc291cmNlc1xuICAgICAqIEByZXR1cm4ge09iamVjdH1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZGVmYXVsdHMob2JqZWN0KSB7XG4gICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgc291cmNlcyA9IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgICAgc291cmNlc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgICB9XG5cbiAgICAgIC8vIFNoYWxsb3cgY2xvbmVcbiAgICAgIHZhciBuZXdPYmplY3QgPSB7fTtcbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgbmV3T2JqZWN0W2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2xvbmUgc291cmNlc1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzb3VyY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2ldO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBuZXdPYmplY3Rba2V5XSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIG5ld09iamVjdFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXdPYmplY3Q7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZXh0ZW5kJyxcblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0KHMpIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdC4gU3Vic2VxdWVudCBzb3VyY2VzIG92ZXJ3cml0ZSBwcm9wZXJ0eSBhc3NpZ25tZW50cyBvZiBwcmV2aW91c1xuICAgICAqIHNvdXJjZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSAuLi5zb3VyY2VzXG4gICAgICogQHJldHVybiB7T2JqZWN0fVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBleHRlbmQob2JqZWN0KSB7XG4gICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIHNvdXJjZXMgPSBBcnJheShfbGVuMiA+IDEgPyBfbGVuMiAtIDEgOiAwKSwgX2tleTIgPSAxOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7XG4gICAgICAgIHNvdXJjZXNbX2tleTIgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgICB9XG5cbiAgICAgIC8vIFNoYWxsb3cgY2xvbmVcbiAgICAgIHZhciBuZXdPYmplY3QgPSB7fTtcbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgbmV3T2JqZWN0W2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICAgIH1cblxuICAgICAgLy8gRXh0ZW5kIHNvdXJjZXNcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc291cmNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc291cmNlID0gc291cmNlc1tpXTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgIG5ld09iamVjdFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ld09iamVjdDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdmZXRjaCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBwcm9wZXJ0eSB2YWx1ZSBhdCBgcGF0aGAgb2YgYG9iamVjdGBcbiAgICAgKiBAcGFyYW0gIHtPYmplY3R9IG9iamVjdFxuICAgICAqIEBwYXJhbSAge1N0cmluZ30ga2V5XG4gICAgICogQHBhcmFtICB7P30gW2RlZmF1bHRWYWx1ZV1cbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBmZXRjaChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgLy8gUmVwbGFjZSBpbmRleGVzIHdpdGggcHJvcGVydHkgYWNjZXNzb3JzXG4gICAgICBwYXRoID0gcGF0aC5yZXBsYWNlKC9cXFsoXFx3KylcXF0vZywgJy4kMScpO1xuICAgICAgLy8gU3RyaXAgbGVhZGluZyBkb3QgKHdoZW4gcGF0aCBiZWdpbnMgd2l0aCBbMF0gZm9yIGV4YW1wbGUpXG4gICAgICBwYXRoID0gcGF0aC5yZXBsYWNlKC9eXFwuLywgJycpO1xuXG4gICAgICB2YXIgcGF0aFNlZ21lbnRzID0gcGF0aC5zcGxpdCgnLicpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRoU2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNlZ21lbnQgPSBwYXRoU2VnbWVudHNbaV07XG4gICAgICAgIG9iamVjdCA9IG9iamVjdFtzZWdtZW50XTtcbiAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgb2JqZWN0ID0gZGVmYXVsdFZhbHVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBVdGlscztcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFV0aWxzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL2xpYi91dGlscy5qc1xuICoqIG1vZHVsZSBpZCA9IDVcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBjb2xvclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuQ29sb3JcbiAqIEBwYXJhbSB7TnVtYmVyfSByXG4gKiBAcGFyYW0ge051bWJlcn0gZ1xuICogQHBhcmFtIHtOdW1iZXJ9IGJcbiAqIEBwYXJhbSB7TnVtYmVyfSBbYV1cbiAqIEBwcml2YXRlXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgQ29sb3IgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBDb2xvcihyLCBnLCBiLCBhKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbG9yKTtcblxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGEgPSAxO1xuICAgIH1cblxuICAgIHRoaXMuciA9IHI7XG4gICAgdGhpcy5nID0gZztcbiAgICB0aGlzLmIgPSBiO1xuICAgIHRoaXMuYSA9IGE7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoQ29sb3IsIFt7XG4gICAga2V5OiAndG9SR0JBJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gcmdiYSgpIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgY29sb3JcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvUkdCQSgpIHtcbiAgICAgIHZhciBjb2xvcnMgPSBbTWF0aC5yb3VuZCh0aGlzLnIgKiAyNTUpLCBNYXRoLnJvdW5kKHRoaXMuZyAqIDI1NSksIE1hdGgucm91bmQodGhpcy5iICogMjU1KSwgdGhpcy5hXTtcbiAgICAgIHJldHVybiAncmdiYSgnICsgY29sb3JzLmpvaW4oJywnKSArICcpJztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd0b0hleCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgY29sb3JcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvSGV4KCkge1xuICAgICAgdmFyIGNvbXBvbmVudHMgPSBbdGhpcy5fY29tcG9uZW50VG9IZXgoTWF0aC5yb3VuZCh0aGlzLnIgKiAyNTUpKSwgdGhpcy5fY29tcG9uZW50VG9IZXgoTWF0aC5yb3VuZCh0aGlzLmcgKiAyNTUpKSwgdGhpcy5fY29tcG9uZW50VG9IZXgoTWF0aC5yb3VuZCh0aGlzLmIgKiAyNTUpKV07XG4gICAgICByZXR1cm4gJyMnICsgY29tcG9uZW50cy5qb2luKCcnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd0b0dMQ29sb3InLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSB3aXRoIDQgdmFsdWVzICgwLi4uMSlcbiAgICAgKiBAcmV0dXJuIHtBcnJheS48TnVtYmVyPn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gdG9HTENvbG9yKCkge1xuICAgICAgcmV0dXJuIFt0aGlzLnIsIHRoaXMuZywgdGhpcy5iLCB0aGlzLmFdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3RvUkdCR0xDb2xvcicsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IHdpdGggMyB2YWx1ZXMgKDAuLi4xKVxuICAgICAqIEByZXR1cm4ge0FycmF5LjxOdW1iZXI+fVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiB0b1JHQkdMQ29sb3IoKSB7XG4gICAgICByZXR1cm4gW3RoaXMuciwgdGhpcy5nLCB0aGlzLmJdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3RvSFNWJyxcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBSR0IgdmFsdWUgdG8gSFNWXG4gICAgICogQHJldHVybiB7QXJyYXkuPE51bWJlcj59XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvSFNWKCkge1xuICAgICAgdmFyIG1heCA9IE1hdGgubWF4KHRoaXMuciwgdGhpcy5nLCB0aGlzLmIpO1xuICAgICAgdmFyIG1pbiA9IE1hdGgubWluKHRoaXMuciwgdGhpcy5nLCB0aGlzLmIpO1xuICAgICAgdmFyIGggPSB1bmRlZmluZWQ7XG4gICAgICB2YXIgcyA9IHVuZGVmaW5lZDtcbiAgICAgIHZhciB2ID0gbWF4O1xuICAgICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgICBzID0gbWF4ID09PSAwID8gMCA6IGQgLyBtYXg7XG5cbiAgICAgIGlmIChtYXggPT09IG1pbikge1xuICAgICAgICBoID0gMCAvLyBhY2hyb21hdGljXG4gICAgICAgIDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN3aXRjaCAobWF4KSB7XG4gICAgICAgICAgY2FzZSB0aGlzLnI6XG4gICAgICAgICAgICBoID0gKHRoaXMuZyAtIHRoaXMuYikgLyBkICsgKHRoaXMuZyA8IHRoaXMuYiA/IDYgOiAwKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgdGhpcy5nOlxuICAgICAgICAgICAgaCA9ICh0aGlzLmIgLSB0aGlzLnIpIC8gZCArIDI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIHRoaXMuYjpcbiAgICAgICAgICAgIGggPSAodGhpcy5yIC0gdGhpcy5nKSAvIGQgKyA0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaCAvPSA2O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gW2gsIHMsIHZdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2Zyb21IU1YnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgUkdCIHZhbHVlcyBvZiB0aGlzIGNvbG9yIHRvIG1hdGNoIHRoZSBnaXZlbiBIU1YgdmFsdWVzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGhcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gc1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB2XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21IU1YoaCwgcywgdikge1xuICAgICAgdmFyIHIgPSB0aGlzLnI7XG4gICAgICB2YXIgZyA9IHRoaXMuZztcbiAgICAgIHZhciBiID0gdGhpcy5iO1xuXG4gICAgICB2YXIgaSA9IE1hdGguZmxvb3IoaCAqIDYpO1xuICAgICAgdmFyIGYgPSBoICogNiAtIGk7XG4gICAgICB2YXIgcCA9IHYgKiAoMSAtIHMpO1xuICAgICAgdmFyIHEgPSB2ICogKDEgLSBmICogcyk7XG4gICAgICB2YXIgdCA9IHYgKiAoMSAtICgxIC0gZikgKiBzKTtcblxuICAgICAgc3dpdGNoIChpICUgNikge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgciA9IHY7XG4gICAgICAgICAgZyA9IHQ7XG4gICAgICAgICAgYiA9IHA7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICByID0gcTtcbiAgICAgICAgICBnID0gdjtcbiAgICAgICAgICBiID0gcDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHIgPSBwO1xuICAgICAgICAgIGcgPSB2O1xuICAgICAgICAgIGIgPSB0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgciA9IHA7XG4gICAgICAgICAgZyA9IHE7XG4gICAgICAgICAgYiA9IHY7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICByID0gdDtcbiAgICAgICAgICBnID0gcDtcbiAgICAgICAgICBiID0gdjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIHIgPSB2O1xuICAgICAgICAgIGcgPSBwO1xuICAgICAgICAgIGIgPSBxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnIgPSByO1xuICAgICAgdGhpcy5nID0gZztcbiAgICAgIHRoaXMuYiA9IGI7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY2xvbmUnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGNsb25lIG9mIHRoZSBjdXJyZW50IGNvbG9yXG4gICAgICogQHJldHVybiB7Q29sb3J9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNsb25lKCkge1xuICAgICAgcmV0dXJuIG5ldyBDb2xvcih0aGlzLnIsIHRoaXMuZywgdGhpcy5iLCB0aGlzLmEpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19jb21wb25lbnRUb0hleCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBnaXZlbiBudW1iZXIgYXMgaGV4XG4gICAgICogQHBhcmFtICB7TnVtYmVyfSBjb21wb25lbnRcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NvbXBvbmVudFRvSGV4KGNvbXBvbmVudCkge1xuICAgICAgdmFyIGhleCA9IGNvbXBvbmVudC50b1N0cmluZygxNik7XG4gICAgICByZXR1cm4gaGV4Lmxlbmd0aCA9PT0gMSA/ICcwJyArIGhleCA6IGhleDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd0b1N0cmluZycsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBjb2xvclxuICAgICAqIEByZXR1cm5zIHtTdHJpbmd9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgcmV0dXJuICdDb2xvcignICsgdGhpcy5yICsgJywgJyArIHRoaXMuZyArICcsICcgKyB0aGlzLmIgKyAnLCAnICsgdGhpcy5hICsgJyknO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDb2xvcjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvbG9yO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL2xpYi9jb2xvci5qc1xuICoqIG1vZHVsZSBpZCA9IDZcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGpzaGludCB1bnVzZWQ6IGZhbHNlICovXG4vKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuLyoqXG4gKiBCYXNlIGNsYXNzIGZvciBmaWx0ZXJzLiBFeHRlbmRhYmxlIHZpYSB7QGxpbmsgSW1nbHlLaXQuRmlsdGVyI2V4dGVuZH1cbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlclxuICovXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIEZpbHRlciA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmlsdGVyKTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBFcnJvcignRmlsdGVyI3JlbmRlciBpcyBhYnN0cmFjdCBhbmQgbm90IGltcGxlbWVudGVkIGluIGluaGVyaXRlZCBjbGFzcy4nKTtcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBGaWx0ZXI7XG59KSgpO1xuXG4vKipcbiAqIFRvIGNyZWF0ZSBhbiB7QGxpbmsgSW1nbHlLaXQuRmlsdGVyfSBjbGFzcyBvZiB5b3VyIG93biwgY2FsbCB0aGlzXG4gKiBtZXRob2QgYW5kIHByb3ZpZGUgaW5zdGFuY2UgcHJvcGVydGllcyBhbmQgZnVuY3Rpb25zLlxuICogQGZ1bmN0aW9uXG4gKi9cbkZpbHRlci5leHRlbmQgPSByZXF1aXJlKCcuLi8uLi9saWIvZXh0ZW5kJyk7XG5cbi8vIEV4cG9zZWQgY2xhc3Nlc1xuRmlsdGVyLlByaW1pdGl2ZXNTdGFjayA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlcy1zdGFjaycpO1xuRmlsdGVyLlByaW1pdGl2ZXMgPSB7fTtcbkZpbHRlci5QcmltaXRpdmVzLlNhdHVyYXRpb24gPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMvc2F0dXJhdGlvbicpO1xuRmlsdGVyLlByaW1pdGl2ZXMuTG9va3VwVGFibGUgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMvbG9va3VwLXRhYmxlJyk7XG5GaWx0ZXIuUHJpbWl0aXZlcy5Ub25lQ3VydmUgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMvdG9uZS1jdXJ2ZScpO1xuRmlsdGVyLlByaW1pdGl2ZXMuU29mdENvbG9yT3ZlcmxheSA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlcy9zb2Z0LWNvbG9yLW92ZXJsYXknKTtcbkZpbHRlci5QcmltaXRpdmVzLkRlc2F0dXJhdGlvbiA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlcy9kZXNhdHVyYXRpb24nKTtcbkZpbHRlci5QcmltaXRpdmVzLlg0MDAgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMveDQwMCcpO1xuRmlsdGVyLlByaW1pdGl2ZXMuR3JheXNjYWxlID0gcmVxdWlyZSgnLi9wcmltaXRpdmVzL2dyYXlzY2FsZScpO1xuRmlsdGVyLlByaW1pdGl2ZXMuQ29udHJhc3QgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMvY29udHJhc3QnKTtcbkZpbHRlci5QcmltaXRpdmVzLkdsb3cgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZXMvZ2xvdycpO1xuRmlsdGVyLlByaW1pdGl2ZXMuR29iYmxpbiA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlcy9nb2JibGluJyk7XG5GaWx0ZXIuUHJpbWl0aXZlcy5CcmlnaHRuZXNzID0gcmVxdWlyZSgnLi9wcmltaXRpdmVzL2JyaWdodG5lc3MnKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA3XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBqc2hpbnQgdW51c2VkOmZhbHNlICovXG4vKiBqc2hpbnQgLVcwODMgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDIsIF94MywgX3g0KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MiwgcHJvcGVydHkgPSBfeDMsIHJlY2VpdmVyID0gX3g0OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDIgPSBwYXJlbnQ7IF94MyA9IHByb3BlcnR5OyBfeDQgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG52YXIgX2xpYkNvbG9yID0gcmVxdWlyZSgnLi4vbGliL2NvbG9yJyk7XG5cbnZhciBfbGliQ29sb3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliQ29sb3IpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX2xpYkV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJy4uL2xpYi9ldmVudC1lbWl0dGVyJyk7XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkV2ZW50RW1pdHRlcik7XG5cbnZhciBfdmVuZG9yUHJvbWlzZSA9IHJlcXVpcmUoJy4uL3ZlbmRvci9wcm9taXNlJyk7XG5cbnZhciBfdmVuZG9yUHJvbWlzZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF92ZW5kb3JQcm9taXNlKTtcblxuLyoqXG4gKiBUbyBjcmVhdGUgYW4ge0BsaW5rIEltZ2x5S2l0Lk9wZXJhdGlvbn0gY2xhc3Mgb2YgeW91ciBvd24sIGNhbGwgdGhpc1xuICogbWV0aG9kIGFuZCBwcm92aWRlIGluc3RhbmNlIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9ucy5cbiAqIEBmdW5jdGlvblxuICovXG5cbnZhciBfbGliRXh0ZW5kID0gcmVxdWlyZSgnLi4vbGliL2V4dGVuZCcpO1xuXG52YXIgX2xpYkV4dGVuZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFeHRlbmQpO1xuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIE9wZXJhdGlvbnMuIEV4dGVuZGFibGUgdmlhIHtAbGluayBJbWdseUtpdC5PcGVyYXRpb24jZXh0ZW5kfS5cbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0Lk9wZXJhdGlvblxuICovXG5cbnZhciBPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9FdmVudEVtaXR0ZXIpIHtcbiAgZnVuY3Rpb24gT3BlcmF0aW9uKGtpdCwgb3B0aW9ucykge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBPcGVyYXRpb24pO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoT3BlcmF0aW9uLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmNhbGwodGhpcyk7XG5cbiAgICB0aGlzLl9raXQgPSBraXQ7XG4gICAgdGhpcy5hdmFpbGFibGVPcHRpb25zID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmV4dGVuZCh0aGlzLmF2YWlsYWJsZU9wdGlvbnMgfHwge30sIHtcbiAgICAgIG51bWJlckZvcm1hdDogeyB0eXBlOiAnc3RyaW5nJywgJ2RlZmF1bHQnOiAncmVsYXRpdmUnLCBhdmFpbGFibGU6IFsnYWJzb2x1dGUnLCAncmVsYXRpdmUnXSB9XG4gICAgfSk7XG4gICAgdGhpcy5fZGlydHkgPSB0cnVlO1xuXG4gICAgdGhpcy5fZ2xzbFByb2dyYW1zID0ge307XG4gICAgdGhpcy5fdXVpZCA9ICd4eHh4eHh4eC14eHh4LTR4eHgteXh4eC14eHh4eHh4eHh4eHgnLnJlcGxhY2UoL1t4eV0vZywgZnVuY3Rpb24gKGMpIHtcbiAgICAgIHZhciByID0gTWF0aC5yYW5kb20oKSAqIDE2IHwgMDtcbiAgICAgIHZhciB2ID0gYyA9PT0gJ3gnID8gciA6IHIgJiAzIHwgODtcbiAgICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2luaXRPcHRpb25zKG9wdGlvbnMgfHwge30pO1xuICB9XG5cbiAgX2luaGVyaXRzKE9wZXJhdGlvbiwgX0V2ZW50RW1pdHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKE9wZXJhdGlvbiwgW3tcbiAgICBrZXk6ICd2YWxpZGF0ZVNldHRpbmdzJyxcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHRoaXMgT3BlcmF0aW9uIGNhbiBiZSBhcHBsaWVkIHRoZSB3YXkgaXQgaXMgY29uZmlndXJlZFxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHZhbGlkYXRlU2V0dGluZ3MoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuaWRlbnRpZmllcjtcbiAgICAgIHJldHVybiBuZXcgX3ZlbmRvclByb21pc2UyWydkZWZhdWx0J10oZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAvLyBDaGVjayBmb3IgcmVxdWlyZWQgb3B0aW9uc1xuICAgICAgICBmb3IgKHZhciBvcHRpb25OYW1lIGluIF90aGlzLmF2YWlsYWJsZU9wdGlvbnMpIHtcbiAgICAgICAgICB2YXIgb3B0aW9uQ29uZmlnID0gX3RoaXMuYXZhaWxhYmxlT3B0aW9uc1tvcHRpb25OYW1lXTtcbiAgICAgICAgICBpZiAob3B0aW9uQ29uZmlnLnJlcXVpcmVkICYmIHR5cGVvZiBfdGhpcy5fb3B0aW9uc1tvcHRpb25OYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKCdPcGVyYXRpb24gYCcgKyBpZGVudGlmaWVyICsgJ2A6IE9wdGlvbiBgJyArIG9wdGlvbk5hbWUgKyAnYCBpcyByZXF1aXJlZC4nKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgdGhpcyBvcGVyYXRpb25cbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqIEBhYnN0cmFjdFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciByZW5kZXJGbiA9IHVuZGVmaW5lZDtcbiAgICAgIGlmIChyZW5kZXJlci5pZGVudGlmaWVyID09PSAnd2ViZ2wnKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIHJlbmRlckZuID0gdGhpcy5fcmVuZGVyV2ViR0wuYmluZCh0aGlzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlbmRlckZuID0gdGhpcy5fcmVuZGVyQ2FudmFzLmJpbmQodGhpcyk7XG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBjYWNoaW5nXG4gICAgICBpZiAodGhpcy5fZGlydHkpIHtcbiAgICAgICAgcmVuZGVyRm4ocmVuZGVyZXIpO1xuICAgICAgICByZW5kZXJlci5jYWNoZSh0aGlzLl91dWlkKTtcbiAgICAgICAgdGhpcy5fZGlydHkgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlbmRlcmVyLmRyYXdDYWNoZWQodGhpcy5fdXVpZCk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgdGhpcyBvcGVyYXRpb24gdXNpbmcgV2ViR0xcbiAgICAgKiBAcmV0dXJuIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlcldlYkdMKCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPcGVyYXRpb24jX3JlbmRlcldlYkdMIGlzIGFic3RyYWN0IGFuZCBub3QgaW1wbGVtZW50ZWQgaW4gaW5oZXJpdGVkIGNsYXNzLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyB0aGlzIG9wZXJhdGlvbiB1c2luZyBDYW52YXMyRFxuICAgICAqIEByZXR1cm4ge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJDYW52YXMoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09wZXJhdGlvbiNfcmVuZGVyQ2FudmFzIGlzIGFic3RyYWN0IGFuZCBub3QgaW1wbGVtZW50ZWQgaW4gaW5oZXJpdGVkIGNsYXNzLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0T3B0aW9ucycsXG5cbiAgICAvKipcbiAgICAgKiBHb2VzIHRocm91Z2ggdGhlIGF2YWlsYWJsZSBvcHRpb25zLCBzZXRzIF9vcHRpb25zIGRlZmF1bHRzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHVzZXJPcHRpb25zXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRPcHRpb25zKHVzZXJPcHRpb25zKSB7XG4gICAgICB0aGlzLl9vcHRpb25zID0ge307XG5cbiAgICAgIC8vIFNldCBkZWZhdWx0cywgY3JlYXRlIGdldHRlcnMgYW5kIHNldHRlcnNcbiAgICAgIHZhciBvcHRpb25OYW1lLCBvcHRpb24sIGNhcGl0YWxpemVkO1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgZm9yIChvcHRpb25OYW1lIGluIHRoaXMuYXZhaWxhYmxlT3B0aW9ucykge1xuICAgICAgICBjYXBpdGFsaXplZCA9IG9wdGlvbk5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBvcHRpb25OYW1lLnNsaWNlKDEpO1xuICAgICAgICBvcHRpb24gPSB0aGlzLmF2YWlsYWJsZU9wdGlvbnNbb3B0aW9uTmFtZV07XG5cbiAgICAgICAgLy8gQ3JlYXRlIHNldHRlciBhbmQgZ2V0dGVyXG4gICAgICAgIHZhciBmbiA9IGZ1bmN0aW9uIGZuKG9wdGlvbk5hbWUsIG9wdGlvbikge1xuICAgICAgICAgIHNlbGZbJ3NldCcgKyBjYXBpdGFsaXplZF0gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIHNlbGYuX3NldE9wdGlvbihvcHRpb25OYW1lLCB2YWx1ZSk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIC8vIERlZmF1bHQgZ2V0dGVyXG4gICAgICAgICAgc2VsZlsnZ2V0JyArIGNhcGl0YWxpemVkXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLl9nZXRPcHRpb24ob3B0aW9uTmFtZSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgZm4ob3B0aW9uTmFtZSwgb3B0aW9uKTtcblxuICAgICAgICAvLyBTZXQgZGVmYXVsdCBpZiBhdmFpbGFibGVcbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25bJ2RlZmF1bHQnXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB0aGlzWydzZXQnICsgY2FwaXRhbGl6ZWRdKG9wdGlvblsnZGVmYXVsdCddKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPdmVyd3JpdGUgb3B0aW9ucyB3aXRoIHRoZSBvbmVzIGdpdmVuIGJ5IHVzZXJcbiAgICAgIGZvciAob3B0aW9uTmFtZSBpbiB1c2VyT3B0aW9ucykge1xuICAgICAgICAvLyBDaGVjayBpZiBvcHRpb24gaXMgYXZhaWxhYmxlXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5hdmFpbGFibGVPcHRpb25zW29wdGlvbk5hbWVdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvcHRpb246ICcgKyBvcHRpb25OYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENhbGwgc2V0dGVyXG4gICAgICAgIGNhcGl0YWxpemVkID0gb3B0aW9uTmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG9wdGlvbk5hbWUuc2xpY2UoMSk7XG4gICAgICAgIHRoaXNbJ3NldCcgKyBjYXBpdGFsaXplZF0odXNlck9wdGlvbnNbb3B0aW9uTmFtZV0pO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NldCcsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBnaXZlbiBvcHRpb25zXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0KG9wdGlvbnMpIHtcbiAgICAgIGZvciAodmFyIG9wdGlvbk5hbWUgaW4gb3B0aW9ucykge1xuICAgICAgICB0aGlzLl9zZXRPcHRpb24ob3B0aW9uTmFtZSwgb3B0aW9uc1tvcHRpb25OYW1lXSwgZmFsc2UpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmVtaXQoJ3VwZGF0ZScpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRPcHRpb24nLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmFsdWUgZm9yIHRoZSBnaXZlbiBvcHRpb25cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9uTmFtZVxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldE9wdGlvbihvcHRpb25OYW1lKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9uc1tvcHRpb25OYW1lXTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0T3B0aW9uJyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZhbHVlIGZvciB0aGUgZ2l2ZW4gb3B0aW9uLCB2YWxpZGF0ZXMgaXRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9uTmFtZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHVwZGF0ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zZXRPcHRpb24ob3B0aW9uTmFtZSwgdmFsdWUpIHtcbiAgICAgIHZhciB1cGRhdGUgPSBhcmd1bWVudHNbMl0gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbMl07XG5cbiAgICAgIHZhciBvcHRpb25Db25maWcgPSB0aGlzLmF2YWlsYWJsZU9wdGlvbnNbb3B0aW9uTmFtZV07XG4gICAgICB2YXIgaWRlbnRpZmllciA9IHRoaXMuaWRlbnRpZmllcjtcblxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25Db25maWcuc2V0dGVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB2YWx1ZSA9IG9wdGlvbkNvbmZpZy5zZXR0ZXIuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9uQ29uZmlnLnZhbGlkYXRpb24gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIG9wdGlvbkNvbmZpZy52YWxpZGF0aW9uKHZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoIChvcHRpb25Db25maWcudHlwZSkge1xuICAgICAgICAvLyBTdHJpbmcgb3B0aW9uc1xuICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ09wZXJhdGlvbiBgJyArIGlkZW50aWZpZXIgKyAnYDogT3B0aW9uIGAnICsgb3B0aW9uTmFtZSArICdgIGhhcyB0byBiZSBhIHN0cmluZy4nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBTdHJpbmcgdmFsdWUgcmVzdHJpY3Rpb25zXG4gICAgICAgICAgdmFyIGF2YWlsYWJsZSA9IG9wdGlvbkNvbmZpZy5hdmFpbGFibGU7XG4gICAgICAgICAgaWYgKHR5cGVvZiBhdmFpbGFibGUgIT09ICd1bmRlZmluZWQnICYmIGF2YWlsYWJsZS5pbmRleE9mKHZhbHVlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT3BlcmF0aW9uIGAnICsgaWRlbnRpZmllciArICdgOiBJbnZhbGlkIHZhbHVlIGZvciBgJyArIG9wdGlvbk5hbWUgKyAnYCAodmFsaWQgdmFsdWVzIGFyZTogJyArIG9wdGlvbkNvbmZpZy5hdmFpbGFibGUuam9pbignLCAnKSArICcpJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fb3B0aW9uc1tvcHRpb25OYW1lXSA9IHZhbHVlO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIC8vIE51bWJlciBvcHRpb25zXG4gICAgICAgIGNhc2UgJ251bWJlcic6XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT3BlcmF0aW9uIGAnICsgaWRlbnRpZmllciArICdgOiBPcHRpb24gYCcgKyBvcHRpb25OYW1lICsgJ2AgaGFzIHRvIGJlIGEgbnVtYmVyLicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX29wdGlvbnNbb3B0aW9uTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAvLyBCb29sZWFuIG9wdGlvbnNcbiAgICAgICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ09wZXJhdGlvbiBgJyArIGlkZW50aWZpZXIgKyAnYDogT3B0aW9uIGAnICsgb3B0aW9uTmFtZSArICdgIGhhcyB0byBiZSBhIGJvb2xlYW4uJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fb3B0aW9uc1tvcHRpb25OYW1lXSA9IHZhbHVlO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIC8vIFZlY3RvcjIgb3B0aW9uc1xuICAgICAgICBjYXNlICd2ZWN0b3IyJzpcbiAgICAgICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT3BlcmF0aW9uIGAnICsgaWRlbnRpZmllciArICdgOiBPcHRpb24gYCcgKyBvcHRpb25OYW1lICsgJ2AgaGFzIHRvIGJlIGFuIGluc3RhbmNlIG9mIEltZ2x5S2l0LlZlY3RvcjIuJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fb3B0aW9uc1tvcHRpb25OYW1lXSA9IHZhbHVlLmNsb25lKCk7XG5cbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAvLyBDb2xvciBvcHRpb25zXG4gICAgICAgIGNhc2UgJ2NvbG9yJzpcbiAgICAgICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIF9saWJDb2xvcjJbJ2RlZmF1bHQnXSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT3BlcmF0aW9uIGAnICsgaWRlbnRpZmllciArICdgOiBPcHRpb24gYCcgKyBvcHRpb25OYW1lICsgJ2AgaGFzIHRvIGJlIGFuIGluc3RhbmNlIG9mIEltZ2x5S2l0LkNvbG9yLicpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX29wdGlvbnNbb3B0aW9uTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAvLyBPYmplY3Qgb3B0aW9uc1xuICAgICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICAgIHRoaXMuX29wdGlvbnNbb3B0aW9uTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZGlydHkgPSB0cnVlO1xuICAgICAgaWYgKHVwZGF0ZSkge1xuICAgICAgICB0aGlzLmVtaXQoJ3VwZGF0ZScpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldE5ld0RpbWVuc2lvbnMnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmV3IGRpbWVuc2lvbnNcbiAgICAgKiBAcGFyYW0ge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwYXJhbSB7VmVjdG9yMn0gW2RpbWVuc2lvbnNdXG4gICAgICogQHJldHVybiB7VmVjdG9yMn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXROZXdEaW1lbnNpb25zKHJlbmRlcmVyLCBkaW1lbnNpb25zKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICBkaW1lbnNpb25zID0gZGltZW5zaW9ucyB8fCBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHJldHVybiBkaW1lbnNpb25zO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RpcnR5JyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhpcyBvcGVyYXRpb24gdG8gZGlydHksIHNvIHRoYXQgaXQgd2lsbCByZS1yZW5kZXIgbmV4dCB0aW1lXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBkaXJ0eSA9IHRydWVcbiAgICAgKi9cbiAgICBzZXQ6IGZ1bmN0aW9uIChkaXJ0eSkge1xuICAgICAgdGhpcy5fZGlydHkgPSBkaXJ0eTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZGlydHkgc3RhdGVcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9kaXJ0eTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gT3BlcmF0aW9uO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuT3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyID0gbnVsbDtcbk9wZXJhdGlvbi5leHRlbmQgPSBfbGliRXh0ZW5kMlsnZGVmYXVsdCddO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9vcGVyYXRpb24uanNcbiAqKiBtb2R1bGUgaWQgPSA4XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX29wZXJhdGlvbiA9IHJlcXVpcmUoJy4vb3BlcmF0aW9uJyk7XG5cbnZhciBfb3BlcmF0aW9uMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX29wZXJhdGlvbik7XG5cbnZhciBfZmlsdGVyc0lkZW50aXR5RmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXJzL2lkZW50aXR5LWZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcnNJZGVudGl0eUZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXJzSWRlbnRpdHlGaWx0ZXIpO1xuXG4vKipcbiAqIEFuIG9wZXJhdGlvbiB0aGF0IGNhbiBhcHBseSBhIHNlbGVjdGVkIGZpbHRlclxuICpcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0Lk9wZXJhdGlvbnMuRmlsdGVyc09wZXJhdGlvblxuICogQGV4dGVuZHMgSW1nbHlLaXQuT3BlcmF0aW9uXG4gKi9cblxudmFyIEZpbHRlcnNPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gRmlsdGVyc09wZXJhdGlvbigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmlsdGVyc09wZXJhdGlvbik7XG5cbiAgICBpZiAoX09wZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICBfT3BlcmF0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEZpbHRlcnNPcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhGaWx0ZXJzT3BlcmF0aW9uLCBbe1xuICAgIGtleTogJ19yZW5kZXJXZWJHTCcsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXIgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgdGhpcy5fcmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlciB1c2luZyBDYW52YXMyRFxuICAgICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHRoaXMuX3JlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXIgKGFsbCByZW5kZXJlcnMgc3VwcG9ydGVkKVxuICAgICAqIEBwYXJhbSB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlcihyZW5kZXJlcikge1xuICAgICAgdGhpcy5fc2VsZWN0ZWRGaWx0ZXIucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRmlsdGVyc09wZXJhdGlvbjtcbn0pKF9vcGVyYXRpb24yWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICogb3BlcmF0aW9ucy5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cbkZpbHRlcnNPcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAnZmlsdGVycyc7XG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhpcyBvcGVyYXRpb25cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbkZpbHRlcnNPcGVyYXRpb24ucHJvdG90eXBlLmF2YWlsYWJsZU9wdGlvbnMgPSB7XG4gIGZpbHRlcjogeyB0eXBlOiAnb2JqZWN0JywgJ2RlZmF1bHQnOiBfZmlsdGVyc0lkZW50aXR5RmlsdGVyMlsnZGVmYXVsdCddLFxuICAgIHNldHRlcjogZnVuY3Rpb24gc2V0dGVyKEZpbHRlcikge1xuICAgICAgdGhpcy5fc2VsZWN0ZWRGaWx0ZXIgPSBuZXcgRmlsdGVyKCk7XG4gICAgICByZXR1cm4gRmlsdGVyO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRmlsdGVyc09wZXJhdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMtb3BlcmF0aW9uLmpzXG4gKiogbW9kdWxlIGlkID0gOVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxuLyoqXG4gKiBBbiBvcGVyYXRpb24gdGhhdCBjYW4gY3JvcCBvdXQgYSBwYXJ0IG9mIHRoZSBpbWFnZVxuICpcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0Lk9wZXJhdGlvbnMuQ3JvcE9wZXJhdGlvblxuICogQGV4dGVuZHMgSW1nbHlLaXQuT3BlcmF0aW9uXG4gKi9cblxudmFyIENyb3BPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gQ3JvcE9wZXJhdGlvbigpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ3JvcE9wZXJhdGlvbik7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihDcm9wT3BlcmF0aW9uLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciB1c2VkIGZvciB0aGlzIG9wZXJhdGlvblxuICAgICAqL1xuICAgIHRoaXMuZnJhZ21lbnRTaGFkZXIgPSAnXFxuICAgICAgcHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHZlYzIgdV9jcm9wU3RhcnQ7XFxuICAgICAgdW5pZm9ybSB2ZWMyIHVfY3JvcEVuZDtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWMyIHNpemUgPSB1X2Nyb3BFbmQgLSB1X2Nyb3BTdGFydDtcXG4gICAgICAgIGdsX0ZyYWdDb2xvciA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleENvb3JkICogc2l6ZSArIHVfY3JvcFN0YXJ0KTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoQ3JvcE9wZXJhdGlvbiwgX09wZXJhdGlvbik7XG5cbiAgX2NyZWF0ZUNsYXNzKENyb3BPcGVyYXRpb24sIFt7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIFJvdGF0ZXMgYW5kIGNyb3BzIHRoZSBpbWFnZSB1c2luZyBXZWJHTFxuICAgICAqIEBwYXJhbSAge1dlYkdMUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQG92ZXJyaWRlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBjYW52YXNTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICB2YXIgc3RhcnQgPSB0aGlzLl9vcHRpb25zLnN0YXJ0LmNsb25lKCk7XG4gICAgICB2YXIgZW5kID0gdGhpcy5fb3B0aW9ucy5lbmQuY2xvbmUoKTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMubnVtYmVyRm9ybWF0ID09PSAnYWJzb2x1dGUnKSB7XG4gICAgICAgIHN0YXJ0LmRpdmlkZShjYW52YXNTaXplKTtcbiAgICAgICAgZW5kLmRpdmlkZShjYW52YXNTaXplKTtcbiAgICAgIH1cblxuICAgICAgLy8gMC4uMSA+IDEuLjAgb24geS1heGlzXG4gICAgICB2YXIgb3JpZ2luYWxTdGFydFkgPSBzdGFydC55O1xuICAgICAgc3RhcnQueSA9IDEgLSBlbmQueTtcbiAgICAgIGVuZC55ID0gMSAtIG9yaWdpbmFsU3RhcnRZO1xuXG4gICAgICAvLyBUaGUgbmV3IHNpemVcbiAgICAgIHZhciBuZXdEaW1lbnNpb25zID0gdGhpcy5nZXROZXdEaW1lbnNpb25zKHJlbmRlcmVyKTtcblxuICAgICAgLy8gUmVzaXplIHRoZSBjYW52YXNcbiAgICAgIGNhbnZhcy53aWR0aCA9IG5ld0RpbWVuc2lvbnMueDtcbiAgICAgIGNhbnZhcy5oZWlnaHQgPSBuZXdEaW1lbnNpb25zLnk7XG5cbiAgICAgIC8vIFJ1biB0aGUgY3JvcHBpbmcgc2hhZGVyXG4gICAgICByZW5kZXJlci5ydW5TaGFkZXIobnVsbCwgdGhpcy5mcmFnbWVudFNoYWRlciwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfY3JvcFN0YXJ0OiB7IHR5cGU6ICcyZicsIHZhbHVlOiBbc3RhcnQueCwgc3RhcnQueV0gfSxcbiAgICAgICAgICB1X2Nyb3BFbmQ6IHsgdHlwZTogJzJmJywgdmFsdWU6IFtlbmQueCwgZW5kLnldIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBDcm9wcyB0aGUgaW1hZ2UgdXNpbmcgQ2FudmFzXG4gICAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgZGltZW5zaW9ucyA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgdmFyIG5ld0RpbWVuc2lvbnMgPSB0aGlzLmdldE5ld0RpbWVuc2lvbnMocmVuZGVyZXIpO1xuXG4gICAgICAvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgY2FudmFzIHRvIGRyYXcgdG9cbiAgICAgIHZhciBuZXdDYW52YXMgPSByZW5kZXJlci5jcmVhdGVDYW52YXMoKTtcbiAgICAgIG5ld0NhbnZhcy53aWR0aCA9IG5ld0RpbWVuc2lvbnMueDtcbiAgICAgIG5ld0NhbnZhcy5oZWlnaHQgPSBuZXdEaW1lbnNpb25zLnk7XG4gICAgICB2YXIgbmV3Q29udGV4dCA9IG5ld0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAvLyBUaGUgdXBwZXIgbGVmdCBjb3JuZXIgb2YgdGhlIGNyb3BwZWQgYXJlYSBvbiB0aGUgb3JpZ2luYWwgaW1hZ2VcbiAgICAgIHZhciBzdGFydFBvc2l0aW9uID0gdGhpcy5fb3B0aW9ucy5zdGFydC5jbG9uZSgpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgc3RhcnRQb3NpdGlvbi5tdWx0aXBseShkaW1lbnNpb25zKTtcbiAgICAgIH1cblxuICAgICAgLy8gRHJhdyB0aGUgc291cmNlIGNhbnZhcyBvbnRvIHRoZSBuZXcgb25lXG4gICAgICBuZXdDb250ZXh0LmRyYXdJbWFnZShjYW52YXMsIHN0YXJ0UG9zaXRpb24ueCwgc3RhcnRQb3NpdGlvbi55LCAvLyBzb3VyY2UgeCwgeVxuICAgICAgbmV3RGltZW5zaW9ucy54LCBuZXdEaW1lbnNpb25zLnksIC8vIHNvdXJjZSBkaW1lbnNpb25zXG4gICAgICAwLCAwLCAvLyBkZXN0aW5hdGlvbiB4LCB5XG4gICAgICBuZXdEaW1lbnNpb25zLngsIG5ld0RpbWVuc2lvbnMueSAvLyBkZXN0aW5hdGlvbiBkaW1lbnNpb25zXG4gICAgICApO1xuXG4gICAgICAvLyBTZXQgdGhlIG5ldyBjYW52YXNcbiAgICAgIHJlbmRlcmVyLnNldENhbnZhcyhuZXdDYW52YXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldE5ld0RpbWVuc2lvbnMnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmV3IGRpbWVuc2lvbnNcbiAgICAgKiBAcGFyYW0ge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwYXJhbSB7VmVjdG9yMn0gW2RpbWVuc2lvbnNdXG4gICAgICogQHJldHVybiB7VmVjdG9yMn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TmV3RGltZW5zaW9ucyhyZW5kZXJlciwgZGltZW5zaW9ucykge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgZGltZW5zaW9ucyA9IGRpbWVuc2lvbnMgfHwgbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICB2YXIgbmV3RGltZW5zaW9ucyA9IHRoaXMuX29wdGlvbnMuZW5kLmNsb25lKCkuc3VidHJhY3QodGhpcy5fb3B0aW9ucy5zdGFydCk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLm51bWJlckZvcm1hdCA9PT0gJ3JlbGF0aXZlJykge1xuICAgICAgICBuZXdEaW1lbnNpb25zLm11bHRpcGx5KGRpbWVuc2lvbnMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3RGltZW5zaW9ucztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQ3JvcE9wZXJhdGlvbjtcbn0pKF9vcGVyYXRpb24yWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICogb3BlcmF0aW9ucy5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cbkNyb3BPcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAnY3JvcCc7XG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhpcyBvcGVyYXRpb25cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbkNyb3BPcGVyYXRpb24ucHJvdG90eXBlLmF2YWlsYWJsZU9wdGlvbnMgPSB7XG4gIHN0YXJ0OiB7IHR5cGU6ICd2ZWN0b3IyJywgcmVxdWlyZWQ6IHRydWUsICdkZWZhdWx0JzogbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKSB9LFxuICBlbmQ6IHsgdHlwZTogJ3ZlY3RvcjInLCByZXF1aXJlZDogdHJ1ZSwgJ2RlZmF1bHQnOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDEsIDEpIH1cbn07XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENyb3BPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9jcm9wLW9wZXJhdGlvbi5qc1xuICoqIG1vZHVsZSBpZCA9IDEwXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gsIF94MiwgX3gzKSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94LCBwcm9wZXJ0eSA9IF94MiwgcmVjZWl2ZXIgPSBfeDM7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94ID0gcGFyZW50OyBfeDIgPSBwcm9wZXJ0eTsgX3gzID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX29wZXJhdGlvbiA9IHJlcXVpcmUoJy4vb3BlcmF0aW9uJyk7XG5cbnZhciBfb3BlcmF0aW9uMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX29wZXJhdGlvbik7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG4vKipcbiAqIEFuIG9wZXJhdGlvbiB0aGF0IGNhbiBjcm9wIG91dCBhIHBhcnQgb2YgdGhlIGltYWdlIGFuZCByb3RhdGVzIGl0XG4gKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5Sb3RhdGlvbk9wZXJhdGlvblxuICogQGV4dGVuZHMgSW1nbHlLaXQuT3BlcmF0aW9uXG4gKi9cblxudmFyIFJvdGF0aW9uT3BlcmF0aW9uID0gKGZ1bmN0aW9uIChfT3BlcmF0aW9uKSB7XG4gIGZ1bmN0aW9uIFJvdGF0aW9uT3BlcmF0aW9uKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSb3RhdGlvbk9wZXJhdGlvbik7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihSb3RhdGlvbk9wZXJhdGlvbi5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBmcmFnbWVudCBzaGFkZXIgdXNlZCBmb3IgdGhpcyBvcGVyYXRpb25cbiAgICAgKi9cbiAgICB0aGlzLnZlcnRleFNoYWRlciA9ICdcXG4gICAgICBhdHRyaWJ1dGUgdmVjMiBhX3Bvc2l0aW9uO1xcbiAgICAgIGF0dHJpYnV0ZSB2ZWMyIGFfdGV4Q29vcmQ7XFxuICAgICAgdmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XFxuICAgICAgdW5pZm9ybSBtYXQzIHVfbWF0cml4O1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIGdsX1Bvc2l0aW9uID0gdmVjNCgodV9tYXRyaXggKiB2ZWMzKGFfcG9zaXRpb24sIDEpKS54eSwgMCwgMSk7XFxuICAgICAgICB2X3RleENvb3JkID0gYV90ZXhDb29yZDtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoUm90YXRpb25PcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhSb3RhdGlvbk9wZXJhdGlvbiwgW3tcbiAgICBrZXk6ICdfcmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUm90YXRlcyB0aGUgaW1hZ2UgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuXG4gICAgICB2YXIgYWN0dWFsRGVncmVlcyA9IHRoaXMuX29wdGlvbnMuZGVncmVlcyAlIDM2MDtcblxuICAgICAgLy8gSWYgd2UncmUgbm90IHJvdGF0aW5nIGJ5IDE4MCBkZWdyZWVzLCB3ZSBuZWVkIHRvIHJlc2l6ZSB0aGUgY2FudmFzXG4gICAgICAvLyBhbmQgdGhlIHRleHR1cmVcbiAgICAgIGlmIChhY3R1YWxEZWdyZWVzICUgMTgwICE9PSAwKSB7XG4gICAgICAgIHZhciBuZXdEaW1lbnNpb25zID0gdGhpcy5nZXROZXdEaW1lbnNpb25zKHJlbmRlcmVyKTtcblxuICAgICAgICAvLyBSZXNpemUgdGhlIGNhbnZhc1xuICAgICAgICBjYW52YXMud2lkdGggPSBuZXdEaW1lbnNpb25zLng7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBuZXdEaW1lbnNpb25zLnk7XG4gICAgICB9XG5cbiAgICAgIC8vIEJ1aWxkIHRoZSByb3RhdGlvbiBtYXRyaXhcbiAgICAgIHZhciByYWRpYW5zID0gYWN0dWFsRGVncmVlcyAqIChNYXRoLlBJIC8gMTgwKTtcbiAgICAgIHZhciBjID0gTWF0aC5jb3MocmFkaWFucyk7XG4gICAgICB2YXIgcyA9IE1hdGguc2luKHJhZGlhbnMpO1xuICAgICAgdmFyIHJvdGF0aW9uTWF0cml4ID0gW2MsIC1zLCAwLCBzLCBjLCAwLCAwLCAwLCAxXTtcblxuICAgICAgLy8gUnVuIHRoZSBzaGFkZXJcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcih0aGlzLnZlcnRleFNoYWRlciwgbnVsbCwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfbWF0cml4OiB7IHR5cGU6ICdtYXQzZnYnLCB2YWx1ZTogcm90YXRpb25NYXRyaXggfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIENyb3BzIHRoZSBpbWFnZSB1c2luZyBDYW52YXMyRFxuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG5cbiAgICAgIHZhciBhY3R1YWxEZWdyZWVzID0gdGhpcy5fb3B0aW9ucy5kZWdyZWVzICUgMzYwO1xuICAgICAgdmFyIG5ld0RpbWVuc2lvbnMgPSB0aGlzLmdldE5ld0RpbWVuc2lvbnMocmVuZGVyZXIpO1xuXG4gICAgICAvLyBDcmVhdGUgYSByb3RhdGVkIGNhbnZhc1xuICAgICAgdmFyIG5ld0NhbnZhcyA9IHJlbmRlcmVyLmNyZWF0ZUNhbnZhcygpO1xuICAgICAgbmV3Q2FudmFzLndpZHRoID0gbmV3RGltZW5zaW9ucy54O1xuICAgICAgbmV3Q2FudmFzLmhlaWdodCA9IG5ld0RpbWVuc2lvbnMueTtcbiAgICAgIHZhciBuZXdDb250ZXh0ID0gbmV3Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIG5ld0NvbnRleHQuc2F2ZSgpO1xuXG4gICAgICAvLyBUcmFuc2xhdGUgdGhlIGNhbnZhc1xuICAgICAgbmV3Q29udGV4dC50cmFuc2xhdGUobmV3Q2FudmFzLndpZHRoIC8gMiwgbmV3Q2FudmFzLmhlaWdodCAvIDIpO1xuXG4gICAgICAvLyBSb3RhdGUgdGhlIGNhbnZhc1xuICAgICAgbmV3Q29udGV4dC5yb3RhdGUoYWN0dWFsRGVncmVlcyAqIChNYXRoLlBJIC8gMTgwKSk7XG5cbiAgICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBjYW52YXMgc28gdGhhdCB3ZSBjYW4gZHJhdyB0aGUgaW1hZ2VcbiAgICAgIC8vIHdpdGggdGhlIGFwcGxpZWQgdHJhbnNmb3JtYXRpb25cbiAgICAgIHZhciB0ZW1wQ2FudmFzID0gcmVuZGVyZXIuY2xvbmVDYW52YXMoKTtcbiAgICAgIG5ld0NvbnRleHQuZHJhd0ltYWdlKHRlbXBDYW52YXMsIC1jYW52YXMud2lkdGggLyAyLCAtY2FudmFzLmhlaWdodCAvIDIpO1xuXG4gICAgICAvLyBSZXN0b3JlIG9sZCB0cmFuc2Zvcm1hdGlvblxuICAgICAgbmV3Q29udGV4dC5yZXN0b3JlKCk7XG5cbiAgICAgIHJlbmRlcmVyLnNldENhbnZhcyhuZXdDYW52YXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldE5ld0RpbWVuc2lvbnMnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmV3IGRpbWVuc2lvbnNcbiAgICAgKiBAcGFyYW0ge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwYXJhbSB7VmVjdG9yMn0gW2RpbWVuc2lvbnNdXG4gICAgICogQHJldHVybiB7VmVjdG9yMn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TmV3RGltZW5zaW9ucyhyZW5kZXJlciwgZGltZW5zaW9ucykge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgZGltZW5zaW9ucyA9IGRpbWVuc2lvbnMgfHwgbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICB2YXIgYWN0dWFsRGVncmVlcyA9IHRoaXMuX29wdGlvbnMuZGVncmVlcyAlIDM2MDtcbiAgICAgIGlmIChhY3R1YWxEZWdyZWVzICUgMTgwICE9PSAwKSB7XG4gICAgICAgIHZhciB0ZW1wWCA9IGRpbWVuc2lvbnMueDtcbiAgICAgICAgZGltZW5zaW9ucy54ID0gZGltZW5zaW9ucy55O1xuICAgICAgICBkaW1lbnNpb25zLnkgPSB0ZW1wWDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRpbWVuc2lvbnM7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFJvdGF0aW9uT3BlcmF0aW9uO1xufSkoX29wZXJhdGlvbjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuUm90YXRpb25PcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAncm90YXRpb24nO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5Sb3RhdGlvbk9wZXJhdGlvbi5wcm90b3R5cGUuYXZhaWxhYmxlT3B0aW9ucyA9IHtcbiAgZGVncmVlczogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAwLCB2YWxpZGF0aW9uOiBmdW5jdGlvbiB2YWxpZGF0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAodmFsdWUgJSA5MCAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JvdGF0aW9uT3BlcmF0aW9uOiBgcm90YXRpb25gIGhhcyB0byBiZSBhIG11bHRpcGxlIG9mIDkwLicpO1xuICAgICAgfVxuICAgIH0gfVxufTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUm90YXRpb25PcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9yb3RhdGlvbi1vcGVyYXRpb24uanNcbiAqKiBtb2R1bGUgaWQgPSAxMVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2ZpbHRlcnNQcmltaXRpdmVzU3RhY2sgPSByZXF1aXJlKCcuL2ZpbHRlcnMvcHJpbWl0aXZlcy1zdGFjaycpO1xuXG52YXIgX2ZpbHRlcnNQcmltaXRpdmVzU3RhY2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyc1ByaW1pdGl2ZXNTdGFjayk7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNTYXR1cmF0aW9uID0gcmVxdWlyZSgnLi9maWx0ZXJzL3ByaW1pdGl2ZXMvc2F0dXJhdGlvbicpO1xuXG52YXIgX2ZpbHRlcnNQcmltaXRpdmVzU2F0dXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXJzUHJpbWl0aXZlc1NhdHVyYXRpb24pO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0Lk9wZXJhdGlvbnMuU2F0dXJhdGlvbk9wZXJhdGlvblxuICogQGV4dGVuZHMgSW1nbHlLaXQuT3BlcmF0aW9uXG4gKi9cblxudmFyIFNhdHVyYXRpb25PcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gU2F0dXJhdGlvbk9wZXJhdGlvbigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU2F0dXJhdGlvbk9wZXJhdGlvbik7XG5cbiAgICBpZiAoX09wZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICBfT3BlcmF0aW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKFNhdHVyYXRpb25PcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhTYXR1cmF0aW9uT3BlcmF0aW9uLCBbe1xuICAgIGtleTogJ19yZW5kZXJXZWJHTCcsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBzYXR1cmF0aW9uIHVzaW5nIFdlYkdMXG4gICAgICogQHBhcmFtICB7V2ViR0xSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHRoaXMuX3JlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBzYXR1cmF0aW9uIHVzaW5nIENhbnZhczJEXG4gICAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdGhpcy5fcmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHNhdHVyYXRpb24gKGFsbCByZW5kZXJlcnMgc3VwcG9ydGVkKVxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIGlmICghdGhpcy5fc3RhY2spIHtcbiAgICAgICAgdGhpcy5fc3RhY2sgPSBuZXcgX2ZpbHRlcnNQcmltaXRpdmVzU3RhY2syWydkZWZhdWx0J10oKTtcbiAgICAgICAgdGhpcy5fcHJpbWl0aXZlID0gbmV3IF9maWx0ZXJzUHJpbWl0aXZlc1NhdHVyYXRpb24yWydkZWZhdWx0J10oe1xuICAgICAgICAgIHNhdHVyYXRpb246IHRoaXMuX29wdGlvbnMuc2F0dXJhdGlvblxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fc3RhY2suYWRkKHRoaXMuX3ByaW1pdGl2ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEBUT0RPXG4gICAgICAvLyBQcmltaXRpdmVzIHNob3VsZCBoYXZlIHRoZSBzYW1lIG9wdGlvbiBsb2dpYyBhcyBvcGVyYXRpb25zIC0gd2hpY2hcbiAgICAgIC8vIHNob3VsZCBhbGxvdyB1cyB0byBkbyBgdGhpcy5fcHJpbWl0aXZlLnNldFNhdHVyYXRpb25gXG4gICAgICB0aGlzLl9wcmltaXRpdmUub3B0aW9ucy5zYXR1cmF0aW9uID0gdGhpcy5fb3B0aW9ucy5zYXR1cmF0aW9uO1xuICAgICAgdGhpcy5fc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gU2F0dXJhdGlvbk9wZXJhdGlvbjtcbn0pKF9vcGVyYXRpb24yWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICogb3BlcmF0aW9ucy5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cblNhdHVyYXRpb25PcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAnc2F0dXJhdGlvbic7XG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhpcyBvcGVyYXRpb25cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cblNhdHVyYXRpb25PcGVyYXRpb24ucHJvdG90eXBlLmF2YWlsYWJsZU9wdGlvbnMgPSB7XG4gIHNhdHVyYXRpb246IHsgdHlwZTogJ251bWJlcicsICdkZWZhdWx0JzogMSB9XG59O1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTYXR1cmF0aW9uT3BlcmF0aW9uO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvc2F0dXJhdGlvbi1vcGVyYXRpb24uanNcbiAqKiBtb2R1bGUgaWQgPSAxMlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2ZpbHRlcnNQcmltaXRpdmVzU3RhY2sgPSByZXF1aXJlKCcuL2ZpbHRlcnMvcHJpbWl0aXZlcy1zdGFjaycpO1xuXG52YXIgX2ZpbHRlcnNQcmltaXRpdmVzU3RhY2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyc1ByaW1pdGl2ZXNTdGFjayk7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNDb250cmFzdCA9IHJlcXVpcmUoJy4vZmlsdGVycy9wcmltaXRpdmVzL2NvbnRyYXN0Jyk7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNDb250cmFzdDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXJzUHJpbWl0aXZlc0NvbnRyYXN0KTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5PcGVyYXRpb25zLkNvbnRyYXN0T3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgQ29udHJhc3RPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gQ29udHJhc3RPcGVyYXRpb24oKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbnRyYXN0T3BlcmF0aW9uKTtcblxuICAgIGlmIChfT3BlcmF0aW9uICE9IG51bGwpIHtcbiAgICAgIF9PcGVyYXRpb24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQ29udHJhc3RPcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhDb250cmFzdE9wZXJhdGlvbiwgW3tcbiAgICBrZXk6ICdfcmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY29udHJhc3QgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgdGhpcy5fcmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGNvbnRyYXN0IHVzaW5nIENhbnZhczJEXG4gICAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdGhpcy5fcmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGNvbnRyYXN0IChhbGwgcmVuZGVyZXJzIHN1cHBvcnRlZClcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICBpZiAoIXRoaXMuX3N0YWNrKSB7XG4gICAgICAgIHRoaXMuX3N0YWNrID0gbmV3IF9maWx0ZXJzUHJpbWl0aXZlc1N0YWNrMlsnZGVmYXVsdCddKCk7XG4gICAgICAgIHRoaXMuX3ByaW1pdGl2ZSA9IG5ldyBfZmlsdGVyc1ByaW1pdGl2ZXNDb250cmFzdDJbJ2RlZmF1bHQnXSh7XG4gICAgICAgICAgY29udHJhc3Q6IHRoaXMuX29wdGlvbnMuY29udHJhc3RcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX3N0YWNrLmFkZCh0aGlzLl9wcmltaXRpdmUpO1xuICAgICAgfVxuXG4gICAgICAvLyBAVE9ET1xuICAgICAgLy8gUHJpbWl0aXZlcyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBvcHRpb24gbG9naWMgYXMgb3BlcmF0aW9ucyAtIHdoaWNoXG4gICAgICAvLyBzaG91bGQgYWxsb3cgdXMgdG8gZG8gYHRoaXMuX3ByaW1pdGl2ZS5zZXRDb250cmFzdGBcbiAgICAgIHRoaXMuX3ByaW1pdGl2ZS5vcHRpb25zLmNvbnRyYXN0ID0gdGhpcy5fb3B0aW9ucy5jb250cmFzdDtcbiAgICAgIHRoaXMuX3N0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENvbnRyYXN0T3BlcmF0aW9uO1xufSkoX29wZXJhdGlvbjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuQ29udHJhc3RPcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAnY29udHJhc3QnO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5Db250cmFzdE9wZXJhdGlvbi5wcm90b3R5cGUuYXZhaWxhYmxlT3B0aW9ucyA9IHtcbiAgY29udHJhc3Q6IHsgdHlwZTogJ251bWJlcicsICdkZWZhdWx0JzogMSB9XG59O1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBDb250cmFzdE9wZXJhdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2NvbnRyYXN0LW9wZXJhdGlvbi5qc1xuICoqIG1vZHVsZSBpZCA9IDEzXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX29wZXJhdGlvbiA9IHJlcXVpcmUoJy4vb3BlcmF0aW9uJyk7XG5cbnZhciBfb3BlcmF0aW9uMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX29wZXJhdGlvbik7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNTdGFjayA9IHJlcXVpcmUoJy4vZmlsdGVycy9wcmltaXRpdmVzLXN0YWNrJyk7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNTdGFjazIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXJzUHJpbWl0aXZlc1N0YWNrKTtcblxudmFyIF9maWx0ZXJzUHJpbWl0aXZlc0JyaWdodG5lc3MgPSByZXF1aXJlKCcuL2ZpbHRlcnMvcHJpbWl0aXZlcy9icmlnaHRuZXNzJyk7XG5cbnZhciBfZmlsdGVyc1ByaW1pdGl2ZXNCcmlnaHRuZXNzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcnNQcmltaXRpdmVzQnJpZ2h0bmVzcyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5CcmlnaHRuZXNzT3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgQnJpZ2h0bmVzc09wZXJhdGlvbiA9IChmdW5jdGlvbiAoX09wZXJhdGlvbikge1xuICBmdW5jdGlvbiBCcmlnaHRuZXNzT3BlcmF0aW9uKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBCcmlnaHRuZXNzT3BlcmF0aW9uKTtcblxuICAgIGlmIChfT3BlcmF0aW9uICE9IG51bGwpIHtcbiAgICAgIF9PcGVyYXRpb24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQnJpZ2h0bmVzc09wZXJhdGlvbiwgX09wZXJhdGlvbik7XG5cbiAgX2NyZWF0ZUNsYXNzKEJyaWdodG5lc3NPcGVyYXRpb24sIFt7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGJyaWdodG5lc3MgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgdGhpcy5fcmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGJyaWdodG5lc3MgdXNpbmcgQ2FudmFzMkRcbiAgICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB0aGlzLl9yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgYnJpZ2h0bmVzcyAoYWxsIHJlbmRlcmVycyBzdXBwb3J0ZWQpXG4gICAgICogQHBhcmFtIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICBpZiAoIXRoaXMuX3N0YWNrKSB7XG4gICAgICAgIHRoaXMuX3N0YWNrID0gbmV3IF9maWx0ZXJzUHJpbWl0aXZlc1N0YWNrMlsnZGVmYXVsdCddKCk7XG4gICAgICAgIHRoaXMuX3ByaW1pdGl2ZSA9IG5ldyBfZmlsdGVyc1ByaW1pdGl2ZXNCcmlnaHRuZXNzMlsnZGVmYXVsdCddKHtcbiAgICAgICAgICBicmlnaHRuZXNzOiB0aGlzLl9vcHRpb25zLmJyaWdodG5lc3NcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX3N0YWNrLmFkZCh0aGlzLl9wcmltaXRpdmUpO1xuICAgICAgfVxuXG4gICAgICAvLyBAVE9ET1xuICAgICAgLy8gUHJpbWl0aXZlcyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBvcHRpb24gbG9naWMgYXMgb3BlcmF0aW9ucyAtIHdoaWNoXG4gICAgICAvLyBzaG91bGQgYWxsb3cgdXMgdG8gZG8gYHRoaXMuX3ByaW1pdGl2ZS5zZXRCcmlnaHRuZXNzYFxuICAgICAgdGhpcy5fcHJpbWl0aXZlLm9wdGlvbnMuYnJpZ2h0bmVzcyA9IHRoaXMuX29wdGlvbnMuYnJpZ2h0bmVzcztcbiAgICAgIHRoaXMuX3N0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEJyaWdodG5lc3NPcGVyYXRpb247XG59KShfb3BlcmF0aW9uMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAqIG9wZXJhdGlvbnMuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5CcmlnaHRuZXNzT3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ2JyaWdodG5lc3MnO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5CcmlnaHRuZXNzT3BlcmF0aW9uLnByb3RvdHlwZS5hdmFpbGFibGVPcHRpb25zID0ge1xuICBicmlnaHRuZXNzOiB7IHR5cGU6ICdudW1iZXInLCAnZGVmYXVsdCc6IDAgfVxufTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQnJpZ2h0bmVzc09wZXJhdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2JyaWdodG5lc3Mtb3BlcmF0aW9uLmpzXG4gKiogbW9kdWxlIGlkID0gMTRcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfb3BlcmF0aW9uID0gcmVxdWlyZSgnLi9vcGVyYXRpb24nKTtcblxudmFyIF9vcGVyYXRpb24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfb3BlcmF0aW9uKTtcblxuLyoqXG4gKiBBbiBvcGVyYXRpb24gdGhhdCBjYW4gZmxpcCB0aGUgY2FudmFzXG4gKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5GbGlwT3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgRmxpcE9wZXJhdGlvbiA9IChmdW5jdGlvbiAoX09wZXJhdGlvbikge1xuICBmdW5jdGlvbiBGbGlwT3BlcmF0aW9uKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGbGlwT3BlcmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKEZsaXBPcGVyYXRpb24ucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIHVzZWQgZm9yIHRoaXMgb3BlcmF0aW9uXG4gICAgICovXG4gICAgdGhpcy5mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gYm9vbCB1X2ZsaXBWZXJ0aWNhbDtcXG4gICAgICB1bmlmb3JtIGJvb2wgdV9mbGlwSG9yaXpvbnRhbDtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWMyIHRleENvb3JkID0gdmVjMih2X3RleENvb3JkKTtcXG4gICAgICAgIGlmICh1X2ZsaXBWZXJ0aWNhbCkge1xcbiAgICAgICAgICB0ZXhDb29yZC55ID0gMS4wIC0gdGV4Q29vcmQueTtcXG4gICAgICAgIH1cXG4gICAgICAgIGlmICh1X2ZsaXBIb3Jpem9udGFsKSB7XFxuICAgICAgICAgIHRleENvb3JkLnggPSAxLjAgLSB0ZXhDb29yZC54O1xcbiAgICAgICAgfVxcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHRleENvb3JkKTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoRmxpcE9wZXJhdGlvbiwgX09wZXJhdGlvbik7XG5cbiAgX2NyZWF0ZUNsYXNzKEZsaXBPcGVyYXRpb24sIFt7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIENyb3BzIHRoaXMgaW1hZ2UgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgcmVuZGVyZXIucnVuU2hhZGVyKG51bGwsIHRoaXMuZnJhZ21lbnRTaGFkZXIsIHtcbiAgICAgICAgdW5pZm9ybXM6IHtcbiAgICAgICAgICB1X2ZsaXBWZXJ0aWNhbDogeyB0eXBlOiAnZicsIHZhbHVlOiB0aGlzLl9vcHRpb25zLnZlcnRpY2FsIH0sXG4gICAgICAgICAgdV9mbGlwSG9yaXpvbnRhbDogeyB0eXBlOiAnZicsIHZhbHVlOiB0aGlzLl9vcHRpb25zLmhvcml6b250YWwgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIENyb3BzIHRoZSBpbWFnZSB1c2luZyBDYW52YXMyRFxuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgY29udGV4dCA9IHJlbmRlcmVyLmdldENvbnRleHQoKTtcblxuICAgICAgdmFyIHNjYWxlWCA9IDEsXG4gICAgICAgICAgc2NhbGVZID0gMTtcbiAgICAgIHZhciB0cmFuc2xhdGVYID0gMCxcbiAgICAgICAgICB0cmFuc2xhdGVZID0gMDtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuaG9yaXpvbnRhbCkge1xuICAgICAgICBzY2FsZVggPSAtMTtcbiAgICAgICAgdHJhbnNsYXRlWCA9IGNhbnZhcy53aWR0aDtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudmVydGljYWwpIHtcbiAgICAgICAgc2NhbGVZID0gLTE7XG4gICAgICAgIHRyYW5zbGF0ZVkgPSBjYW52YXMuaGVpZ2h0O1xuICAgICAgfVxuXG4gICAgICAvLyBTYXZlIHRoZSBjdXJyZW50IHN0YXRlXG4gICAgICBjb250ZXh0LnNhdmUoKTtcblxuICAgICAgLy8gQXBwbHkgdGhlIHRyYW5zZm9ybWF0aW9uXG4gICAgICBjb250ZXh0LnRyYW5zbGF0ZSh0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKTtcbiAgICAgIGNvbnRleHQuc2NhbGUoc2NhbGVYLCBzY2FsZVkpO1xuXG4gICAgICAvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgY2FudmFzIHNvIHRoYXQgd2UgY2FuIGRyYXcgdGhlIGltYWdlXG4gICAgICAvLyB3aXRoIHRoZSBhcHBsaWVkIHRyYW5zZm9ybWF0aW9uXG4gICAgICB2YXIgdGVtcENhbnZhcyA9IHJlbmRlcmVyLmNsb25lQ2FudmFzKCk7XG4gICAgICBjb250ZXh0LmRyYXdJbWFnZSh0ZW1wQ2FudmFzLCAwLCAwKTtcblxuICAgICAgLy8gUmVzdG9yZSBvbGQgdHJhbnNmb3JtYXRpb25cbiAgICAgIGNvbnRleHQucmVzdG9yZSgpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBGbGlwT3BlcmF0aW9uO1xufSkoX29wZXJhdGlvbjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuRmxpcE9wZXJhdGlvbi5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdmbGlwJztcblxuLyoqXG4gKiBTcGVjaWZpZXMgdGhlIGF2YWlsYWJsZSBvcHRpb25zIGZvciB0aGlzIG9wZXJhdGlvblxuICogQHR5cGUge09iamVjdH1cbiAqL1xuRmxpcE9wZXJhdGlvbi5wcm90b3R5cGUuYXZhaWxhYmxlT3B0aW9ucyA9IHtcbiAgaG9yaXpvbnRhbDogeyB0eXBlOiAnYm9vbGVhbicsICdkZWZhdWx0JzogZmFsc2UgfSxcbiAgdmVydGljYWw6IHsgdHlwZTogJ2Jvb2xlYW4nLCAnZGVmYXVsdCc6IGZhbHNlIH1cbn07XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEZsaXBPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9mbGlwLW9wZXJhdGlvbi5qc1xuICoqIG1vZHVsZSBpZCA9IDE1XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9zZXQgPSBmdW5jdGlvbiBzZXQob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIHJlY2VpdmVyKSB7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgIT09IG51bGwpIHsgc2V0KHBhcmVudCwgcHJvcGVydHksIHZhbHVlLCByZWNlaXZlcik7IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MgJiYgZGVzYy53cml0YWJsZSkgeyBkZXNjLnZhbHVlID0gdmFsdWU7IH0gZWxzZSB7IHZhciBzZXR0ZXIgPSBkZXNjLnNldDsgaWYgKHNldHRlciAhPT0gdW5kZWZpbmVkKSB7IHNldHRlci5jYWxsKHJlY2VpdmVyLCB2YWx1ZSk7IH0gfSByZXR1cm4gdmFsdWU7IH07XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIF92ZW5kb3JTdGFja0JsdXIgPSByZXF1aXJlKCcuLi92ZW5kb3Ivc3RhY2stYmx1cicpO1xuXG52YXIgX3ZlbmRvclN0YWNrQmx1cjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF92ZW5kb3JTdGFja0JsdXIpO1xuXG4vKipcbiAqIEFuIG9wZXJhdGlvbiB0aGF0IGNhbiBjcm9wIG91dCBhIHBhcnQgb2YgdGhlIGltYWdlXG4gKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5UaWx0U2hpZnRPcGVyYXRpb25cbiAqIEBleHRlbmRzIEltZ2x5S2l0Lk9wZXJhdGlvblxuICovXG5cbnZhciBUaWx0U2hpZnRPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gVGlsdFNoaWZ0T3BlcmF0aW9uKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUaWx0U2hpZnRPcGVyYXRpb24pO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoVGlsdFNoaWZ0T3BlcmF0aW9uLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciB1c2VkIGZvciB0aGlzIG9wZXJhdGlvblxuICAgICAqIEBpbnRlcm5hbCBCYXNlZCBvbiBldmFudydzIGdsZnguanMgdGlsdCBzaGlmdCBzaGFkZXI6XG4gICAgICogICAgICAgICAgIGh0dHBzOi8vZ2l0aHViLmNvbS9ldmFudy9nbGZ4LmpzL2Jsb2IvbWFzdGVyL3NyYy9maWx0ZXJzL2JsdXIvdGlsdHNoaWZ0LmpzXG4gICAgICovXG4gICAgdGhpcy5fZnJhZ21lbnRTaGFkZXIgPSAnXFxuICAgICAgcHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG4gICAgICB1bmlmb3JtIGZsb2F0IGJsdXJSYWRpdXM7XFxuICAgICAgdW5pZm9ybSBmbG9hdCBncmFkaWVudFJhZGl1cztcXG4gICAgICB1bmlmb3JtIHZlYzIgc3RhcnQ7XFxuICAgICAgdW5pZm9ybSB2ZWMyIGVuZDtcXG4gICAgICB1bmlmb3JtIHZlYzIgZGVsdGE7XFxuICAgICAgdW5pZm9ybSB2ZWMyIHRleFNpemU7XFxuICAgICAgdmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XFxuXFxuICAgICAgZmxvYXQgcmFuZG9tKHZlYzMgc2NhbGUsIGZsb2F0IHNlZWQpIHtcXG4gICAgICAgIHJldHVybiBmcmFjdChzaW4oZG90KGdsX0ZyYWdDb29yZC54eXogKyBzZWVkLCBzY2FsZSkpICogNDM3NTguNTQ1MyArIHNlZWQpO1xcbiAgICAgIH1cXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICAgIHZlYzQgY29sb3IgPSB2ZWM0KDAuMCk7XFxuICAgICAgICAgIGZsb2F0IHRvdGFsID0gMC4wO1xcblxcbiAgICAgICAgICBmbG9hdCBvZmZzZXQgPSByYW5kb20odmVjMygxMi45ODk4LCA3OC4yMzMsIDE1MS43MTgyKSwgMC4wKTtcXG5cXG4gICAgICAgICAgdmVjMiBub3JtYWwgPSBub3JtYWxpemUodmVjMihzdGFydC55IC0gZW5kLnksIGVuZC54IC0gc3RhcnQueCkpO1xcbiAgICAgICAgICBmbG9hdCByYWRpdXMgPSBzbW9vdGhzdGVwKDAuMCwgMS4wLCBhYnMoZG90KHZfdGV4Q29vcmQgKiB0ZXhTaXplIC0gc3RhcnQsIG5vcm1hbCkpIC8gZ3JhZGllbnRSYWRpdXMpICogYmx1clJhZGl1cztcXG4gICAgICAgICAgZm9yIChmbG9hdCB0ID0gLTMwLjA7IHQgPD0gMzAuMDsgdCsrKSB7XFxuICAgICAgICAgICAgICBmbG9hdCBwZXJjZW50ID0gKHQgKyBvZmZzZXQgLSAwLjUpIC8gMzAuMDtcXG4gICAgICAgICAgICAgIGZsb2F0IHdlaWdodCA9IDEuMCAtIGFicyhwZXJjZW50KTtcXG4gICAgICAgICAgICAgIHZlYzQgc2FtcGxlID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQgKyBkZWx0YSAqIHBlcmNlbnQgKiByYWRpdXMgLyB0ZXhTaXplKTtcXG5cXG4gICAgICAgICAgICAgIHNhbXBsZS5yZ2IgKj0gc2FtcGxlLmE7XFxuXFxuICAgICAgICAgICAgICBjb2xvciArPSBzYW1wbGUgKiB3ZWlnaHQ7XFxuICAgICAgICAgICAgICB0b3RhbCArPSB3ZWlnaHQ7XFxuICAgICAgICAgIH1cXG5cXG4gICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gY29sb3IgLyB0b3RhbDtcXG4gICAgICAgICAgZ2xfRnJhZ0NvbG9yLnJnYiAvPSBnbF9GcmFnQ29sb3IuYSArIDAuMDAwMDE7XFxuICAgICAgfVxcbiAgICAnO1xuXG4gICAgdGhpcy5fY2FjaGVkQmx1cnJlZENhbnZhcyA9IG51bGw7XG4gICAgdGhpcy5fbGFzdEJsdXJSYWRpdXMgPSB0aGlzLl9vcHRpb25zLmJsdXJSYWRpdXM7XG4gICAgdGhpcy5fbGFzdEdyYWRpZW50UmFkaXVzID0gdGhpcy5fb3B0aW9ucy5ncmFkaWVudFJhZGl1cztcbiAgfVxuXG4gIF9pbmhlcml0cyhUaWx0U2hpZnRPcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhUaWx0U2hpZnRPcGVyYXRpb24sIFt7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIENyb3BzIHRoaXMgaW1hZ2UgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHZhciBzdGFydCA9IHRoaXMuX29wdGlvbnMuc3RhcnQuY2xvbmUoKTtcbiAgICAgIHZhciBlbmQgPSB0aGlzLl9vcHRpb25zLmVuZC5jbG9uZSgpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgc3RhcnQubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG4gICAgICAgIGVuZC5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIH1cblxuICAgICAgc3RhcnQueSA9IGNhbnZhc1NpemUueSAtIHN0YXJ0Lnk7XG4gICAgICBlbmQueSA9IGNhbnZhc1NpemUueSAtIGVuZC55O1xuXG4gICAgICB2YXIgZGVsdGEgPSBlbmQuY2xvbmUoKS5zdWJ0cmFjdChzdGFydCk7XG4gICAgICB2YXIgZCA9IE1hdGguc3FydChkZWx0YS54ICogZGVsdGEueCArIGRlbHRhLnkgKiBkZWx0YS55KTtcblxuICAgICAgdmFyIHVuaWZvcm1zID0ge1xuICAgICAgICBibHVyUmFkaXVzOiB7IHR5cGU6ICdmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuYmx1clJhZGl1cyB9LFxuICAgICAgICBncmFkaWVudFJhZGl1czogeyB0eXBlOiAnZicsIHZhbHVlOiB0aGlzLl9vcHRpb25zLmdyYWRpZW50UmFkaXVzIH0sXG4gICAgICAgIHN0YXJ0OiB7IHR5cGU6ICcyZicsIHZhbHVlOiBbc3RhcnQueCwgc3RhcnQueV0gfSxcbiAgICAgICAgZW5kOiB7IHR5cGU6ICcyZicsIHZhbHVlOiBbZW5kLngsIGVuZC55XSB9LFxuICAgICAgICBkZWx0YTogeyB0eXBlOiAnMmYnLCB2YWx1ZTogW2RlbHRhLnggLyBkLCBkZWx0YS55IC8gZF0gfSxcbiAgICAgICAgdGV4U2l6ZTogeyB0eXBlOiAnMmYnLCB2YWx1ZTogW2NhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodF0gfVxuICAgICAgfTtcblxuICAgICAgaWYgKCF0aGlzLl9nbHNsUHJvZ3JhbXNbcmVuZGVyZXIuaWRdKSB7XG4gICAgICAgIHRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0gPSByZW5kZXJlci5zZXR1cEdMU0xQcm9ncmFtKG51bGwsIHRoaXMuX2ZyYWdtZW50U2hhZGVyKTtcbiAgICAgIH1cblxuICAgICAgcmVuZGVyZXIucnVuUHJvZ3JhbSh0aGlzLl9nbHNsUHJvZ3JhbXNbcmVuZGVyZXIuaWRdLCB7IHVuaWZvcm1zOiB1bmlmb3JtcyB9KTtcblxuICAgICAgLy8gVXBkYXRlIGRlbHRhIGZvciBzZWNvbmQgcGFzc1xuICAgICAgdW5pZm9ybXMuZGVsdGEudmFsdWUgPSBbLWRlbHRhLnkgLyBkLCBkZWx0YS54IC8gZF07XG5cbiAgICAgIHJlbmRlcmVyLnJ1blByb2dyYW0odGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSwgeyB1bmlmb3JtczogdW5pZm9ybXMgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBDcm9wcyB0aGUgaW1hZ2UgdXNpbmcgQ2FudmFzMkRcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuXG4gICAgICB2YXIgb3B0aW9uc0NoYW5nZWQgPSB0aGlzLl9vcHRpb25zLmJsdXJSYWRpdXMgIT09IHRoaXMuX2xhc3RCbHVyUmFkaXVzIHx8IHRoaXMuX29wdGlvbnMuZ3JhZGllbnRSYWRpdXMgIT09IHRoaXMuX2xhc3RHcmFkaWVudFJhZGl1cztcbiAgICAgIHZhciBibHVycnlDYW52YXMgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAob3B0aW9uc0NoYW5nZWQgfHwgdGhpcy5fY2FjaGVkQmx1cnJlZENhbnZhcyA9PT0gbnVsbCkge1xuICAgICAgICAvLyBCbHVyIGFuZCBjYWNoZSBjYW52YXNcbiAgICAgICAgYmx1cnJ5Q2FudmFzID0gdGhpcy5fYmx1ckNhbnZhcyhyZW5kZXJlcik7XG4gICAgICAgIHRoaXMuX2NhY2hlZEJsdXJyZWRDYW52YXMgPSBibHVycnlDYW52YXM7XG4gICAgICAgIHRoaXMuX2xhc3RCbHVyUmFkaXVzID0gdGhpcy5fb3B0aW9ucy5ibHVyUmFkaXVzO1xuICAgICAgICB0aGlzLl9sYXN0R3JhZGllbnRSYWRpdXMgPSB0aGlzLl9vcHRpb25zLmdyYWRpZW50UmFkaXVzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVXNlIGNhY2hlZCBjYW52YXNcbiAgICAgICAgYmx1cnJ5Q2FudmFzID0gdGhpcy5fY2FjaGVkQmx1cnJlZENhbnZhcztcbiAgICAgIH1cblxuICAgICAgdmFyIG1hc2tDYW52YXMgPSB0aGlzLl9jcmVhdGVNYXNrKHJlbmRlcmVyKTtcblxuICAgICAgdGhpcy5fYXBwbHlNYXNrKGNhbnZhcywgYmx1cnJ5Q2FudmFzLCBtYXNrQ2FudmFzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYmx1ckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYmx1cnJlZCBjb3B5IG9mIHRoZSBjYW52YXNcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtDYW52YXN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2JsdXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBuZXdDYW52YXMgPSByZW5kZXJlci5jbG9uZUNhbnZhcygpO1xuICAgICAgdmFyIGJsdXJyeUNvbnRleHQgPSBuZXdDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIHZhciBibHVycnlJbWFnZURhdGEgPSBibHVycnlDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBuZXdDYW52YXMud2lkdGgsIG5ld0NhbnZhcy5oZWlnaHQpO1xuICAgICAgX3ZlbmRvclN0YWNrQmx1cjJbJ2RlZmF1bHQnXS5zdGFja0JsdXJDYW52YXNSR0JBKGJsdXJyeUltYWdlRGF0YSwgMCwgMCwgbmV3Q2FudmFzLndpZHRoLCBuZXdDYW52YXMuaGVpZ2h0LCB0aGlzLl9vcHRpb25zLmJsdXJSYWRpdXMpO1xuICAgICAgYmx1cnJ5Q29udGV4dC5wdXRJbWFnZURhdGEoYmx1cnJ5SW1hZ2VEYXRhLCAwLCAwKTtcblxuICAgICAgcmV0dXJuIG5ld0NhbnZhcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY3JlYXRlTWFzaycsXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHRoZSBtYXNrIGNhbnZhc1xuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge0NhbnZhc31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfY3JlYXRlTWFzayhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBncmFkaWVudFJhZGl1cyA9IHRoaXMuX29wdGlvbnMuZ3JhZGllbnRSYWRpdXM7XG5cbiAgICAgIHZhciBtYXNrQ2FudmFzID0gcmVuZGVyZXIuY3JlYXRlQ2FudmFzKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgbWFza0NvbnRleHQgPSBtYXNrQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIHZhciBzdGFydCA9IHRoaXMuX29wdGlvbnMuc3RhcnQuY2xvbmUoKTtcbiAgICAgIHZhciBlbmQgPSB0aGlzLl9vcHRpb25zLmVuZC5jbG9uZSgpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgc3RhcnQubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG4gICAgICAgIGVuZC5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGRpc3QgPSBlbmQuY2xvbmUoKS5zdWJ0cmFjdChzdGFydCk7XG4gICAgICB2YXIgbWlkZGxlID0gc3RhcnQuY2xvbmUoKS5hZGQoZGlzdC5jbG9uZSgpLmRpdmlkZSgyKSk7XG5cbiAgICAgIHZhciB0b3RhbERpc3QgPSBNYXRoLnNxcnQoTWF0aC5wb3coZGlzdC54LCAyKSArIE1hdGgucG93KGRpc3QueSwgMikpO1xuICAgICAgdmFyIGZhY3RvciA9IGRpc3QuY2xvbmUoKS5kaXZpZGUodG90YWxEaXN0KTtcblxuICAgICAgdmFyIGdyYWRpZW50U3RhcnQgPSBtaWRkbGUuY2xvbmUoKS5hZGQoZ3JhZGllbnRSYWRpdXMgKiBmYWN0b3IueSwgLWdyYWRpZW50UmFkaXVzICogZmFjdG9yLngpO1xuICAgICAgdmFyIGdyYWRpZW50RW5kID0gbWlkZGxlLmNsb25lKCkuYWRkKC1ncmFkaWVudFJhZGl1cyAqIGZhY3Rvci55LCBncmFkaWVudFJhZGl1cyAqIGZhY3Rvci54KTtcblxuICAgICAgLy8gQnVpbGQgZ3JhZGllbnRcbiAgICAgIHZhciBncmFkaWVudCA9IG1hc2tDb250ZXh0LmNyZWF0ZUxpbmVhckdyYWRpZW50KGdyYWRpZW50U3RhcnQueCwgZ3JhZGllbnRTdGFydC55LCBncmFkaWVudEVuZC54LCBncmFkaWVudEVuZC55KTtcbiAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgwLCAnIzAwMDAwMCcpO1xuICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDAuNSwgJyNGRkZGRkYnKTtcbiAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgxLCAnIzAwMDAwMCcpO1xuXG4gICAgICAvLyBEcmF3IGdyYWRpZW50XG4gICAgICBtYXNrQ29udGV4dC5maWxsU3R5bGUgPSBncmFkaWVudDtcbiAgICAgIG1hc2tDb250ZXh0LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHJldHVybiBtYXNrQ2FudmFzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19hcHBseU1hc2snLFxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyB0aGUgYmx1ciBhbmQgbWFzayB0byB0aGUgaW5wdXQgY2FudmFzXG4gICAgICogQHBhcmFtICB7Q2FudmFzfSBpbnB1dENhbnZhc1xuICAgICAqIEBwYXJhbSAge0NhbnZhc30gYmx1cnJ5Q2FudmFzXG4gICAgICogQHBhcmFtICB7Q2FudmFzfSBtYXNrQ2FudmFzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FwcGx5TWFzayhpbnB1dENhbnZhcywgYmx1cnJ5Q2FudmFzLCBtYXNrQ2FudmFzKSB7XG4gICAgICB2YXIgaW5wdXRDb250ZXh0ID0gaW5wdXRDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIHZhciBibHVycnlDb250ZXh0ID0gYmx1cnJ5Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICB2YXIgbWFza0NvbnRleHQgPSBtYXNrQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIHZhciBpbnB1dEltYWdlRGF0YSA9IGlucHV0Q29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW5wdXRDYW52YXMud2lkdGgsIGlucHV0Q2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgcGl4ZWxzID0gaW5wdXRJbWFnZURhdGEuZGF0YTtcbiAgICAgIHZhciBibHVycnlQaXhlbHMgPSBibHVycnlDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBpbnB1dENhbnZhcy53aWR0aCwgaW5wdXRDYW52YXMuaGVpZ2h0KS5kYXRhO1xuICAgICAgdmFyIG1hc2tQaXhlbHMgPSBtYXNrQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW5wdXRDYW52YXMud2lkdGgsIGlucHV0Q2FudmFzLmhlaWdodCkuZGF0YTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtYXNrUGl4ZWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhbHBoYSA9IG1hc2tQaXhlbHNbaV0gLyAyNTU7XG4gICAgICAgIHBpeGVsc1tpXSA9IGFscGhhICogcGl4ZWxzW2ldICsgKDEgLSBhbHBoYSkgKiBibHVycnlQaXhlbHNbaV07XG4gICAgICB9XG5cbiAgICAgIGlucHV0Q29udGV4dC5wdXRJbWFnZURhdGEoaW5wdXRJbWFnZURhdGEsIDAsIDApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RpcnR5JyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGRpcnR5IHN0YXRlIG9mIHRoaXMgb3BlcmF0aW9uXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBkaXJ0eVxuICAgICAqIEBjb21tZW50IFNpbmNlIGJsdXIgb3BlcmF0aW9ucyBkbyBzZXBlcmF0ZSBjYWNoaW5nIG9mIHRoZVxuICAgICAqICAgICAgICAgIGJsdXJyZWQgY2FudmFzLCB3ZSBuZWVkIHRvIGludmFsaWRhdGUgdGhlIGNhY2hlIHdoZW4gdGhlXG4gICAgICogICAgICAgICAgZGlydHkgc3RhdGUgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBzZXQ6IGZ1bmN0aW9uIChkaXJ0eSkge1xuICAgICAgX3NldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoVGlsdFNoaWZ0T3BlcmF0aW9uLnByb3RvdHlwZSksICdkaXJ0eScsIGRpcnR5LCB0aGlzKTtcbiAgICAgIHRoaXMuX2NhY2hlZEJsdXJyZWRDYW52YXMgPSBudWxsO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBkaXJ0eSBzdGF0ZVxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFRpbHRTaGlmdE9wZXJhdGlvbi5wcm90b3R5cGUpLCAnZGlydHknLCB0aGlzKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gVGlsdFNoaWZ0T3BlcmF0aW9uO1xufSkoX29wZXJhdGlvbjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuVGlsdFNoaWZ0T3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ3RpbHQtc2hpZnQnO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5UaWx0U2hpZnRPcGVyYXRpb24ucHJvdG90eXBlLmF2YWlsYWJsZU9wdGlvbnMgPSB7XG4gIHN0YXJ0OiB7IHR5cGU6ICd2ZWN0b3IyJywgJ2RlZmF1bHQnOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDAuNSkgfSxcbiAgZW5kOiB7IHR5cGU6ICd2ZWN0b3IyJywgJ2RlZmF1bHQnOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDEsIDAuNSkgfSxcbiAgYmx1clJhZGl1czogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAzMCB9LFxuICBncmFkaWVudFJhZGl1czogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiA1MCB9XG59O1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBUaWx0U2hpZnRPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy90aWx0LXNoaWZ0LW9wZXJhdGlvbi5qc1xuICoqIG1vZHVsZSBpZCA9IDE2XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9zZXQgPSBmdW5jdGlvbiBzZXQob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIHJlY2VpdmVyKSB7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgIT09IG51bGwpIHsgc2V0KHBhcmVudCwgcHJvcGVydHksIHZhbHVlLCByZWNlaXZlcik7IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MgJiYgZGVzYy53cml0YWJsZSkgeyBkZXNjLnZhbHVlID0gdmFsdWU7IH0gZWxzZSB7IHZhciBzZXR0ZXIgPSBkZXNjLnNldDsgaWYgKHNldHRlciAhPT0gdW5kZWZpbmVkKSB7IHNldHRlci5jYWxsKHJlY2VpdmVyLCB2YWx1ZSk7IH0gfSByZXR1cm4gdmFsdWU7IH07XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIF92ZW5kb3JTdGFja0JsdXIgPSByZXF1aXJlKCcuLi92ZW5kb3Ivc3RhY2stYmx1cicpO1xuXG52YXIgX3ZlbmRvclN0YWNrQmx1cjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF92ZW5kb3JTdGFja0JsdXIpO1xuXG4vKipcbiAqIEFuIG9wZXJhdGlvbiB0aGF0IGNhbiBjcm9wIG91dCBhIHBhcnQgb2YgdGhlIGltYWdlXG4gKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5SYWRpYWxCbHVyT3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgUmFkaWFsQmx1ck9wZXJhdGlvbiA9IChmdW5jdGlvbiAoX09wZXJhdGlvbikge1xuICBmdW5jdGlvbiBSYWRpYWxCbHVyT3BlcmF0aW9uKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSYWRpYWxCbHVyT3BlcmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFJhZGlhbEJsdXJPcGVyYXRpb24ucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIHVzZWQgZm9yIHRoaXMgb3BlcmF0aW9uXG4gICAgICogQGludGVybmFsIEJhc2VkIG9uIGV2YW53J3MgZ2xmeC5qcyB0aWx0IHNoaWZ0IHNoYWRlcjpcbiAgICAgKiAgICAgICAgICAgaHR0cHM6Ly9naXRodWIuY29tL2V2YW53L2dsZnguanMvYmxvYi9tYXN0ZXIvc3JjL2ZpbHRlcnMvYmx1ci90aWx0c2hpZnQuanNcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHVuaWZvcm0gZmxvYXQgYmx1clJhZGl1cztcXG4gICAgICB1bmlmb3JtIGZsb2F0IGdyYWRpZW50UmFkaXVzO1xcbiAgICAgIHVuaWZvcm0gdmVjMiBwb3NpdGlvbjtcXG4gICAgICB1bmlmb3JtIHZlYzIgZGVsdGE7XFxuICAgICAgdW5pZm9ybSB2ZWMyIHRleFNpemU7XFxuICAgICAgdmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XFxuXFxuICAgICAgZmxvYXQgcmFuZG9tKHZlYzMgc2NhbGUsIGZsb2F0IHNlZWQpIHtcXG4gICAgICAgIHJldHVybiBmcmFjdChzaW4oZG90KGdsX0ZyYWdDb29yZC54eXogKyBzZWVkLCBzY2FsZSkpICogNDM3NTguNTQ1MyArIHNlZWQpO1xcbiAgICAgIH1cXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICAgIHZlYzQgY29sb3IgPSB2ZWM0KDAuMCk7XFxuICAgICAgICAgIGZsb2F0IHRvdGFsID0gMC4wO1xcblxcbiAgICAgICAgICBmbG9hdCBvZmZzZXQgPSByYW5kb20odmVjMygxMi45ODk4LCA3OC4yMzMsIDE1MS43MTgyKSwgMC4wKTtcXG4gICAgICAgICAgZmxvYXQgcmFkaXVzID0gc21vb3Roc3RlcCgwLjAsIDEuMCwgYWJzKGRpc3RhbmNlKHZfdGV4Q29vcmQgKiB0ZXhTaXplLCBwb3NpdGlvbikpIC8gKGdyYWRpZW50UmFkaXVzICogMi4wKSkgKiBibHVyUmFkaXVzO1xcbiAgICAgICAgICBmb3IgKGZsb2F0IHQgPSAtMzAuMDsgdCA8PSAzMC4wOyB0KyspIHtcXG4gICAgICAgICAgICAgIGZsb2F0IHBlcmNlbnQgPSAodCArIG9mZnNldCAtIDAuNSkgLyAzMC4wO1xcbiAgICAgICAgICAgICAgZmxvYXQgd2VpZ2h0ID0gMS4wIC0gYWJzKHBlcmNlbnQpO1xcbiAgICAgICAgICAgICAgdmVjNCBzYW1wbGUgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCArIGRlbHRhICogcGVyY2VudCAqIHJhZGl1cyAvIHRleFNpemUpO1xcblxcbiAgICAgICAgICAgICAgc2FtcGxlLnJnYiAqPSBzYW1wbGUuYTtcXG5cXG4gICAgICAgICAgICAgIGNvbG9yICs9IHNhbXBsZSAqIHdlaWdodDtcXG4gICAgICAgICAgICAgIHRvdGFsICs9IHdlaWdodDtcXG4gICAgICAgICAgfVxcblxcbiAgICAgICAgICBnbF9GcmFnQ29sb3IgPSBjb2xvciAvIHRvdGFsO1xcbiAgICAgICAgICBnbF9GcmFnQ29sb3IucmdiIC89IGdsX0ZyYWdDb2xvci5hICsgMC4wMDAwMTtcXG4gICAgICB9XFxuICAgICc7XG5cbiAgICB0aGlzLl9jYWNoZWRCbHVycmVkQ2FudmFzID0gbnVsbDtcbiAgICB0aGlzLl9sYXN0Qmx1clJhZGl1cyA9IHRoaXMuX29wdGlvbnMuYmx1clJhZGl1cztcbiAgICB0aGlzLl9sYXN0R3JhZGllbnRSYWRpdXMgPSB0aGlzLl9vcHRpb25zLmdyYWRpZW50UmFkaXVzO1xuICB9XG5cbiAgX2luaGVyaXRzKFJhZGlhbEJsdXJPcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhSYWRpYWxCbHVyT3BlcmF0aW9uLCBbe1xuICAgIGtleTogJ19yZW5kZXJXZWJHTCcsXG5cbiAgICAvKipcbiAgICAgKiBDcm9wcyB0aGlzIGltYWdlIHVzaW5nIFdlYkdMXG4gICAgICogQHBhcmFtICB7V2ViR0xSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBjYW52YXNTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9vcHRpb25zLnBvc2l0aW9uLmNsb25lKCk7XG4gICAgICBwb3NpdGlvbi55ID0gMSAtIHBvc2l0aW9uLnk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLm51bWJlckZvcm1hdCA9PT0gJ3JlbGF0aXZlJykge1xuICAgICAgICBwb3NpdGlvbi5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHVuaWZvcm1zID0ge1xuICAgICAgICBibHVyUmFkaXVzOiB7IHR5cGU6ICdmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuYmx1clJhZGl1cyB9LFxuICAgICAgICBncmFkaWVudFJhZGl1czogeyB0eXBlOiAnZicsIHZhbHVlOiB0aGlzLl9vcHRpb25zLmdyYWRpZW50UmFkaXVzIH0sXG4gICAgICAgIHBvc2l0aW9uOiB7IHR5cGU6ICcyZicsIHZhbHVlOiBbcG9zaXRpb24ueCwgcG9zaXRpb24ueV0gfSxcbiAgICAgICAgdGV4U2l6ZTogeyB0eXBlOiAnMmYnLCB2YWx1ZTogW2NhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodF0gfSxcbiAgICAgICAgZGVsdGE6IHsgdHlwZTogJzJmJywgdmFsdWU6IFsxLCAxXSB9XG4gICAgICB9O1xuXG4gICAgICAvLyBTZXR1cCBwcm9ncmFtXG4gICAgICBpZiAoIXRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0pIHtcbiAgICAgICAgdGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSA9IHJlbmRlcmVyLnNldHVwR0xTTFByb2dyYW0obnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5ydW5Qcm9ncmFtKHRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0sIHsgdW5pZm9ybXM6IHVuaWZvcm1zIH0pO1xuXG4gICAgICAvLyBVcGRhdGUgZGVsdGEgZm9yIHNlY29uZCBwYXNzXG4gICAgICB1bmlmb3Jtcy5kZWx0YS52YWx1ZSA9IFstMSwgMV07XG5cbiAgICAgIHJlbmRlcmVyLnJ1blByb2dyYW0odGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSwgeyB1bmlmb3JtczogdW5pZm9ybXMgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBDcm9wcyB0aGUgaW1hZ2UgdXNpbmcgQ2FudmFzMkRcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuXG4gICAgICB2YXIgYmx1clJhZGl1c0NoYW5nZWQgPSB0aGlzLl9vcHRpb25zLmJsdXJSYWRpdXMgIT09IHRoaXMuX2xhc3RCbHVyUmFkaXVzO1xuICAgICAgdmFyIGJsdXJyeUNhbnZhcyA9IHVuZGVmaW5lZDtcbiAgICAgIGlmIChibHVyUmFkaXVzQ2hhbmdlZCB8fCB0aGlzLl9jYWNoZWRCbHVycmVkQ2FudmFzID09PSBudWxsKSB7XG4gICAgICAgIC8vIEJsdXIgYW5kIGNhY2hlIGNhbnZhc1xuICAgICAgICBibHVycnlDYW52YXMgPSB0aGlzLl9ibHVyQ2FudmFzKHJlbmRlcmVyKTtcbiAgICAgICAgdGhpcy5fY2FjaGVkQmx1cnJlZENhbnZhcyA9IGJsdXJyeUNhbnZhcztcbiAgICAgICAgdGhpcy5fbGFzdEJsdXJSYWRpdXMgPSB0aGlzLl9vcHRpb25zLmJsdXJSYWRpdXM7XG4gICAgICAgIHRoaXMuX2xhc3RHcmFkaWVudFJhZGl1cyA9IHRoaXMuX29wdGlvbnMuZ3JhZGllbnRSYWRpdXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBVc2UgY2FjaGVkIGNhbnZhc1xuICAgICAgICBibHVycnlDYW52YXMgPSB0aGlzLl9jYWNoZWRCbHVycmVkQ2FudmFzO1xuICAgICAgfVxuXG4gICAgICB2YXIgbWFza0NhbnZhcyA9IHRoaXMuX2NyZWF0ZU1hc2socmVuZGVyZXIpO1xuXG4gICAgICB0aGlzLl9hcHBseU1hc2soY2FudmFzLCBibHVycnlDYW52YXMsIG1hc2tDYW52YXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19ibHVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBibHVycmVkIGNvcHkgb2YgdGhlIGNhbnZhc1xuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge0NhbnZhc31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfYmx1ckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIG5ld0NhbnZhcyA9IHJlbmRlcmVyLmNsb25lQ2FudmFzKCk7XG4gICAgICB2YXIgYmx1cnJ5Q29udGV4dCA9IG5ld0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgdmFyIGJsdXJyeUltYWdlRGF0YSA9IGJsdXJyeUNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIG5ld0NhbnZhcy53aWR0aCwgbmV3Q2FudmFzLmhlaWdodCk7XG4gICAgICBfdmVuZG9yU3RhY2tCbHVyMlsnZGVmYXVsdCddLnN0YWNrQmx1ckNhbnZhc1JHQkEoYmx1cnJ5SW1hZ2VEYXRhLCAwLCAwLCBuZXdDYW52YXMud2lkdGgsIG5ld0NhbnZhcy5oZWlnaHQsIHRoaXMuX29wdGlvbnMuYmx1clJhZGl1cyk7XG4gICAgICBibHVycnlDb250ZXh0LnB1dEltYWdlRGF0YShibHVycnlJbWFnZURhdGEsIDAsIDApO1xuXG4gICAgICByZXR1cm4gbmV3Q2FudmFzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19jcmVhdGVNYXNrJyxcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgdGhlIG1hc2sgY2FudmFzXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7Q2FudmFzfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jcmVhdGVNYXNrKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG5cbiAgICAgIHZhciBjYW52YXNTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgICAgdmFyIGdyYWRpZW50UmFkaXVzID0gdGhpcy5fb3B0aW9ucy5ncmFkaWVudFJhZGl1cztcblxuICAgICAgdmFyIG1hc2tDYW52YXMgPSByZW5kZXJlci5jcmVhdGVDYW52YXMoY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBtYXNrQ29udGV4dCA9IG1hc2tDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fb3B0aW9ucy5wb3NpdGlvbi5jbG9uZSgpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgcG9zaXRpb24ubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEJ1aWxkIGdyYWRpZW50XG4gICAgICB2YXIgZ3JhZGllbnQgPSBtYXNrQ29udGV4dC5jcmVhdGVSYWRpYWxHcmFkaWVudChwb3NpdGlvbi54LCBwb3NpdGlvbi55LCAwLCBwb3NpdGlvbi54LCBwb3NpdGlvbi55LCBncmFkaWVudFJhZGl1cyk7XG4gICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMCwgJyNGRkZGRkYnKTtcbiAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgxLCAnIzAwMDAwMCcpO1xuXG4gICAgICAvLyBEcmF3IGdyYWRpZW50XG4gICAgICBtYXNrQ29udGV4dC5maWxsU3R5bGUgPSBncmFkaWVudDtcbiAgICAgIG1hc2tDb250ZXh0LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHJldHVybiBtYXNrQ2FudmFzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19hcHBseU1hc2snLFxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyB0aGUgYmx1ciBhbmQgbWFzayB0byB0aGUgaW5wdXQgY2FudmFzXG4gICAgICogQHBhcmFtICB7Q2FudmFzfSBpbnB1dENhbnZhc1xuICAgICAqIEBwYXJhbSAge0NhbnZhc30gYmx1cnJ5Q2FudmFzXG4gICAgICogQHBhcmFtICB7Q2FudmFzfSBtYXNrQ2FudmFzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FwcGx5TWFzayhpbnB1dENhbnZhcywgYmx1cnJ5Q2FudmFzLCBtYXNrQ2FudmFzKSB7XG4gICAgICB2YXIgaW5wdXRDb250ZXh0ID0gaW5wdXRDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIHZhciBibHVycnlDb250ZXh0ID0gYmx1cnJ5Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICB2YXIgbWFza0NvbnRleHQgPSBtYXNrQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIHZhciBpbnB1dEltYWdlRGF0YSA9IGlucHV0Q29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW5wdXRDYW52YXMud2lkdGgsIGlucHV0Q2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgcGl4ZWxzID0gaW5wdXRJbWFnZURhdGEuZGF0YTtcbiAgICAgIHZhciBibHVycnlQaXhlbHMgPSBibHVycnlDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBpbnB1dENhbnZhcy53aWR0aCwgaW5wdXRDYW52YXMuaGVpZ2h0KS5kYXRhO1xuICAgICAgdmFyIG1hc2tQaXhlbHMgPSBtYXNrQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgaW5wdXRDYW52YXMud2lkdGgsIGlucHV0Q2FudmFzLmhlaWdodCkuZGF0YTtcblxuICAgICAgdmFyIGluZGV4LCBhbHBoYTtcbiAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgaW5wdXRDYW52YXMuaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBpbnB1dENhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgICAgaW5kZXggPSAoeSAqIGlucHV0Q2FudmFzLndpZHRoICsgeCkgKiA0O1xuICAgICAgICAgIGFscGhhID0gbWFza1BpeGVsc1tpbmRleF0gLyAyNTU7XG5cbiAgICAgICAgICBwaXhlbHNbaW5kZXhdID0gYWxwaGEgKiBwaXhlbHNbaW5kZXhdICsgKDEgLSBhbHBoYSkgKiBibHVycnlQaXhlbHNbaW5kZXhdO1xuICAgICAgICAgIHBpeGVsc1tpbmRleCArIDFdID0gYWxwaGEgKiBwaXhlbHNbaW5kZXggKyAxXSArICgxIC0gYWxwaGEpICogYmx1cnJ5UGl4ZWxzW2luZGV4ICsgMV07XG4gICAgICAgICAgcGl4ZWxzW2luZGV4ICsgMl0gPSBhbHBoYSAqIHBpeGVsc1tpbmRleCArIDJdICsgKDEgLSBhbHBoYSkgKiBibHVycnlQaXhlbHNbaW5kZXggKyAyXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpbnB1dENvbnRleHQucHV0SW1hZ2VEYXRhKGlucHV0SW1hZ2VEYXRhLCAwLCAwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdkaXJ0eScsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkaXJ0eSBzdGF0ZSBvZiB0aGlzIG9wZXJhdGlvblxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gZGlydHlcbiAgICAgKiBAY29tbWVudCBTaW5jZSBibHVyIG9wZXJhdGlvbnMgZG8gc2VwZXJhdGUgY2FjaGluZyBvZiB0aGVcbiAgICAgKiAgICAgICAgICBibHVycmVkIGNhbnZhcywgd2UgbmVlZCB0byBpbnZhbGlkYXRlIHRoZSBjYWNoZSB3aGVuIHRoZVxuICAgICAqICAgICAgICAgIGRpcnR5IHN0YXRlIGNoYW5nZXMuXG4gICAgICovXG4gICAgc2V0OiBmdW5jdGlvbiAoZGlydHkpIHtcbiAgICAgIF9zZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFJhZGlhbEJsdXJPcGVyYXRpb24ucHJvdG90eXBlKSwgJ2RpcnR5JywgZGlydHksIHRoaXMpO1xuICAgICAgdGhpcy5fY2FjaGVkQmx1cnJlZENhbnZhcyA9IG51bGw7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGRpcnR5IHN0YXRlXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoUmFkaWFsQmx1ck9wZXJhdGlvbi5wcm90b3R5cGUpLCAnZGlydHknLCB0aGlzKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gUmFkaWFsQmx1ck9wZXJhdGlvbjtcbn0pKF9vcGVyYXRpb24yWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICogb3BlcmF0aW9ucy5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cblJhZGlhbEJsdXJPcGVyYXRpb24ucHJvdG90eXBlLmlkZW50aWZpZXIgPSAncmFkaWFsLWJsdXInO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5SYWRpYWxCbHVyT3BlcmF0aW9uLnByb3RvdHlwZS5hdmFpbGFibGVPcHRpb25zID0ge1xuICBwb3NpdGlvbjogeyB0eXBlOiAndmVjdG9yMicsICdkZWZhdWx0JzogbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLjUsIDAuNSkgfSxcbiAgZ3JhZGllbnRSYWRpdXM6IHsgdHlwZTogJ251bWJlcicsICdkZWZhdWx0JzogNTAgfSxcbiAgYmx1clJhZGl1czogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAyMCB9XG59O1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSYWRpYWxCbHVyT3BlcmF0aW9uO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvcmFkaWFsLWJsdXItb3BlcmF0aW9uLmpzXG4gKiogbW9kdWxlIGlkID0gMTdcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfb3BlcmF0aW9uID0gcmVxdWlyZSgnLi9vcGVyYXRpb24nKTtcblxudmFyIF9vcGVyYXRpb24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfb3BlcmF0aW9uKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBfbGliQ29sb3IgPSByZXF1aXJlKCcuLi9saWIvY29sb3InKTtcblxudmFyIF9saWJDb2xvcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJDb2xvcik7XG5cbi8qKlxuICogQW4gb3BlcmF0aW9uIHRoYXQgY2FuIGRyYXcgdGV4dCBvbiB0aGUgY2FudmFzXG4gKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuT3BlcmF0aW9ucy5UZXh0T3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgVGV4dE9wZXJhdGlvbiA9IChmdW5jdGlvbiAoX09wZXJhdGlvbikge1xuICBmdW5jdGlvbiBUZXh0T3BlcmF0aW9uKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUZXh0T3BlcmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFRleHRPcGVyYXRpb24ucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdGV4dHVyZSBpbmRleCB1c2VkIGZvciB0aGUgdGV4dFxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl90ZXh0dXJlSW5kZXggPSAxO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciB1c2VkIGZvciB0aGlzIG9wZXJhdGlvblxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV90ZXh0SW1hZ2U7XFxuICAgICAgdW5pZm9ybSB2ZWMyIHVfcG9zaXRpb247XFxuICAgICAgdW5pZm9ybSB2ZWMyIHVfc2l6ZTtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IGNvbG9yMCA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleENvb3JkKTtcXG4gICAgICAgIHZlYzIgcmVsYXRpdmUgPSAodl90ZXhDb29yZCAtIHVfcG9zaXRpb24pIC8gdV9zaXplO1xcblxcbiAgICAgICAgaWYgKHJlbGF0aXZlLnggPj0gMC4wICYmIHJlbGF0aXZlLnggPD0gMS4wICYmXFxuICAgICAgICAgIHJlbGF0aXZlLnkgPj0gMC4wICYmIHJlbGF0aXZlLnkgPD0gMS4wKSB7XFxuXFxuICAgICAgICAgICAgdmVjNCBjb2xvcjEgPSB0ZXh0dXJlMkQodV90ZXh0SW1hZ2UsIHJlbGF0aXZlKTtcXG5cXG4gICAgICAgICAgICAvLyBHTF9TT1VSQ0VfQUxQSEEsIEdMX09ORV9NSU5VU19TT1VSQ0VfQUxQSEFcXG4gICAgICAgICAgICBnbF9GcmFnQ29sb3IgPSBjb2xvcjEgKyBjb2xvcjAgKiAoMS4wIC0gY29sb3IxLmEpO1xcblxcbiAgICAgICAgfSBlbHNlIHtcXG5cXG4gICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gY29sb3IwO1xcblxcbiAgICAgICAgfVxcbiAgICAgIH1cXG4gICAgJztcbiAgfVxuXG4gIF9pbmhlcml0cyhUZXh0T3BlcmF0aW9uLCBfT3BlcmF0aW9uKTtcblxuICBfY3JlYXRlQ2xhc3MoVGV4dE9wZXJhdGlvbiwgW3tcbiAgICBrZXk6ICdfcmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogQ3JvcHMgdGhpcyBpbWFnZSB1c2luZyBXZWJHTFxuICAgICAqIEBwYXJhbSAge1dlYkdMUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgdGV4dENhbnZhcyA9IHRoaXMuX3JlbmRlclRleHRDYW52YXMocmVuZGVyZXIpO1xuXG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgZ2wgPSByZW5kZXJlci5nZXRDb250ZXh0KCk7XG5cbiAgICAgIHZhciBwb3NpdGlvbiA9IHRoaXMuX29wdGlvbnMucG9zaXRpb24uY2xvbmUoKTtcbiAgICAgIHZhciBjYW52YXNTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgICAgdmFyIHNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRleHRDYW52YXMud2lkdGgsIHRleHRDYW52YXMuaGVpZ2h0KS5kaXZpZGUoY2FudmFzU2l6ZSk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLm51bWJlckZvcm1hdCA9PT0gJ2Fic29sdXRlJykge1xuICAgICAgICBwb3NpdGlvbi5kaXZpZGUoY2FudmFzU2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIHBvc2l0aW9uLnkgPSAxIC0gcG9zaXRpb24ueTsgLy8gSW52ZXJ0IHlcbiAgICAgIHBvc2l0aW9uLnkgLT0gc2l6ZS55OyAvLyBGaXggeVxuXG4gICAgICAvLyBBZGp1c3QgdmVydGljYWwgYWxpZ25tZW50XG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy52ZXJ0aWNhbEFsaWdubWVudCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgcG9zaXRpb24ueSArPSBzaXplLnkgLyAyO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9vcHRpb25zLnZlcnRpY2FsQWxpZ25tZW50ID09PSAnYm90dG9tJykge1xuICAgICAgICBwb3NpdGlvbi55ICs9IHNpemUueTtcbiAgICAgIH1cblxuICAgICAgLy8gQWRqdXN0IGhvcml6b250YWwgYWxpZ25tZW50XG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5hbGlnbm1lbnQgPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHBvc2l0aW9uLnggLT0gc2l6ZS54IC8gMjtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5hbGlnbm1lbnQgPT09ICdyaWdodCcpIHtcbiAgICAgICAgcG9zaXRpb24ueCAtPSBzaXplLng7XG4gICAgICB9XG5cbiAgICAgIC8vIFVwbG9hZCB0aGUgdGV4dHVyZVxuICAgICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCArIHRoaXMuX3RleHR1cmVJbmRleCk7XG4gICAgICB0aGlzLl90ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy5fdGV4dHVyZSk7XG5cbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01BR19GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1QsIGdsLkNMQU1QX1RPX0VER0UpO1xuXG4gICAgICAvLyBTZXQgcHJlbXVsdGlwbGllZCBhbHBoYVxuICAgICAgZ2wucGl4ZWxTdG9yZWkoZ2wuVU5QQUNLX1BSRU1VTFRJUExZX0FMUEhBX1dFQkdMLCB0cnVlKTtcblxuICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCB0ZXh0Q2FudmFzKTtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgICAvLyBFeGVjdXRlIHRoZSBzaGFkZXJcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcihudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlciwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfdGV4dEltYWdlOiB7IHR5cGU6ICdpJywgdmFsdWU6IHRoaXMuX3RleHR1cmVJbmRleCB9LFxuICAgICAgICAgIHVfcG9zaXRpb246IHsgdHlwZTogJzJmJywgdmFsdWU6IFtwb3NpdGlvbi54LCBwb3NpdGlvbi55XSB9LFxuICAgICAgICAgIHVfc2l6ZTogeyB0eXBlOiAnMmYnLCB2YWx1ZTogW3NpemUueCwgc2l6ZS55XSB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogQ3JvcHMgdGhlIGltYWdlIHVzaW5nIENhbnZhczJEXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciB0ZXh0Q2FudmFzID0gdGhpcy5fcmVuZGVyVGV4dENhbnZhcyhyZW5kZXJlcik7XG5cbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBjb250ZXh0ID0gcmVuZGVyZXIuZ2V0Q29udGV4dCgpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBzY2FsZWRQb3NpdGlvbiA9IHRoaXMuX29wdGlvbnMucG9zaXRpb24uY2xvbmUoKTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMubnVtYmVyRm9ybWF0ID09PSAncmVsYXRpdmUnKSB7XG4gICAgICAgIHNjYWxlZFBvc2l0aW9uLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGp1c3QgdmVydGljYWwgYWxpZ25tZW50XG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy52ZXJ0aWNhbEFsaWdubWVudCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgc2NhbGVkUG9zaXRpb24ueSAtPSB0ZXh0Q2FudmFzLmhlaWdodCAvIDI7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX29wdGlvbnMudmVydGljYWxBbGlnbm1lbnQgPT09ICdib3R0b20nKSB7XG4gICAgICAgIHNjYWxlZFBvc2l0aW9uLnkgLT0gdGV4dENhbnZhcy5oZWlnaHQ7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkanVzdCBob3Jpem9udGFsIGFsaWdubWVudFxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMuYWxpZ25tZW50ID09PSAnY2VudGVyJykge1xuICAgICAgICBzY2FsZWRQb3NpdGlvbi54IC09IHRleHRDYW52YXMud2lkdGggLyAyO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9vcHRpb25zLmFsaWdubWVudCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBzY2FsZWRQb3NpdGlvbi54IC09IHRleHRDYW52YXMud2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGNvbnRleHQuZHJhd0ltYWdlKHRleHRDYW52YXMsIHNjYWxlZFBvc2l0aW9uLngsIHNjYWxlZFBvc2l0aW9uLnkpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJUZXh0Q2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHRleHQgY2FudmFzIHRoYXQgd2lsbCBiZSB1c2VkIGFzIGEgdGV4dHVyZSBpbiBXZWJHTFxuICAgICAqIGFuZCBhcyBhbiBpbWFnZSBpbiBjYW52YXNcbiAgICAgKiBAcmV0dXJuIHtDYW52YXN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlclRleHRDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBsaW5lID0gdW5kZWZpbmVkLFxuICAgICAgICAgIGxpbmVOdW0gPSB1bmRlZmluZWQ7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuY3JlYXRlQ2FudmFzKCk7XG4gICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICB2YXIgb3V0cHV0Q2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10ob3V0cHV0Q2FudmFzLndpZHRoLCBvdXRwdXRDYW52YXMuaGVpZ2h0KTtcblxuICAgICAgdmFyIG1heFdpZHRoID0gdGhpcy5fb3B0aW9ucy5tYXhXaWR0aDtcbiAgICAgIHZhciBhY3R1YWxGb250U2l6ZSA9IHRoaXMuX29wdGlvbnMuZm9udFNpemUgKiBjYW52YXNTaXplLnk7XG4gICAgICB2YXIgYWN0dWFsTGluZUhlaWdodCA9IHRoaXMuX29wdGlvbnMubGluZUhlaWdodCAqIGFjdHVhbEZvbnRTaXplO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgbWF4V2lkdGggKj0gcmVuZGVyZXIuZ2V0Q2FudmFzKCkud2lkdGg7XG4gICAgICB9XG5cbiAgICAgIC8vIEFwcGx5IHRleHQgb3B0aW9uc1xuICAgICAgdGhpcy5fYXBwbHlUZXh0T3B0aW9ucyhyZW5kZXJlciwgY29udGV4dCk7XG5cbiAgICAgIHZhciBib3VuZGluZ0JveCA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oKTtcblxuICAgICAgdmFyIGxpbmVzID0gdGhpcy5fb3B0aW9ucy50ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgIGlmICh0eXBlb2YgbWF4V2lkdGggIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYm91bmRpbmcgYm94XG4gICAgICAgIGJvdW5kaW5nQm94LnggPSBtYXhXaWR0aDtcbiAgICAgICAgbGluZXMgPSB0aGlzLl9idWlsZE91dHB1dExpbmVzKGNvbnRleHQsIG1heFdpZHRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGluZU51bSA9IDA7IGxpbmVOdW0gPCBsaW5lcy5sZW5ndGg7IGxpbmVOdW0rKykge1xuICAgICAgICAgIGxpbmUgPSBsaW5lc1tsaW5lTnVtXTtcbiAgICAgICAgICBib3VuZGluZ0JveC54ID0gTWF0aC5tYXgoYm91bmRpbmdCb3gueCwgY29udGV4dC5tZWFzdXJlVGV4dChsaW5lKS53aWR0aCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2FsY3VsYXRlIGJvdW5kaW5nYm94IGhlaWdodFxuICAgICAgYm91bmRpbmdCb3gueSA9IGFjdHVhbExpbmVIZWlnaHQgKiBsaW5lcy5sZW5ndGg7XG5cbiAgICAgIC8vIFJlc2l6ZSB0aGUgY2FudmFzXG4gICAgICBjYW52YXMud2lkdGggPSBib3VuZGluZ0JveC54O1xuICAgICAgY2FudmFzLmhlaWdodCA9IGJvdW5kaW5nQm94Lnk7XG5cbiAgICAgIC8vIEdldCB0aGUgY29udGV4dCBhZ2FpblxuICAgICAgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAvLyBSZW5kZXIgYmFja2dyb3VuZCBjb2xvclxuICAgICAgY29udGV4dC5maWxsU3R5bGUgPSB0aGlzLl9vcHRpb25zLmJhY2tncm91bmRDb2xvci50b1JHQkEoKTtcbiAgICAgIGNvbnRleHQuZmlsbFJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgLy8gQXBwbHkgdGV4dCBvcHRpb25zXG4gICAgICB0aGlzLl9hcHBseVRleHRPcHRpb25zKHJlbmRlcmVyLCBjb250ZXh0KTtcblxuICAgICAgLy8gRHJhdyBsaW5lc1xuICAgICAgZm9yIChsaW5lTnVtID0gMDsgbGluZU51bSA8IGxpbmVzLmxlbmd0aDsgbGluZU51bSsrKSB7XG4gICAgICAgIGxpbmUgPSBsaW5lc1tsaW5lTnVtXTtcbiAgICAgICAgdGhpcy5fZHJhd1RleHQoY29udGV4dCwgbGluZSwgYWN0dWFsTGluZUhlaWdodCAqIGxpbmVOdW0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY2FudmFzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19hcHBseVRleHRPcHRpb25zJyxcblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgdGhlIHRleHQgb3B0aW9ucyBvbiB0aGUgZ2l2ZW4gY29udGV4dFxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9hcHBseVRleHRPcHRpb25zKHJlbmRlcmVyLCBjb250ZXh0KSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBhY3R1YWxGb250U2l6ZSA9IHRoaXMuX29wdGlvbnMuZm9udFNpemUgKiBjYW52YXNTaXplLnk7XG5cbiAgICAgIGNvbnRleHQuZm9udCA9IHRoaXMuX29wdGlvbnMuZm9udFdlaWdodCArICcgJyArIGFjdHVhbEZvbnRTaXplICsgJ3B4ICcgKyB0aGlzLl9vcHRpb25zLmZvbnRGYW1pbHk7XG4gICAgICBjb250ZXh0LnRleHRCYXNlbGluZSA9ICd0b3AnO1xuICAgICAgY29udGV4dC50ZXh0QWxpZ24gPSB0aGlzLl9vcHRpb25zLmFsaWdubWVudDtcbiAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gdGhpcy5fb3B0aW9ucy5jb2xvci50b1JHQkEoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYnVpbGRPdXRwdXRMaW5lcycsXG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlIG92ZXIgYWxsIGxpbmVzIGFuZCBzcGxpdCB0aGVtIGludG8gbXVsdGlwbGUgbGluZXMsIGRlcGVuZGluZ1xuICAgICAqIG9uIHRoZSB3aWR0aCB0aGV5IG5lZWRcbiAgICAgKiBAcGFyYW0ge1JlbmRlcmluZ0NvbnRleHQyZH0gY29udGV4dFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBtYXhXaWR0aFxuICAgICAqIEByZXR1cm4ge0FycmF5LjxzdHJpbmc+fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9idWlsZE91dHB1dExpbmVzKGNvbnRleHQsIG1heFdpZHRoKSB7XG4gICAgICB2YXIgaW5wdXRMaW5lcyA9IHRoaXMuX29wdGlvbnMudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICB2YXIgb3V0cHV0TGluZXMgPSBbXTtcbiAgICAgIHZhciBjdXJyZW50Q2hhcnMgPSBbXTtcblxuICAgICAgZm9yICh2YXIgbGluZU51bSA9IDA7IGxpbmVOdW0gPCBpbnB1dExpbmVzLmxlbmd0aDsgbGluZU51bSsrKSB7XG4gICAgICAgIHZhciBpbnB1dExpbmUgPSBpbnB1dExpbmVzW2xpbmVOdW1dO1xuICAgICAgICB2YXIgbGluZUNoYXJzID0gaW5wdXRMaW5lLnNwbGl0KCcnKTtcblxuICAgICAgICBpZiAobGluZUNoYXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIG91dHB1dExpbmVzLnB1c2goJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgY2hhck51bSA9IDA7IGNoYXJOdW0gPCBsaW5lQ2hhcnMubGVuZ3RoOyBjaGFyTnVtKyspIHtcbiAgICAgICAgICB2YXIgY3VycmVudENoYXIgPSBsaW5lQ2hhcnNbY2hhck51bV07XG4gICAgICAgICAgY3VycmVudENoYXJzLnB1c2goY3VycmVudENoYXIpO1xuICAgICAgICAgIHZhciBjdXJyZW50TGluZSA9IGN1cnJlbnRDaGFycy5qb2luKCcnKTtcbiAgICAgICAgICB2YXIgbGluZVdpZHRoID0gY29udGV4dC5tZWFzdXJlVGV4dChjdXJyZW50TGluZSkud2lkdGg7XG5cbiAgICAgICAgICBpZiAobGluZVdpZHRoID4gbWF4V2lkdGggJiYgY3VycmVudENoYXJzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgb3V0cHV0TGluZXMucHVzaChjdXJyZW50Q2hhcnNbMF0pO1xuICAgICAgICAgICAgY3VycmVudENoYXJzID0gW107XG4gICAgICAgICAgfSBlbHNlIGlmIChsaW5lV2lkdGggPiBtYXhXaWR0aCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBsYXN0IHdvcmRcbiAgICAgICAgICAgIHZhciBsYXN0V29yZCA9IGN1cnJlbnRDaGFycy5wb3AoKTtcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBsaW5lLCBjbGVhciB0aGUgd29yZHNcbiAgICAgICAgICAgIG91dHB1dExpbmVzLnB1c2goY3VycmVudENoYXJzLmpvaW4oJycpKTtcbiAgICAgICAgICAgIGN1cnJlbnRDaGFycyA9IFtdO1xuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdG8gdXNlIHRoZSBsYXN0IHdvcmQgZm9yIHRoZSBuZXh0IGxpbmVcbiAgICAgICAgICAgIGN1cnJlbnRDaGFycyA9IFtsYXN0V29yZF07XG4gICAgICAgICAgfSBlbHNlIGlmIChjaGFyTnVtID09PSBsaW5lQ2hhcnMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgLy8gQWRkIHRoZSBsaW5lLCBjbGVhciB0aGUgd29yZHNcbiAgICAgICAgICAgIG91dHB1dExpbmVzLnB1c2goY3VycmVudENoYXJzLmpvaW4oJycpKTtcbiAgICAgICAgICAgIGN1cnJlbnRDaGFycyA9IFtdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExpbmUgZW5kZWQsIGJ1dCB0aGVyZSdzIHdvcmRzIGxlZnRcbiAgICAgICAgaWYgKGN1cnJlbnRDaGFycy5sZW5ndGgpIHtcbiAgICAgICAgICBvdXRwdXRMaW5lcy5wdXNoKGN1cnJlbnRDaGFycy5qb2luKCcnKSk7XG4gICAgICAgICAgY3VycmVudENoYXJzID0gW107XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG91dHB1dExpbmVzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19kcmF3VGV4dCcsXG5cbiAgICAvKipcbiAgICAgKiBEcmF3cyB0aGUgZ2l2ZW4gbGluZSBvbnRvIHRoZSBnaXZlbiBjb250ZXh0IGF0IHRoZSBnaXZlbiBZIHBvc2l0aW9uXG4gICAgICogQHBhcmFtICB7UmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0XG4gICAgICogQHBhcmFtICB7U3RyaW5nfSB0ZXh0XG4gICAgICogQHBhcmFtICB7TnVtYmVyfSB5XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2RyYXdUZXh0KGNvbnRleHQsIHRleHQsIHkpIHtcbiAgICAgIHZhciBjYW52YXMgPSBjb250ZXh0LmNhbnZhcztcbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmFsaWdubWVudCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgY29udGV4dC5maWxsVGV4dCh0ZXh0LCBjYW52YXMud2lkdGggLyAyLCB5KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fb3B0aW9ucy5hbGlnbm1lbnQgPT09ICdsZWZ0Jykge1xuICAgICAgICBjb250ZXh0LmZpbGxUZXh0KHRleHQsIDAsIHkpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9vcHRpb25zLmFsaWdubWVudCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBjb250ZXh0LmZpbGxUZXh0KHRleHQsIGNhbnZhcy53aWR0aCwgeSk7XG4gICAgICB9XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFRleHRPcGVyYXRpb247XG59KShfb3BlcmF0aW9uMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAqIG9wZXJhdGlvbnMuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5UZXh0T3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ3RleHQnO1xuXG4vKipcbiAqIFNwZWNpZmllcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoaXMgb3BlcmF0aW9uXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5UZXh0T3BlcmF0aW9uLnByb3RvdHlwZS5hdmFpbGFibGVPcHRpb25zID0ge1xuICBmb250U2l6ZTogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAwLjEgfSxcbiAgbGluZUhlaWdodDogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAxLjEgfSxcbiAgZm9udEZhbWlseTogeyB0eXBlOiAnc3RyaW5nJywgJ2RlZmF1bHQnOiAnVGltZXMgTmV3IFJvbWFuJyB9LFxuICBmb250V2VpZ2h0OiB7IHR5cGU6ICdzdHJpbmcnLCAnZGVmYXVsdCc6ICdub3JtYWwnIH0sXG4gIGFsaWdubWVudDogeyB0eXBlOiAnc3RyaW5nJywgJ2RlZmF1bHQnOiAnbGVmdCcsIGF2YWlsYWJsZTogWydsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddIH0sXG4gIHZlcnRpY2FsQWxpZ25tZW50OiB7IHR5cGU6ICdzdHJpbmcnLCAnZGVmYXVsdCc6ICd0b3AnLCBhdmFpbGFibGU6IFsndG9wJywgJ2NlbnRlcicsICdib3R0b20nXSB9LFxuICBjb2xvcjogeyB0eXBlOiAnY29sb3InLCAnZGVmYXVsdCc6IG5ldyBfbGliQ29sb3IyWydkZWZhdWx0J10oMSwgMSwgMSwgMSkgfSxcbiAgYmFja2dyb3VuZENvbG9yOiB7IHR5cGU6ICdjb2xvcicsICdkZWZhdWx0JzogbmV3IF9saWJDb2xvcjJbJ2RlZmF1bHQnXSgwLCAwLCAwLCAwKSB9LFxuICBwb3NpdGlvbjogeyB0eXBlOiAndmVjdG9yMicsICdkZWZhdWx0JzogbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKSB9LFxuICB0ZXh0OiB7IHR5cGU6ICdzdHJpbmcnLCByZXF1aXJlZDogdHJ1ZSB9LFxuICBtYXhXaWR0aDogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAxIH1cbn07XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFRleHRPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy90ZXh0LW9wZXJhdGlvbi5qc1xuICoqIG1vZHVsZSBpZCA9IDE4XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgSW1hZ2UgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfb3BlcmF0aW9uID0gcmVxdWlyZSgnLi9vcGVyYXRpb24nKTtcblxudmFyIF9vcGVyYXRpb24yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfb3BlcmF0aW9uKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBfdmVuZG9yUHJvbWlzZSA9IHJlcXVpcmUoJy4uL3ZlbmRvci9wcm9taXNlJyk7XG5cbnZhciBfdmVuZG9yUHJvbWlzZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF92ZW5kb3JQcm9taXNlKTtcblxuLyoqXG4gKiBBbiBvcGVyYXRpb24gdGhhdCBjYW4gZHJhdyB0ZXh0IG9uIHRoZSBjYW52YXNcbiAqXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5PcGVyYXRpb25zLlN0aWNrZXJzT3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgU3RpY2tlcnNPcGVyYXRpb24gPSAoZnVuY3Rpb24gKF9PcGVyYXRpb24pIHtcbiAgZnVuY3Rpb24gU3RpY2tlcnNPcGVyYXRpb24oKSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFN0aWNrZXJzT3BlcmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFN0aWNrZXJzT3BlcmF0aW9uLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHRleHR1cmUgaW5kZXggdXNlZCBmb3IgdGhlIHN0aWNrZXJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fdGV4dHVyZUluZGV4ID0gMTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBmcmFnbWVudCBzaGFkZXIgdXNlZCBmb3IgdGhpcyBvcGVyYXRpb25cbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfc3RpY2tlckltYWdlO1xcbiAgICAgIHVuaWZvcm0gdmVjMiB1X3Bvc2l0aW9uO1xcbiAgICAgIHVuaWZvcm0gdmVjMiB1X3NpemU7XFxuXFxuICAgICAgdm9pZCBtYWluKCkge1xcbiAgICAgICAgdmVjNCBjb2xvcjAgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCk7XFxuICAgICAgICB2ZWMyIHJlbGF0aXZlID0gKHZfdGV4Q29vcmQgLSB1X3Bvc2l0aW9uKSAvIHVfc2l6ZTtcXG5cXG4gICAgICAgIGlmIChyZWxhdGl2ZS54ID49IDAuMCAmJiByZWxhdGl2ZS54IDw9IDEuMCAmJlxcbiAgICAgICAgICByZWxhdGl2ZS55ID49IDAuMCAmJiByZWxhdGl2ZS55IDw9IDEuMCkge1xcblxcbiAgICAgICAgICAgIHZlYzQgY29sb3IxID0gdGV4dHVyZTJEKHVfc3RpY2tlckltYWdlLCByZWxhdGl2ZSk7XFxuXFxuICAgICAgICAgICAgLy8gR0xfU09VUkNFX0FMUEhBLCBHTF9PTkVfTUlOVVNfU09VUkNFX0FMUEhBXFxuICAgICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gY29sb3IxICsgY29sb3IwICogKDEuMCAtIGNvbG9yMS5hKTtcXG5cXG4gICAgICAgIH0gZWxzZSB7XFxuXFxuICAgICAgICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yMDtcXG5cXG4gICAgICAgIH1cXG4gICAgICB9XFxuICAgICc7XG5cbiAgICB0aGlzLl9sb2FkZWRTdGlja2VycyA9IHt9O1xuICB9XG5cbiAgX2luaGVyaXRzKFN0aWNrZXJzT3BlcmF0aW9uLCBfT3BlcmF0aW9uKTtcblxuICBfY3JlYXRlQ2xhc3MoU3RpY2tlcnNPcGVyYXRpb24sIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgdGhpcyBvcGVyYXRpb25cbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqIEBhYnN0cmFjdFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHJldHVybiB0aGlzLl9sb2FkU3RpY2tlcigpLnRoZW4oZnVuY3Rpb24gKGltYWdlKSB7XG4gICAgICAgIGlmIChyZW5kZXJlci5pZGVudGlmaWVyID09PSAnd2ViZ2wnKSB7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgICByZXR1cm4gc2VsZi5fcmVuZGVyV2ViR0wocmVuZGVyZXIsIGltYWdlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gc2VsZi5fcmVuZGVyQ2FudmFzKHJlbmRlcmVyLCBpbWFnZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJXZWJHTCcsXG5cbiAgICAvKipcbiAgICAgKiBDcm9wcyB0aGlzIGltYWdlIHVzaW5nIFdlYkdMXG4gICAgICogQHBhcmFtICB7V2ViR0xSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gIHtJbWFnZX0gaW1hZ2VcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJXZWJHTChyZW5kZXJlciwgaW1hZ2UpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBnbCA9IHJlbmRlcmVyLmdldENvbnRleHQoKTtcblxuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fb3B0aW9ucy5wb3NpdGlvbi5jbG9uZSgpO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLm51bWJlckZvcm1hdCA9PT0gJ2Fic29sdXRlJykge1xuICAgICAgICBwb3NpdGlvbi5kaXZpZGUoY2FudmFzU2l6ZSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBzaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShpbWFnZS53aWR0aCwgaW1hZ2UuaGVpZ2h0KTtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5zaXplICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBzaXplLmNvcHkodGhpcy5fb3B0aW9ucy5zaXplKTtcblxuICAgICAgICBpZiAodGhpcy5fb3B0aW9ucy5udW1iZXJGb3JtYXQgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgICAgICBzaXplLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIGltYWdlIHJhdGlvLCBzY2FsZSBieSB3aWR0aFxuICAgICAgICB2YXIgcmF0aW8gPSBpbWFnZS5oZWlnaHQgLyBpbWFnZS53aWR0aDtcbiAgICAgICAgc2l6ZS55ID0gc2l6ZS54ICogcmF0aW87XG4gICAgICB9XG4gICAgICBzaXplLmRpdmlkZShjYW52YXNTaXplKTtcblxuICAgICAgcG9zaXRpb24ueSA9IDEgLSBwb3NpdGlvbi55OyAvLyBJbnZlcnQgeVxuICAgICAgcG9zaXRpb24ueSAtPSBzaXplLnk7IC8vIEZpeCB5XG5cbiAgICAgIC8vIFVwbG9hZCB0aGUgdGV4dHVyZVxuICAgICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCArIHRoaXMuX3RleHR1cmVJbmRleCk7XG4gICAgICB0aGlzLl90ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuXG4gICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0aGlzLl90ZXh0dXJlKTtcblxuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLkxJTkVBUik7XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1MsIGdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfVCwgZ2wuQ0xBTVBfVE9fRURHRSk7XG5cbiAgICAgIC8vIFNldCBwcmVtdWx0aXBsaWVkIGFscGhhXG4gICAgICBnbC5waXhlbFN0b3JlaShnbC5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsIHRydWUpO1xuXG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGltYWdlKTtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuXG4gICAgICAvLyBFeGVjdXRlIHRoZSBzaGFkZXJcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcihudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlciwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfc3RpY2tlckltYWdlOiB7IHR5cGU6ICdpJywgdmFsdWU6IHRoaXMuX3RleHR1cmVJbmRleCB9LFxuICAgICAgICAgIHVfcG9zaXRpb246IHsgdHlwZTogJzJmJywgdmFsdWU6IFtwb3NpdGlvbi54LCBwb3NpdGlvbi55XSB9LFxuICAgICAgICAgIHVfc2l6ZTogeyB0eXBlOiAnMmYnLCB2YWx1ZTogW3NpemUueCwgc2l6ZS55XSB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogQ3JvcHMgdGhlIGltYWdlIHVzaW5nIENhbnZhczJEXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHBhcmFtICB7SW1hZ2V9IGltYWdlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlciwgaW1hZ2UpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBjb250ZXh0ID0gcmVuZGVyZXIuZ2V0Q29udGV4dCgpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBzY2FsZWRQb3NpdGlvbiA9IHRoaXMuX29wdGlvbnMucG9zaXRpb24uY2xvbmUoKTtcblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMubnVtYmVyRm9ybWF0ID09PSAncmVsYXRpdmUnKSB7XG4gICAgICAgIHNjYWxlZFBvc2l0aW9uLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oaW1hZ2Uud2lkdGgsIGltYWdlLmhlaWdodCk7XG4gICAgICBpZiAodHlwZW9mIHRoaXMuX29wdGlvbnMuc2l6ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgc2l6ZS5jb3B5KHRoaXMuX29wdGlvbnMuc2l6ZSk7XG5cbiAgICAgICAgaWYgKHRoaXMuX29wdGlvbnMubnVtYmVyRm9ybWF0ID09PSAncmVsYXRpdmUnKSB7XG4gICAgICAgICAgc2l6ZS5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb250ZXh0LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgaW1hZ2Uud2lkdGgsIGltYWdlLmhlaWdodCwgc2NhbGVkUG9zaXRpb24ueCwgc2NhbGVkUG9zaXRpb24ueSwgc2l6ZS54LCBzaXplLnkpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19sb2FkU3RpY2tlcicsXG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyB0aGUgc3RpY2tlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2xvYWRTdGlja2VyKCkge1xuICAgICAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnO1xuICAgICAgaWYgKGlzQnJvd3Nlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZEltYWdlQnJvd3Nlcih0aGlzLl9vcHRpb25zLnN0aWNrZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRJbWFnZU5vZGUodGhpcy5fb3B0aW9ucy5zdGlja2VyKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfbG9hZEltYWdlQnJvd3NlcicsXG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyB0aGUgZ2l2ZW4gaW1hZ2UgdXNpbmcgdGhlIGJyb3dzZXIncyBgSW1hZ2VgIGNsYXNzXG4gICAgICogQHBhcmFtICB7U3RyaW5nfSBmaWxlTmFtZVxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2xvYWRJbWFnZUJyb3dzZXIoZmlsZU5hbWUpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHJldHVybiBuZXcgX3ZlbmRvclByb21pc2UyWydkZWZhdWx0J10oZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAvLyBSZXR1cm4gcHJlbG9hZGVkIHN0aWNrZXIgaWYgYXZhaWxhYmxlXG4gICAgICAgIGlmIChzZWxmLl9sb2FkZWRTdGlja2Vyc1tmaWxlTmFtZV0pIHtcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZShzZWxmLl9sb2FkZWRTdGlja2Vyc1tmaWxlTmFtZV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBzZWxmLl9sb2FkZWRTdGlja2Vyc1tmaWxlTmFtZV0gPSBpbWFnZTtcbiAgICAgICAgICByZXNvbHZlKGltYWdlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0NvdWxkIG5vdCBsb2FkIHN0aWNrZXI6ICcgKyBmaWxlTmFtZSkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpbWFnZS5zcmMgPSBzZWxmLl9raXQuZ2V0QXNzZXRQYXRoKGZpbGVOYW1lKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19sb2FkSW1hZ2VOb2RlJyxcblxuICAgIC8qKlxuICAgICAqIExvYWRzIHRoZSBnaXZlbiBpbWFnZSB1c2luZyBub2RlLmpzJyBgZnNgIGFuZCBub2RlLWNhbnZhcyBgSW1hZ2VgXG4gICAgICogQHBhcmFtICB7U3RyaW5nfSBmaWxlTmFtZVxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2xvYWRJbWFnZU5vZGUoZmlsZU5hbWUpIHtcbiAgICAgIHZhciBDYW52YXMgPSByZXF1aXJlKCdjYW52YXMnKTtcbiAgICAgIHZhciBmcyA9IHJlcXVpcmUoJ2ZzJyk7XG5cbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHZhciBpbWFnZSA9IG5ldyBDYW52YXMuSW1hZ2UoKTtcbiAgICAgIHZhciBwYXRoID0gc2VsZi5fa2l0LmdldEFzc2V0UGF0aChmaWxlTmFtZSk7XG5cbiAgICAgIHJldHVybiBuZXcgX3ZlbmRvclByb21pc2UyWydkZWZhdWx0J10oZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmcy5yZWFkRmlsZShwYXRoLCBmdW5jdGlvbiAoZXJyLCBidWZmZXIpIHtcbiAgICAgICAgICBpZiAoZXJyKSByZXR1cm4gcmVqZWN0KGVycik7XG5cbiAgICAgICAgICBpbWFnZS5zcmMgPSBidWZmZXI7XG4gICAgICAgICAgcmVzb2x2ZShpbWFnZSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc3RpY2tlcnMnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHJlZ2lzdGVyZWQgc3RpY2tlcnNcbiAgICAgKiBAdHlwZSB7T2JqZWN0LjxTdHJpbmcsU3RyaW5nPn1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zdGlja2VycztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gU3RpY2tlcnNPcGVyYXRpb247XG59KShfb3BlcmF0aW9uMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAqIG9wZXJhdGlvbnMuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5TdGlja2Vyc09wZXJhdGlvbi5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdzdGlja2Vycyc7XG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhpcyBvcGVyYXRpb25cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cblN0aWNrZXJzT3BlcmF0aW9uLnByb3RvdHlwZS5hdmFpbGFibGVPcHRpb25zID0ge1xuICBzdGlja2VyOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG4gIHBvc2l0aW9uOiB7IHR5cGU6ICd2ZWN0b3IyJywgJ2RlZmF1bHQnOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDApIH0sXG4gIHNpemU6IHsgdHlwZTogJ3ZlY3RvcjInLCAnZGVmYXVsdCc6IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMCwgMCkgfVxufTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gU3RpY2tlcnNPcGVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9zdGlja2Vycy1vcGVyYXRpb24uanNcbiAqKiBtb2R1bGUgaWQgPSAxOVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9vcGVyYXRpb24gPSByZXF1aXJlKCcuL29wZXJhdGlvbicpO1xuXG52YXIgX29wZXJhdGlvbjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9vcGVyYXRpb24pO1xuXG52YXIgX2xpYkNvbG9yID0gcmVxdWlyZSgnLi4vbGliL2NvbG9yJyk7XG5cbnZhciBfbGliQ29sb3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliQ29sb3IpO1xuXG4vKipcbiAqIEFuIG9wZXJhdGlvbiB0aGF0IGNhbiBmcmFtZXMgb24gdGhlIGNhbnZhc1xuICpcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0Lk9wZXJhdGlvbnMuRnJhbWVzT3BlcmF0aW9uXG4gKiBAZXh0ZW5kcyBJbWdseUtpdC5PcGVyYXRpb25cbiAqL1xuXG52YXIgRnJhbWVzT3BlcmF0aW9uID0gKGZ1bmN0aW9uIChfT3BlcmF0aW9uKSB7XG4gIGZ1bmN0aW9uIEZyYW1lc09wZXJhdGlvbigpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRnJhbWVzT3BlcmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKEZyYW1lc09wZXJhdGlvbi5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0ZXh0dXJlIGluZGV4IHVzZWQgZm9yIHRoZSBmcmFtZVxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl90ZXh0dXJlSW5kZXggPSAxO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciB1c2VkIGZvciB0aGlzIG9wZXJhdGlvblxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV9mcmFtZUltYWdlO1xcbiAgICAgIHVuaWZvcm0gdmVjNCB1X2NvbG9yO1xcbiAgICAgIHVuaWZvcm0gdmVjMiB1X3RoaWNrbmVzcztcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IGZyYWdDb2xvciA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleENvb3JkKTtcXG4gICAgICAgIGlmICh2X3RleENvb3JkLnggPCB1X3RoaWNrbmVzcy54IHx8IHZfdGV4Q29vcmQueCA+IDEuMCAtIHVfdGhpY2tuZXNzLnggfHxcXG4gICAgICAgICAgdl90ZXhDb29yZC55IDwgdV90aGlja25lc3MueSB8fCB2X3RleENvb3JkLnkgPiAxLjAgLSB1X3RoaWNrbmVzcy55KSB7XFxuICAgICAgICAgICAgZnJhZ0NvbG9yID0gbWl4KGZyYWdDb2xvciwgdV9jb2xvciwgdV9jb2xvci5hKTtcXG4gICAgICAgICAgfVxcblxcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcbiAgICAgIH1cXG4gICAgJztcbiAgfVxuXG4gIF9pbmhlcml0cyhGcmFtZXNPcGVyYXRpb24sIF9PcGVyYXRpb24pO1xuXG4gIF9jcmVhdGVDbGFzcyhGcmFtZXNPcGVyYXRpb24sIFt7XG4gICAga2V5OiAnX3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIENyb3BzIHRoaXMgaW1hZ2UgdXNpbmcgV2ViR0xcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG5cbiAgICAgIHZhciBjb2xvciA9IHRoaXMuX29wdGlvbnMuY29sb3I7XG4gICAgICB2YXIgdGhpY2tuZXNzID0gdGhpcy5fb3B0aW9ucy50aGlja25lc3MgKiBjYW52YXMuaGVpZ2h0O1xuICAgICAgdmFyIHRoaWNrbmVzc1ZlYzIgPSBbdGhpY2tuZXNzIC8gY2FudmFzLndpZHRoLCB0aGlja25lc3MgLyBjYW52YXMuaGVpZ2h0XTtcblxuICAgICAgdmFyIHVuaWZvcm1zID0ge1xuICAgICAgICB1X2NvbG9yOiB7IHR5cGU6ICc0ZicsIHZhbHVlOiBjb2xvci50b0dMQ29sb3IoKSB9LFxuICAgICAgICB1X3RoaWNrbmVzczogeyB0eXBlOiAnMmYnLCB2YWx1ZTogdGhpY2tuZXNzVmVjMiB9XG4gICAgICB9O1xuXG4gICAgICBpZiAoIXRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0pIHtcbiAgICAgICAgdGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSA9IHJlbmRlcmVyLnNldHVwR0xTTFByb2dyYW0obnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5ydW5Qcm9ncmFtKHRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0sIHsgdW5pZm9ybXM6IHVuaWZvcm1zIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogQ3JvcHMgdGhlIGltYWdlIHVzaW5nIENhbnZhczJEXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgdmFyIGNvbnRleHQgPSByZW5kZXJlci5nZXRDb250ZXh0KCk7XG5cbiAgICAgIHZhciBjb2xvciA9IHRoaXMuX29wdGlvbnMuY29sb3I7XG4gICAgICB2YXIgdGhpY2tuZXNzID0gdGhpcy5fb3B0aW9ucy50aGlja25lc3MgKiBjYW52YXMuaGVpZ2h0O1xuXG4gICAgICBjb250ZXh0LnNhdmUoKTtcbiAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgICBjb250ZXh0LmxpbmVXaWR0aCA9IHRoaWNrbmVzcyAqIDI7XG4gICAgICBjb250ZXh0LnN0cm9rZVN0eWxlID0gY29sb3IudG9SR0JBKCk7XG4gICAgICBjb250ZXh0LnJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRnJhbWVzT3BlcmF0aW9uO1xufSkoX29wZXJhdGlvbjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gKiBvcGVyYXRpb25zLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuRnJhbWVzT3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ2ZyYW1lcyc7XG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyBmb3IgdGhpcyBvcGVyYXRpb25cbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbkZyYW1lc09wZXJhdGlvbi5wcm90b3R5cGUuYXZhaWxhYmxlT3B0aW9ucyA9IHtcbiAgY29sb3I6IHsgdHlwZTogJ2NvbG9yJywgJ2RlZmF1bHQnOiBuZXcgX2xpYkNvbG9yMlsnZGVmYXVsdCddKDAsIDAsIDAsIDEpIH0sXG4gIHRoaWNrbmVzczogeyB0eXBlOiAnbnVtYmVyJywgJ2RlZmF1bHQnOiAwLjAyIH1cbn07XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEZyYW1lc09wZXJhdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZyYW1lcy1vcGVyYXRpb24uanNcbiAqKiBtb2R1bGUgaWQgPSAyMFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIEExNSBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuQTE1RmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBBMTVGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gQTE1RmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBMTVGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhBMTVGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhBMTVGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkNvbnRyYXN0KHtcbiAgICAgICAgY29udHJhc3Q6IDAuNjNcbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuQnJpZ2h0bmVzcyh7XG4gICAgICAgIGJyaWdodG5lc3M6IDAuMTJcbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCAzOF0sIFs5NCwgOTRdLCBbMTQ4LCAxNDJdLCBbMTc1LCAxODddLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBncmVlbjogW1swLCAwXSwgWzc3LCA1M10sIFsxNzEsIDE5MF0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgMTBdLCBbNDgsIDg1XSwgWzE3NCwgMjI4XSwgWzI1NSwgMjU1XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnMTUnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdhMTUnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBBMTVGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQTE1RmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9hMTUtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMjFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBCcmVlemUgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLkJyZWV6ZUZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgQnJlZXplRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEJyZWV6ZUZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQnJlZXplRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQnJlZXplRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQnJlZXplRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICAvLyBEZXNhdHVyYXRpb25cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkRlc2F0dXJhdGlvbih7XG4gICAgICAgIGRlc2F0dXJhdGlvbjogMC41XG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFRvbmUgY3VydmVcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIHJnYkNvbnRyb2xQb2ludHM6IHtcbiAgICAgICAgICByZWQ6IFtbMCwgMF0sIFsxNzAsIDE3MF0sIFsyMTIsIDIxOV0sIFsyMzQsIDI0Ml0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDBdLCBbMTcwLCAxNjhdLCBbMjM0LCAyMzFdLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBibHVlOiBbWzAsIDBdLCBbMTcwLCAxNzBdLCBbMjEyLCAyMDhdLCBbMjU1LCAyNTVdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdCcmVlemUnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdicmVlemUnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBCcmVlemVGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQnJlZXplRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9icmVlemUtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMjJcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBCVyBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuQldGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIEJXRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEJXRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBCV0ZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEJXRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQldGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkdyYXlzY2FsZSgpKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0ImVyc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2J3JztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQldGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQldGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2J3LWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDIzXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogQldIYXJkIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5CV0hhcmRGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIEJXSGFyZEZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBCV0hhcmRGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEJXSGFyZEZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEJXSGFyZEZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEJXSGFyZEZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuR3JheXNjYWxlKCkpO1xuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuQ29udHJhc3Qoe1xuICAgICAgICBjb250cmFzdDogMS41XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICcxOTIwJztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnYndoYXJkJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQldIYXJkRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEJXSGFyZEZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvYndoYXJkLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDI0XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogQ2Vsc2l1cyBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuQ2Vsc2l1c0ZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgQ2Vsc2l1c0ZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBDZWxzaXVzRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDZWxzaXVzRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQ2Vsc2l1c0ZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKENlbHNpdXNGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIHJnYkNvbnRyb2xQb2ludHM6IHtcbiAgICAgICAgICByZWQ6IFtbMCwgNjldLCBbNTUsIDExMF0sIFsyMDIsIDIzMF0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDQ0XSwgWzg5LCA5M10sIFsxODUsIDE0MV0sIFsyNTUsIDE4OV1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgNzZdLCBbMzksIDgyXSwgWzIxOCwgMTM4XSwgWzI1NSwgMTcxXV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnQ2Vsc2l1cyc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2NlbHNpdXMnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDZWxzaXVzRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENlbHNpdXNGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2NlbHNpdXMtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMjVcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBDaGVzdCBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuQ2hlc3RGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIENoZXN0RmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIENoZXN0RmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDaGVzdEZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKENoZXN0RmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQ2hlc3RGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIC8vIFRvbmUgY3VydmVcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIHJnYkNvbnRyb2xQb2ludHM6IHtcbiAgICAgICAgICByZWQ6IFtbMCwgMF0sIFs0NCwgNDRdLCBbMTI0LCAxNDNdLCBbMjIxLCAyMDRdLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBncmVlbjogW1swLCAwXSwgWzEzMCwgMTI3XSwgWzIxMywgMTk5XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCAwXSwgWzUxLCA1Ml0sIFsyMTksIDIwNF0sIFsyNTUsIDI1NV1dXG4gICAgICAgIH1cbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0NoZXN0JztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnY2hlc3QnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDaGVzdEZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBDaGVzdEZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvY2hlc3QtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMjZcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBGaXhpZSBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuRml4aWVGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIEZpeGllRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEZpeGllRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGaXhpZUZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEZpeGllRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoRml4aWVGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIC8vIFRvbmUgY3VydmVcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIHJnYkNvbnRyb2xQb2ludHM6IHtcbiAgICAgICAgICByZWQ6IFtbMCwgMF0sIFs0NCwgMjhdLCBbNjMsIDQ4XSwgWzEyOCwgMTMyXSwgWzIzNSwgMjQ4XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgMF0sIFsyMCwgMTBdLCBbNjAsIDQ1XSwgWzE5MCwgMjA5XSwgWzIxMSwgMjMxXSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCAzMV0sIFs0MSwgNjJdLCBbMTUwLCAxNDJdLCBbMjM0LCAyMTJdLCBbMjU1LCAyMjRdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdGaXhpZSc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2ZpeGllJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRml4aWVGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRml4aWVGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2ZpeGllLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDI3XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogRm9vZCBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuRm9vZEZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgRm9vZEZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBGb29kRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGb29kRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoRm9vZEZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEZvb2RGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlNhdHVyYXRpb24oe1xuICAgICAgICBzYXR1cmF0aW9uOiAxLjM1XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkNvbnRyYXN0KHtcbiAgICAgICAgY29udHJhc3Q6IDEuMVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnRm9vZCc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2Zvb2QnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBGb29kRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEZvb2RGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2Zvb2QtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMjhcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBGcmlkZ2UgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLkZyaWRnZUZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgRnJpZGdlRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEZyaWRnZUZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRnJpZGdlRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoRnJpZGdlRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoRnJpZGdlRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICAvLyBUb25lIGN1cnZlXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDldLCBbMjEsIDExXSwgWzQ1LCAyNF0sIFsyNTUsIDIyMF1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDEyXSwgWzIxLCAyMV0sIFs0MiwgNDJdLCBbMTUwLCAxNTBdLCBbMTcwLCAxNzNdLCBbMjU1LCAyMTBdXSxcbiAgICAgICAgICBibHVlOiBbWzAsIDI4XSwgWzQzLCA3Ml0sIFsxMjgsIDE4NV0sIFsyNTUsIDIyMF1dXG4gICAgICAgIH1cbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0ZyaWRnZSc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2ZyaWRnZSc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEZyaWRnZUZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBGcmlkZ2VGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2ZyaWRnZS1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAyOVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIEZyb250IEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5Gcm9udEZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgRnJvbnRGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gRnJvbnRGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEZyb250RmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoRnJvbnRGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhGcm9udEZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgLy8gVG9uZSBjdXJ2ZVxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCA2NV0sIFsyOCwgNjddLCBbNjcsIDExM10sIFsxMjUsIDE4M10sIFsxODcsIDIxN10sIFsyNTUsIDIyOV1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDUyXSwgWzQyLCA1OV0sIFsxMDQsIDEzNF0sIFsxNjksIDIwOV0sIFsyNTUsIDI0MF1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgNTJdLCBbNjUsIDY4XSwgWzkzLCAxMDRdLCBbMTUwLCAxNTNdLCBbMjU1LCAxOThdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdGcm9udCc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2Zyb250JztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRnJvbnRGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRnJvbnRGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2Zyb250LWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDMwXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogR2xhbSBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuR2xhbUZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgR2xhbUZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBHbGFtRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBHbGFtRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoR2xhbUZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEdsYW1GaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkNvbnRyYXN0KHtcbiAgICAgICAgY29udHJhc3Q6IDEuMVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDBdLCBbOTQsIDc0XSwgWzE4MSwgMjA1XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgMF0sIFsxMjcsIDEyN10sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgMF0sIFsxMDIsIDczXSwgWzIyNywgMjEzXSwgWzI1NSwgMjU1XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnR2xhbSc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2dsYW0nO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBHbGFtRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEdsYW1GaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2dsYW0tZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMzFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBHb2JibGluIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5Hb2JibGluRmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBHb2JibGluRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEdvYmJsaW5GaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEdvYmJsaW5GaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhHb2JibGluRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoR29iYmxpbkZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuR29iYmxpbigpKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0dvYmJsaW4nO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdnb2JibGluJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gR29iYmxpbkZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBHb2JibGluRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9nb2JibGluLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDMyXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogSzEgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLksxRmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBLMUZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBLMUZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSzFGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhLMUZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEsxRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICAvLyBUb25lIGN1cnZlXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICBjb250cm9sUG9pbnRzOiBbWzAsIDBdLCBbNTMsIDMyXSwgWzkxLCA4MF0sIFsxNzYsIDIwNV0sIFsyNTUsIDI1NV1dXG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFNhdHVyYXRpb25cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlNhdHVyYXRpb24oe1xuICAgICAgICBzYXR1cmF0aW9uOiAwLjlcbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0sxJztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnazEnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBLMUZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBLMUZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvazEtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMzNcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxudmFyIF9saWJDb2xvciA9IHJlcXVpcmUoJy4uLy4uL2xpYi9jb2xvcicpO1xuXG52YXIgX2xpYkNvbG9yMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkNvbG9yKTtcblxuLyoqXG4gKiBLMiBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuSzJGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIEsyRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIEsyRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBLMkZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEsyRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoSzJGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIC8vIFRvbmUgY3VydmVcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIGNvbnRyb2xQb2ludHM6IFtbMCwgMF0sIFs1NCwgMzNdLCBbNzcsIDgyXSwgWzk0LCAxMDNdLCBbMTIyLCAxMjZdLCBbMTc3LCAxOTNdLCBbMjI5LCAyMzJdLCBbMjU1LCAyNTVdXVxuICAgICAgfSkpO1xuXG4gICAgICAvLyBTb2Z0IGNvbG9yIG92ZXJsYXlcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlNvZnRDb2xvck92ZXJsYXkoe1xuICAgICAgICBjb2xvcjogbmV3IF9saWJDb2xvcjJbJ2RlZmF1bHQnXSg0MCAvIDI1NSwgNDAgLyAyNTUsIDQwIC8gMjU1KVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnSzInO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdrMic7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEsyRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEsyRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9rMi1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAzNFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIEs2IEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5LNkZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgSzZGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gSzZGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEs2RmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoSzZGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhLNkZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgLy8gU2F0dXJhdGlvblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuU2F0dXJhdGlvbih7XG4gICAgICAgIHNhdHVyYXRpb246IDAuNVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnSzYnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdrNic7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEs2RmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEs2RmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9rNi1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAzNVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIEtEeW5hbWljIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5LRHluYW1pY0ZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgS0R5bmFtaWNGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gS0R5bmFtaWNGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEtEeW5hbWljRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoS0R5bmFtaWNGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhLRHluYW1pY0ZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgLy8gVG9uZSBjdXJ2ZVxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgY29udHJvbFBvaW50czogW1swLCAwXSwgWzE3LCAyN10sIFs0NiwgNjldLCBbOTAsIDExMl0sIFsxNTYsIDIwMF0sIFsyMDMsIDI0M10sIFsyNTUsIDI1NV1dXG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFNhdHVyYXRpb25cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlNhdHVyYXRpb24oe1xuICAgICAgICBzYXR1cmF0aW9uOiAwLjdcbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0tEeW5hbWljJztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAna2R5bmFtaWMnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBLRHluYW1pY0ZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBLRHluYW1pY0ZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMva2R5bmFtaWMtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gMzZcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBMZW5pbiBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuTGVuaW5GaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIExlbmluRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIExlbmluRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBMZW5pbkZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKExlbmluRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoTGVuaW5GaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIC8vIERlc2F0dXJhdGlvblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuRGVzYXR1cmF0aW9uKHtcbiAgICAgICAgZGVzYXR1cmF0aW9uOiAwLjRcbiAgICAgIH0pKTtcblxuICAgICAgLy8gVG9uZSBjdXJ2ZVxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCAyMF0sIFs0MCwgMjBdLCBbMTA2LCAxMTFdLCBbMTI5LCAxNTNdLCBbMTkwLCAyMjNdLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBncmVlbjogW1swLCAyMF0sIFs0MCwgMjBdLCBbNjIsIDQxXSwgWzEwNiwgMTA4XSwgWzEzMiwgMTU5XSwgWzIwMywgMjM3XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCA0MF0sIFs0MCwgNDBdLCBbNzMsIDYwXSwgWzEzMywgMTYwXSwgWzE5MSwgMjk3XSwgWzIwMywgMjM3XSwgWzIzNywgMjM5XSwgWzI1NSwgMjU1XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnTGVuaW4nO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdsZW5pbic7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIExlbmluRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IExlbmluRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9sZW5pbi1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAzN1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIExvbW8gRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLkxvbW9GaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIExvbW9GaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gTG9tb0ZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTG9tb0ZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKExvbW9GaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhMb21vRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICBjb250cm9sUG9pbnRzOiBbWzAsIDBdLCBbODcsIDIwXSwgWzEzMSwgMTU2XSwgWzE4MywgMjA1XSwgWzI1NSwgMjAwXV1cbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0xvbW8nO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdsb21vJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gTG9tb0ZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBMb21vRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9sb21vLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDM4XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogTWVsbG93IEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5NZWxsb3dGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIE1lbGxvd0ZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBNZWxsb3dGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIE1lbGxvd0ZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKE1lbGxvd0ZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKE1lbGxvd0ZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCAwXSwgWzQxLCA4NF0sIFs4NywgMTM0XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgMF0sIFsyNTUsIDIxNl1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgMF0sIFsyNTUsIDEzMV1dXG4gICAgICAgIH1cbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ01lbGxvdyc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ21lbGxvdyc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIE1lbGxvd0ZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBNZWxsb3dGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL21lbGxvdy1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAzOVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIE1vcm5pbmcgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLk1vcm5pbmdGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIE1vcm5pbmdGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gTW9ybmluZ0ZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgTW9ybmluZ0ZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKE1vcm5pbmdGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhNb3JuaW5nRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDQwXSwgWzI1NSwgMjMwXV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgMTBdLCBbMjU1LCAyMjVdXSxcbiAgICAgICAgICBibHVlOiBbWzAsIDIwXSwgWzI1NSwgMTgxXV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5HbG93KCkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnTW9ybmluZyc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ21vcm5pbmcnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBNb3JuaW5nRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IE1vcm5pbmdGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL21vcm5pbmctZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gNDBcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBPcmNoaWQgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLk9yY2hpZEZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgT3JjaGlkRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIE9yY2hpZEZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgT3JjaGlkRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoT3JjaGlkRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoT3JjaGlkRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICAvLyBUb25lIGN1cnZlXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDBdLCBbMTE1LCAxMzBdLCBbMTk1LCAyMTVdLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBncmVlbjogW1swLCAwXSwgWzE0OCwgMTUzXSwgWzE3MiwgMjE1XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCA0Nl0sIFs1OCwgNzVdLCBbMTc4LCAyMDVdLCBbMjU1LCAyNTVdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFRvbmUgY3VydmVcbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIGNvbnRyb2xQb2ludHM6IFtbMCwgMF0sIFsxMTcsIDE1MV0sIFsxODksIDIxN10sIFsyNTUsIDI1NV1dXG4gICAgICB9KSk7XG5cbiAgICAgIC8vIERlc2F0dXJhdGlvblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuRGVzYXR1cmF0aW9uKHtcbiAgICAgICAgZGVzYXR1cmF0aW9uOiAwLjY1XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdPcmNoaWQnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdvcmNoaWQnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBPcmNoaWRGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gT3JjaGlkRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9vcmNoaWQtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gNDFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBQb2xhIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5Qb2xhRmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBQb2xhRmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIFBvbGFGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFBvbGFGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhQb2xhRmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoUG9sYUZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCAwXSwgWzk0LCA3NF0sIFsxODEsIDIwNV0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDBdLCBbMzQsIDM0XSwgWzk5LCA3Nl0sIFsxNzYsIDE5MF0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgMF0sIFsxMDIsIDczXSwgWzIyNywgMjEzXSwgWzI1NSwgMjU1XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5TYXR1cmF0aW9uKHtcbiAgICAgICAgc2F0dXJhdGlvbjogMC44XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLkNvbnRyYXN0KHtcbiAgICAgICAgY29udHJhc3Q6IDEuNVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnUG9sYSBTWCc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ3BvbGEnO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBQb2xhRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFBvbGFGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3BvbGEtZmlsdGVyLmpzXG4gKiogbW9kdWxlIGlkID0gNDJcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfZmlsdGVyID0gcmVxdWlyZSgnLi9maWx0ZXInKTtcblxudmFyIF9maWx0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZmlsdGVyKTtcblxuLyoqXG4gKiBQb2xhNjY5IEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5Qb2xhNjY5RmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBQb2xhNjY5RmlsdGVyID0gKGZ1bmN0aW9uIChfRmlsdGVyKSB7XG4gIGZ1bmN0aW9uIFBvbGE2NjlGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFBvbGE2NjlGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhQb2xhNjY5RmlsdGVyLCBfRmlsdGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoUG9sYTY2OUZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCAwXSwgWzU2LCAxOF0sIFsxOTYsIDIwOV0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGdyZWVuOiBbWzAsIDM4XSwgWzcxLCA4NF0sIFsyNTUsIDI1NV1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgMF0sIFsxMzEsIDEzM10sIFsyMDQsIDIxMV0sIFsyNTUsIDI1NV1dXG4gICAgICAgIH1cbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuU2F0dXJhdGlvbih7XG4gICAgICAgIHNhdHVyYXRpb246IDAuOFxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Db250cmFzdCh7XG4gICAgICAgIGNvbnRyYXN0OiAxLjVcbiAgICAgIH0pKTtcblxuICAgICAgc3RhY2sucmVuZGVyKHJlbmRlcmVyKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICduYW1lJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBVSVxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1BvbGEgNjY5JztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAncG9sYTY2OSc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFBvbGE2NjlGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gUG9sYTY2OUZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcG9sYTY2OS1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA0M1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIFF1b3ppIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5RdW96aUZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgUXVvemlGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gUXVvemlGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFF1b3ppRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoUXVvemlGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhRdW96aUZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgLy8gRGVzYXR1cmF0aW9uXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5EZXNhdHVyYXRpb24oe1xuICAgICAgICBkZXNhdHVyYXRpb246IDAuNjVcbiAgICAgIH0pKTtcblxuICAgICAgLy8gVG9uZSBjdXJ2ZVxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCA1MF0sIFs0MCwgNzhdLCBbMTE4LCAxNzBdLCBbMTgxLCAyMTFdLCBbMjU1LCAyNTVdXSxcbiAgICAgICAgICBncmVlbjogW1swLCAyN10sIFsyOCwgNDVdLCBbMTA5LCAxNTddLCBbMTU3LCAxOTVdLCBbMTc5LCAyMDhdLCBbMjA2LCAyMTJdLCBbMjU1LCAyNDBdXSxcbiAgICAgICAgICBibHVlOiBbWzAsIDUwXSwgWzEyLCA1NV0sIFs0NiwgMTAzXSwgWzEwMywgMTYyXSwgWzE5NCwgMTgyXSwgWzI0MSwgMjAxXSwgWzI1NSwgMjE5XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnUXVvemknO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdxdW96aSc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFF1b3ppRmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFF1b3ppRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9xdW96aS1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA0NFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIFNlbWlyZWQgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLlNlbWlyZWRGaWx0ZXJcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXJ9XG4gKi9cblxudmFyIFNlbWlyZWRGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gU2VtaXJlZEZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU2VtaXJlZEZpbHRlcik7XG5cbiAgICBpZiAoX0ZpbHRlciAhPSBudWxsKSB7XG4gICAgICBfRmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKFNlbWlyZWRGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhTZW1pcmVkRmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDEyOV0sIFs3NSwgMTUzXSwgWzE4MSwgMjI3XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgOF0sIFsxMTEsIDg1XSwgWzIxMiwgMTU4XSwgWzI1NSwgMjI2XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCA1XSwgWzc1LCAyMl0sIFsxOTMsIDkwXSwgWzI1NSwgMjI5XV1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5HbG93KCkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnU2VtaSBSZWQnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdzZW1pcmVkJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gU2VtaXJlZEZpbHRlcjtcbn0pKF9maWx0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTZW1pcmVkRmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9zZW1pcmVkLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDQ1XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogU3VubnkgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLlN1bm55RmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBTdW5ueUZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBTdW5ueUZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU3VubnlGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhTdW5ueUZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKFN1bm55RmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIHZhciBzdGFjayA9IG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXNTdGFjaygpO1xuXG4gICAgICBzdGFjay5hZGQobmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlcy5Ub25lQ3VydmUoe1xuICAgICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgICAgcmVkOiBbWzAsIDBdLCBbNjIsIDgyXSwgWzE0MSwgMTU0XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgZ3JlZW46IFtbMCwgMzldLCBbNTYsIDk2XSwgWzE5MiwgMTc2XSwgWzI1NSwgMjU1XV0sXG4gICAgICAgICAgYmx1ZTogW1swLCAwXSwgWzE3NCwgOTldLCBbMjU1LCAyMzVdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlRvbmVDdXJ2ZSh7XG4gICAgICAgIGNvbnRyb2xQb2ludHM6IFtbMCwgMF0sIFs1NSwgMjBdLCBbMTU4LCAxOTFdLCBbMjU1LCAyNTVdXVxuICAgICAgfSkpO1xuXG4gICAgICBzdGFjay5yZW5kZXIocmVuZGVyZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ25hbWUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hbWUgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIFVJXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnU3VubnknO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLiBDYW4gYmUgdXNlZCB0byBzZWxlY3RcbiAgICAgKiB0aGUgYWN0aXZlIGZpbHRlci5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdzdW5ueSc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFN1bm55RmlsdGVyO1xufSkoX2ZpbHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFN1bm55RmlsdGVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9zdW5ueS1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA0NlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9maWx0ZXIgPSByZXF1aXJlKCcuL2ZpbHRlcicpO1xuXG52YXIgX2ZpbHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9maWx0ZXIpO1xuXG4vKipcbiAqIFRleGFzIEZpbHRlclxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVycy5UZXhhc0ZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgVGV4YXNGaWx0ZXIgPSAoZnVuY3Rpb24gKF9GaWx0ZXIpIHtcbiAgZnVuY3Rpb24gVGV4YXNGaWx0ZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFRleGFzRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoVGV4YXNGaWx0ZXIsIF9GaWx0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhUZXhhc0ZpbHRlciwgW3tcbiAgICBrZXk6ICdyZW5kZXInLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgZmlsdGVyXG4gICAgICogQHBhcmFtICB7UmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgc3RhY2sgPSBuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzU3RhY2soKTtcblxuICAgICAgc3RhY2suYWRkKG5ldyBfZmlsdGVyMlsnZGVmYXVsdCddLlByaW1pdGl2ZXMuVG9uZUN1cnZlKHtcbiAgICAgICAgcmdiQ29udHJvbFBvaW50czoge1xuICAgICAgICAgIHJlZDogW1swLCA3Ml0sIFs4OSwgOTldLCBbMTc2LCAyMTJdLCBbMjU1LCAyMzddXSxcbiAgICAgICAgICBncmVlbjogW1swLCA0OV0sIFsyNTUsIDE5Ml1dLFxuICAgICAgICAgIGJsdWU6IFtbMCwgNzJdLCBbMjU1LCAxNTFdXVxuICAgICAgICB9XG4gICAgICB9KSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdUZXhhcyc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ3RleGFzJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gVGV4YXNGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gVGV4YXNGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3RleGFzLWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDQ3XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogWDQwMCBGaWx0ZXJcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlcnMuWDQwMEZpbHRlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlcn1cbiAqL1xuXG52YXIgWDQwMEZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBYNDAwRmlsdGVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBYNDAwRmlsdGVyKTtcblxuICAgIGlmIChfRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIF9GaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoWDQwMEZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKFg0MDBGaWx0ZXIsIFt7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGZpbHRlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcihyZW5kZXJlcikge1xuICAgICAgdmFyIHN0YWNrID0gbmV3IF9maWx0ZXIyWydkZWZhdWx0J10uUHJpbWl0aXZlc1N0YWNrKCk7XG5cbiAgICAgIHN0YWNrLmFkZChuZXcgX2ZpbHRlcjJbJ2RlZmF1bHQnXS5QcmltaXRpdmVzLlg0MDAoKSk7XG5cbiAgICAgIHN0YWNrLnJlbmRlcihyZW5kZXJlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdYNDAwJztcbiAgICB9XG4gIH1dLCBbe1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi4gQ2FuIGJlIHVzZWQgdG8gc2VsZWN0XG4gICAgICogdGhlIGFjdGl2ZSBmaWx0ZXIuXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAneDQwMCc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFg0MDBGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gWDQwMEZpbHRlcjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMveDQwMC1maWx0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA0OFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbi8qKlxuICogUmVwcmVzZW50cyBhIDItZGltZW5zaW9uYWwgdmVjdG9yIHdoaWxlIHByb3ZpZGluZyBtYXRoIGZ1bmN0aW9ucyB0b1xuICogbW9kaWZ5IC8gY2xvbmUgdGhlIHZlY3Rvci4gRnVsbHkgY2hhaW5hYmxlLlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuVmVjdG9yMlxuICogQHBhcmFtIHtudW1iZXJ9IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XG4gKiBAcHJpdmF0ZVxuICovXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIFZlY3RvcjIgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBWZWN0b3IyKHgsIHkpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVmVjdG9yMik7XG5cbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG4gICAgaWYgKHR5cGVvZiB0aGlzLnggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLnggPSAwO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMueSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMueSA9IDA7XG4gICAgfVxuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKFZlY3RvcjIsIFt7XG4gICAga2V5OiAnc2V0JyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGdpdmVuIHZhbHVlc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHlcbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzZXQoeCwgeSkge1xuICAgICAgdGhpcy54ID0geDtcbiAgICAgIHRoaXMueSA9IHk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjbG9uZScsXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhpcyB2ZWN0b3JcbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBjbG9uZSgpIHtcbiAgICAgIHJldHVybiBuZXcgVmVjdG9yMih0aGlzLngsIHRoaXMueSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29weScsXG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgdGhlIHZhbHVlcyBvZiB0aGUgZ2l2ZW4gdmVjdG9yXG4gICAgICogQHBhcmFtICB7VmVjdG9yMn0gb3RoZXJcbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBjb3B5KG90aGVyKSB7XG4gICAgICB0aGlzLnggPSBvdGhlci54O1xuICAgICAgdGhpcy55ID0gb3RoZXIueTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NsYW1wJyxcblxuICAgIC8qKlxuICAgICAqIENsYW1wcyB0aGlzIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBWZWN0b3IyIC8gbnVtYmVyXG4gICAgICogQHBhcmFtICB7KG51bWJlcnxWZWN0b3IyKX0gbWluaW11bVxuICAgICAqIEBwYXJhbSAgeyhudW1iZXJ8VmVjdG9yMil9IG1heGltdW1cbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBjbGFtcChtaW5pbXVtLCBtYXhpbXVtKSB7XG4gICAgICB2YXIgbWluaW11bVNldCA9IG1pbmltdW0gIT09IG51bGwgJiYgdHlwZW9mIG1pbmltdW0gIT09ICd1bmRlZmluZWQnO1xuICAgICAgdmFyIG1heGltdW1TZXQgPSBtYXhpbXVtICE9PSBudWxsICYmIHR5cGVvZiBtYXhpbXVtICE9PSAndW5kZWZpbmVkJztcblxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgICovXG4gICAgICBpZiAoIShtaW5pbXVtIGluc3RhbmNlb2YgVmVjdG9yMikgJiYgbWluaW11bVNldCkge1xuICAgICAgICBtaW5pbXVtID0gbmV3IFZlY3RvcjIobWluaW11bSwgbWluaW11bSk7XG4gICAgICB9XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAgKi9cbiAgICAgIGlmICghKG1heGltdW0gaW5zdGFuY2VvZiBWZWN0b3IyKSAmJiBtYXhpbXVtU2V0KSB7XG4gICAgICAgIG1heGltdW0gPSBuZXcgVmVjdG9yMihtYXhpbXVtLCBtYXhpbXVtKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1pbmltdW1TZXQpIHtcbiAgICAgICAgdGhpcy54ID0gTWF0aC5tYXgobWluaW11bS54LCB0aGlzLngpO1xuICAgICAgICB0aGlzLnkgPSBNYXRoLm1heChtaW5pbXVtLnksIHRoaXMueSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhpbXVtU2V0KSB7XG4gICAgICAgIHRoaXMueCA9IE1hdGgubWluKG1heGltdW0ueCwgdGhpcy54KTtcbiAgICAgICAgdGhpcy55ID0gTWF0aC5taW4obWF4aW11bS55LCB0aGlzLnkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZGl2aWRlJyxcblxuICAgIC8qKlxuICAgICAqIERpdmlkZXMgdGhpcyB2ZWN0b3IgYnkgdGhlIGdpdmVuIFZlY3RvcjIgLyBudW1iZXJcbiAgICAgKiBAcGFyYW0gIHsobnVtYmVyfFZlY3RvcjIpfSBkaXZpc29yXG4gICAgICogQHBhcmFtICB7bnVtYmVyfSBbeV1cbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBkaXZpZGUoZGl2aXNvciwgeSkge1xuICAgICAgaWYgKGRpdmlzb3IgaW5zdGFuY2VvZiBWZWN0b3IyKSB7XG4gICAgICAgIHRoaXMueCAvPSBkaXZpc29yLng7XG4gICAgICAgIHRoaXMueSAvPSBkaXZpc29yLnk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnggLz0gZGl2aXNvcjtcbiAgICAgICAgdGhpcy55IC89IHR5cGVvZiB5ID09PSAndW5kZWZpbmVkJyA/IGRpdmlzb3IgOiB5O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc3VidHJhY3QnLFxuXG4gICAgLyoqXG4gICAgICogU3VidHJhY3RzIHRoZSBnaXZlbiBWZWN0b3IyIC8gbnVtYmVyIGZyb20gdGhpcyB2ZWN0b3JcbiAgICAgKiBAcGFyYW0gIHsobnVtYmVyfFZlY3RvcjIpfSBzdWJ0cmFoZW5kXG4gICAgICogQHBhcmFtICB7bnVtYmVyfSBbeV1cbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzdWJ0cmFjdChzdWJ0cmFoZW5kLCB5KSB7XG4gICAgICBpZiAoc3VidHJhaGVuZCBpbnN0YW5jZW9mIFZlY3RvcjIpIHtcbiAgICAgICAgdGhpcy54IC09IHN1YnRyYWhlbmQueDtcbiAgICAgICAgdGhpcy55IC09IHN1YnRyYWhlbmQueTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMueCAtPSBzdWJ0cmFoZW5kO1xuICAgICAgICB0aGlzLnkgLT0gdHlwZW9mIHkgPT09ICd1bmRlZmluZWQnID8gc3VidHJhaGVuZCA6IHk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdtdWx0aXBseScsXG5cbiAgICAvKipcbiAgICAgKiBNdWx0aXBsaWVzIHRoZSBnaXZlbiBWZWN0b3IyIC8gbnVtYmVyIHdpdGggdGhpcyB2ZWN0b3JcbiAgICAgKiBAcGFyYW0gIHsobnVtYmVyfFZlY3RvcjIpfSBzdWJ0cmFoZW5kXG4gICAgICogQHBhcmFtICB7bnVtYmVyfSBbeV1cbiAgICAgKiBAcmV0dXJuIHtWZWN0b3IyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBtdWx0aXBseShmYWN0b3IsIHkpIHtcbiAgICAgIGlmIChmYWN0b3IgaW5zdGFuY2VvZiBWZWN0b3IyKSB7XG4gICAgICAgIHRoaXMueCAqPSBmYWN0b3IueDtcbiAgICAgICAgdGhpcy55ICo9IGZhY3Rvci55O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy54ICo9IGZhY3RvcjtcbiAgICAgICAgdGhpcy55ICo9IHR5cGVvZiB5ID09PSAndW5kZWZpbmVkJyA/IGZhY3RvciA6IHk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdhZGQnLFxuXG4gICAgLyoqXG4gICAgICogQWRkcyB0aGUgZ2l2ZW4gVmVjdG9yMiAvIG51bWJlcnMgdG8gdGhpcyB2ZWN0b3JcbiAgICAgKiBAcGFyYW0geyhudW1iZXJ8VmVjdG9yMil9IGFkZGVuZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbeV1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gYWRkKGFkZGVuZCwgeSkge1xuICAgICAgaWYgKGFkZGVuZCBpbnN0YW5jZW9mIFZlY3RvcjIpIHtcbiAgICAgICAgdGhpcy54ICs9IGFkZGVuZC54O1xuICAgICAgICB0aGlzLnkgKz0gYWRkZW5kLnk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnggKz0gYWRkZW5kO1xuICAgICAgICB0aGlzLnkgKz0gdHlwZW9mIHkgPT09ICd1bmRlZmluZWQnID8gYWRkZW5kIDogeTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2VxdWFscycsXG5cbiAgICAvKipcbiAgICAgKiBDaGVja3Mgd2hldGhlciB0aGUgeCBhbmQgeSB2YWx1ZSBhcmUgdGhlIHNhbWUgYXMgdGhlIGdpdmVuIG9uZXNcbiAgICAgKiBAcGFyYW0gIHsobnVtYmVyfFZlY3RvcjIpfSB2ZWNcbiAgICAgKiBAcGFyYW0gIHtudW1iZXJ9IHlcbiAgICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBlcXVhbHModmVjLCB5KSB7XG4gICAgICBpZiAodmVjIGluc3RhbmNlb2YgVmVjdG9yMikge1xuICAgICAgICByZXR1cm4gdmVjLnggPT09IHRoaXMueCAmJiB2ZWMueSA9PT0gdGhpcy55O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHZlYyA9PT0gdGhpcy54ICYmIHkgPT09IHRoaXMueTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdmbGlwJyxcblxuICAgIC8qKlxuICAgICAqIEZsaXBzIHRoZSB4IGFuZCB5IHZhbHVlcyBvZiB0aGlzIHZlY3RvclxuICAgICAqIEByZXR1cm4ge1ZlY3RvcjJ9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGZsaXAoKSB7XG4gICAgICB2YXIgdGVtcFggPSB0aGlzLng7XG4gICAgICB0aGlzLnggPSB0aGlzLnk7XG4gICAgICB0aGlzLnkgPSB0ZW1wWDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3RvU3RyaW5nJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB2ZWN0b3JcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgcmV0dXJuICdWZWN0b3IyKHsgeDogJyArIHRoaXMueCArICcsIHk6ICcgKyB0aGlzLnkgKyAnIH0pJztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gVmVjdG9yMjtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFZlY3RvcjI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL21hdGgvdmVjdG9yMi5qc1xuICoqIG1vZHVsZSBpZCA9IDQ5XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgRmlsZVJlYWRlciwgSW1hZ2UsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDIsIF94MywgX3g0KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MiwgcHJvcGVydHkgPSBfeDMsIHJlY2VpdmVyID0gX3g0OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDIgPSBwYXJlbnQ7IF94MyA9IHByb3BlcnR5OyBfeDQgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBfYmFzZVVpID0gcmVxdWlyZSgnLi4vYmFzZS91aScpO1xuXG52YXIgX2Jhc2VVaTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9iYXNlVWkpO1xuXG52YXIgX2xpYkNhbnZhcyA9IHJlcXVpcmUoJy4vbGliL2NhbnZhcycpO1xuXG52YXIgX2xpYkNhbnZhczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJDYW52YXMpO1xuXG52YXIgX2xpYkZpbGVMb2FkZXIgPSByZXF1aXJlKCcuL2xpYi9maWxlLWxvYWRlcicpO1xuXG52YXIgX2xpYkZpbGVMb2FkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliRmlsZUxvYWRlcik7XG5cbnZhciBfbGliV2ViY2FtSGFuZGxlciA9IHJlcXVpcmUoJy4vbGliL3dlYmNhbS1oYW5kbGVyJyk7XG5cbnZhciBfbGliV2ViY2FtSGFuZGxlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJXZWJjYW1IYW5kbGVyKTtcblxudmFyIF9saWJUb3BDb250cm9scyA9IHJlcXVpcmUoJy4vbGliL3RvcC1jb250cm9scycpO1xuXG52YXIgX2xpYlRvcENvbnRyb2xzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlRvcENvbnRyb2xzKTtcblxudmFyIF9saWJTY3JvbGxiYXIgPSByZXF1aXJlKCcuL2xpYi9zY3JvbGxiYXInKTtcblxudmFyIF9saWJTY3JvbGxiYXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliU2Nyb2xsYmFyKTtcblxudmFyIF9jb25zdGFudHMgPSByZXF1aXJlKCcuLi8uLi9jb25zdGFudHMnKTtcblxudmFyIE5pZ2h0VUkgPSAoZnVuY3Rpb24gKF9VSSkge1xuICBmdW5jdGlvbiBOaWdodFVJKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBOaWdodFVJKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKE5pZ2h0VUkucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICB0aGlzLl9vcGVyYXRpb25zTWFwID0ge307XG4gICAgdGhpcy5fdGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1sb2FkaW5nT3ZlcmxheVwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtbG9hZGluZ092ZXJsYXktY29udGVudFwiPiA8aW1nIHNyYz1cIicrKCBpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvbG9hZGluZy5naWYnKSkrJ1wiIC8+IDxzcGFuPicrKCBpdC5oZWxwZXJzLnRyYW5zbGF0ZSgnZ2VuZXJpYy5sb2FkaW5nJykgKSsnLi4uPC9zcGFuPiA8L2Rpdj4gPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250YWluZXJcIj4gJztpZighaXQub3B0aW9ucy51aS5oaWRlSGVhZGVyKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LWhlYWRlci1yb3dcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWhlYWRlclwiPiBpbWcubHkgUGhvdG8gRWRpdG9yIFNESyAnO2lmKGl0Lm9wdGlvbnMudWkuc2hvd0Nsb3NlQnV0dG9uKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNsb3NlLWJ1dHRvblwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9jbG9zZS5wbmcnKSkrJ1wiIC8+IDwvZGl2PiAnO31vdXQrPScgPC9kaXY+IDwvZGl2PiAnO31vdXQrPScgJztpZihpdC5yZW5kZXJDb250cm9scyl7b3V0Kz0nIDxkaXYgY2xhc3M9XCJpbWdseWtpdC10b3AtY29udHJvbHMtcm93XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC10b3AtY29udHJvbHNcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXRvcC1jb250cm9scy1sZWZ0XCI+ICc7aWYoaXQub3B0aW9ucy51aS5zaG93TmV3QnV0dG9uKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LW5ld1wiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC90b3AvbmV3LnBuZycpKSsnXCIgLz4gJysoIGl0LmhlbHBlcnMudHJhbnNsYXRlKCd0b3AtY29udHJvbHMubmV3JykgKSsnIDwvZGl2PiAnO31vdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LXVuZG9cIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvdG9wL3VuZG8ucG5nJykpKydcIiAvPiAnKyggaXQuaGVscGVycy50cmFuc2xhdGUoJ3RvcC1jb250cm9scy51bmRvJykgKSsnIDwvZGl2PiAnO2lmKGl0Lm9wdGlvbnMudWkuc2hvd0V4cG9ydEJ1dHRvbil7b3V0Kz0nIDxkaXYgY2xhc3M9XCJpbWdseWtpdC1leHBvcnRcIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvdG9wL2V4cG9ydC5wbmcnKSkrJ1wiIC8+ICcrKCBpdC5oZWxwZXJzLnRyYW5zbGF0ZSgndG9wLWNvbnRyb2xzLmV4cG9ydCcpICkrJyA8L2Rpdj4gJzt9b3V0Kz0nIDwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtdG9wLWNvbnRyb2xzLXJpZ2h0XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC16b29tLWZpdFwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtem9vbS1sZXZlbFwiPicrKCBpdC5oZWxwZXJzLnRyYW5zbGF0ZSgndG9wLWNvbnRyb2xzLnpvb20nKSApKyc6IDxzcGFuIGNsYXNzPVwiaW1nbHlraXQtem9vbS1sZXZlbC1udW1cIj4xMDA8L3NwYW4+JTwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtem9vbS1pblwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC90b3Avem9vbS1pbi5wbmcnKSkrJ1wiIC8+IDwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtem9vbS1vdXRcIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvdG9wL3pvb20tb3V0LnBuZycpKSsnXCIgLz4gPC9kaXY+IDwvZGl2PiA8L2Rpdj4gPC9kaXY+ICc7fW91dCs9JyA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNvbnRhaW5lci1yb3dcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jb250YWluZXJcIj4gJztpZihpdC5yZW5kZXJXZWJjYW0pe291dCs9JyA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWlubmVyLWNvbnRhaW5lclwiPiA8dmlkZW8gY2xhc3M9XCJpbWdseWtpdC13ZWJjYW0tdmlkZW9cIiBhdXRvcGxheT48L3ZpZGVvPiA8L2Rpdj4gJzt9b3V0Kz0nICc7aWYoIShpdC5yZW5kZXJTcGxhc2hTY3JlZW4gfHwgaXQucmVuZGVyV2ViY2FtKSl7b3V0Kz0nIDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtaW5uZXItY29udGFpbmVyXCI+IDxjYW52YXMgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtZHJhZ2dhYmxlXCI+PC9jYW52YXM+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY29udHJvbHMgaW1nbHlraXQtY2FudmFzLWNvbnRyb2xzLWRpc2FibGVkXCI+PC9kaXY+IDwvZGl2PiAnO31vdXQrPScgJztpZihpdC5yZW5kZXJTcGxhc2hTY3JlZW4pe291dCs9JyA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc3BsYXNoLWNvbnRhaW5lclwiPiAnO2lmKGl0Lm9wdGlvbnMudWkuc2hvd1VwbG9hZEJ1dHRvbil7b3V0Kz0nIDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtcm93IGltZ2x5a2l0LXNwbGFzaC1yb3ctLXVwbG9hZFwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc3BsYXNoLWNlbGxcIj4gPGlucHV0IHR5cGU9XCJmaWxlXCIgY2xhc3M9XCJpbWdseWtpdC11cGxvYWQtaGlkZGVuLWlucHV0XCIgLz4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvdXBsb2FkLnBuZycpKSsnXCIgLz4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1jb250ZW50XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtYnV0dG9uXCI+JysoIGl0LmhlbHBlcnMudHJhbnNsYXRlKCdzcGxhc2gudXBsb2FkLmhlYWRsaW5lJykgKSsnPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtdGV4dFwiPicrKCBpdC5oZWxwZXJzLnRyYW5zbGF0ZSgnc3BsYXNoLnVwbG9hZC5kZXNjcmlwdGlvbicpICkrJzwvZGl2PiA8L2Rpdj4gPC9kaXY+IDwvZGl2PiAnO31vdXQrPScgJztpZihpdC5vcHRpb25zLnVpLnNob3dVcGxvYWRCdXR0b24gJiYgaXQub3B0aW9ucy51aS5zaG93V2ViY2FtQnV0dG9uKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1yb3cgaW1nbHlraXQtc3BsYXNoLXJvdy0tb3JcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1vclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc3BsYXNoLW9yLWxpbmVcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1vci13b3JkXCI+JysoIGl0LmhlbHBlcnMudHJhbnNsYXRlKCdzcGxhc2gub3InKSApKyc8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1vci1saW5lXCI+PC9kaXY+IDwvZGl2PiA8L2Rpdj4gJzt9b3V0Kz0nICc7aWYoaXQub3B0aW9ucy51aS5zaG93V2ViY2FtQnV0dG9uKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1yb3cgaW1nbHlraXQtc3BsYXNoLXJvdy0tY2FtZXJhXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtY2VsbFwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9zaHV0dGVyLnBuZycpKSsnXCIgLz4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNwbGFzaC1jb250ZW50XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtYnV0dG9uXCI+JysoIGl0LmhlbHBlcnMudHJhbnNsYXRlKCdzcGxhc2gud2ViY2FtLmhlYWRsaW5lJykgKSsnPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zcGxhc2gtdGV4dFwiPicrKCBpdC5oZWxwZXJzLnRyYW5zbGF0ZSgnc3BsYXNoLndlYmNhbS5kZXNjcmlwdGlvbicpICkrJzwvZGl2PiA8L2Rpdj4gPC9kaXY+IDwvZGl2PiAnO31vdXQrPScgPC9kaXY+ICc7fW91dCs9JyA8L2Rpdj4gPC9kaXY+ICc7aWYoaXQucmVuZGVyV2ViY2FtKXtvdXQrPScgPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLXJvd1wiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtY29udGFpbmVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9sc1wiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtd2ViY2FtLWJ1dHRvblwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9zaHV0dGVyLWJ1dHRvbi5wbmcnKSkrJ1wiIC8+IDwvZGl2PiA8L2Rpdj4gPC9kaXY+IDwvZGl2PiAnO31vdXQrPScgJztpZihpdC5yZW5kZXJDb250cm9scyl7b3V0Kz0nIDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1yb3dcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWNvbnRhaW5lclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHNcIj4gPGRpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLW92ZXJ2aWV3XCI+IDx1bCBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWxpc3RcIj4gJzsgZm9yICh2YXIgaWRlbnRpZmllciBpbiBpdC5jb250cm9scykgeyBvdXQrPScgJzsgdmFyIGNvbnRyb2wgPSBpdC5jb250cm9sc1tpZGVudGlmaWVyXTsgb3V0Kz0nIDxsaSBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWl0ZW0tLXdpdGgtbGFiZWxcIiBkYXRhLWlkZW50aWZpZXI9XCInKyggY29udHJvbC5pZGVudGlmaWVyKSsnXCInO2lmKGl0LmNvbnRyb2xzRGlzYWJsZWQpe291dCs9JyBkYXRhLWRpc2FibGVkJzt9b3V0Kz0nPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9vcGVyYXRpb25zLycgKyBjb250cm9sLmlkZW50aWZpZXIgKyAnLnBuZycpICkrJ1wiIC8+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1sYWJlbFwiPicrKGl0LmhlbHBlcnMudHJhbnNsYXRlKCdvcGVyYXRpb25zLicgKyBjb250cm9sLmlkZW50aWZpZXIpKSsnPC9kaXY+IDwvbGk+ICc7IH0gb3V0Kz0nIDwvdWw+IDwvZGl2PiA8L2Rpdj4gPC9kaXY+IDwvZGl2PiA8L2Rpdj4gJzt9b3V0Kz0nIDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgdGhpcy5fcmVnaXN0ZXJlZENvbnRyb2xzID0ge307XG4gICAgdGhpcy5faGlzdG9yeSA9IFtdO1xuXG4gICAgLy8gVGhlIGBOaWdodGAgVUkgaGFzIGEgZml4ZWQgb3BlcmF0aW9uIG9yZGVyXG4gICAgdGhpcy5fcHJlZmVycmVkT3BlcmF0aW9uT3JkZXIgPSBbXG4gICAgLy8gRmlyc3QsIGFsbCBvcGVyYXRpb25zIHRoYXQgYWZmZWN0IHRoZSBpbWFnZSBkaW1lbnNpb25zXG4gICAgJ3JvdGF0aW9uJywgJ2Nyb3AnLCAnZmxpcCcsXG5cbiAgICAvLyBUaGVuIGNvbG9yIG9wZXJhdGlvbnMgKGZpcnN0IGZpbHRlcnMsIHRoZW4gZmluZS10dW5pbmcpXG4gICAgJ2ZpbHRlcnMnLCAnY29udHJhc3QnLCAnYnJpZ2h0bmVzcycsICdzYXR1cmF0aW9uJyxcblxuICAgIC8vIFRoZW4gcG9zdC1wcm9jZXNzaW5nXG4gICAgJ3JhZGlhbC1ibHVyJywgJ3RpbHQtc2hpZnQnLCAnZnJhbWVzJywgJ3N0aWNrZXJzJywgJ3RleHQnXTtcblxuICAgIHRoaXMuX3BhdXNlZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5fb3B0aW9ucy51aSA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5kZWZhdWx0cyh0aGlzLl9vcHRpb25zLnVpLCB7XG4gICAgICBzaG93TmV3QnV0dG9uOiAhdGhpcy5fb3B0aW9ucy5pbWFnZSxcbiAgICAgIHNob3dVcGxvYWRCdXR0b246IHRydWUsXG4gICAgICBzaG93V2ViY2FtQnV0dG9uOiB0cnVlLFxuICAgICAgc2hvd0hlYWRlcjogdHJ1ZSxcbiAgICAgIHNob3dDbG9zZUJ1dHRvbjogZmFsc2UsXG4gICAgICBzaG93RXhwb3J0QnV0dG9uOiBmYWxzZSxcbiAgICAgIGxhbmd1YWdlOiAnZW4nLFxuICAgICAgJ2V4cG9ydCc6IHt9XG4gICAgfSk7XG5cbiAgICB0aGlzLl9vcHRpb25zLnVpWydleHBvcnQnXSA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5kZWZhdWx0cyh0aGlzLl9vcHRpb25zLnVpWydleHBvcnQnXSwge1xuICAgICAgdHlwZTogX2NvbnN0YW50cy5JbWFnZUZvcm1hdC5KUEVHLFxuICAgICAgcXVhbGl0eTogMC44XG4gICAgfSk7XG4gIH1cblxuICBfaW5oZXJpdHMoTmlnaHRVSSwgX1VJKTtcblxuICBfY3JlYXRlQ2xhc3MoTmlnaHRVSSwgW3tcbiAgICBrZXk6ICdydW4nLFxuXG4gICAgLyoqXG4gICAgICogUHJlcGFyZXMgdGhlIFVJIGZvciB1c2VcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcnVuKCkge1xuICAgICAgdGhpcy5fcmVnaXN0ZXJDb250cm9scygpO1xuICAgICAgdGhpcy5fcmVnaXN0ZXJMYW5ndWFnZXMoKTtcblxuICAgICAgdGhpcy5fbG9hZExhbmd1YWdlKCk7XG5cbiAgICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKE5pZ2h0VUkucHJvdG90eXBlKSwgJ3J1bicsIHRoaXMpLmNhbGwodGhpcyk7XG5cbiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLl9vcHRpb25zLmNvbnRhaW5lcjtcblxuICAgICAgdGhpcy5fY29udHJvbHNDb250YWluZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNvbnRyb2xzJyk7XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc0NvbnRhaW5lciA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY2FudmFzLWNvbnRyb2xzJyk7XG4gICAgICB0aGlzLl9vdmVydmlld0NvbnRyb2xzQ29udGFpbmVyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jb250cm9scy1vdmVydmlldycpO1xuICAgICAgdGhpcy5fbG9hZGluZ092ZXJsYXkgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWxvYWRpbmdPdmVybGF5Jyk7XG4gICAgICB0aGlzLl9sb2FkaW5nU3BhbiA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtbG9hZGluZ092ZXJsYXkgc3BhbicpO1xuXG4gICAgICB0aGlzLl9oYW5kbGVPdmVydmlldygpO1xuXG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5pbWFnZSkge1xuICAgICAgICB0aGlzLl9pbml0Q2FudmFzKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmNvbnRleHQucmVuZGVyU3BsYXNoU2NyZWVuKSB7XG4gICAgICAgIHRoaXMuX2luaXRGaWxlTG9hZGVyKCk7XG4gICAgICAgIGlmICh0aGlzLl9vcHRpb25zLnVpLnNob3dXZWJjYW1CdXR0b24pIHtcbiAgICAgICAgICB0aGlzLl9oYW5kbGVXZWJjYW1CdXR0b24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5jb250ZXh0LnJlbmRlcldlYmNhbSkge1xuICAgICAgICB0aGlzLl9pbml0V2ViY2FtKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2luaXRUb3BDb250cm9scygpO1xuICAgICAgdGhpcy5faW5pdENvbnRyb2xzKCk7XG5cbiAgICAgIGlmICh0aGlzLl9vcHRpb25zLmltYWdlKSB7XG4gICAgICAgIHRoaXMuc2hvd1pvb20oKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX29wdGlvbnMudWkuc2hvd0Nsb3NlQnV0dG9uKSB7XG4gICAgICAgIHRoaXMuX2hhbmRsZUNsb3NlQnV0dG9uKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl90b3BDb250cm9scykge1xuICAgICAgICB0aGlzLl90b3BDb250cm9scy51cGRhdGVFeHBvcnRCdXR0b24oKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfbG9hZExhbmd1YWdlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2xvYWRMYW5ndWFnZSgpIHtcbiAgICAgIHRoaXMuX2xhbmd1YWdlID0gdGhpcy5fbGFuZ3VhZ2VzW3RoaXMuX29wdGlvbnMudWkubGFuZ3VhZ2VdO1xuICAgICAgaWYgKCF0aGlzLl9sYW5ndWFnZSkge1xuICAgICAgICB2YXIgYXZhaWxhYmxlTGFuZ3VhZ2VzID0gT2JqZWN0LmtleXModGhpcy5fbGFuZ3VhZ2VzKS5qb2luKCcsICcpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gbGFuZ3VhZ2UgXFwnJyArIHRoaXMuX29wdGlvbnMudWkubGFuZ3VhZ2UgKyAnXFwnLiBBdmFpbGFibGUgbGFuZ3VhZ2VzIGFyZTogJyArIGF2YWlsYWJsZUxhbmd1YWdlcyk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2luaXRXZWJjYW0nLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHdlYmNhbVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbml0V2ViY2FtKCkge1xuICAgICAgdGhpcy5fd2ViY2FtID0gbmV3IF9saWJXZWJjYW1IYW5kbGVyMlsnZGVmYXVsdCddKHRoaXMuX2tpdCwgdGhpcyk7XG4gICAgICB0aGlzLl93ZWJjYW0ub24oJ2ltYWdlJywgdGhpcy5fb25XZWJjYW1JbWFnZVRha2VuLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbldlYmNhbUltYWdlVGFrZW4nLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25XZWJjYW1JbWFnZVRha2VuKGltYWdlKSB7XG4gICAgICB0aGlzLl9vcHRpb25zLnVpLnN0YXJ0V2l0aFdlYmNhbSA9IGZhbHNlO1xuICAgICAgdGhpcy5fc2V0SW1hZ2UoaW1hZ2UpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVXZWJjYW1CdXR0b24nLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgd2ViY2FtIGJ1dHRvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVXZWJjYW1CdXR0b24oKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fb3B0aW9ucy5jb250YWluZXI7XG5cbiAgICAgIHZhciB3ZWJjYW1CdXR0b24gPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNwbGFzaC1yb3ctLWNhbWVyYScpO1xuICAgICAgd2ViY2FtQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy5fb3B0aW9ucy51aS5zdGFydFdpdGhXZWJjYW0gPSB0cnVlO1xuICAgICAgICBfdGhpcy5ydW4oKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0RmlsZUxvYWRlcicsXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgZmlsZSBsb2FkZXJcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaW5pdEZpbGVMb2FkZXIoKSB7XG4gICAgICB0aGlzLl9maWxlTG9hZGVyID0gbmV3IF9saWJGaWxlTG9hZGVyMlsnZGVmYXVsdCddKHRoaXMuX2tpdCwgdGhpcyk7XG4gICAgICB0aGlzLl9maWxlTG9hZGVyLm9uKCdmaWxlJywgdGhpcy5fb25GaWxlTG9hZGVkLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkZpbGVMb2FkZWQnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBsb2FkZWQgYSBmaWxlIHVzaW5nIHRoZSBGaWxlTG9hZGVyXG4gICAgICogQHBhcmFtIHtGaWxlfSBmaWxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRmlsZUxvYWRlZChmaWxlKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICByZWFkZXIub25sb2FkID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgICBpbWFnZS5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMyLl9zZXRJbWFnZShpbWFnZSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpbWFnZS5zcmMgPSBkYXRhO1xuICAgICAgICB9O1xuICAgICAgfSkoZmlsZSk7XG4gICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0SW1hZ2UnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaW1hZ2Ugb3B0aW9uIGFuZCBzdGFydHMgcmVuZGVyaW5nXG4gICAgICogQHBhcmFtIHtJbWFnZX0gaW1hZ2VcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0SW1hZ2UoaW1hZ2UpIHtcbiAgICAgIHRoaXMuX29wdGlvbnMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgIHRoaXMucnVuKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2luaXRUb3BDb250cm9scycsXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgdG9wIGNvbnRyb2xzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRUb3BDb250cm9scygpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICBpZiAoIXRoaXMuY29udGV4dC5yZW5kZXJDb250cm9scykgcmV0dXJuO1xuXG4gICAgICB0aGlzLl90b3BDb250cm9scyA9IG5ldyBfbGliVG9wQ29udHJvbHMyWydkZWZhdWx0J10odGhpcy5fa2l0LCB0aGlzKTtcbiAgICAgIHRoaXMuX3RvcENvbnRyb2xzLnJ1bigpO1xuXG4gICAgICB0aGlzLl90b3BDb250cm9scy5vbignbmV3JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpczMuX29wdGlvbnMuaW1hZ2UgPSBudWxsO1xuICAgICAgICBfdGhpczMucnVuKCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fdG9wQ29udHJvbHMub24oJ3VuZG8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzMy51bmRvKCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fdG9wQ29udHJvbHMub24oJ2V4cG9ydCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMzWydleHBvcnQnXSgpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFBhc3Mgem9vbSBpbiBldmVudFxuICAgICAgdGhpcy5fdG9wQ29udHJvbHMub24oJ3pvb20taW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzMy5fY2FudmFzLnpvb21JbigpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChfdGhpczMuX2N1cnJlbnRDb250cm9sKSB7XG4gICAgICAgICAgICBfdGhpczMuX2N1cnJlbnRDb250cm9sLm9uWm9vbSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgLy8gUGFzcyB6b29tIG91dCBldmVudFxuICAgICAgdGhpcy5fdG9wQ29udHJvbHMub24oJ3pvb20tb3V0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpczMuX2NhbnZhcy56b29tT3V0KCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgaWYgKF90aGlzMy5fY3VycmVudENvbnRyb2wpIHtcbiAgICAgICAgICAgIF90aGlzMy5fY3VycmVudENvbnRyb2wub25ab29tKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0Q2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIEluaXRpdGlhbGl6ZXMgdGhlIGNhbnZhc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbml0Q2FudmFzKCkge1xuICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgIHRoaXMuX2NhbnZhcyA9IG5ldyBfbGliQ2FudmFzMlsnZGVmYXVsdCddKHRoaXMuX2tpdCwgdGhpcywgdGhpcy5fb3B0aW9ucyk7XG4gICAgICB0aGlzLl9jYW52YXMucnVuKCk7XG4gICAgICB0aGlzLl9jYW52YXMub24oJ3pvb20nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzNC5fdG9wQ29udHJvbHMudXBkYXRlWm9vbUxldmVsKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzZWxlY3RPcGVyYXRpb25zJyxcblxuICAgIC8qKlxuICAgICAqIFNlbGVjdHMgdGhlIGVuYWJsZWQgb3BlcmF0aW9uc1xuICAgICAqIEBwYXJhbSB7SW1nbHlLaXQuU2VsZWN0b3J9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNlbGVjdE9wZXJhdGlvbnMoc2VsZWN0b3IpIHtcbiAgICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKE5pZ2h0VUkucHJvdG90eXBlKSwgJ3NlbGVjdE9wZXJhdGlvbnMnLCB0aGlzKS5jYWxsKHRoaXMsIHNlbGVjdG9yKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRPckNyZWF0ZU9wZXJhdGlvbicsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIG9yIGNyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgdGhlIG9wZXJhdGlvbiB3aXRoIHRoZSBnaXZlbiBpZGVudGlmaWVyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0T3JDcmVhdGVPcGVyYXRpb24oaWRlbnRpZmllcikge1xuICAgICAgdmFyIF9raXQgPSB0aGlzLl9raXQ7XG4gICAgICB2YXIgb3BlcmF0aW9uc1N0YWNrID0gX2tpdC5vcGVyYXRpb25zU3RhY2s7XG4gICAgICB2YXIgcmVnaXN0ZXJlZE9wZXJhdGlvbnMgPSBfa2l0LnJlZ2lzdGVyZWRPcGVyYXRpb25zO1xuXG4gICAgICB2YXIgT3BlcmF0aW9uID0gcmVnaXN0ZXJlZE9wZXJhdGlvbnNbaWRlbnRpZmllcl07XG5cbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3BlcmF0aW9uc01hcFtpZGVudGlmaWVyXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG9wZXJhdGlvblxuICAgICAgICB2YXIgb3BlcmF0aW9uSW5zdGFuY2UgPSBuZXcgT3BlcmF0aW9uKHRoaXMuX2tpdCk7XG4gICAgICAgIHRoaXMuX29wZXJhdGlvbnNNYXBbaWRlbnRpZmllcl0gPSBvcGVyYXRpb25JbnN0YW5jZTtcblxuICAgICAgICAvLyBGaW5kIGluZGV4IGluIHByZWZlcnJlZCBvcGVyYXRpb24gb3JkZXJcbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5fcHJlZmVycmVkT3BlcmF0aW9uT3JkZXIuaW5kZXhPZihpZGVudGlmaWVyKTtcbiAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgIGluZGV4ID0gdGhpcy5fcHJlZmVycmVkT3BlcmF0aW9uT3JkZXIubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIG9wZXJhdGlvbnNTdGFja1tpbmRleF0gPSBvcGVyYXRpb25JbnN0YW5jZTtcblxuICAgICAgICByZXR1cm4gb3BlcmF0aW9uSW5zdGFuY2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3BlcmF0aW9uc01hcFtpZGVudGlmaWVyXTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW1vdmVPcGVyYXRpb24nLFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgb3BlcmF0aW9uIHdpdGggdGhlIGdpdmVuIGlkZW50aWZpZXIgZnJvbSB0aGUgc3RhY2tcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWRlbnRpZmllclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVPcGVyYXRpb24oaWRlbnRpZmllcikge1xuICAgICAgaWYgKCF0aGlzLl9vcGVyYXRpb25zTWFwW2lkZW50aWZpZXJdKSByZXR1cm47XG5cbiAgICAgIHZhciBvcGVyYXRpb24gPSB0aGlzLl9vcGVyYXRpb25zTWFwW2lkZW50aWZpZXJdO1xuICAgICAgZGVsZXRlIHRoaXMuX29wZXJhdGlvbnNNYXBbaWRlbnRpZmllcl07XG5cbiAgICAgIHZhciBpbmRleCA9IHRoaXMuX2tpdC5vcGVyYXRpb25zU3RhY2suaW5kZXhPZihvcGVyYXRpb24pO1xuICAgICAgdGhpcy5fa2l0Lm9wZXJhdGlvbnNTdGFjay5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZWdpc3RlckNvbnRyb2xzJyxcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbGwgZGVmYXVsdCBvcGVyYXRpb24gY29udHJvbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVnaXN0ZXJDb250cm9scygpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdmaWx0ZXJzJywgJ2ZpbHRlcnMnLCByZXF1aXJlKCcuL2NvbnRyb2xzL2ZpbHRlcnMtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdyb3RhdGlvbicsICdyb3RhdGlvbicsIHJlcXVpcmUoJy4vY29udHJvbHMvcm90YXRpb24tY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdmbGlwJywgJ2ZsaXAnLCByZXF1aXJlKCcuL2NvbnRyb2xzL2ZsaXAtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdicmlnaHRuZXNzJywgJ2JyaWdodG5lc3MnLCByZXF1aXJlKCcuL2NvbnRyb2xzL2JyaWdodG5lc3MtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdjb250cmFzdCcsICdjb250cmFzdCcsIHJlcXVpcmUoJy4vY29udHJvbHMvY29udHJhc3QtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdzYXR1cmF0aW9uJywgJ3NhdHVyYXRpb24nLCByZXF1aXJlKCcuL2NvbnRyb2xzL3NhdHVyYXRpb24tY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdjcm9wJywgJ2Nyb3AnLCByZXF1aXJlKCcuL2NvbnRyb2xzL2Nyb3AtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdyYWRpYWwtYmx1cicsICdyYWRpYWwtYmx1cicsIHJlcXVpcmUoJy4vY29udHJvbHMvcmFkaWFsLWJsdXItY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCd0aWx0LXNoaWZ0JywgJ3RpbHQtc2hpZnQnLCByZXF1aXJlKCcuL2NvbnRyb2xzL3RpbHQtc2hpZnQtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdmcmFtZXMnLCAnZnJhbWVzJywgcmVxdWlyZSgnLi9jb250cm9scy9mcmFtZXMtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCdzdGlja2VycycsICdzdGlja2VycycsIHJlcXVpcmUoJy4vY29udHJvbHMvc3RpY2tlcnMtY29udHJvbCcpKTtcbiAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKCd0ZXh0JywgJ3RleHQnLCByZXF1aXJlKCcuL2NvbnRyb2xzL3RleHQtY29udHJvbCcpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVnaXN0ZXJMYW5ndWFnZXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYWxsIGRlZmF1bHQgbGFuZ3VhZ2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlZ2lzdGVyTGFuZ3VhZ2VzKCkge1xuICAgICAgdGhpcy5yZWdpc3Rlckxhbmd1YWdlKCdlbicsIHJlcXVpcmUoJy4vbGFuZy9lbi5qc29uJykpO1xuICAgICAgdGhpcy5yZWdpc3Rlckxhbmd1YWdlKCdkZScsIHJlcXVpcmUoJy4vbGFuZy9kZS5qc29uJykpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVPdmVydmlldycsXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSBvdmVydmlldyBidXR0b24gY2xpY2sgZXZlbnRzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2hhbmRsZU92ZXJ2aWV3KCkge1xuICAgICAgdmFyIF90aGlzNSA9IHRoaXM7XG5cbiAgICAgIGlmICghdGhpcy5jb250ZXh0LnJlbmRlckNvbnRyb2xzKSByZXR1cm47XG5cbiAgICAgIHZhciBpdGVtc0xpc3QgPSB0aGlzLl9vdmVydmlld0NvbnRyb2xzQ29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJ3VsJyk7XG4gICAgICBpZiAoIWl0ZW1zTGlzdC5wYXJlbnROb2RlID09PSB0aGlzLl9vdmVydmlld0NvbnRyb2xzQ29udGFpbmVyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBsaXN0SXRlbXMgPSBbXS5maWx0ZXIuY2FsbChpdGVtc0xpc3QucXVlcnlTZWxlY3RvckFsbCgnbGknKSwgZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHJldHVybiBlbC5wYXJlbnROb2RlID09PSBpdGVtc0xpc3Q7XG4gICAgICB9KTtcblxuICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgdmFyIGxpc3RJdGVtID0gbGlzdEl0ZW1zW2ldO1xuICAgICAgICB2YXIgaWRlbnRpZmllciA9IGxpc3RJdGVtLmRhdGFzZXQuaWRlbnRpZmllcjtcblxuICAgICAgICBsaXN0SXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpczUuc3dpdGNoVG9Db250cm9sKGlkZW50aWZpZXIpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIC8vIEFkZCBjbGljayBldmVudHMgdG8gYWxsIGl0ZW1zXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbG9vcChpKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZW5hYmxlQ29udHJvbHMnLFxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyB0aGUgb3ZlcnZpZXcgY29udHJvbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfZW5hYmxlQ29udHJvbHMoKSB7XG4gICAgICB2YXIgaXRlbXNMaXN0ID0gdGhpcy5fb3ZlcnZpZXdDb250cm9sc0NvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCd1bCcpO1xuICAgICAgaWYgKCFpdGVtc0xpc3QucGFyZW50Tm9kZSA9PT0gdGhpcy5fb3ZlcnZpZXdDb250cm9sc0NvbnRhaW5lcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgbGlzdEl0ZW1zID0gW10uZmlsdGVyLmNhbGwoaXRlbXNMaXN0LnF1ZXJ5U2VsZWN0b3JBbGwoJ2xpJyksIGZ1bmN0aW9uIChlbCkge1xuICAgICAgICByZXR1cm4gZWwucGFyZW50Tm9kZSA9PT0gaXRlbXNMaXN0O1xuICAgICAgfSk7XG5cbiAgICAgIC8vIEFkZCBjbGljayBldmVudHMgdG8gYWxsIGl0ZW1zXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGlzdEl0ZW0gPSBsaXN0SXRlbXNbaV07XG4gICAgICAgIGxpc3RJdGVtLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1kaXNhYmxlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3N3aXRjaFRvQ29udHJvbCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIGFuIG92ZXJ2aWV3IGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc3dpdGNoVG9Db250cm9sKGlkZW50aWZpZXIpIHtcbiAgICAgIGlmICh0aGlzLmNvbnRleHQuY29udHJvbHNEaXNhYmxlZCkgcmV0dXJuO1xuICAgICAgdGhpcy5fb3ZlcnZpZXdDb250cm9sc0NvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICB0aGlzLl9zY3JvbGxiYXIucmVtb3ZlKCk7XG5cbiAgICAgIGlmICh0aGlzLl9jdXJyZW50Q29udHJvbCkge1xuICAgICAgICB0aGlzLl9jdXJyZW50Q29udHJvbC5sZWF2ZSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jdXJyZW50Q29udHJvbCA9IHRoaXMuX3JlZ2lzdGVyZWRDb250cm9sc1tpZGVudGlmaWVyXTtcbiAgICAgIHRoaXMuX2N1cnJlbnRDb250cm9sLmVudGVyKCk7XG4gICAgICB0aGlzLl9jdXJyZW50Q29udHJvbC5vbmNlKCdiYWNrJywgdGhpcy5fc3dpdGNoVG9PdmVydmlldy5iaW5kKHRoaXMpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc3dpdGNoVG9PdmVydmlldycsXG5cbiAgICAvKipcbiAgICAgKiBTd2l0Y2hlcyBiYWNrIHRvIHRoZSBvdmVydmlldyBjb250cm9sc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zd2l0Y2hUb092ZXJ2aWV3KCkge1xuICAgICAgaWYgKHRoaXMuX2N1cnJlbnRDb250cm9sKSB7XG4gICAgICAgIHRoaXMuX2N1cnJlbnRDb250cm9sLmxlYXZlKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2N1cnJlbnRDb250cm9sID0gbnVsbDtcbiAgICAgIHRoaXMuX292ZXJ2aWV3Q29udHJvbHNDb250YWluZXIuc3R5bGUuZGlzcGxheSA9ICcnO1xuXG4gICAgICB0aGlzLl9pbml0U2Nyb2xsYmFyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVnaXN0ZXJDb250cm9sJyxcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyB0aGUgY29udHJvbHMgZm9yIGFuIG9wZXJhdGlvblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAgKiBAcGFyYW0ge0NvbnRyb2x9IENvbnRyb2xDbGFzc1xuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZWdpc3RlckNvbnRyb2woaWRlbnRpZmllciwgb3BlcmF0aW9uSWRlbnRpZmllciwgQ29udHJvbENsYXNzKSB7XG4gICAgICBpZiAoIXRoaXMuaXNPcGVyYXRpb25TZWxlY3RlZChvcGVyYXRpb25JZGVudGlmaWVyKSkgcmV0dXJuO1xuXG4gICAgICB2YXIgaW5zdGFuY2UgPSBuZXcgQ29udHJvbENsYXNzKHRoaXMuX2tpdCwgdGhpcyk7XG4gICAgICB0aGlzLl9yZWdpc3RlcmVkQ29udHJvbHNbaWRlbnRpZmllcl0gPSBpbnN0YW5jZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW5pdENvbnRyb2xzJyxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSByZWdpc3RlcmVkIGNvbnRyb2xzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRDb250cm9scygpIHtcbiAgICAgIGZvciAodmFyIGlkZW50aWZpZXIgaW4gdGhpcy5fcmVnaXN0ZXJlZENvbnRyb2xzKSB7XG4gICAgICAgIHZhciBjb250cm9sID0gdGhpcy5fcmVnaXN0ZXJlZENvbnRyb2xzW2lkZW50aWZpZXJdO1xuICAgICAgICBjb250cm9sLnNldENvbnRhaW5lcnModGhpcy5fY29udHJvbHNDb250YWluZXIsIHRoaXMuX2NhbnZhc0NvbnRyb2xzQ29udGFpbmVyKTtcbiAgICAgICAgY29udHJvbC5pbml0KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2luaXRTY3JvbGxiYXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW5pdFNjcm9sbGJhcicsXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgY3VzdG9tIHNjcm9sbGJhclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbml0U2Nyb2xsYmFyKCkge1xuICAgICAgaWYgKCF0aGlzLmNvbnRleHQucmVuZGVyQ29udHJvbHMpIHJldHVybjtcblxuICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRyb2xzQ29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jb250cm9scy1saXN0JykucGFyZW50Tm9kZTtcbiAgICAgIHRoaXMuX3Njcm9sbGJhciA9IG5ldyBfbGliU2Nyb2xsYmFyMlsnZGVmYXVsdCddKGNvbnRhaW5lcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZUNsb3NlQnV0dG9uJyxcblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgdGhlIGNsaWNrIGV2ZW50IG9uIHRoZSBjbG9zZSBidXR0b24sIGVtaXRzIGEgYGNsb3NlYCBldmVudFxuICAgICAqIHdoZW4gY2xpY2tpbmdcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlQ2xvc2VCdXR0b24oKSB7XG4gICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgdmFyIGNsb3NlQnV0dG9uID0gdGhpcy5fb3B0aW9ucy5jb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNsb3NlLWJ1dHRvbicpO1xuICAgICAgY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIF90aGlzNi5lbWl0KCdjbG9zZScpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlLXJlbmRlcnMgdGhlIGNhbnZhc1xuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICBpZiAodGhpcy5fY2FudmFzKSB7XG4gICAgICAgIHRoaXMuX2NhbnZhcy5yZW5kZXIoKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdwYXVzZScsXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIFVJLiBPcGVyYXRpb24gdXBkYXRlcyB3aWxsIG5vdCBjYXVzZSBhIHJlLXJlbmRlcmluZ1xuICAgICAqIG9mIHRoZSBjYW52YXMuXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHBhdXNlKCkge1xuICAgICAgdGhpcy5fcGF1c2VkID0gdHJ1ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXN1bWUnLFxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgVUkgYW5kIHJlLXJlbmRlcnMgdGhlIGNhbnZhc1xuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVyZW5kZXIgPSB0cnVlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlc3VtZSgpIHtcbiAgICAgIHZhciByZXJlbmRlciA9IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgdGhpcy5fcGF1c2VkID0gZmFsc2U7XG4gICAgICBpZiAocmVyZW5kZXIpIHtcbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdhZGRIaXN0b3J5JyxcblxuICAgIC8qKlxuICAgICAqIEFkZHMgdGhlIGdpdmVuIG9wZXJhdGlvbiBhbmQgb3B0aW9ucyB0byB0aGUgaGlzdG9yeSBzdGFja1xuICAgICAqIEBwYXJhbSB7T3BlcmF0aW9ufSBvcGVyYXRpb25cbiAgICAgKiBAcGFyYW0ge09iamVjdC48U3RyaW5nLCAqPn0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gZXhpc3RlbnRcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gYWRkSGlzdG9yeShvcGVyYXRpb24sIG9wdGlvbnMsIGV4aXN0ZW50KSB7XG4gICAgICB0aGlzLl9oaXN0b3J5LnB1c2goeyBvcGVyYXRpb246IG9wZXJhdGlvbiwgb3B0aW9uczogb3B0aW9ucywgZXhpc3RlbnQ6IGV4aXN0ZW50IH0pO1xuICAgICAgdGhpcy5fdG9wQ29udHJvbHMudXBkYXRlVW5kb0J1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2hpZGVab29tJyxcblxuICAgIC8qKlxuICAgICAqIEhpZGVzIHRoZSB6b29tIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaGlkZVpvb20oKSB7XG4gICAgICB0aGlzLl90b3BDb250cm9scy5oaWRlWm9vbSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Nob3dab29tJyxcblxuICAgIC8qKlxuICAgICAqIEhpZGVzIHRoZSB6b29tIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2hvd1pvb20oKSB7XG4gICAgICB0aGlzLl90b3BDb250cm9scy5zaG93Wm9vbSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3VuZG8nLFxuXG4gICAgLyoqXG4gICAgICogVGFrZXMgdGhlIGxhc3QgaGlzdG9yeSBpdGVtIGFuZCBhcHBsaWVzIGl0cyBvcHRpb25zXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHVuZG8oKSB7XG4gICAgICB2YXIgbGFzdEl0ZW0gPSB0aGlzLl9oaXN0b3J5LnBvcCgpO1xuICAgICAgaWYgKGxhc3RJdGVtKSB7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSBsYXN0SXRlbS5vcGVyYXRpb247XG4gICAgICAgIHZhciBleGlzdGVudCA9IGxhc3RJdGVtLmV4aXN0ZW50O1xuICAgICAgICB2YXIgb3B0aW9ucyA9IGxhc3RJdGVtLm9wdGlvbnM7XG5cbiAgICAgICAgaWYgKCFleGlzdGVudCkge1xuICAgICAgICAgIHRoaXMucmVtb3ZlT3BlcmF0aW9uKG9wZXJhdGlvbi5pZGVudGlmaWVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvcGVyYXRpb24gPSB0aGlzLmdldE9yQ3JlYXRlT3BlcmF0aW9uKG9wZXJhdGlvbi5pZGVudGlmaWVyKTtcbiAgICAgICAgICBvcGVyYXRpb24uc2V0KG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FudmFzLnpvb21Ub0ZpdCh0cnVlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3RvcENvbnRyb2xzLnVwZGF0ZVVuZG9CdXR0b24oKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdleHBvcnQnLFxuXG4gICAgLyoqXG4gICAgICogRXhwb3J0cyB0aGUgY3VycmVudCBpbWFnZSB3aXRoIHRoZSBkZWZhdWx0IHNldHRpbmdzXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9leHBvcnQoKSB7XG4gICAgICB2YXIgX3RoaXM3ID0gdGhpcztcblxuICAgICAgdGhpcy5kaXNwbGF5TG9hZGluZ01lc3NhZ2UodGhpcy50cmFuc2xhdGUoJ2dlbmVyaWMuZXhwb3J0aW5nJykgKyAnLi4uJyk7XG5cbiAgICAgIHZhciByZW5kZXJUeXBlID0gX2NvbnN0YW50cy5SZW5kZXJUeXBlLkRBVEFVUkw7XG5cbiAgICAgIC8vIENoZWNrIGlmIG1zVG9CbG9iIGlzIGF2YWlsYWJsZVxuICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgaWYgKHR5cGVvZiBjYW52YXMubXNUb0Jsb2IgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJlbmRlclR5cGUgPSBfY29uc3RhbnRzLlJlbmRlclR5cGUuTVNCTE9CO1xuICAgICAgfVxuXG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXM3Ll9raXQucmVuZGVyKHJlbmRlclR5cGUsIF90aGlzNy5fb3B0aW9ucy51aVsnZXhwb3J0J10udHlwZSwgX3RoaXM3Ll9vcHRpb25zLnVpWydleHBvcnQnXS5kaW1lbnNpb25zLCBfdGhpczcuX29wdGlvbnMudWlbJ2V4cG9ydCddLnF1YWxpdHkpLnRoZW4oZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICBzd2l0Y2ggKHJlbmRlclR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgX2NvbnN0YW50cy5SZW5kZXJUeXBlLkRBVEFVUkw6XG4gICAgICAgICAgICAgIHZhciBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgICB2YXIgZXh0ZW5zaW9uID0gX3RoaXM3Ll9vcHRpb25zLnVpWydleHBvcnQnXS50eXBlLnNwbGl0KCcvJykucG9wKCk7XG4gICAgICAgICAgICAgIGxpbmsuZG93bmxvYWQgPSAnaW1nbHlraXQtZXhwb3J0LicgKyBleHRlbnNpb247XG5cbiAgICAgICAgICAgICAgbGluay5ocmVmID0gZGF0YTtcbiAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChsaW5rKTtcbiAgICAgICAgICAgICAgbGluay5jbGljaygpO1xuICAgICAgICAgICAgICAvLyBDbGVhbnVwIHRoZSBET01cbiAgICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChsaW5rKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIF9jb25zdGFudHMuUmVuZGVyVHlwZS5NU0JMT0I6XG4gICAgICAgICAgICAgIG5hdmlnYXRvci5tc1NhdmVCbG9iKGRhdGEsICdpbWdseWtpdC1leHBvcnQucG5nJyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF90aGlzNy5oaWRlTG9hZGluZ01lc3NhZ2UoKTtcbiAgICAgICAgfSk7XG4gICAgICB9LCAxMDAwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdkaXNwbGF5TG9hZGluZ01lc3NhZ2UnLFxuXG4gICAgLyoqXG4gICAgICogRGlzcGxheXMgdGhlIGdpdmVuIG1lc3NhZ2UgaW5zaWRlIHRoZSBsb2FkaW5nIG92ZXJsYXlcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBkaXNwbGF5TG9hZGluZ01lc3NhZ2UobWVzc2FnZSkge1xuICAgICAgdGhpcy5fbG9hZGluZ1NwYW4uaW5uZXJUZXh0ID0gbWVzc2FnZTtcbiAgICAgIHRoaXMuX2xvYWRpbmdPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2hpZGVMb2FkaW5nTWVzc2FnZScsXG5cbiAgICAvKipcbiAgICAgKiBIaWRlcyB0aGUgbG9hZGluZyBtZXNzYWdlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGhpZGVMb2FkaW5nTWVzc2FnZSgpIHtcbiAgICAgIHRoaXMuX2xvYWRpbmdPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIHRoaXMgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICduaWdodCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnb3BlcmF0aW9ucycsXG5cbiAgICAvKipcbiAgICAgKiBBbiBvYmplY3QgY29udGFpbmluZyBhbGwgYWN0aXZlIG9wZXJhdGlvbnNcbiAgICAgKiBAdHlwZSB7T2JqZWN0LjxTdHJpbmcsT3BlcmF0aW9uPn1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vcGVyYXRpb25zTWFwO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NvbnRyb2xzJyxcblxuICAgIC8qKlxuICAgICAqIEFuIG9iamVjdCBjb250YWluaW5nIGFsbCByZWdpc3RlcmVkIGNvbnRyb2xzXG4gICAgICogQHR5cGUge09iamVjdC48U3RyaW5nLENvbnRyb2w+fVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3JlZ2lzdGVyZWRDb250cm9scztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIHRoYXQgaXMgcGFzc2VkIHRvIHRoZSB0ZW1wbGF0ZSByZW5kZXJlclxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY29udGV4dCA9IF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKE5pZ2h0VUkucHJvdG90eXBlKSwgJ2NvbnRleHQnLCB0aGlzKTtcbiAgICAgIGNvbnRleHQuY29udHJvbHMgPSB0aGlzLl9yZWdpc3RlcmVkQ29udHJvbHM7XG4gICAgICBjb250ZXh0LnJlbmRlclNwbGFzaFNjcmVlbiA9ICF0aGlzLl9vcHRpb25zLmltYWdlICYmICF0aGlzLl9vcHRpb25zLnVpLnN0YXJ0V2l0aFdlYmNhbTtcbiAgICAgIGNvbnRleHQucmVuZGVyQ29udHJvbHMgPSAhIXRoaXMuX29wdGlvbnMuaW1hZ2U7XG4gICAgICBjb250ZXh0LnJlbmRlcldlYmNhbSA9IHRoaXMuX29wdGlvbnMudWkuc3RhcnRXaXRoV2ViY2FtO1xuICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaGlzdG9yeScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdW5kbyBoaXN0b3J5XG4gICAgICogQHR5cGUge0FycmF5LjxPYmplY3Q+fVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hpc3Rvcnk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZmlsZUxvYWRlcicsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgZmlsZSBsb2FkZXJcbiAgICAgKiBAdHlwZSB7RmlsZUxvYWRlcn1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9maWxlTG9hZGVyO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBOaWdodFVJO1xufSkoX2Jhc2VVaTJbJ2RlZmF1bHQnXSk7XG5cbk5pZ2h0VUkuQ29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbHMvY29udHJvbCcpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBOaWdodFVJO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L3VpLmpzXG4gKiogbW9kdWxlIGlkID0gNTBcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIm1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV81Ml9fO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogZXh0ZXJuYWwgXCJjYW52YXNcIlxuICoqIG1vZHVsZSBpZCA9IDUyXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuLyoqXG4gKiBQYXJzZXMgdGhlIGRpbWVuc2lvbnMgc3RyaW5nIGFuZCBwcm92aWRlcyBjYWxjdWxhdGlvbiBmdW5jdGlvbnNcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkltYWdlRGltZW5zaW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IGRpbWVuc2lvbnNcbiAqIEBwcml2YXRlXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgSW1hZ2VEaW1lbnNpb25zID0gKGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gSW1hZ2VEaW1lbnNpb25zKGRpbWVuc2lvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSW1hZ2VEaW1lbnNpb25zKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBhdmFpbGFibGUgZGltZW5zaW9uIG1vZGlmaWVyc1xuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9tb2RpZmllcnMgPSB7XG4gICAgICBGSVhFRDogJyEnXG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9kaW1lbnNpb25zU3RyaW5nID0gZGltZW5zaW9ucztcblxuICAgIC8qKlxuICAgICAqIEFuIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIHBhcnNlZCBkaW1lbnNpb25zIHN0cmluZ1xuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgdGhpcy5fcnVsZXMgPSB0aGlzLl9wYXJzZSgpO1xuXG4gICAgdGhpcy5fdmFsaWRhdGVSdWxlcygpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEltYWdlRGltZW5zaW9ucywgW3tcbiAgICBrZXk6ICdfcGFyc2UnLFxuXG4gICAgLyoqXG4gICAgICogUGFyc2VzIHRoZSBkaW1lbnNpb25zIHN0cmluZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9wYXJzZSgpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fZGltZW5zaW9uc1N0cmluZyA9PT0gJ3VuZGVmaW5lZCcgfHwgdGhpcy5fZGltZW5zaW9uc1N0cmluZyA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgdmFyIG1hdGNoID0gdGhpcy5fZGltZW5zaW9uc1N0cmluZy5tYXRjaCgvXihbMC05XSspP3goWzAtOV0rKT8oW1xcIV0pPyQvaSk7XG4gICAgICBpZiAoIW1hdGNoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaXplIG9wdGlvbjogJyArIHRoaXMuX2RpbWVuc2lvbnNTdHJpbmcpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB4OiBpc05hTihtYXRjaFsxXSkgPyBudWxsIDogcGFyc2VJbnQobWF0Y2hbMV0sIDEwKSxcbiAgICAgICAgeTogaXNOYU4obWF0Y2hbMl0pID8gbnVsbCA6IHBhcnNlSW50KG1hdGNoWzJdLCAxMCksXG4gICAgICAgIG1vZGlmaWVyOiBtYXRjaFszXVxuICAgICAgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdmFsaWRhdGVSdWxlcycsXG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZXMgdGhlIHJ1bGVzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3ZhbGlkYXRlUnVsZXMoKSB7XG4gICAgICBpZiAodGhpcy5fcnVsZXMgPT09IG51bGwpIHJldHVybjtcblxuICAgICAgdmFyIHhBdmFpbGFibGUgPSB0aGlzLl9ydWxlcy54ICE9PSBudWxsO1xuICAgICAgdmFyIHlBdmFpbGFibGUgPSB0aGlzLl9ydWxlcy55ICE9PSBudWxsO1xuXG4gICAgICBpZiAodGhpcy5fcnVsZXMubW9kaWZpZXIgPT09IHRoaXMuX21vZGlmaWVycy5GSVhFRCAmJiAhKHhBdmFpbGFibGUgJiYgeUF2YWlsYWJsZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb3RoIGB4YCBhbmQgYHlgIGhhdmUgdG8gYmUgc2V0IHdoZW4gdXNpbmcgdGhlIGZpeGVkICghKSBtb2RpZmllci4nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF4QXZhaWxhYmxlICYmICF5QXZhaWxhYmxlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTmVpdGhlciBgeGAgbm9yIGB5YCBhcmUgZ2l2ZW4uJyk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY2FsY3VsYXRlRmluYWxEaW1lbnNpb25zJyxcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIGZpbmFsIGRpbWVuc2lvbnMgdXNpbmcgdGhlIGRpbWVuc2lvbnMgc3RyaW5nIGFuZCB0aGVcbiAgICAgKiBnaXZlbiBpbml0aWFsIGRpbWVuc2lvbnNcbiAgICAgKiBAcGFyYW0gIHtWZWN0b3IyfSBpbml0aWFsRGltZW5zaW9uc1xuICAgICAqIEByZXR1cm4ge1ZlY3RvcjJ9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNhbGN1bGF0ZUZpbmFsRGltZW5zaW9ucyhpbml0aWFsRGltZW5zaW9ucykge1xuICAgICAgdmFyIGRpbWVuc2lvbnMgPSBpbml0aWFsRGltZW5zaW9ucy5jbG9uZSgpLFxuICAgICAgICAgIHJhdGlvO1xuXG4gICAgICBpZiAodGhpcy5fcnVsZXMgPT09IG51bGwpIHJldHVybiBkaW1lbnNpb25zO1xuXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKHRoaXMuX3J1bGVzLm1vZGlmaWVyID09PSB0aGlzLl9tb2RpZmllcnMuRklYRUQpIHtcbiAgICAgICAgLy8gRml4ZWQgZGltZW5zaW9uc1xuICAgICAgICBkaW1lbnNpb25zLnNldCh0aGlzLl9ydWxlcy54LCB0aGlzLl9ydWxlcy55KTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fcnVsZXMueCAhPT0gbnVsbCAmJiB0aGlzLl9ydWxlcy55ICE9PSBudWxsKSB7XG4gICAgICAgIC8vIEJvdGggeCBhbmQgeSBnaXZlbiwgcmVzaXplIHRvIGZpdFxuICAgICAgICByYXRpbyA9IE1hdGgubWluKHRoaXMuX3J1bGVzLnggLyBkaW1lbnNpb25zLngsIHRoaXMuX3J1bGVzLnkgLyBkaW1lbnNpb25zLnkpO1xuICAgICAgICBkaW1lbnNpb25zLm11bHRpcGx5KHJhdGlvKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fcnVsZXMueCAhPT0gbnVsbCkge1xuICAgICAgICAvLyBGaXhlZCB4LCB5IGJ5IHJhdGlvXG4gICAgICAgIHJhdGlvID0gaW5pdGlhbERpbWVuc2lvbnMueSAvIGluaXRpYWxEaW1lbnNpb25zLng7XG4gICAgICAgIGRpbWVuc2lvbnMueCA9IHRoaXMuX3J1bGVzLng7XG4gICAgICAgIGRpbWVuc2lvbnMueSA9IGRpbWVuc2lvbnMueCAqIHJhdGlvO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl9ydWxlcy55ICE9PSBudWxsKSB7XG4gICAgICAgIC8vIEZpeGVkIHksIHggYnkgcmF0aW9cbiAgICAgICAgcmF0aW8gPSBpbml0aWFsRGltZW5zaW9ucy54IC8gaW5pdGlhbERpbWVuc2lvbnMueTtcbiAgICAgICAgZGltZW5zaW9ucy55ID0gdGhpcy5fcnVsZXMueTtcbiAgICAgICAgZGltZW5zaW9ucy54ID0gZGltZW5zaW9ucy55ICogcmF0aW87XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBkaW1lbnNpb25zO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBJbWFnZURpbWVuc2lvbnM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBJbWFnZURpbWVuc2lvbnM7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL2ltYWdlLWRpbWVuc2lvbnMuanNcbiAqKiBtb2R1bGUgaWQgPSA1M1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcmVuZGVyZXIgPSByZXF1aXJlKCcuL3JlbmRlcmVyJyk7XG5cbnZhciBfcmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVuZGVyZXIpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIF92ZW5kb3JQcm9taXNlID0gcmVxdWlyZSgnLi4vdmVuZG9yL3Byb21pc2UnKTtcblxudmFyIF92ZW5kb3JQcm9taXNlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ZlbmRvclByb21pc2UpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkNhbnZhc1JlbmRlcmVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuUmVuZGVyZXJ9XG4gKiBAcHJpdmF0ZVxuICovXG5cbnZhciBDYW52YXNSZW5kZXJlciA9IChmdW5jdGlvbiAoX1JlbmRlcmVyKSB7XG4gIGZ1bmN0aW9uIENhbnZhc1JlbmRlcmVyKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDYW52YXNSZW5kZXJlcik7XG5cbiAgICBpZiAoX1JlbmRlcmVyICE9IG51bGwpIHtcbiAgICAgIF9SZW5kZXJlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhDYW52YXNSZW5kZXJlciwgX1JlbmRlcmVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQ2FudmFzUmVuZGVyZXIsIFt7XG4gICAga2V5OiAnY2FjaGUnLFxuXG4gICAgLyoqXG4gICAgICogQ2FjaGVzIHRoZSBjdXJyZW50IGNhbnZhcyBjb250ZW50IGZvciB0aGUgZ2l2ZW4gaWRlbnRpZmllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNhY2hlKGlkZW50aWZpZXIpIHtcbiAgICAgIHRoaXMuX2NhY2hlW2lkZW50aWZpZXJdID0ge1xuICAgICAgICBkYXRhOiB0aGlzLl9jb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB0aGlzLl9jYW52YXMud2lkdGgsIHRoaXMuX2NhbnZhcy5oZWlnaHQpLFxuICAgICAgICBzaXplOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodClcbiAgICAgIH07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZHJhd0NhY2hlZCcsXG5cbiAgICAvKipcbiAgICAgKiBEcmF3cyB0aGUgc3RvcmVkIHRleHR1cmUgLyBpbWFnZSBkYXRhIGZvciB0aGUgZ2l2ZW4gaWRlbnRpZmllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRyYXdDYWNoZWQoaWRlbnRpZmllcikge1xuICAgICAgdmFyIF9jYWNoZSRpZGVudGlmaWVyID0gdGhpcy5fY2FjaGVbaWRlbnRpZmllcl07XG4gICAgICB2YXIgZGF0YSA9IF9jYWNoZSRpZGVudGlmaWVyLmRhdGE7XG4gICAgICB2YXIgc2l6ZSA9IF9jYWNoZSRpZGVudGlmaWVyLnNpemU7XG5cbiAgICAgIHRoaXMuX2NhbnZhcy53aWR0aCA9IHNpemUueDtcbiAgICAgIHRoaXMuX2NhbnZhcy5oZWlnaHQgPSBzaXplLnk7XG4gICAgICB0aGlzLl9jb250ZXh0LnB1dEltYWdlRGF0YShkYXRhLCAwLCAwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0Q29udGV4dCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByZW5kZXJpbmcgY29udGV4dCBmcm9tIHRoZSBDYW52YVxuICAgICAqIEByZXR1cm4ge1JlbmRlcmluZ0NvbnRleHR9XG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRDb250ZXh0KCkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHJldHVybiB0aGlzLl9jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdkcmF3SW1hZ2UnLFxuXG4gICAgLyoqXG4gICAgICogRHJhd3MgdGhlIGdpdmVuIGltYWdlIG9uIHRoZSBjYW52YXNcbiAgICAgKiBAcGFyYW0gIHtJbWFnZX0gaW1hZ2VcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBkcmF3SW1hZ2UoaW1hZ2UpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHJldHVybiBuZXcgX3ZlbmRvclByb21pc2UyWydkZWZhdWx0J10oZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBfdGhpcy5fY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQsIDAsIDAsIF90aGlzLl9jYW52YXMud2lkdGgsIF90aGlzLl9jYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVzaXplVG8nLFxuXG4gICAgLyoqXG4gICAgICogUmVzaXplcyB0aGUgY3VycmVudCBjYW52YXMgcGljdHVyZSB0byB0aGUgZ2l2ZW4gZGltZW5zaW9uc1xuICAgICAqIEBwYXJhbSAge1ZlY3RvcjJ9IGRpbWVuc2lvbnNcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZXNpemVUbyhkaW1lbnNpb25zKSB7XG4gICAgICAvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgY2FudmFzIHRvIGRyYXcgdG9cbiAgICAgIHZhciBuZXdDYW52YXMgPSB0aGlzLmNyZWF0ZUNhbnZhcygpO1xuICAgICAgbmV3Q2FudmFzLndpZHRoID0gZGltZW5zaW9ucy54O1xuICAgICAgbmV3Q2FudmFzLmhlaWdodCA9IGRpbWVuc2lvbnMueTtcbiAgICAgIHZhciBuZXdDb250ZXh0ID0gbmV3Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIC8vIERyYXcgdGhlIHNvdXJjZSBjYW52YXMgb250byB0aGUgbmV3IG9uZVxuICAgICAgbmV3Q29udGV4dC5kcmF3SW1hZ2UodGhpcy5fY2FudmFzLCAwLCAwLCB0aGlzLl9jYW52YXMud2lkdGgsIHRoaXMuX2NhbnZhcy5oZWlnaHQsIDAsIDAsIG5ld0NhbnZhcy53aWR0aCwgbmV3Q2FudmFzLmhlaWdodCk7XG5cbiAgICAgIC8vIFNldCB0aGUgbmV3IGNhbnZhcyBhbmQgY29udGV4dFxuICAgICAgdGhpcy5zZXRDYW52YXMobmV3Q2FudmFzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjbG9uZUNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgY2xvbmVkIHZlcnNpb24gb2YgdGhlIGN1cnJlbnQgY2FudmFzXG4gICAgICogQHJldHVybiB7Q2FudmFzfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBjbG9uZUNhbnZhcygpIHtcbiAgICAgIHZhciBjYW52YXMgPSB0aGlzLmNyZWF0ZUNhbnZhcygpO1xuICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgLy8gUmVzaXplIHRoZSBjYW52YXNcbiAgICAgIGNhbnZhcy53aWR0aCA9IHRoaXMuX2NhbnZhcy53aWR0aDtcbiAgICAgIGNhbnZhcy5oZWlnaHQgPSB0aGlzLl9jYW52YXMuaGVpZ2h0O1xuXG4gICAgICAvLyBEcmF3IHRoZSBjdXJyZW50IGNhbnZhcyBvbiB0aGUgbmV3IG9uZVxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UodGhpcy5fY2FudmFzLCAwLCAwKTtcblxuICAgICAgcmV0dXJuIGNhbnZhcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXNldCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXNldHMgdGhlIHJlbmRlcmVyXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZXNldENhY2hlID0gZmFsc2VcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICB2YXIgcmVzZXRDYWNoZSA9IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgIGlmIChyZXNldENhY2hlKSB7XG4gICAgICAgIHRoaXMuX2NhY2hlID0gW107XG4gICAgICB9XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpc1N1cHBvcnRlZCcsXG5cbiAgICAvKipcbiAgICAgKiBDaGVja3Mgd2hldGhlciB0aGlzIHR5cGUgb2YgcmVuZGVyZXIgaXMgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50XG4gICAgICogQGFic3RyYWN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGlzU3VwcG9ydGVkKCkge1xuICAgICAgdmFyIGVsZW0gPSB0aGlzLnByb3RvdHlwZS5jcmVhdGVDYW52YXMoKTtcbiAgICAgIHJldHVybiAhIShlbGVtLmdldENvbnRleHQgJiYgZWxlbS5nZXRDb250ZXh0KCcyZCcpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyByZW5kZXJlclxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2NhbnZhcyc7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENhbnZhc1JlbmRlcmVyO1xufSkoX3JlbmRlcmVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ2FudmFzUmVuZGVyZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vcmVuZGVyZXJzL2NhbnZhcy1yZW5kZXJlci5qc1xuICoqIG1vZHVsZSBpZCA9IDU0XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgSW1hZ2UgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDIsIF94MywgX3g0KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MiwgcHJvcGVydHkgPSBfeDMsIHJlY2VpdmVyID0gX3g0OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDIgPSBwYXJlbnQ7IF94MyA9IHByb3BlcnR5OyBfeDQgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcmVuZGVyZXIgPSByZXF1aXJlKCcuL3JlbmRlcmVyJyk7XG5cbnZhciBfcmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVuZGVyZXIpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIF9saWJFeGlmUmVzdG9yZXIgPSByZXF1aXJlKCcuLi9saWIvZXhpZi1yZXN0b3JlcicpO1xuXG52YXIgX2xpYkV4aWZSZXN0b3JlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFeGlmUmVzdG9yZXIpO1xuXG52YXIgX3ZlbmRvclByb21pc2UgPSByZXF1aXJlKCcuLi92ZW5kb3IvcHJvbWlzZScpO1xuXG52YXIgX3ZlbmRvclByb21pc2UyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdmVuZG9yUHJvbWlzZSk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuV2ViR0xSZW5kZXJlclxuICogQGV4dGVuZHMge0ltZ2x5S2l0LlJlbmRlcmVyfVxuICogQHByaXZhdGVcbiAqL1xuXG52YXIgV2ViR0xSZW5kZXJlciA9IChmdW5jdGlvbiAoX1JlbmRlcmVyKSB7XG4gIGZ1bmN0aW9uIFdlYkdMUmVuZGVyZXIoKSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFdlYkdMUmVuZGVyZXIpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoV2ViR0xSZW5kZXJlci5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIHRoaXMuX2RlZmF1bHRQcm9ncmFtID0gdGhpcy5zZXR1cEdMU0xQcm9ncmFtKCk7XG4gICAgdGhpcy5yZXNldCgpO1xuXG4gICAgdGhpcy5pZCA9IFdlYkdMUmVuZGVyZXIuY29udGV4dElkO1xuICAgIFdlYkdMUmVuZGVyZXIuY29udGV4dElkKys7XG4gIH1cblxuICBfaW5oZXJpdHMoV2ViR0xSZW5kZXJlciwgX1JlbmRlcmVyKTtcblxuICBfY3JlYXRlQ2xhc3MoV2ViR0xSZW5kZXJlciwgW3tcbiAgICBrZXk6ICdjYWNoZScsXG5cbiAgICAvKipcbiAgICAgKiBDYWNoZXMgdGhlIGN1cnJlbnQgY2FudmFzIGNvbnRlbnQgZm9yIHRoZSBnaXZlbiBpZGVudGlmaWVyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gY2FjaGUoaWRlbnRpZmllcikge1xuICAgICAgdmFyIHNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIC8vIFJlLXVzZSBGQk8gYW5kIHRleHR1cmVzXG4gICAgICB2YXIgZmJvID0gdW5kZWZpbmVkLFxuICAgICAgICAgIHRleHR1cmUgPSB1bmRlZmluZWQsXG4gICAgICAgICAgY2FjaGVPYmplY3QgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAoIXRoaXMuX2NhY2hlW2lkZW50aWZpZXJdKSB7XG4gICAgICAgIGNhY2hlT2JqZWN0ID0gdGhpcy5fY3JlYXRlRnJhbWVidWZmZXIoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhY2hlT2JqZWN0ID0gdGhpcy5fY2FjaGVbaWRlbnRpZmllcl07XG4gICAgICB9XG5cbiAgICAgIC8vIEV4dHJhY3QgRkJPIGFuZCB0ZXh0dXJlXG4gICAgICBmYm8gPSBjYWNoZU9iamVjdC5mYm87XG4gICAgICB0ZXh0dXJlID0gY2FjaGVPYmplY3QudGV4dHVyZTtcblxuICAgICAgLy8gUmVzaXplIG91dHB1dCB0ZXh0dXJlXG4gICAgICB2YXIgZ2wgPSB0aGlzLl9jb250ZXh0O1xuICAgICAgZ2wudXNlUHJvZ3JhbSh0aGlzLl9kZWZhdWx0UHJvZ3JhbSk7XG5cbiAgICAgIC8vIFJlc2l6ZSBjYWNoZWQgdGV4dHVyZVxuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIHNpemUueCwgc2l6ZS55LCAwLCBnbC5SR0JBLCBnbC5VTlNJR05FRF9CWVRFLCBudWxsKTtcblxuICAgICAgLy8gUmVuZGVyIHRvIEZCT1xuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBmYm8pO1xuICAgICAgZ2wudmlld3BvcnQoMCwgMCwgc2l6ZS54LCBzaXplLnkpO1xuXG4gICAgICAvLyBVc2UgbGFzdCBmYm8gdGV4dHVyZSBhcyBpbnB1dFxuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy5fbGFzdFRleHR1cmUpO1xuXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgNik7XG5cbiAgICAgIHRoaXMuX2NhY2hlW2lkZW50aWZpZXJdID0geyBmYm86IGZibywgdGV4dHVyZTogdGV4dHVyZSwgc2l6ZTogc2l6ZSB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19kcmF3Q2FjaGVkRmluYWwnLFxuXG4gICAgLyoqXG4gICAgICogRGVidWdnaW5nIG1ldGhvZCB0byBkcmF3IGEgY2FjaGVkIHRleHR1cmUgdG8gdGhlIGNhbnZhcyBpbnN0ZWFkXG4gICAgICogdG8gYW4gRkJPXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2RyYXdDYWNoZWRGaW5hbChpZGVudGlmaWVyKSB7XG4gICAgICB2YXIgX2NhY2hlJGlkZW50aWZpZXIgPSB0aGlzLl9jYWNoZVtpZGVudGlmaWVyXTtcbiAgICAgIHZhciB0ZXh0dXJlID0gX2NhY2hlJGlkZW50aWZpZXIudGV4dHVyZTtcbiAgICAgIHZhciBzaXplID0gX2NhY2hlJGlkZW50aWZpZXIuc2l6ZTtcblxuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcbiAgICAgIGdsLnVzZVByb2dyYW0odGhpcy5fZGVmYXVsdFByb2dyYW0pO1xuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcblxuICAgICAgLy8gVXNlIHRoZSBjYWNoZWQgdGV4dHVyZSBhcyBpbnB1dFxuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG5cbiAgICAgIC8vIFJlc2l6ZSB0aGUgY2FudmFzXG4gICAgICB0aGlzLl9jYW52YXMud2lkdGggPSBzaXplLng7XG4gICAgICB0aGlzLl9jYW52YXMuaGVpZ2h0ID0gc2l6ZS55O1xuXG4gICAgICBnbC52aWV3cG9ydCgwLCAwLCBzaXplLngsIHNpemUueSk7XG5cbiAgICAgIC8vIERyYXcgdGhlIHJlY3RhbmdsZVxuICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIDYpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RyYXdDYWNoZWQnLFxuXG4gICAgLyoqXG4gICAgICogRHJhd3MgdGhlIHN0b3JlZCB0ZXh0dXJlIC8gaW1hZ2UgZGF0YSBmb3IgdGhlIGdpdmVuIGlkZW50aWZpZXJcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaWRlbnRpZmllclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBkcmF3Q2FjaGVkKGlkZW50aWZpZXIpIHtcbiAgICAgIHZhciBfY2FjaGUkaWRlbnRpZmllcjIgPSB0aGlzLl9jYWNoZVtpZGVudGlmaWVyXTtcbiAgICAgIHZhciB0ZXh0dXJlID0gX2NhY2hlJGlkZW50aWZpZXIyLnRleHR1cmU7XG4gICAgICB2YXIgc2l6ZSA9IF9jYWNoZSRpZGVudGlmaWVyMi5zaXplO1xuXG4gICAgICB2YXIgZmJvID0gdGhpcy5nZXRDdXJyZW50RnJhbWVidWZmZXIoKTtcbiAgICAgIHZhciBjdXJyZW50VGV4dHVyZSA9IHRoaXMuZ2V0Q3VycmVudFRleHR1cmUoKTtcblxuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcbiAgICAgIGdsLnVzZVByb2dyYW0odGhpcy5fZGVmYXVsdFByb2dyYW0pO1xuXG4gICAgICAvLyBSZXNpemUgdGhlIGNhbnZhc1xuICAgICAgdGhpcy5fY2FudmFzLndpZHRoID0gc2l6ZS54O1xuICAgICAgdGhpcy5fY2FudmFzLmhlaWdodCA9IHNpemUueTtcblxuICAgICAgLy8gUmVzaXplIGFsbCB0ZXh0dXJlc1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl90ZXh0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3RoZXJUZXh0dXJlID0gdGhpcy5fdGV4dHVyZXNbaV07XG4gICAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIG90aGVyVGV4dHVyZSk7XG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgc2l6ZS54LCBzaXplLnksIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIG51bGwpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZWxlY3QgdGhlIGN1cnJlbnQgZnJhbWVidWZmZXIgdG8gZHJhdyB0b1xuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBmYm8pO1xuXG4gICAgICAvLyBSZXNpemUgdGhlIHRleHR1cmUgd2UncmUgZHJhd2luZyB0b1xuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgY3VycmVudFRleHR1cmUpO1xuICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCBzaXplLngsIHNpemUueSwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICAgIC8vIFVzZSB0aGUgY2FjaGVkIHRleHR1cmUgYXMgaW5wdXRcbiAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuXG4gICAgICBnbC52aWV3cG9ydCgwLCAwLCBzaXplLngsIHNpemUueSk7XG5cbiAgICAgIC8vIENsZWFyXG4gICAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUIHwgZ2wuREVQVEhfQlVGRkVSX0JJVCk7XG5cbiAgICAgIC8vIERyYXcgdGhlIHJlY3RhbmdsZVxuICAgICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIDYpO1xuXG4gICAgICB0aGlzLnNldExhc3RUZXh0dXJlKGN1cnJlbnRUZXh0dXJlKTtcbiAgICAgIHRoaXMuc2VsZWN0TmV4dEJ1ZmZlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRDb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJlbmRlcmluZyBjb250ZXh0IGZyb20gdGhlIENhbnZhc1xuICAgICAqIEByZXR1cm4ge1JlbmRlcmluZ0NvbnRleHR9XG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRDb250ZXh0KCkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHZhciBnbCA9IHRoaXMuX2NhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcsIHRoaXMuX2NvbnRleHRPcHRpb25zKSB8fCB0aGlzLl9jYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgdGhpcy5fY29udGV4dE9wdGlvbnMpO1xuXG4gICAgICBnbC5kaXNhYmxlKGdsLkRFUFRIX1RFU1QpO1xuICAgICAgZ2wuZGlzYWJsZShnbC5DVUxMX0ZBQ0UpO1xuXG4gICAgICB0aGlzLl9tYXhUZXh0dXJlU2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfVEVYVFVSRV9TSVpFKTtcblxuICAgICAgcmV0dXJuIGdsO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RyYXdJbWFnZScsXG5cbiAgICAvKipcbiAgICAgKiBEcmF3cyB0aGUgZ2l2ZW4gaW1hZ2Ugb24gdGhlIGNhbnZhc1xuICAgICAqIEBwYXJhbSAge0ltYWdlfSBpbWFnZVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRyYXdJbWFnZShpbWFnZSkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgcmV0dXJuIG5ldyBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIHZhciBnbCA9IF90aGlzLl9jb250ZXh0O1xuICAgICAgICBnbC51c2VQcm9ncmFtKF90aGlzLl9kZWZhdWx0UHJvZ3JhbSk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSB0ZXh0dXJlXG4gICAgICAgIHZhciB0ZXh0dXJlID0gX3RoaXMuY3JlYXRlVGV4dHVyZSgpO1xuICAgICAgICBnbC5waXhlbFN0b3JlaShnbC5VTlBBQ0tfRkxJUF9ZX1dFQkdMLCB0cnVlKTtcbiAgICAgICAgX3RoaXMuX2lucHV0VGV4dHVyZSA9IHRleHR1cmU7XG4gICAgICAgIF90aGlzLnNldExhc3RUZXh0dXJlKHRleHR1cmUpO1xuXG4gICAgICAgIC8vIFNldCBwcmVtdWx0aXBsaWVkIGFscGhhXG4gICAgICAgIGdsLnBpeGVsU3RvcmVpKGdsLlVOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCwgdHJ1ZSk7XG5cbiAgICAgICAgLy8gVXBsb2FkIHRoZSBpbWFnZSBpbnRvIHRoZSB0ZXh0dXJlXG4gICAgICAgIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZ2wuUkdCQSwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgaW1hZ2UpO1xuXG4gICAgICAgIF90aGlzLl9jbGVhcihnbCk7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgcmVjdGFuZ2xlXG4gICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCA2KTtcblxuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdwcmVwYXJlSW1hZ2UnLFxuXG4gICAgLyoqXG4gICAgICogUmVzaXplcyB0aGUgZ2l2ZW4gaW1hZ2UgdG8gZml0IHRoZSBtYXhpbXVtIHRleHR1cmUgc2l6ZVxuICAgICAqIEBwYXJhbSB7SW1hZ2V9XG4gICAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcHJlcGFyZUltYWdlKGltYWdlKSB7XG4gICAgICBpZiAoaW1hZ2Uud2lkdGggPD0gdGhpcy5fbWF4VGV4dHVyZVNpemUgJiYgaW1hZ2UuaGVpZ2h0IDw9IHRoaXMuX21heFRleHR1cmVTaXplKSB7XG4gICAgICAgIHJldHVybiBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXS5yZXNvbHZlKGltYWdlKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2FsY3VsYXRlIG5ldyBzaXplIHRoYXQgZml0cyB0aGUgZ3JhcGhpY3MgY2FyZCdzIG1heCB0ZXh0dXJlIHNpemVcbiAgICAgIHZhciBtYXhTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9tYXhUZXh0dXJlU2l6ZSwgdGhpcy5fbWF4VGV4dHVyZVNpemUpO1xuICAgICAgdmFyIHNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQpO1xuICAgICAgdmFyIHNjYWxlID0gTWF0aC5taW4obWF4U2l6ZS54IC8gc2l6ZS54LCBtYXhTaXplLnkgLyBzaXplLnkpO1xuICAgICAgdmFyIG5ld1NpemUgPSBzaXplLmNsb25lKCkubXVsdGlwbHkoc2NhbGUpO1xuXG4gICAgICAvLyBDcmVhdGUgYSBuZXcgY2FudmFzIHRvIGRyYXcgdGhlIGltYWdlIHRvXG4gICAgICB2YXIgY2FudmFzID0gdGhpcy5jcmVhdGVDYW52YXMobmV3U2l6ZS54LCBuZXdTaXplLnkpO1xuICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgLy8gRHJhdyB0aGUgcmVzaXplZCBpbWFnZVxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHNpemUueCwgc2l6ZS55LCAwLCAwLCBuZXdTaXplLngsIG5ld1NpemUueSk7XG5cbiAgICAgIC8vIFR1cm4gaW50byBhIGRhdGEgdXJsIGFuZCBtYWtlIGFuIGltYWdlIG91dCBvZiBpdFxuICAgICAgdmFyIGRhdGEgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9qcGVnJyk7XG5cbiAgICAgIHZhciBqcGVnTWF0Y2ggPSAvXmRhdGE6aW1hZ2VcXC9qcGVnL2k7XG4gICAgICBpZiAoaW1hZ2Uuc3JjLm1hdGNoKGpwZWdNYXRjaCkgJiYgZGF0YS5tYXRjaChqcGVnTWF0Y2gpKSB7XG4gICAgICAgIGRhdGEgPSBfbGliRXhpZlJlc3RvcmVyMlsnZGVmYXVsdCddLnJlc3RvcmUoaW1hZ2Uuc3JjLCBkYXRhKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIHZhciBpbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBpbWFnZS5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJlc29sdmUoaW1hZ2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgaW1hZ2Uuc3JjID0gZGF0YTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19jbGVhcicsXG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgdGhlIFdlYkdMIGNvbnRleHRcbiAgICAgKiBAcGFyYW0ge1dlYkdMUmVuZGVyaW5nQ29udGV4dH0gZ2xcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfY2xlYXIoZ2wpIHtcbiAgICAgIGdsLmNsZWFyQ29sb3IoMCwgMCwgMCwgMCk7XG4gICAgICBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdydW5Qcm9ncmFtJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gcnVuUHJvZ3JhbShwcm9ncmFtLCBvcHRpb25zKSB7XG4gICAgICB2YXIgZ2wgPSB0aGlzLl9jb250ZXh0O1xuICAgICAgZ2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcblxuICAgICAgdmFyIGZibyA9IHRoaXMuZ2V0Q3VycmVudEZyYW1lYnVmZmVyKCk7XG4gICAgICB2YXIgY3VycmVudFRleHR1cmUgPSB0aGlzLmdldEN1cnJlbnRUZXh0dXJlKCk7XG5cbiAgICAgIC8vIFNlbGVjdCB0aGUgY3VycmVudCBmcmFtZWJ1ZmZlclxuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBmYm8pO1xuICAgICAgZ2wudmlld3BvcnQoMCwgMCwgdGhpcy5fY2FudmFzLndpZHRoLCB0aGlzLl9jYW52YXMuaGVpZ2h0KTtcblxuICAgICAgLy8gUmVzaXplIHRoZSB0ZXh0dXJlIHRvIGNhbnZhcyBzaXplXG4gICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBjdXJyZW50VGV4dHVyZSk7XG5cbiAgICAgIC8vIFNldCBwcmVtdWx0aXBsaWVkIGFscGhhXG4gICAgICBnbC5waXhlbFN0b3JlaShnbC5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsIHRydWUpO1xuXG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICAgIC8vIE1ha2Ugc3VyZSB3ZSBzZWxlY3QgdGhlIGN1cnJlbnQgdGV4dHVyZVxuICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGhpcy5fbGFzdFRleHR1cmUpO1xuXG4gICAgICAvLyBTZXQgdGhlIHVuaWZvcm1zXG4gICAgICBmb3IgKHZhciBuYW1lIGluIG9wdGlvbnMudW5pZm9ybXMpIHtcbiAgICAgICAgdmFyIGxvY2F0aW9uID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIG5hbWUpO1xuICAgICAgICB2YXIgdW5pZm9ybSA9IG9wdGlvbnMudW5pZm9ybXNbbmFtZV07XG5cbiAgICAgICAgc3dpdGNoICh1bmlmb3JtLnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdpJzpcbiAgICAgICAgICBjYXNlICcxaSc6XG4gICAgICAgICAgICBnbC51bmlmb3JtMWkobG9jYXRpb24sIHVuaWZvcm0udmFsdWUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZic6XG4gICAgICAgICAgY2FzZSAnMWYnOlxuICAgICAgICAgICAgZ2wudW5pZm9ybTFmKGxvY2F0aW9uLCB1bmlmb3JtLnZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJzJmJzpcbiAgICAgICAgICAgIGdsLnVuaWZvcm0yZihsb2NhdGlvbiwgdW5pZm9ybS52YWx1ZVswXSwgdW5pZm9ybS52YWx1ZVsxXSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICczZic6XG4gICAgICAgICAgICBnbC51bmlmb3JtM2YobG9jYXRpb24sIHVuaWZvcm0udmFsdWVbMF0sIHVuaWZvcm0udmFsdWVbMV0sIHVuaWZvcm0udmFsdWVbMl0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnNGYnOlxuICAgICAgICAgICAgZ2wudW5pZm9ybTRmKGxvY2F0aW9uLCB1bmlmb3JtLnZhbHVlWzBdLCB1bmlmb3JtLnZhbHVlWzFdLCB1bmlmb3JtLnZhbHVlWzJdLCB1bmlmb3JtLnZhbHVlWzNdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJzJmdic6XG4gICAgICAgICAgICBnbC51bmlmb3JtMmZ2KGxvY2F0aW9uLCB1bmlmb3JtLnZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ21hdDNmdic6XG4gICAgICAgICAgICBnbC51bmlmb3JtTWF0cml4M2Z2KGxvY2F0aW9uLCBmYWxzZSwgdW5pZm9ybS52YWx1ZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHVuaWZvcm0gdHlwZTogJyArIHVuaWZvcm0udHlwZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2xlYXJcbiAgICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQgfCBnbC5ERVBUSF9CVUZGRVJfQklUKTtcblxuICAgICAgLy8gRHJhdyB0aGUgcmVjdGFuZ2xlXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgNik7XG5cbiAgICAgIHRoaXMuc2V0TGFzdFRleHR1cmUoY3VycmVudFRleHR1cmUpO1xuICAgICAgdGhpcy5zZWxlY3ROZXh0QnVmZmVyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncnVuU2hhZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJ1bnMgdGhlIGdpdmVuIHNoYWRlclxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gW3ZlcnRleFNoYWRlcl1cbiAgICAgKiBAcGFyYW0gIHtTdHJpbmd9IFtmcmFnbWVudFNoYWRlcl1cbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBydW5TaGFkZXIodmVydGV4U2hhZGVyLCBmcmFnbWVudFNoYWRlciwgb3B0aW9ucykge1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAndW5kZWZpbmVkJykgb3B0aW9ucyA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnVuaWZvcm1zID09PSAndW5kZWZpbmVkJykgb3B0aW9ucy51bmlmb3JtcyA9IHt9O1xuXG4gICAgICB2YXIgcHJvZ3JhbSA9IHRoaXMuc2V0dXBHTFNMUHJvZ3JhbSh2ZXJ0ZXhTaGFkZXIsIGZyYWdtZW50U2hhZGVyKTtcbiAgICAgIHRoaXMucnVuUHJvZ3JhbShwcm9ncmFtLCBvcHRpb25zKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJGaW5hbCcsXG5cbiAgICAvKipcbiAgICAgKiBEcmF3cyB0aGUgbGFzdCB1c2VkIGJ1ZmZlciBvbnRvIHRoZSBjYW52YXNcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJGaW5hbCgpIHtcbiAgICAgIHZhciBnbCA9IHRoaXMuX2NvbnRleHQ7XG4gICAgICB2YXIgcHJvZ3JhbSA9IHRoaXMuX2RlZmF1bHRQcm9ncmFtO1xuICAgICAgZ2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcblxuICAgICAgLy8gRG9uJ3QgZHJhdyB0byBmcmFtZWJ1ZmZlclxuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcblxuICAgICAgLy8gTWFrZSBzdXJlIHRoZSB2aWV3cG9ydCBzaXplIGlzIGNvcnJlY3RcbiAgICAgIGdsLnZpZXdwb3J0KDAsIDAsIHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIC8vIFNlbGVjdCB0aGUgbGFzdCB0ZXh0dXJlIHRoYXQgaGFzIGJlZW4gcmVuZGVyZWQgdG9cbiAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMuX2xhc3RUZXh0dXJlKTtcblxuICAgICAgLy8gQ2xlYXJcbiAgICAgIHRoaXMuX2NsZWFyKGdsKTtcblxuICAgICAgLy8gRHJhdyB0aGUgcmVjdGFuZ2xlXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgNik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0dXBHTFNMUHJvZ3JhbScsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHVwIGEgR0xTTCBwcm9ncmFtLiBVc2VzIHRoZSBkZWZhdWx0IHZlcnRleCBhbmQgZnJhZ21lbnQgc2hhZGVyXG4gICAgICogaWYgbm9uZSBhcmUgZ2l2ZW4uXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IFt2ZXJ0ZXhTaGFkZXJdXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IFtmcmFnbWVudFNoYWRlcl1cbiAgICAgKiBAcmV0dXJuIHtXZWJHTFByb2dyYW19XG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0dXBHTFNMUHJvZ3JhbSh2ZXJ0ZXhTaGFkZXIsIGZyYWdtZW50U2hhZGVyKSB7XG4gICAgICB2YXIgZ2wgPSB0aGlzLl9jb250ZXh0O1xuICAgICAgdmFyIHNoYWRlcnMgPSBbXTtcblxuICAgICAgLy8gVXNlIGRlZmF1bHQgdmVydGV4IHNoYWRlclxuICAgICAgdmVydGV4U2hhZGVyID0gdGhpcy5fY3JlYXRlU2hhZGVyKGdsLlZFUlRFWF9TSEFERVIsIHZlcnRleFNoYWRlciB8fCBXZWJHTFJlbmRlcmVyLnByb3RvdHlwZS5kZWZhdWx0VmVydGV4U2hhZGVyKTtcbiAgICAgIHNoYWRlcnMucHVzaCh2ZXJ0ZXhTaGFkZXIpO1xuXG4gICAgICAvLyBVc2UgZGVmYXVsdCBmcmFnbWVudCBzaGFkZXJcbiAgICAgIGZyYWdtZW50U2hhZGVyID0gdGhpcy5fY3JlYXRlU2hhZGVyKGdsLkZSQUdNRU5UX1NIQURFUiwgZnJhZ21lbnRTaGFkZXIgfHwgV2ViR0xSZW5kZXJlci5wcm90b3R5cGUuZGVmYXVsdEZyYWdtZW50U2hhZGVyKTtcbiAgICAgIHNoYWRlcnMucHVzaChmcmFnbWVudFNoYWRlcik7XG5cbiAgICAgIC8vIENyZWF0ZSB0aGUgcHJvZ3JhbVxuICAgICAgdmFyIHByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKCk7XG5cbiAgICAgIC8vIEF0dGFjaCB0aGUgc2hhZGVyc1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaGFkZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBzaGFkZXJzW2ldKTtcbiAgICAgIH1cblxuICAgICAgLy8gTGluayB0aGUgcHJvZ3JhbVxuICAgICAgZ2wubGlua1Byb2dyYW0ocHJvZ3JhbSk7XG5cbiAgICAgIC8vIENoZWNrIGxpbmtpbmcgc3RhdHVzXG4gICAgICB2YXIgbGlua2VkID0gZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcihwcm9ncmFtLCBnbC5MSU5LX1NUQVRVUyk7XG4gICAgICBpZiAoIWxpbmtlZCkge1xuICAgICAgICB2YXIgbGFzdEVycm9yID0gZ2wuZ2V0UHJvZ3JhbUluZm9Mb2cocHJvZ3JhbSk7XG4gICAgICAgIGdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2ViR0wgcHJvZ3JhbSBsaW5raW5nIGVycm9yOiAnICsgbGFzdEVycm9yKTtcbiAgICAgIH1cblxuICAgICAgLy8gTG9va3VwIHRleHR1cmUgY29vcmRpbmF0ZXMgbG9jYXRpb25cbiAgICAgIHZhciBwb3NpdGlvbkxvY2F0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgJ2FfcG9zaXRpb24nKTtcbiAgICAgIHZhciB0ZXhDb29yZExvY2F0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgJ2FfdGV4Q29vcmQnKTtcblxuICAgICAgLy8gUHJvdmlkZSB0ZXh0dXJlIGNvb3JkaW5hdGVzXG4gICAgICB2YXIgdGV4Q29vcmRCdWZmZXIgPSBnbC5jcmVhdGVCdWZmZXIoKTtcbiAgICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCB0ZXhDb29yZEJ1ZmZlcik7XG4gICAgICBnbC5idWZmZXJEYXRhKGdsLkFSUkFZX0JVRkZFUiwgbmV3IEZsb2F0MzJBcnJheShbXG4gICAgICAvLyBGaXJzdCB0cmlhbmdsZVxuICAgICAgMCwgMCwgMSwgMCwgMCwgMSxcblxuICAgICAgLy8gU2Vjb25kIHRyaWFuZ2xlXG4gICAgICAwLCAxLCAxLCAwLCAxLCAxXSksIGdsLlNUQVRJQ19EUkFXKTtcbiAgICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KHRleENvb3JkTG9jYXRpb24pO1xuICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcih0ZXhDb29yZExvY2F0aW9uLCAyLCBnbC5GTE9BVCwgZmFsc2UsIDAsIDApO1xuXG4gICAgICAvLyBDcmVhdGUgYSBidWZmZXIgZm9yIHRoZSByZWN0YW5nbGUgcG9zaXRpb25zXG4gICAgICB2YXIgYnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgYnVmZmVyKTtcbiAgICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KHBvc2l0aW9uTG9jYXRpb24pO1xuICAgICAgZ2wudmVydGV4QXR0cmliUG9pbnRlcihwb3NpdGlvbkxvY2F0aW9uLCAyLCBnbC5GTE9BVCwgZmFsc2UsIDAsIDApO1xuICAgICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIG5ldyBGbG9hdDMyQXJyYXkoW1xuICAgICAgLy8gRmlyc3QgdHJpYW5nbGVcbiAgICAgIC0xLCAtMSwgMSwgLTEsIC0xLCAxLFxuXG4gICAgICAvLyBTZWNvbmQgdHJpYW5nbGVcbiAgICAgIC0xLCAxLCAxLCAtMSwgMSwgMV0pLCBnbC5TVEFUSUNfRFJBVyk7XG5cbiAgICAgIHJldHVybiBwcm9ncmFtO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19jcmVhdGVTaGFkZXInLFxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIFdlYkdMIHNoYWRlciB3aXRoIHRoZSBnaXZlbiB0eXBlIGFuZCBzb3VyY2UgY29kZVxuICAgICAqIEBwYXJhbSAge1dlYkdMU2hhZGVyVHlwZX0gc2hhZGVyVHlwZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gc2hhZGVyU291cmNlXG4gICAgICogQHJldHVybiB7V2ViR0xTaGFkZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfY3JlYXRlU2hhZGVyKHNoYWRlclR5cGUsIHNoYWRlclNvdXJjZSkge1xuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcblxuICAgICAgLy8gQ3JlYXRlIHRoZSBzaGFkZXIgYW5kIGNvbXBpbGUgaXRcbiAgICAgIHZhciBzaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIoc2hhZGVyVHlwZSk7XG4gICAgICBnbC5zaGFkZXJTb3VyY2Uoc2hhZGVyLCBzaGFkZXJTb3VyY2UpO1xuICAgICAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuXG4gICAgICAvLyBDaGVjayBjb21waWxhdGlvbiBzdGF0dXNcbiAgICAgIHZhciBjb21waWxlZCA9IGdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIGdsLkNPTVBJTEVfU1RBVFVTKTtcbiAgICAgIGlmICghY29tcGlsZWQpIHtcbiAgICAgICAgdmFyIGxhc3RFcnJvciA9IGdsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKTtcbiAgICAgICAgZ2wuZGVsZXRlU2hhZGVyKHNoYWRlcik7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2ViR0wgc2hhZGVyIGNvbXBpbGF0aW9uIGVycm9yOiAnICsgbGFzdEVycm9yKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNoYWRlcjtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjcmVhdGVUZXh0dXJlJyxcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gZW1wdHkgdGV4dHVyZVxuICAgICAqIEByZXR1cm4ge1dlYkdMVGV4dHVyZX1cbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBjcmVhdGVUZXh0dXJlKCkge1xuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcbiAgICAgIHZhciB0ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuXG4gICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcblxuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCBnbC5ORUFSRVNUKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5ORUFSRVNUKTtcblxuICAgICAgcmV0dXJuIHRleHR1cmU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZUZyYW1lYnVmZmVycycsXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHR3byB0ZXh0dXJlcyBhbmQgZnJhbWVidWZmZXJzIHRoYXQgYXJlIHVzZWQgZm9yIHRoZSBzdGFja1xuICAgICAqIHJlbmRlcmluZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NyZWF0ZUZyYW1lYnVmZmVycygpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgIHZhciBfY3JlYXRlRnJhbWVidWZmZXIyID0gdGhpcy5fY3JlYXRlRnJhbWVidWZmZXIoKTtcblxuICAgICAgICB2YXIgZmJvID0gX2NyZWF0ZUZyYW1lYnVmZmVyMi5mYm87XG4gICAgICAgIHZhciB0ZXh0dXJlID0gX2NyZWF0ZUZyYW1lYnVmZmVyMi50ZXh0dXJlO1xuXG4gICAgICAgIHRoaXMuX3RleHR1cmVzLnB1c2godGV4dHVyZSk7XG4gICAgICAgIHRoaXMuX2ZyYW1lYnVmZmVycy5wdXNoKGZibyk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NyZWF0ZUZyYW1lYnVmZmVyJyxcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW5kIHJldHVybnMgYSBmcmFtZSBidWZmZXIgYW5kIHRleHR1cmVcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2NyZWF0ZUZyYW1lYnVmZmVyKCkge1xuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcblxuICAgICAgLy8gQ3JlYXRlIHRleHR1cmVcbiAgICAgIHZhciB0ZXh0dXJlID0gdGhpcy5jcmVhdGVUZXh0dXJlKCk7XG5cbiAgICAgIC8vIFNldCBwcmVtdWx0aXBsaWVkIGFscGhhXG4gICAgICBnbC5waXhlbFN0b3JlaShnbC5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsIHRydWUpO1xuXG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGdsLlJHQkEsIHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCwgMCwgZ2wuUkdCQSwgZ2wuVU5TSUdORURfQllURSwgbnVsbCk7XG5cbiAgICAgIC8vIENyZWF0ZSBmcmFtZWJ1ZmZlclxuICAgICAgdmFyIGZibyA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGZibyk7XG5cbiAgICAgIC8vIEF0dGFjaCB0aGUgdGV4dHVyZVxuICAgICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoZ2wuRlJBTUVCVUZGRVIsIGdsLkNPTE9SX0FUVEFDSE1FTlQwLCBnbC5URVhUVVJFXzJELCB0ZXh0dXJlLCAwKTtcblxuICAgICAgcmV0dXJuIHsgZmJvOiBmYm8sIHRleHR1cmU6IHRleHR1cmUgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXNpemVUbycsXG5cbiAgICAvKipcbiAgICAgKiBSZXNpemVzIHRoZSBjdXJyZW50IGNhbnZhcyBwaWN0dXJlIHRvIHRoZSBnaXZlbiBkaW1lbnNpb25zXG4gICAgICogQHBhcmFtICB7VmVjdG9yMn0gZGltZW5zaW9uc1xuICAgICAqIEB0b2RvIFVzZSBhIGRvd25zYW1wbGluZyBzaGFkZXIgZm9yIHNtb290aGVyIGltYWdlIHJlc2l6aW5nXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzaXplVG8oZGltZW5zaW9ucykge1xuICAgICAgdmFyIGdsID0gdGhpcy5fY29udGV4dDtcblxuICAgICAgLy8gUmVzaXplIHRoZSBjYW52YXNcbiAgICAgIHRoaXMuX2NhbnZhcy53aWR0aCA9IGRpbWVuc2lvbnMueDtcbiAgICAgIHRoaXMuX2NhbnZhcy5oZWlnaHQgPSBkaW1lbnNpb25zLnk7XG5cbiAgICAgIC8vIFVwZGF0ZSB0aGUgdmlld3BvcnQgZGltZW5zaW9uc1xuICAgICAgZ2wudmlld3BvcnQoMCwgMCwgdGhpcy5fY2FudmFzLndpZHRoLCB0aGlzLl9jYW52YXMuaGVpZ2h0KTtcblxuICAgICAgLy8gRHJhdyB0aGUgcmVjdGFuZ2xlXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgNik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0Q3VycmVudEZyYW1lYnVmZmVyJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgZnJhbWVidWZmZXJcbiAgICAgKiBAcmV0dXJuIHtXZWJHTEZyYW1lYnVmZmVyfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDdXJyZW50RnJhbWVidWZmZXIoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZnJhbWVidWZmZXJzW3RoaXMuX2J1ZmZlckluZGV4ICUgMl07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0Q3VycmVudFRleHR1cmUnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCB0ZXh0dXJlXG4gICAgICogQHJldHVybiB7V2ViR0xUZXh0dXJlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDdXJyZW50VGV4dHVyZSgpIHtcbiAgICAgIHJldHVybiB0aGlzLl90ZXh0dXJlc1t0aGlzLl9idWZmZXJJbmRleCAlIDJdO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NlbGVjdE5leHRCdWZmZXInLFxuXG4gICAgLyoqXG4gICAgICogSW5jcmVhc2VzIHRoZSBidWZmZXIgaW5kZXhcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2VsZWN0TmV4dEJ1ZmZlcigpIHtcbiAgICAgIHRoaXMuX2J1ZmZlckluZGV4Kys7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0RGVmYXVsdFByb2dyYW0nLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZGVmYXVsdCBwcm9ncmFtXG4gICAgICogQHJldHVybiB7V2ViR0xQcm9ncmFtfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXREZWZhdWx0UHJvZ3JhbSgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9kZWZhdWx0UHJvZ3JhbTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRMYXN0VGV4dHVyZScsXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IHRleHR1cmUgdGhhdCBoYXMgYmVlbiBkcmF3biB0b1xuICAgICAqIEByZXR1cm4ge1dlYkdMVGV4dHVyZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TGFzdFRleHR1cmUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbGFzdFRleHR1cmU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZ2V0VGV4dHVyZXMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbGwgdGV4dHVyZXNcbiAgICAgKiBAcmV0dXJuIHtBcnJheS48V2ViR0xUZXh0dXJlPn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0VGV4dHVyZXMoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdGV4dHVyZXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0TGFzdFRleHR1cmUnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbGFzdCB0ZXh0dXJlXG4gICAgICogQHBhcmFtIHtXZWJHTFRleHR1cmV9IHRleHR1cmVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0TGFzdFRleHR1cmUodGV4dHVyZSkge1xuICAgICAgdGhpcy5fbGFzdFRleHR1cmUgPSB0ZXh0dXJlO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Jlc2V0JyxcblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgcmVuZGVyZXJcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlc2V0Q2FjaGUgPSBmYWxzZVxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgIHZhciByZXNldENhY2hlID0gYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGFyZ3VtZW50c1swXTtcblxuICAgICAgdGhpcy5fbGFzdFRleHR1cmUgPSBudWxsO1xuICAgICAgdGhpcy5fdGV4dHVyZXMgPSBbXTtcbiAgICAgIHRoaXMuX2ZyYW1lYnVmZmVycyA9IFtdO1xuICAgICAgdGhpcy5fYnVmZmVySW5kZXggPSAwO1xuXG4gICAgICBpZiAocmVzZXRDYWNoZSkge1xuICAgICAgICB0aGlzLl9jYWNoZSA9IFtdO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jcmVhdGVGcmFtZWJ1ZmZlcnMoKTtcbiAgICAgIHRoaXMuc2V0TGFzdFRleHR1cmUodGhpcy5faW5wdXRUZXh0dXJlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY29udGV4dE9wdGlvbnMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29udGV4dCBvcHRpb25zIHBhc3NlZCB0byBnZXRDb250ZXh0KClcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbHBoYTogdHJ1ZSxcbiAgICAgICAgcHJlbXVsdGlwbGllZEFscGhhOiB0cnVlXG4gICAgICB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2lkZW50aWZpZXInLFxuXG4gICAgLyoqXG4gICAgICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIHJlbmRlcmVyXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnd2ViZ2wnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2RlZmF1bHRWZXJ0ZXhTaGFkZXInLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGRlZmF1bHQgdmVydGV4IHNoYWRlciB3aGljaCBqdXN0IHBhc3NlcyB0aGUgdGV4Q29vcmQgdG8gdGhlXG4gICAgICogZnJhZ21lbnQgc2hhZGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBzaGFkZXIgPSAnXFxuICAgICAgYXR0cmlidXRlIHZlYzIgYV9wb3NpdGlvbjtcXG4gICAgICBhdHRyaWJ1dGUgdmVjMiBhX3RleENvb3JkO1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIGdsX1Bvc2l0aW9uID0gdmVjNChhX3Bvc2l0aW9uLCAwLCAxKTtcXG4gICAgICAgIHZfdGV4Q29vcmQgPSBhX3RleENvb3JkO1xcbiAgICAgIH1cXG4gICAgJztcbiAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZGVmYXVsdEZyYWdtZW50U2hhZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkZWZhdWx0IGZyYWdtZW50IHNoYWRlciB3aGljaCB3aWxsIGp1c3QgbG9vayB1cCB0aGUgY29sb3JzIGZyb20gdGhlXG4gICAgICogdGV4dHVyZS5cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgc2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XFxuXFxuICAgICAgdm9pZCBtYWluKCkge1xcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xcbiAgICAgIH1cXG4gICAgJztcbiAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnbWF4VGV4dHVyZVNpemUnLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX21heFRleHR1cmVTaXplO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAnaXNTdXBwb3J0ZWQnLFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgdGhpcyB0eXBlIG9mIHJlbmRlcmVyIGlzIHN1cHBvcnRlZCBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudFxuICAgICAqIEBhYnN0cmFjdFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpc1N1cHBvcnRlZCgpIHtcbiAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgIHZhciBnbCA9IGNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcpIHx8IGNhbnZhcy5nZXRDb250ZXh0KCdleHBlcmltZW50YWwtd2ViZ2wnKTtcbiAgICAgIHJldHVybiAhIWdsO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBXZWJHTFJlbmRlcmVyO1xufSkoX3JlbmRlcmVyMlsnZGVmYXVsdCddKTtcblxuV2ViR0xSZW5kZXJlci5jb250ZXh0SWQgPSAwO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBXZWJHTFJlbmRlcmVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3JlbmRlcmVycy93ZWJnbC1yZW5kZXJlci5qc1xuICoqIG1vZHVsZSBpZCA9IDU1XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKlxuICogRXh0cmFjdGVkIGZyb20gTWluaWZ5SnBlZyAoQ29weXJpZ2h0IChjKSAyMDE0IEhpcm9ha2kgTWF0b2JhLCBNSVQgTGljZW5zZSk6XG4gKiBodHRwczovL2dpdGh1Yi5jb20vaE1hdG9iYS9NaW5pZnlKcGVnXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIF9iYXNlNjQgPSByZXF1aXJlKCcuL2Jhc2U2NCcpO1xuXG52YXIgX2Jhc2U2NDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9iYXNlNjQpO1xuXG52YXIgREFUQV9KUEVHX1BSRUZJWCA9ICdkYXRhOmltYWdlL2pwZWc7YmFzZTY0LCc7XG5cbnZhciBFeGlmUmVzdG9yZXIgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBFeGlmUmVzdG9yZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEV4aWZSZXN0b3Jlcik7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoRXhpZlJlc3RvcmVyLCBudWxsLCBbe1xuICAgIGtleTogJ3Jlc3RvcmUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiByZXN0b3JlKG9yaWdpbmFsRGF0YSwgbmV3RGF0YSkge1xuICAgICAgLy8gT25seSBmb3IganBlZ1xuICAgICAgaWYgKCFvcmlnaW5hbERhdGEubWF0Y2goREFUQV9KUEVHX1BSRUZJWCkpIHtcbiAgICAgICAgcmV0dXJuIG5ld0RhdGE7XG4gICAgICB9XG5cbiAgICAgIHZhciByYXdJbWFnZSA9IF9iYXNlNjQyWydkZWZhdWx0J10uZGVjb2RlKG9yaWdpbmFsRGF0YS5yZXBsYWNlKERBVEFfSlBFR19QUkVGSVgsICcnKSk7XG4gICAgICB2YXIgc2VnbWVudHMgPSB0aGlzLl9zbGljZUludG9TZWdtZW50cyhyYXdJbWFnZSk7XG5cbiAgICAgIHZhciBpbWFnZSA9IHRoaXMuX2V4aWZNYW5pcHVsYXRpb24obmV3RGF0YSwgc2VnbWVudHMpO1xuXG4gICAgICByZXR1cm4gREFUQV9KUEVHX1BSRUZJWCArIF9iYXNlNjQyWydkZWZhdWx0J10uZW5jb2RlKGltYWdlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZXhpZk1hbmlwdWxhdGlvbicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9leGlmTWFuaXB1bGF0aW9uKGRhdGEsIHNlZ21lbnRzKSB7XG4gICAgICB2YXIgZXhpZkFycmF5ID0gdGhpcy5fZ2V0RXhpZkFycmF5KHNlZ21lbnRzKTtcbiAgICAgIHZhciBuZXdJbWFnZUFycmF5ID0gdGhpcy5faW5zZXJ0RXhpZihkYXRhLCBleGlmQXJyYXkpO1xuICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KG5ld0ltYWdlQXJyYXkpO1xuICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0RXhpZkFycmF5JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldEV4aWZBcnJheShzZWdtZW50cykge1xuICAgICAgdmFyIHNlZyA9IHVuZGVmaW5lZDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc2VnID0gc2VnbWVudHNbaV07XG4gICAgICAgIGlmIChzZWdbMF0gPT09IDI1NSAmJiBzZWdbMV0gPT09IDIyNSkge1xuICAgICAgICAgIHJldHVybiBzZWc7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW5zZXJ0RXhpZicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbnNlcnRFeGlmKGRhdGEsIGV4aWZBcnJheSkge1xuICAgICAgdmFyIGltYWdlRGF0YSA9IGRhdGEucmVwbGFjZShEQVRBX0pQRUdfUFJFRklYLCAnJyk7XG4gICAgICB2YXIgYnVmID0gX2Jhc2U2NDJbJ2RlZmF1bHQnXS5kZWNvZGUoaW1hZ2VEYXRhKTtcbiAgICAgIHZhciBzZXBhcmF0ZVBvaW50ID0gYnVmLmluZGV4T2YoMjU1LCAzKTtcbiAgICAgIHZhciBtYWUgPSBidWYuc2xpY2UoMCwgc2VwYXJhdGVQb2ludCk7XG4gICAgICB2YXIgYXRvID0gYnVmLnNsaWNlKHNlcGFyYXRlUG9pbnQpO1xuICAgICAgdmFyIGFycmF5ID0gbWFlO1xuXG4gICAgICBhcnJheSA9IGFycmF5LmNvbmNhdChleGlmQXJyYXkpO1xuICAgICAgYXJyYXkgPSBhcnJheS5jb25jYXQoYXRvKTtcbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2xpY2VJbnRvU2VnbWVudHMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2xpY2VJbnRvU2VnbWVudHMoZGF0YSkge1xuICAgICAgdmFyIGhlYWQgPSAwO1xuICAgICAgdmFyIHNlZ21lbnRzID0gW107XG5cbiAgICAgIHdoaWxlICgxKSB7XG4gICAgICAgIGlmIChkYXRhW2hlYWRdID09PSAyNTUgJiYgZGF0YVtoZWFkICsgMV0gPT09IDIxOCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGFbaGVhZF0gPT09IDI1NSAmJiBkYXRhW2hlYWQgKyAxXSA9PT0gMjE2KSB7XG4gICAgICAgICAgaGVhZCArPSAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBfbGVuZ3RoID0gZGF0YVtoZWFkICsgMl0gKiAyNTYgKyBkYXRhW2hlYWQgKyAzXTtcbiAgICAgICAgICB2YXIgZW5kUG9pbnQgPSBoZWFkICsgX2xlbmd0aCArIDI7XG4gICAgICAgICAgdmFyIHNlZyA9IGRhdGEuc2xpY2UoaGVhZCwgZW5kUG9pbnQpO1xuICAgICAgICAgIHNlZ21lbnRzLnB1c2goc2VnKTtcbiAgICAgICAgICBoZWFkID0gZW5kUG9pbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGVhZCA+IGRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNlZ21lbnRzO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBFeGlmUmVzdG9yZXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBFeGlmUmVzdG9yZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL2V4aWYtcmVzdG9yZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA1NlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG52YXIgcm9vdCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiBudWxsO1xudmFyIHAgPSByb290LlByb21pc2U7XG5cbmlmICghcCkge1xuICBwID0gcmVxdWlyZSgnLi9uYXRpdmUtcHJvbWlzZS1vbmx5Jyk7XG59XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IHA7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdmVuZG9yL3Byb21pc2UuanNcbiAqKiBtb2R1bGUgaWQgPSA1N1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbi8qKlxuICogSGVscGVyIGZ1bmN0aW9uIHRvIGNvcnJlY3RseSBzZXQgdXAgdGhlIHByb3RvdHlwZSBjaGFpblxuICogQmFzZWQgb24gdGhlIGJhY2tib25lLmpzIGV4dGVuZCBmdW5jdGlvbjpcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvYmFja2JvbmUvYmxvYi9tYXN0ZXIvYmFja2JvbmUuanNcbiAqIEBwYXJhbSAge09iamVjdH0gcHJvdG90eXBlUHJvcGVydGllc1xuICogQHBhcmFtICB7T2JqZWN0fSBjbGFzc1Byb3BlcnRpZXNcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm90b3R5cGVQcm9wZXJ0aWVzLCBjbGFzc1Byb3BlcnRpZXMpIHtcbiAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUqL1xuICB2YXIgcGFyZW50ID0gdGhpcztcbiAgdmFyIGNoaWxkO1xuXG4gIC8vIFRoZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiBmb3IgdGhlIG5ldyBzdWJjbGFzcyBpcyBlaXRoZXIgZGVmaW5lZCBieSB5b3VcbiAgLy8gKHRoZSAnY29uc3RydWN0b3InIHByb3BlcnR5IGluIHlvdXIgYGV4dGVuZGAgZGVmaW5pdGlvbiksIG9yIGRlZmF1bHRlZFxuICAvLyBieSB1cyB0byBzaW1wbHkgY2FsbCB0aGUgcGFyZW50J3MgY29uc3RydWN0b3IuXG4gIGlmIChwcm90b3R5cGVQcm9wZXJ0aWVzICYmIHByb3RvdHlwZVByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkoJ2NvbnN0cnVjdG9yJykpIHtcbiAgICBjaGlsZCA9IHByb3RvdHlwZVByb3BlcnRpZXMuY29uc3RydWN0b3I7XG4gIH0gZWxzZSB7XG4gICAgY2hpbGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcGFyZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxuXG4gIC8vIEFkZCBzdGF0aWMgcHJvcGVydGllcyB0byB0aGUgY29uc3RydWN0b3IgZnVuY3Rpb24sIGlmIHN1cHBsaWVkLlxuICB2YXIga2V5O1xuICBmb3IgKGtleSBpbiBwYXJlbnQpIHtcbiAgICBjaGlsZFtrZXldID0gcGFyZW50W2tleV07XG4gIH1cbiAgaWYgKHR5cGVvZiBjbGFzc1Byb3BlcnRpZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZm9yIChrZXkgaW4gY2xhc3NQcm9wZXJ0aWVzKSB7XG4gICAgICBjaGlsZFtrZXldID0gY2xhc3NQcm9wZXJ0aWVzW2tleV07XG4gICAgfVxuICB9XG5cbiAgLy8gU2V0IHRoZSBwcm90b3R5cGUgY2hhaW4gdG8gaW5oZXJpdCBmcm9tIGBwYXJlbnRgLCB3aXRob3V0IGNhbGxpbmdcbiAgLy8gYHBhcmVudGAncyBjb25zdHJ1Y3RvciBmdW5jdGlvbi5cbiAgdmFyIFN1cnJvZ2F0ZSA9IGZ1bmN0aW9uIFN1cnJvZ2F0ZSgpIHtcbiAgICB0aGlzLmNvbnN0cnVjdG9yID0gY2hpbGQ7XG4gIH07XG4gIFN1cnJvZ2F0ZS5wcm90b3R5cGUgPSBwYXJlbnQucHJvdG90eXBlO1xuICBjaGlsZC5wcm90b3R5cGUgPSBuZXcgU3Vycm9nYXRlKCk7XG5cbiAgLy8gQWRkIHByb3RvdHlwZSBwcm9wZXJ0aWVzIChpbnN0YW5jZSBwcm9wZXJ0aWVzKSB0byB0aGUgc3ViY2xhc3MsXG4gIC8vIGlmIHN1cHBsaWVkLlxuICBpZiAocHJvdG90eXBlUHJvcGVydGllcykge1xuICAgIGZvciAoa2V5IGluIHByb3RvdHlwZVByb3BlcnRpZXMpIHtcbiAgICAgIGNoaWxkLnByb3RvdHlwZVtrZXldID0gcHJvdG90eXBlUHJvcGVydGllc1trZXldO1xuICAgIH1cbiAgfVxuXG4gIC8vIFNldCBhIGNvbnZlbmllbmNlIHByb3BlcnR5IGluIGNhc2UgdGhlIHBhcmVudCdzIHByb3RvdHlwZSBpcyBuZWVkZWRcbiAgLy8gbGF0ZXIuXG4gIGNoaWxkLl9fc3VwZXJfXyA9IHBhcmVudC5wcm90b3R5cGU7XG5cbiAgcmV0dXJuIGNoaWxkO1xufTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL2V4dGVuZC5qc1xuICoqIG1vZHVsZSBpZCA9IDU4XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuLyoqXG4gKiBBIGhlbHBlciBjbGFzcyB0aGF0IGNhbiBjb2xsZWN0IHtAbGluayBQcmltaXRpdmV9IGluc3RhbmNlcyBhbmQgcmVuZGVyXG4gKiB0aGUgc3RhY2tcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmVzU3RhY2tcbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFByaW1pdGl2ZXNTdGFjayA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIFByaW1pdGl2ZXNTdGFjaygpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHJpbWl0aXZlc1N0YWNrKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBzdGFjayBvZiB7QGxpbmsgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZX0gaW5zdGFuY2VzXG4gICAgICogQHR5cGUge0FycmF5fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fc3RhY2sgPSBbXTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhQcmltaXRpdmVzU3RhY2ssIFt7XG4gICAga2V5OiBcImFkZFwiLFxuXG4gICAgLyoqXG4gICAgICogQWRkcyB0aGUgZ2l2ZW4gcHJpbWl0aXZlIHRvIHRoZSBzdGFja1xuICAgICAqIEBwYXJhbSB7SW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZX0gcHJpbWl0aXZlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZChwcmltaXRpdmUpIHtcbiAgICAgIHRoaXMuX3N0YWNrLnB1c2gocHJpbWl0aXZlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6IFwicmVuZGVyXCIsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBzdGFjayBvZiBwcmltaXRpdmVzIG9uIHRoZSByZW5kZXJlclxuICAgICAqIEBwYXJhbSAge1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fc3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHByaW1pdGl2ZSA9IHRoaXMuX3N0YWNrW2ldO1xuICAgICAgICBwcmltaXRpdmUucmVuZGVyKHJlbmRlcmVyKTtcbiAgICAgIH1cbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gUHJpbWl0aXZlc1N0YWNrO1xufSkoKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBQcmltaXRpdmVzU3RhY2s7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbXCJkZWZhdWx0XCJdO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy1zdGFjay5qc1xuICoqIG1vZHVsZSBpZCA9IDU5XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gsIF94MiwgX3gzKSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94LCBwcm9wZXJ0eSA9IF94MiwgcmVjZWl2ZXIgPSBfeDM7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94ID0gcGFyZW50OyBfeDIgPSBwcm9wZXJ0eTsgX3gzID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX3ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlJyk7XG5cbnZhciBfcHJpbWl0aXZlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ByaW1pdGl2ZSk7XG5cbi8qKlxuICogU2F0dXJhdGlvbiBwcmltaXRpdmVcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmVzLlNhdHVyYXRpb25cbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlfVxuICovXG5cbnZhciBTYXR1cmF0aW9uID0gKGZ1bmN0aW9uIChfUHJpbWl0aXZlKSB7XG4gIGZ1bmN0aW9uIFNhdHVyYXRpb24oKSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFNhdHVyYXRpb24pO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoU2F0dXJhdGlvbi5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIHRoaXMuX29wdGlvbnMgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZGVmYXVsdHModGhpcy5fb3B0aW9ucywge1xuICAgICAgc2F0dXJhdGlvbjogMFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciBmb3IgdGhpcyBwcmltaXRpdmVcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHVuaWZvcm0gZmxvYXQgdV9zYXR1cmF0aW9uO1xcblxcbiAgICAgIGNvbnN0IHZlYzMgbHVtaW5hbmNlV2VpZ2h0aW5nID0gdmVjMygwLjIxMjUsIDAuNzE1NCwgMC4wNzIxKTtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IHRleENvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xcbiAgICAgICAgZmxvYXQgbHVtaW5hbmNlID0gZG90KHRleENvbG9yLnJnYiwgbHVtaW5hbmNlV2VpZ2h0aW5nKTtcXG5cXG4gICAgICAgIHZlYzMgZ3JleVNjYWxlQ29sb3IgPSB2ZWMzKGx1bWluYW5jZSk7XFxuXFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KG1peChncmV5U2NhbGVDb2xvciwgdGV4Q29sb3IucmdiLCB1X3NhdHVyYXRpb24pICogdGV4Q29sb3IuYSwgdGV4Q29sb3IuYSk7XFxuICAgICAgfVxcbiAgICAnO1xuICB9XG5cbiAgX2luaGVyaXRzKFNhdHVyYXRpb24sIF9QcmltaXRpdmUpO1xuXG4gIF9jcmVhdGVDbGFzcyhTYXR1cmF0aW9uLCBbe1xuICAgIGtleTogJ3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoV2ViR0wpXG4gICAgICogQHBhcmFtICB7V2ViR0xSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJXZWJHTChyZW5kZXJlcikge1xuICAgICAgaWYgKCF0aGlzLl9nbHNsUHJvZ3JhbXNbcmVuZGVyZXIuaWRdKSB7XG4gICAgICAgIHRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0gPSByZW5kZXJlci5zZXR1cEdMU0xQcm9ncmFtKG51bGwsIHRoaXMuX2ZyYWdtZW50U2hhZGVyKTtcbiAgICAgIH1cblxuICAgICAgcmVuZGVyZXIucnVuUHJvZ3JhbSh0aGlzLl9nbHNsUHJvZ3JhbXNbcmVuZGVyZXIuaWRdLCB7XG4gICAgICAgIHVuaWZvcm1zOiB7XG4gICAgICAgICAgdV9zYXR1cmF0aW9uOiB7IHR5cGU6ICdmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuc2F0dXJhdGlvbiB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwcmltaXRpdmUgKENhbnZhcylcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBpbWFnZURhdGEgPSByZW5kZXJlci5nZXRDb250ZXh0KCkuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgc2F0dXJhdGlvbiA9IHRoaXMuX29wdGlvbnMuc2F0dXJhdGlvbjtcblxuICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBjYW52YXMud2lkdGg7IHgrKykge1xuICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGNhbnZhcy5oZWlnaHQ7IHkrKykge1xuICAgICAgICAgIHZhciBpbmRleCA9IChjYW52YXMud2lkdGggKiB5ICsgeCkgKiA0O1xuXG4gICAgICAgICAgdmFyIGx1bWluYW5jZSA9IGltYWdlRGF0YS5kYXRhW2luZGV4XSAqIDAuMjEyNSArIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gKiAwLjcxNTQgKyBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdICogMC4wNzIxO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4XSA9IGx1bWluYW5jZSAqICgxIC0gc2F0dXJhdGlvbikgKyBpbWFnZURhdGEuZGF0YVtpbmRleF0gKiBzYXR1cmF0aW9uO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gPSBsdW1pbmFuY2UgKiAoMSAtIHNhdHVyYXRpb24pICsgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSAqIHNhdHVyYXRpb247XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSA9IGx1bWluYW5jZSAqICgxIC0gc2F0dXJhdGlvbikgKyBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdICogc2F0dXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5nZXRDb250ZXh0KCkucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFNhdHVyYXRpb247XG59KShfcHJpbWl0aXZlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gU2F0dXJhdGlvbjtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9zYXR1cmF0aW9uLmpzXG4gKiogbW9kdWxlIGlkID0gNjBcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcHJpbWl0aXZlID0gcmVxdWlyZSgnLi9wcmltaXRpdmUnKTtcblxudmFyIF9wcmltaXRpdmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcHJpbWl0aXZlKTtcblxuLyoqXG4gKiBTdG9yZXMgYSAyNTYgYnl0ZSBsb25nIGxvb2t1cCB0YWJsZSBpbiBhIDJkIHRleHR1cmUgd2hpY2ggd2lsbCBiZVxuICogdXNlZCB0byBsb29rIHVwIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIGZvciBlYWNoIGNoYW5uZWwuXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlcy5Mb29rdXBUYWJsZVxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmV9XG4gKi9cblxudmFyIExvb2t1cFRhYmxlID0gKGZ1bmN0aW9uIChfUHJpbWl0aXZlKSB7XG4gIGZ1bmN0aW9uIExvb2t1cFRhYmxlKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBMb29rdXBUYWJsZSk7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihMb29rdXBUYWJsZS5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIHRoaXMuX3RleHR1cmVJbmRleCA9IDM7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIGZvciB0aGlzIHByaW1pdGl2ZVxuICAgICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV9sb29rdXBUYWJsZTtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IHRleENvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xcbiAgICAgICAgZmxvYXQgciA9IHRleHR1cmUyRCh1X2xvb2t1cFRhYmxlLCB2ZWMyKHRleENvbG9yLnIsIDAuMCkpLnI7XFxuICAgICAgICBmbG9hdCBnID0gdGV4dHVyZTJEKHVfbG9va3VwVGFibGUsIHZlYzIodGV4Q29sb3IuZywgMC4wKSkuZztcXG4gICAgICAgIGZsb2F0IGIgPSB0ZXh0dXJlMkQodV9sb29rdXBUYWJsZSwgdmVjMih0ZXhDb2xvci5iLCAwLjApKS5iO1xcblxcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCh2ZWMzKHIsIGcsIGIpICogdGV4Q29sb3IuYSwgdGV4Q29sb3IuYSk7XFxuICAgICAgfVxcbiAgICAnO1xuICB9XG5cbiAgX2luaGVyaXRzKExvb2t1cFRhYmxlLCBfUHJpbWl0aXZlKTtcblxuICBfY3JlYXRlQ2xhc3MoTG9va3VwVGFibGUsIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICB0aGlzLl91cGRhdGVUZXh0dXJlKHJlbmRlcmVyKTtcblxuICAgICAgcmVuZGVyZXIucnVuU2hhZGVyKG51bGwsIHRoaXMuX2ZyYWdtZW50U2hhZGVyLCB7XG4gICAgICAgIHVuaWZvcm1zOiB7XG4gICAgICAgICAgdV9sb29rdXBUYWJsZTogeyB0eXBlOiAnaScsIHZhbHVlOiAzIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoQ2FudmFzKVxuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBpbWFnZURhdGEgPSByZW5kZXJlci5nZXRDb250ZXh0KCkuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgdGFibGUgPSB0aGlzLl9vcHRpb25zLmRhdGE7XG5cbiAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgY2FudmFzLndpZHRoOyB4KyspIHtcbiAgICAgICAgZm9yICh2YXIgeSA9IDA7IHkgPCBjYW52YXMuaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICB2YXIgaW5kZXggPSAoY2FudmFzLndpZHRoICogeSArIHgpICogNDtcblxuICAgICAgICAgIHZhciByID0gaW1hZ2VEYXRhLmRhdGFbaW5kZXhdO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4XSA9IHRhYmxlW3IgKiA0XTtcbiAgICAgICAgICB2YXIgZyA9IGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV07XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSA9IHRhYmxlWzEgKyBnICogNF07XG4gICAgICAgICAgdmFyIGIgPSBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gPSB0YWJsZVsyICsgYiAqIDRdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlbmRlcmVyLmdldENvbnRleHQoKS5wdXRJbWFnZURhdGEoaW1hZ2VEYXRhLCAwLCAwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdXBkYXRlVGV4dHVyZScsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBsb29rdXAgdGFibGUgdGV4dHVyZSAoV2ViR0wgb25seSlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVUZXh0dXJlKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgZ2wgPSByZW5kZXJlci5nZXRDb250ZXh0KCk7XG5cbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5kYXRhID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvb2t1cFRhYmxlOiBObyBkYXRhIHNwZWNpZmllZC4nKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGRhdGFUeXBlZEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5fb3B0aW9ucy5kYXRhKTtcblxuICAgICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCArIHRoaXMuX3RleHR1cmVJbmRleCk7XG4gICAgICBpZiAoIXRoaXMuX3RleHR1cmUpIHtcbiAgICAgICAgdGhpcy5fdGV4dHVyZSA9IGdsLmNyZWF0ZVRleHR1cmUoKTtcbiAgICAgIH1cbiAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMuX3RleHR1cmUpO1xuXG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgZ2wuTElORUFSKTtcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5MSU5FQVIpO1xuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX1dSQVBfUywgZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcblxuICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBnbC5SR0JBLCAyNTYsIDEsIDAsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIGRhdGFUeXBlZEFycmF5KTtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTApO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBMb29rdXBUYWJsZTtcbn0pKF9wcmltaXRpdmUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBMb29rdXBUYWJsZTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9sb29rdXAtdGFibGUuanNcbiAqKiBtb2R1bGUgaWQgPSA2MVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIF9sb29rdXBUYWJsZSA9IHJlcXVpcmUoJy4vbG9va3VwLXRhYmxlJyk7XG5cbnZhciBfbG9va3VwVGFibGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbG9va3VwVGFibGUpO1xuXG4vKipcbiAqIFRvbmUgY3VydmUgcHJpbWl0aXZlXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlcy5Ub25lQ3VydmVcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlcy5Mb29rdXBUYWJsZX1cbiAqL1xuXG52YXIgVG9uZUN1cnZlID0gKGZ1bmN0aW9uIChfTG9va3VwVGFibGUpIHtcbiAgZnVuY3Rpb24gVG9uZUN1cnZlKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUb25lQ3VydmUpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoVG9uZUN1cnZlLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgdGhpcy5fb3B0aW9ucyA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5kZWZhdWx0cyh0aGlzLl9vcHRpb25zLCB7XG4gICAgICByZ2JDb250cm9sUG9pbnRzOiB7XG4gICAgICAgIHJlZDogdGhpcy5fb3B0aW9ucy5jb250cm9sUG9pbnRzLFxuICAgICAgICBncmVlbjogdGhpcy5fb3B0aW9ucy5jb250cm9sUG9pbnRzLFxuICAgICAgICBibHVlOiB0aGlzLl9vcHRpb25zLmNvbnRyb2xQb2ludHNcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICh0eXBlb2YgdGhpcy5fb3B0aW9ucy5yZ2JDb250cm9sUG9pbnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5fdXBkYXRlTG9va3VwVGFibGUoKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoVG9uZUN1cnZlLCBfTG9va3VwVGFibGUpO1xuXG4gIF9jcmVhdGVDbGFzcyhUb25lQ3VydmUsIFt7XG4gICAga2V5OiAnX3VwZGF0ZUxvb2t1cFRhYmxlJyxcblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIGxvb2t1cCB0YWJsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVMb29rdXBUYWJsZSgpIHtcbiAgICAgIHZhciByID0gdGhpcy5fY2FsY3VsYXRlU3BsaW5lQ3VydmUodGhpcy5fb3B0aW9ucy5yZ2JDb250cm9sUG9pbnRzLnJlZCk7XG4gICAgICB2YXIgZyA9IHRoaXMuX2NhbGN1bGF0ZVNwbGluZUN1cnZlKHRoaXMuX29wdGlvbnMucmdiQ29udHJvbFBvaW50cy5ncmVlbik7XG4gICAgICB2YXIgYiA9IHRoaXMuX2NhbGN1bGF0ZVNwbGluZUN1cnZlKHRoaXMuX29wdGlvbnMucmdiQ29udHJvbFBvaW50cy5ibHVlKTtcblxuICAgICAgdGhpcy5fb3B0aW9ucy5kYXRhID0gdGhpcy5fYnVpbGRMb29rdXBUYWJsZShyLCBnLCBiKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYnVpbGRMb29rdXBUYWJsZScsXG5cbiAgICAvKipcbiAgICAgKiBCdWlsZHMgdGhlIGxvb2t1cCB0YWJsZVxuICAgICAqIEBwYXJhbSAge0FycmF5fSByXG4gICAgICogQHBhcmFtICB7QXJyYXl9IGdcbiAgICAgKiBAcGFyYW0gIHtBcnJheX0gYlxuICAgICAqIEByZXR1cm4ge0FycmF5fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9idWlsZExvb2t1cFRhYmxlKHIsIGcsIGIpIHtcbiAgICAgIHZhciBkYXRhID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyBpKyspIHtcbiAgICAgICAgZGF0YS5wdXNoKE1hdGgubWluKE1hdGgubWF4KGkgKyByW2ldLCAwKSwgMjU1KSk7XG4gICAgICAgIGRhdGEucHVzaChNYXRoLm1pbihNYXRoLm1heChpICsgZ1tpXSwgMCksIDI1NSkpO1xuICAgICAgICBkYXRhLnB1c2goTWF0aC5taW4oTWF0aC5tYXgoaSArIGJbaV0sIDApLCAyNTUpKTtcbiAgICAgICAgZGF0YS5wdXNoKDI1NSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19jYWxjdWxhdGVTcGxpbmVDdXJ2ZScsXG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBzcGxpbmUgY3VydmUgZGF0YSBmb3IgdGhlIGdpdmVuIHBvaW50c1xuICAgICAqIEBwYXJhbSAge0FycmF5LjxBcnJheS48TnVtYmVyPj59IHBvaW50c1xuICAgICAqIEByZXR1cm4ge0FycmF5LjxOdW1iZXI+fVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfY2FsY3VsYXRlU3BsaW5lQ3VydmUocG9pbnRzKSB7XG4gICAgICBwb2ludHMgPSBwb2ludHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYVswXSA+IGJbMF07XG4gICAgICB9KTtcblxuICAgICAgdmFyIHNwbGluZVBvaW50cyA9IHRoaXMuX2dldFNwbGluZUN1cnZlKHBvaW50cyk7XG4gICAgICB2YXIgZmlyc3RTcGxpbmVQb2ludCA9IHNwbGluZVBvaW50c1swXTtcbiAgICAgIHZhciBpO1xuXG4gICAgICBpZiAoZmlyc3RTcGxpbmVQb2ludFswXSA+IDApIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGZpcnN0U3BsaW5lUG9pbnRbMF07IGkrKykge1xuICAgICAgICAgIHNwbGluZVBvaW50cy51bnNoaWZ0KFswLCAwXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIHByZXBhcmVkUG9pbnRzID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgc3BsaW5lUG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBuZXdQb2ludCA9IHNwbGluZVBvaW50c1tpXTtcbiAgICAgICAgdmFyIG9yaWdQb2ludCA9IFtuZXdQb2ludFswXSwgbmV3UG9pbnRbMF1dO1xuXG4gICAgICAgIHZhciBkaXN0YW5jZSA9IE1hdGguc3FydChNYXRoLnBvdyhvcmlnUG9pbnRbMF0gLSBuZXdQb2ludFswXSwgMikgKyBNYXRoLnBvdyhvcmlnUG9pbnRbMV0gLSBuZXdQb2ludFsxXSwgMikpO1xuXG4gICAgICAgIGlmIChvcmlnUG9pbnRbMV0gPiBuZXdQb2ludFsxXSkge1xuICAgICAgICAgIGRpc3RhbmNlID0gLWRpc3RhbmNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJlcGFyZWRQb2ludHMucHVzaChkaXN0YW5jZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwcmVwYXJlZFBvaW50cztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0U3BsaW5lQ3VydmUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0U3BsaW5lQ3VydmUocG9pbnRzKSB7XG4gICAgICB2YXIgc2RBID0gdGhpcy5fc2Vjb25kRGVyaXZhdGl2ZShwb2ludHMpO1xuXG4gICAgICB2YXIgbiA9IHNkQS5sZW5ndGg7XG4gICAgICB2YXIgc2QgPSBbXTtcbiAgICAgIHZhciBpO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHNkW2ldID0gc2RBW2ldO1xuICAgICAgfVxuXG4gICAgICB2YXIgb3V0cHV0ID0gW107XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBuIC0gMTsgaSsrKSB7XG4gICAgICAgIHZhciBjdXIgPSBwb2ludHNbaV07XG4gICAgICAgIHZhciBuZXh0ID0gcG9pbnRzW2kgKyAxXTtcblxuICAgICAgICBmb3IgKHZhciB4ID0gY3VyWzBdOyB4IDwgbmV4dFswXTsgeCsrKSB7XG4gICAgICAgICAgdmFyIHQgPSAoeCAtIGN1clswXSkgLyAobmV4dFswXSAtIGN1clswXSk7XG5cbiAgICAgICAgICB2YXIgYSA9IDEgLSB0O1xuICAgICAgICAgIHZhciBiID0gdDtcbiAgICAgICAgICB2YXIgaCA9IG5leHRbMF0gLSBjdXJbMF07XG5cbiAgICAgICAgICB2YXIgeSA9IGEgKiBjdXJbMV0gKyBiICogbmV4dFsxXSArIGggKiBoIC8gNiAqICgoYSAqIGEgKiBhIC0gYSkgKiBzZFtpXSArIChiICogYiAqIGIgLSBiKSAqIHNkW2kgKyAxXSk7XG5cbiAgICAgICAgICBpZiAoeSA+IDI1NSkge1xuICAgICAgICAgICAgeSA9IDI1NTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHkgPCAwKSB7XG4gICAgICAgICAgICB5ID0gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBvdXRwdXQucHVzaChbeCwgeV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChvdXRwdXQubGVuZ3RoID09PSAyNTUpIHtcbiAgICAgICAgb3V0cHV0LnB1c2gocG9pbnRzW3BvaW50cy5sZW5ndGggLSAxXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3NlY29uZERlcml2YXRpdmUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2Vjb25kRGVyaXZhdGl2ZShwb2ludHMpIHtcbiAgICAgIHZhciBuID0gcG9pbnRzLmxlbmd0aDtcbiAgICAgIGlmIChuIDw9IDAgfHwgbiA9PT0gMSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgdmFyIG1hdHJpeCA9IFtdO1xuICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgdmFyIGksIGs7XG5cbiAgICAgIG1hdHJpeFswXSA9IFswLCAxLCAwXTtcblxuICAgICAgZm9yIChpID0gMTsgaSA8IG4gLSAxOyBpKyspIHtcbiAgICAgICAgdmFyIFAxID0gcG9pbnRzW2kgLSAxXTtcbiAgICAgICAgdmFyIFAyID0gcG9pbnRzW2ldO1xuICAgICAgICB2YXIgUDMgPSBwb2ludHNbaSArIDFdO1xuXG4gICAgICAgIG1hdHJpeFtpXSA9IG1hdHJpeFtpXSB8fCBbXTtcbiAgICAgICAgbWF0cml4W2ldWzBdID0gKFAyWzBdIC0gUDFbMF0pIC8gNjtcbiAgICAgICAgbWF0cml4W2ldWzFdID0gKFAzWzBdIC0gUDFbMF0pIC8gMztcbiAgICAgICAgbWF0cml4W2ldWzJdID0gKFAzWzBdIC0gUDJbMF0pIC8gNjtcbiAgICAgICAgcmVzdWx0W2ldID0gKFAzWzFdIC0gUDJbMV0pIC8gKFAzWzBdIC0gUDJbMF0pIC0gKFAyWzFdIC0gUDFbMV0pIC8gKFAyWzBdIC0gUDFbMF0pO1xuICAgICAgfVxuXG4gICAgICByZXN1bHRbMF0gPSAwO1xuICAgICAgcmVzdWx0W24gLSAxXSA9IDA7XG5cbiAgICAgIG1hdHJpeFtuIC0gMV0gPSBbMCwgMSwgMF07XG5cbiAgICAgIC8vIFBhc3MgMVxuICAgICAgZm9yIChpID0gMTsgaSA8IG47IGkrKykge1xuICAgICAgICBrID0gbWF0cml4WzFdWzBdIC8gbWF0cml4W2kgLSAxXVsxXTtcbiAgICAgICAgbWF0cml4W2ldWzFdIC09IGsgKiBtYXRyaXhbaSAtIDFdWzJdO1xuICAgICAgICBtYXRyaXhbaV1bMF0gPSAwO1xuICAgICAgICByZXN1bHRbaV0gLT0gayAqIHJlc3VsdFtpIC0gMV07XG4gICAgICB9XG5cbiAgICAgIC8vIFBhc3MgMlxuICAgICAgZm9yIChpID0gbiAtIDI7IGkgPiAwOyBpLS0pIHtcbiAgICAgICAgayA9IG1hdHJpeFtpXVsyXSAvIG1hdHJpeFtpICsgMV1bMV07XG4gICAgICAgIG1hdHJpeFtpXVsxXSAtPSBrICogbWF0cml4W2kgKyAxXVswXTtcbiAgICAgICAgbWF0cml4W2ldWzJdID0gMDtcbiAgICAgICAgcmVzdWx0W2ldIC09IGsgKiByZXN1bHRbaSArIDFdO1xuICAgICAgfVxuXG4gICAgICB2YXIgeTIgPSBbXTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgeTJbaV0gPSByZXN1bHRbaV0gLyBtYXRyaXhbaV1bMV07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB5MjtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gVG9uZUN1cnZlO1xufSkoX2xvb2t1cFRhYmxlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gVG9uZUN1cnZlO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL3RvbmUtY3VydmUuanNcbiAqKiBtb2R1bGUgaWQgPSA2MlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIF9wcmltaXRpdmUgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZScpO1xuXG52YXIgX3ByaW1pdGl2ZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9wcmltaXRpdmUpO1xuXG52YXIgX2xpYkNvbG9yID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL2NvbG9yJyk7XG5cbnZhciBfbGliQ29sb3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliQ29sb3IpO1xuXG4vKipcbiAqIFNvZnRDb2xvck92ZXJsYXkgcHJpbWl0aXZlXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlcy5Tb2Z0Q29sb3JPdmVybGF5XG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZX1cbiAqL1xuXG52YXIgU29mdENvbG9yT3ZlcmxheSA9IChmdW5jdGlvbiAoX1ByaW1pdGl2ZSkge1xuICBmdW5jdGlvbiBTb2Z0Q29sb3JPdmVybGF5KCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBTb2Z0Q29sb3JPdmVybGF5KTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFNvZnRDb2xvck92ZXJsYXkucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICB0aGlzLl9vcHRpb25zID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmRlZmF1bHRzKHRoaXMuX29wdGlvbnMsIHtcbiAgICAgIGNvbG9yOiBuZXcgX2xpYkNvbG9yMlsnZGVmYXVsdCddKDEsIDEsIDEpXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIGZvciB0aGlzIHByaW1pdGl2ZVxuICAgICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSB2ZWMzIHVfb3ZlcmxheTtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IHRleENvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xcbiAgICAgICAgdmVjNCBvdmVybGF5VmVjNCA9IHZlYzQodV9vdmVybGF5LCB0ZXhDb2xvci5hKTtcXG4gICAgICAgIGdsX0ZyYWdDb2xvciA9IG1heChvdmVybGF5VmVjNCAqIHRleENvbG9yLmEsIHRleENvbG9yKTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoU29mdENvbG9yT3ZlcmxheSwgX1ByaW1pdGl2ZSk7XG5cbiAgX2NyZWF0ZUNsYXNzKFNvZnRDb2xvck92ZXJsYXksIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICByZW5kZXJlci5ydW5TaGFkZXIobnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIsIHtcbiAgICAgICAgdW5pZm9ybXM6IHtcbiAgICAgICAgICB1X292ZXJsYXk6IHsgdHlwZTogJzNmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuY29sb3IudG9SR0JHTENvbG9yKCkgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChDYW52YXMpXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgdmFyIGltYWdlRGF0YSA9IHJlbmRlcmVyLmdldENvbnRleHQoKS5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgZm9yICh2YXIgeCA9IDA7IHggPCBjYW52YXMud2lkdGg7IHgrKykge1xuICAgICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGNhbnZhcy5oZWlnaHQ7IHkrKykge1xuICAgICAgICAgIHZhciBpbmRleCA9IChjYW52YXMud2lkdGggKiB5ICsgeCkgKiA0O1xuXG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXhdID0gTWF0aC5tYXgodGhpcy5fb3B0aW9ucy5jb2xvci5yLCBpbWFnZURhdGEuZGF0YVtpbmRleF0pO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gPSBNYXRoLm1heCh0aGlzLl9vcHRpb25zLmNvbG9yLmcsIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0pO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gPSBNYXRoLm1heCh0aGlzLl9vcHRpb25zLmNvbG9yLmIsIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlbmRlcmVyLmdldENvbnRleHQoKS5wdXRJbWFnZURhdGEoaW1hZ2VEYXRhLCAwLCAwKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gU29mdENvbG9yT3ZlcmxheTtcbn0pKF9wcmltaXRpdmUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTb2Z0Q29sb3JPdmVybGF5O1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL3NvZnQtY29sb3Itb3ZlcmxheS5qc1xuICoqIG1vZHVsZSBpZCA9IDYzXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gsIF94MiwgX3gzKSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94LCBwcm9wZXJ0eSA9IF94MiwgcmVjZWl2ZXIgPSBfeDM7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94ID0gcGFyZW50OyBfeDIgPSBwcm9wZXJ0eTsgX3gzID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX3ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlJyk7XG5cbnZhciBfcHJpbWl0aXZlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ByaW1pdGl2ZSk7XG5cbi8qKlxuICogRGVzYXR1cmF0aW9uIHByaW1pdGl2ZVxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZXMuRGVzYXR1cmF0aW9uXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZX1cbiAqL1xuXG52YXIgRGVzYXR1cmF0aW9uID0gKGZ1bmN0aW9uIChfUHJpbWl0aXZlKSB7XG4gIGZ1bmN0aW9uIERlc2F0dXJhdGlvbigpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRGVzYXR1cmF0aW9uKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKERlc2F0dXJhdGlvbi5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIHRoaXMuX29wdGlvbnMgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZGVmYXVsdHModGhpcy5fb3B0aW9ucywge1xuICAgICAgZGVzYXR1cmF0aW9uOiAxXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIGZvciB0aGlzIHByaW1pdGl2ZVxuICAgICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSBmbG9hdCB1X2Rlc2F0dXJhdGlvbjtcXG5cXG4gICAgICBjb25zdCB2ZWMzIGx1bWluYW5jZVdlaWdodGluZyA9IHZlYzMoMC4yMTI1LCAwLjcxNTQsIDAuMDcyMSk7XFxuXFxuICAgICAgdm9pZCBtYWluKCkge1xcbiAgICAgICAgdmVjNCB0ZXhDb2xvciA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleENvb3JkKTtcXG4gICAgICAgIHZlYzMgZ3JheVhmZXIgPSB2ZWMzKDAuMywgMC41OSwgMC4xMSk7XFxuICAgICAgICB2ZWMzIGdyYXkgPSB2ZWMzKGRvdChncmF5WGZlciwgdGV4Q29sb3IueHl6KSk7XFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KG1peCh0ZXhDb2xvci54eXosIGdyYXksIHVfZGVzYXR1cmF0aW9uKSAqIHRleENvbG9yLmEsIHRleENvbG9yLmEpO1xcbiAgICAgIH1cXG4gICAgJztcbiAgfVxuXG4gIF9pbmhlcml0cyhEZXNhdHVyYXRpb24sIF9QcmltaXRpdmUpO1xuXG4gIF9jcmVhdGVDbGFzcyhEZXNhdHVyYXRpb24sIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcihudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlciwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfZGVzYXR1cmF0aW9uOiB7IHR5cGU6ICdmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuZGVzYXR1cmF0aW9uIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoQ2FudmFzKVxuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBpbWFnZURhdGEgPSByZW5kZXJlci5nZXRDb250ZXh0KCkuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgZGVzYXR1cmF0aW9uID0gdGhpcy5fb3B0aW9ucy5kZXNhdHVyYXRpb247XG5cbiAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgY2FudmFzLndpZHRoOyB4KyspIHtcbiAgICAgICAgZm9yICh2YXIgeSA9IDA7IHkgPCBjYW52YXMuaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICB2YXIgaW5kZXggPSAoY2FudmFzLndpZHRoICogeSArIHgpICogNDtcblxuICAgICAgICAgIHZhciBsdW1pbmFuY2UgPSBpbWFnZURhdGEuZGF0YVtpbmRleF0gKiAwLjMgKyBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdICogMC41OSArIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gKiAwLjExO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4XSA9IGx1bWluYW5jZSAqICgxIC0gZGVzYXR1cmF0aW9uKSArIGltYWdlRGF0YS5kYXRhW2luZGV4XSAqIGRlc2F0dXJhdGlvbjtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdID0gbHVtaW5hbmNlICogKDEgLSBkZXNhdHVyYXRpb24pICsgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSAqIGRlc2F0dXJhdGlvbjtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gbHVtaW5hbmNlICogKDEgLSBkZXNhdHVyYXRpb24pICsgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSAqIGRlc2F0dXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5nZXRDb250ZXh0KCkucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIERlc2F0dXJhdGlvbjtcbn0pKF9wcmltaXRpdmUyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBEZXNhdHVyYXRpb247XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvZGVzYXR1cmF0aW9uLmpzXG4gKiogbW9kdWxlIGlkID0gNjRcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcHJpbWl0aXZlID0gcmVxdWlyZSgnLi9wcmltaXRpdmUnKTtcblxudmFyIF9wcmltaXRpdmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcHJpbWl0aXZlKTtcblxuLyoqXG4gKiBYNDAwIHByaW1pdGl2ZVxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZXMuWDQwMFxuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmV9XG4gKi9cblxudmFyIFg0MDAgPSAoZnVuY3Rpb24gKF9QcmltaXRpdmUpIHtcbiAgZnVuY3Rpb24gWDQwMCgpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgWDQwMCk7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihYNDAwLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciBmb3IgdGhpcyBwcmltaXRpdmVcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIHZlYzQgdGV4Q29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCk7XFxuICAgICAgICBmbG9hdCBncmF5ID0gdGV4Q29sb3IuciAqIDAuMyArIHRleENvbG9yLmcgKiAwLjMgKyB0ZXhDb2xvci5iICogMC4zO1xcbiAgICAgICAgZ3JheSAtPSAwLjI7XFxuICAgICAgICBncmF5ID0gY2xhbXAoZ3JheSwgMC4wLCAxLjApO1xcbiAgICAgICAgZ3JheSArPSAwLjE1O1xcbiAgICAgICAgZ3JheSAqPSAxLjQ7XFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KHZlYzMoZ3JheSkgKiB0ZXhDb2xvci5hLCB0ZXhDb2xvci5hKTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoWDQwMCwgX1ByaW1pdGl2ZSk7XG5cbiAgX2NyZWF0ZUNsYXNzKFg0MDAsIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICByZW5kZXJlci5ydW5TaGFkZXIobnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwcmltaXRpdmUgKENhbnZhcylcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgaW1hZ2VEYXRhID0gcmVuZGVyZXIuZ2V0Q29udGV4dCgpLmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGNhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgY2FudmFzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gKGNhbnZhcy53aWR0aCAqIHkgKyB4KSAqIDQ7XG5cbiAgICAgICAgICB2YXIgZ3JheSA9IGltYWdlRGF0YS5kYXRhW2luZGV4XSAvIDI1NSAqIDAuMyArIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gLyAyNTUgKiAwLjMgKyBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdIC8gMjU1ICogMC4zO1xuICAgICAgICAgIGdyYXkgLT0gMC4yO1xuICAgICAgICAgIGdyYXkgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBncmF5KSk7XG4gICAgICAgICAgZ3JheSArPSAwLjE1O1xuICAgICAgICAgIGdyYXkgKj0gMS40O1xuXG4gICAgICAgICAgZ3JheSAqPSAyNTU7XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXhdID0gZ3JheTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdID0gZ3JheTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gZ3JheTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5nZXRDb250ZXh0KCkucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFg0MDA7XG59KShfcHJpbWl0aXZlMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gWDQwMDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy94NDAwLmpzXG4gKiogbW9kdWxlIGlkID0gNjVcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcHJpbWl0aXZlID0gcmVxdWlyZSgnLi9wcmltaXRpdmUnKTtcblxudmFyIF9wcmltaXRpdmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcHJpbWl0aXZlKTtcblxuLyoqXG4gKiBHcmF5c2NhbGUgcHJpbWl0aXZlXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlcy5HcmF5c2NhbGVcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlfVxuICovXG5cbnZhciBHcmF5c2NhbGUgPSAoZnVuY3Rpb24gKF9QcmltaXRpdmUpIHtcbiAgZnVuY3Rpb24gR3JheXNjYWxlKCkge1xuICAgIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgIH1cblxuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBHcmF5c2NhbGUpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoR3JheXNjYWxlLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciBmb3IgdGhpcyBwcmltaXRpdmVcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHZlYzMgVyA9IHZlYzMoMC4yMTI1LCAwLjcxNTQsIDAuMDcyMSk7XFxuXFxuICAgICAgdm9pZCBtYWluKCkge1xcbiAgICAgICAgdmVjNCB0ZXhDb2xvciA9IHRleHR1cmUyRCh1X2ltYWdlLCB2X3RleENvb3JkKTtcXG4gICAgICAgIGZsb2F0IGx1bWluYW5jZSA9IGRvdCh0ZXhDb2xvci5yZ2IsIFcpO1xcbiAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCh2ZWMzKGx1bWluYW5jZSkgKiB0ZXhDb2xvci5hLCB0ZXhDb2xvci5hKTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoR3JheXNjYWxlLCBfUHJpbWl0aXZlKTtcblxuICBfY3JlYXRlQ2xhc3MoR3JheXNjYWxlLCBbe1xuICAgIGtleTogJ3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoV2ViR0wpXG4gICAgICogQHBhcmFtICB7V2ViR0xSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICByZW5kZXJlci5ydW5TaGFkZXIobnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlckNhbnZhcycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwcmltaXRpdmUgKENhbnZhcylcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgaW1hZ2VEYXRhID0gcmVuZGVyZXIuZ2V0Q29udGV4dCgpLmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGNhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgY2FudmFzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gKGNhbnZhcy53aWR0aCAqIHkgKyB4KSAqIDQ7XG5cbiAgICAgICAgICB2YXIgbHVtaW5hbmNlID0gaW1hZ2VEYXRhLmRhdGFbaW5kZXhdICogMC4yMTI1ICsgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSAqIDAuNzE1NCArIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gKiAwLjA3MjE7XG5cbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleF0gPSBsdW1pbmFuY2U7XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSA9IGx1bWluYW5jZTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gbHVtaW5hbmNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJlbmRlcmVyLmdldENvbnRleHQoKS5wdXRJbWFnZURhdGEoaW1hZ2VEYXRhLCAwLCAwKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gR3JheXNjYWxlO1xufSkoX3ByaW1pdGl2ZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEdyYXlzY2FsZTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9ncmF5c2NhbGUuanNcbiAqKiBtb2R1bGUgaWQgPSA2NlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIF9wcmltaXRpdmUgPSByZXF1aXJlKCcuL3ByaW1pdGl2ZScpO1xuXG52YXIgX3ByaW1pdGl2ZTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9wcmltaXRpdmUpO1xuXG4vKipcbiAqIENvbnRyYXN0IHByaW1pdGl2ZVxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZXMuQ29udHJhc3RcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlfVxuICovXG5cbnZhciBDb250cmFzdCA9IChmdW5jdGlvbiAoX1ByaW1pdGl2ZSkge1xuICBmdW5jdGlvbiBDb250cmFzdCgpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29udHJhc3QpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoQ29udHJhc3QucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICB0aGlzLl9vcHRpb25zID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmRlZmF1bHRzKHRoaXMuX29wdGlvbnMsIHtcbiAgICAgIGNvbnRyYXN0OiAxXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnJhZ21lbnQgc2hhZGVyIGZvciB0aGlzIHByaW1pdGl2ZVxuICAgICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2ZyYWdtZW50U2hhZGVyID0gJ1xcbiAgICAgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiAgICAgIHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xcbiAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7XFxuICAgICAgdW5pZm9ybSBmbG9hdCB1X2NvbnRyYXN0O1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIHZlYzQgdGV4Q29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCk7XFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KCgodGV4Q29sb3IucmdiIC0gdmVjMygwLjUpKSAqIHVfY29udHJhc3QgKyB2ZWMzKDAuNSkgKiB0ZXhDb2xvci5hKSwgdGV4Q29sb3IuYSk7XFxuICAgICAgfVxcbiAgICAnO1xuICB9XG5cbiAgX2luaGVyaXRzKENvbnRyYXN0LCBfUHJpbWl0aXZlKTtcblxuICBfY3JlYXRlQ2xhc3MoQ29udHJhc3QsIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcldlYkdMKHJlbmRlcmVyKSB7XG4gICAgICBpZiAoIXRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0pIHtcbiAgICAgICAgdGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSA9IHJlbmRlcmVyLnNldHVwR0xTTFByb2dyYW0obnVsbCwgdGhpcy5fZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5ydW5Qcm9ncmFtKHRoaXMuX2dsc2xQcm9ncmFtc1tyZW5kZXJlci5pZF0sIHtcbiAgICAgICAgdW5pZm9ybXM6IHtcbiAgICAgICAgICB1X2NvbnRyYXN0OiB7IHR5cGU6ICdmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuY29udHJhc3QgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChDYW52YXMpXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgdmFyIGltYWdlRGF0YSA9IHJlbmRlcmVyLmdldENvbnRleHQoKS5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBjb250cmFzdCA9IHRoaXMuX29wdGlvbnMuY29udHJhc3Q7XG5cbiAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgY2FudmFzLndpZHRoOyB4KyspIHtcbiAgICAgICAgZm9yICh2YXIgeSA9IDA7IHkgPCBjYW52YXMuaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICB2YXIgaW5kZXggPSAoY2FudmFzLndpZHRoICogeSArIHgpICogNDtcblxuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4XSA9IChpbWFnZURhdGEuZGF0YVtpbmRleF0gLSAxMjcpICogY29udHJhc3QgKyAxMjc7XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSA9IChpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdIC0gMTI3KSAqIGNvbnRyYXN0ICsgMTI3O1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gPSAoaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSAtIDEyNykgKiBjb250cmFzdCArIDEyNztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZW5kZXJlci5nZXRDb250ZXh0KCkucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENvbnRyYXN0O1xufSkoX3ByaW1pdGl2ZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENvbnRyYXN0O1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL29wZXJhdGlvbnMvZmlsdGVycy9wcmltaXRpdmVzL2NvbnRyYXN0LmpzXG4gKiogbW9kdWxlIGlkID0gNjdcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBfcHJpbWl0aXZlID0gcmVxdWlyZSgnLi9wcmltaXRpdmUnKTtcblxudmFyIF9wcmltaXRpdmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcHJpbWl0aXZlKTtcblxudmFyIF9saWJDb2xvciA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9jb2xvcicpO1xuXG52YXIgX2xpYkNvbG9yMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkNvbG9yKTtcblxuLyoqXG4gKiBHbG93IHByaW1pdGl2ZVxuICogQGNsYXNzXG4gKiBAYWxpYXMgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZXMuR2xvd1xuICogQGV4dGVuZHMge0ltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmV9XG4gKi9cblxudmFyIEdsb3cgPSAoZnVuY3Rpb24gKF9QcmltaXRpdmUpIHtcbiAgZnVuY3Rpb24gR2xvdygpIHtcbiAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgR2xvdyk7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihHbG93LnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmFwcGx5KHRoaXMsIGFyZ3MpO1xuXG4gICAgdGhpcy5fb3B0aW9ucyA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5kZWZhdWx0cyh0aGlzLl9vcHRpb25zLCB7XG4gICAgICBjb2xvcjogbmV3IF9saWJDb2xvcjJbJ2RlZmF1bHQnXSgxLCAxLCAxKVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciBmb3IgdGhpcyBwcmltaXRpdmVcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcblxcbiAgICAgIHVuaWZvcm0gdmVjMyB1X2NvbG9yO1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIHZlYzQgdGV4Q29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCk7XFxuXFxuICAgICAgICB2ZWMyIHRleHR1cmVDb29yZCA9IHZfdGV4Q29vcmQgLSB2ZWMyKDAuNSwgMC41KTtcXG4gICAgICAgIHRleHR1cmVDb29yZCAvPSAwLjc1O1xcblxcbiAgICAgICAgZmxvYXQgZCA9IDEuMCAtIGRvdCh0ZXh0dXJlQ29vcmQsIHRleHR1cmVDb29yZCk7XFxuICAgICAgICBkID0gY2xhbXAoZCwgMC4yLCAxLjApO1xcbiAgICAgICAgdmVjMyBuZXdDb2xvciA9IHRleENvbG9yLnJnYiAqIGQgKiB1X2NvbG9yLnJnYjtcXG4gICAgICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQodmVjMyhuZXdDb2xvcikgKiB0ZXhDb2xvci5hLCB0ZXhDb2xvci5hKTtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoR2xvdywgX1ByaW1pdGl2ZSk7XG5cbiAgX2NyZWF0ZUNsYXNzKEdsb3csIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcihudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlciwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfY29sb3I6IHsgdHlwZTogJzNmJywgdmFsdWU6IHRoaXMuX29wdGlvbnMuY29sb3IudG9SR0JHTENvbG9yKCkgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChDYW52YXMpXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICB2YXIgY2FudmFzID0gcmVuZGVyZXIuZ2V0Q2FudmFzKCk7XG4gICAgICB2YXIgaW1hZ2VEYXRhID0gcmVuZGVyZXIuZ2V0Q29udGV4dCgpLmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuICAgICAgdmFyIGNvbG9yID0gdGhpcy5fb3B0aW9ucy5jb2xvcjtcblxuICAgICAgdmFyIGQ7XG4gICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGNhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgY2FudmFzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gKGNhbnZhcy53aWR0aCAqIHkgKyB4KSAqIDQ7XG5cbiAgICAgICAgICB2YXIgeDAxID0geCAvIGNhbnZhcy53aWR0aDtcbiAgICAgICAgICB2YXIgeTAxID0geSAvIGNhbnZhcy5oZWlnaHQ7XG5cbiAgICAgICAgICB2YXIgbnggPSAoeDAxIC0gMC41KSAvIDAuNzU7XG4gICAgICAgICAgdmFyIG55ID0gKHkwMSAtIDAuNSkgLyAwLjc1O1xuXG4gICAgICAgICAgdmFyIHNjYWxhclggPSBueCAqIG54O1xuICAgICAgICAgIHZhciBzY2FsYXJZID0gbnkgKiBueTtcbiAgICAgICAgICBkID0gMSAtIChzY2FsYXJYICsgc2NhbGFyWSk7XG4gICAgICAgICAgZCA9IE1hdGgubWluKE1hdGgubWF4KGQsIDAuMSksIDEpO1xuXG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXhdID0gaW1hZ2VEYXRhLmRhdGFbaW5kZXhdICogKGQgKiBjb2xvci5yKTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdID0gaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSAqIChkICogY29sb3IuZyk7XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSA9IGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gKiAoZCAqIGNvbG9yLmIpO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgM10gPSAyNTU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVuZGVyZXIuZ2V0Q29udGV4dCgpLnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBHbG93O1xufSkoX3ByaW1pdGl2ZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEdsb3c7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvZ2xvdy5qc1xuICoqIG1vZHVsZSBpZCA9IDY4XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gsIF94MiwgX3gzKSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94LCBwcm9wZXJ0eSA9IF94MiwgcmVjZWl2ZXIgPSBfeDM7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94ID0gcGFyZW50OyBfeDIgPSBwcm9wZXJ0eTsgX3gzID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX3ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlJyk7XG5cbnZhciBfcHJpbWl0aXZlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ByaW1pdGl2ZSk7XG5cbi8qKlxuICogR29iYmxpbiBwcmltaXRpdmVcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmVzLkdvYmJsaW5cbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlfVxuICovXG5cbnZhciBHb2JibGluID0gKGZ1bmN0aW9uIChfUHJpbWl0aXZlKSB7XG4gIGZ1bmN0aW9uIEdvYmJsaW4oKSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEdvYmJsaW4pO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoR29iYmxpbi5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBmcmFnbWVudCBzaGFkZXIgZm9yIHRoaXMgcHJpbWl0aXZlXG4gICAgICogQHJldHVybiB7U3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fZnJhZ21lbnRTaGFkZXIgPSAnXFxuICAgICAgcHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuICAgICAgdmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XFxuICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcXG5cXG4gICAgICB2b2lkIG1haW4oKSB7XFxuICAgICAgICB2ZWM0IHRleENvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xcbiAgICAgICAgdGV4Q29sb3IuYiA9IHRleENvbG9yLmcgKiAwLjMzO1xcbiAgICAgICAgdGV4Q29sb3IuciA9IHRleENvbG9yLnIgKiAwLjY7XFxuICAgICAgICB0ZXhDb2xvci5iICs9IHRleENvbG9yLnIgKiAwLjMzO1xcbiAgICAgICAgdGV4Q29sb3IuZyA9IHRleENvbG9yLmcgKiAwLjc7XFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB0ZXhDb2xvcjtcXG4gICAgICB9XFxuICAgICc7XG4gIH1cblxuICBfaW5oZXJpdHMoR29iYmxpbiwgX1ByaW1pdGl2ZSk7XG5cbiAgX2NyZWF0ZUNsYXNzKEdvYmJsaW4sIFt7XG4gICAga2V5OiAncmVuZGVyV2ViR0wnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChXZWJHTClcbiAgICAgKiBAcGFyYW0gIHtXZWJHTFJlbmRlcmVyfSByZW5kZXJlclxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIHJlbmRlcmVyLnJ1blNoYWRlcihudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoQ2FudmFzKVxuICAgICAqIEBwYXJhbSAge0NhbnZhc1JlbmRlcmVyfSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJDYW52YXMocmVuZGVyZXIpIHtcbiAgICAgIHZhciBjYW52YXMgPSByZW5kZXJlci5nZXRDYW52YXMoKTtcbiAgICAgIHZhciBpbWFnZURhdGEgPSByZW5kZXJlci5nZXRDb250ZXh0KCkuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIGZvciAodmFyIHggPSAwOyB4IDwgY2FudmFzLndpZHRoOyB4KyspIHtcbiAgICAgICAgZm9yICh2YXIgeSA9IDA7IHkgPCBjYW52YXMuaGVpZ2h0OyB5KyspIHtcbiAgICAgICAgICB2YXIgaW5kZXggPSAoY2FudmFzLndpZHRoICogeSArIHgpICogNDtcblxuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gPSBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdICogMC4zMztcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleF0gPSBpbWFnZURhdGEuZGF0YVtpbmRleF0gKiAwLjY7XG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSArPSBpbWFnZURhdGEuZGF0YVtpbmRleF0gKiAwLjMzO1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gPSBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdICogMC43O1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgM10gPSAyNTU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVuZGVyZXIuZ2V0Q29udGV4dCgpLnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBHb2JibGluO1xufSkoX3ByaW1pdGl2ZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEdvYmJsaW47XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvZ29iYmxpbi5qc1xuICoqIG1vZHVsZSBpZCA9IDY5XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gsIF94MiwgX3gzKSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94LCBwcm9wZXJ0eSA9IF94MiwgcmVjZWl2ZXIgPSBfeDM7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94ID0gcGFyZW50OyBfeDIgPSBwcm9wZXJ0eTsgX3gzID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX3ByaW1pdGl2ZSA9IHJlcXVpcmUoJy4vcHJpbWl0aXZlJyk7XG5cbnZhciBfcHJpbWl0aXZlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3ByaW1pdGl2ZSk7XG5cbi8qKlxuICogQnJpZ2h0bmVzcyBwcmltaXRpdmVcbiAqIEBjbGFzc1xuICogQGFsaWFzIEltZ2x5S2l0LkZpbHRlci5QcmltaXRpdmVzLkJyaWdodG5lc3NcbiAqIEBleHRlbmRzIHtJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlfVxuICovXG5cbnZhciBCcmlnaHRuZXNzID0gKGZ1bmN0aW9uIChfUHJpbWl0aXZlKSB7XG4gIGZ1bmN0aW9uIEJyaWdodG5lc3MoKSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICAgIGFyZ3NbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gICAgfVxuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEJyaWdodG5lc3MpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoQnJpZ2h0bmVzcy5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5hcHBseSh0aGlzLCBhcmdzKTtcblxuICAgIHRoaXMuX29wdGlvbnMgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZGVmYXVsdHModGhpcy5fb3B0aW9ucywge1xuICAgICAgYnJpZ2h0bmVzczogMVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGZyYWdtZW50IHNoYWRlciBmb3IgdGhpcyBwcmltaXRpdmVcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9mcmFnbWVudFNoYWRlciA9ICdcXG4gICAgICBwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4gICAgICB2YXJ5aW5nIHZlYzIgdl90ZXhDb29yZDtcXG4gICAgICB1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO1xcbiAgICAgIHVuaWZvcm0gZmxvYXQgdV9icmlnaHRuZXNzO1xcblxcbiAgICAgIHZvaWQgbWFpbigpIHtcXG4gICAgICAgIHZlYzQgdGV4Q29sb3IgPSB0ZXh0dXJlMkQodV9pbWFnZSwgdl90ZXhDb29yZCk7XFxuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KCh0ZXhDb2xvci5yZ2IgKyB2ZWMzKHVfYnJpZ2h0bmVzcykgKiB0ZXhDb2xvci5hKSwgdGV4Q29sb3IuYSk7O1xcbiAgICAgIH1cXG4gICAgJztcbiAgfVxuXG4gIF9pbmhlcml0cyhCcmlnaHRuZXNzLCBfUHJpbWl0aXZlKTtcblxuICBfY3JlYXRlQ2xhc3MoQnJpZ2h0bmVzcywgW3tcbiAgICBrZXk6ICdyZW5kZXJXZWJHTCcsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwcmltaXRpdmUgKFdlYkdMKVxuICAgICAqIEBwYXJhbSAge1dlYkdMUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIGlmICghdGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSkge1xuICAgICAgICB0aGlzLl9nbHNsUHJvZ3JhbXNbcmVuZGVyZXIuaWRdID0gcmVuZGVyZXIuc2V0dXBHTFNMUHJvZ3JhbShudWxsLCB0aGlzLl9mcmFnbWVudFNoYWRlcik7XG4gICAgICB9XG5cbiAgICAgIHJlbmRlcmVyLnJ1blByb2dyYW0odGhpcy5fZ2xzbFByb2dyYW1zW3JlbmRlcmVyLmlkXSwge1xuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgIHVfYnJpZ2h0bmVzczogeyB0eXBlOiAnZicsIHZhbHVlOiB0aGlzLl9vcHRpb25zLmJyaWdodG5lc3MgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChDYW52YXMpXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlckNhbnZhcyhyZW5kZXJlcikge1xuICAgICAgdmFyIGNhbnZhcyA9IHJlbmRlcmVyLmdldENhbnZhcygpO1xuICAgICAgdmFyIGltYWdlRGF0YSA9IHJlbmRlcmVyLmdldENvbnRleHQoKS5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBicmlnaHRuZXNzID0gdGhpcy5fb3B0aW9ucy5icmlnaHRuZXNzO1xuXG4gICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGNhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgY2FudmFzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgICAgdmFyIGluZGV4ID0gKGNhbnZhcy53aWR0aCAqIHkgKyB4KSAqIDQ7XG5cbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleF0gPSBpbWFnZURhdGEuZGF0YVtpbmRleF0gKyBicmlnaHRuZXNzICogMjU1O1xuICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV0gPSBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdICsgYnJpZ2h0bmVzcyAqIDI1NTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAyXSArIGJyaWdodG5lc3MgKiAyNTU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVuZGVyZXIuZ2V0Q29udGV4dCgpLnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBCcmlnaHRuZXNzO1xufSkoX3ByaW1pdGl2ZTJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEJyaWdodG5lc3M7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL3ByaW1pdGl2ZXMvYnJpZ2h0bmVzcy5qc1xuICoqIG1vZHVsZSBpZCA9IDcwXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2ZpbHRlciA9IHJlcXVpcmUoJy4vZmlsdGVyJyk7XG5cbnZhciBfZmlsdGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2ZpbHRlcik7XG5cbi8qKlxuICogSWRlbnRpdHkgRmlsdGVyXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXJzLklkZW50aXR5RmlsdGVyXG4gKiBAZXh0ZW5kcyB7SW1nbHlLaXQuRmlsdGVyfVxuICovXG5cbnZhciBJZGVudGl0eUZpbHRlciA9IChmdW5jdGlvbiAoX0ZpbHRlcikge1xuICBmdW5jdGlvbiBJZGVudGl0eUZpbHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSWRlbnRpdHlGaWx0ZXIpO1xuXG4gICAgaWYgKF9GaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgX0ZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhJZGVudGl0eUZpbHRlciwgX0ZpbHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKElkZW50aXR5RmlsdGVyLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBmaWx0ZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7fVxuICB9LCB7XG4gICAga2V5OiAnbmFtZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSB0aGF0IGlzIGRpc3BsYXllZCBpbiB0aGUgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuICdPcmlnaW5hbCc7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpZGVudGlmaWVyJyxcblxuICAgIC8qKlxuICAgICAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uIENhbiBiZSB1c2VkIHRvIHNlbGVjdFxuICAgICAqIHRoZSBhY3RpdmUgZmlsdGVyLlxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ2lkZW50aXR5JztcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gSWRlbnRpdHlGaWx0ZXI7XG59KShfZmlsdGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gSWRlbnRpdHlGaWx0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuLy8gVGhpcyBpcyB0aGUgaWRlbnRpdHkgZmlsdGVyLCBpdCBkb2Vzbid0IGhhdmUgYW55IGVmZmVjdC5cblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vb3BlcmF0aW9ucy9maWx0ZXJzL2lkZW50aXR5LWZpbHRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDcxXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKipcbiAqIEV2ZW50RW1pdHRlciAoRVM2KSBmcm9tOlxuICogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vYmxvb2R5b3dsLzQxYjFkZTMzODhjNjI2Nzk2ZWNhXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbnZhciBERUZBVUxUX01BWF9MSVNURU5FUlMgPSAxMjtcblxuZnVuY3Rpb24gZXJyb3IobWVzc2FnZSkge1xuICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4gPiAxID8gX2xlbiAtIDEgOiAwKSwgX2tleSA9IDE7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgfVxuXG4gIGNvbnNvbGUuZXJyb3IuYXBwbHkoY29uc29sZSwgW21lc3NhZ2VdLmNvbmNhdChhcmdzKSk7XG4gIGNvbnNvbGUudHJhY2UoKTtcbn1cblxudmFyIEV2ZW50RW1pdHRlciA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRXZlbnRFbWl0dGVyKTtcblxuICAgIHRoaXMuX21heExpc3RlbmVycyA9IERFRkFVTFRfTUFYX0xJU1RFTkVSUztcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhFdmVudEVtaXR0ZXIsIFt7XG4gICAga2V5OiAnb24nLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBvbih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV0gfHwgKHRoaXMuX2V2ZW50c1t0eXBlXSA9IFtdKTtcbiAgICAgIGlmIChsaXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcikgIT09IC0xKSB7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuICAgICAgbGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpO1xuXG4gICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA+IHRoaXMuX21heExpc3RlbmVycykge1xuICAgICAgICBlcnJvcigncG9zc2libGUgbWVtb3J5IGxlYWssIGFkZGVkICVpICVzIGxpc3RlbmVycyxcXG4gICAgICAgIHVzZSBFdmVudEVtaXR0ZXIjc2V0TWF4TGlzdGVuZXJzKG51bWJlcikgaWYgeW91XFxuICAgICAgICB3YW50IHRvIGluY3JlYXNlIHRoZSBsaW1pdCAoJWkgbm93KScsIGxpc3RlbmVycy5sZW5ndGgsIHR5cGUsIHRoaXMuX21heExpc3RlbmVycyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdvbmNlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGV2ZW50c0luc3RhbmNlID0gdGhpcztcbiAgICAgIGZ1bmN0aW9uIG9uY2VDYWxsYmFjaygpIHtcbiAgICAgICAgZXZlbnRzSW5zdGFuY2Uub2ZmKHR5cGUsIG9uY2VDYWxsYmFjayk7XG4gICAgICAgIGxpc3RlbmVyLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5vbih0eXBlLCBvbmNlQ2FsbGJhY2spO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ29mZicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIG9mZih0eXBlKSB7XG4gICAgICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuMiA+IDEgPyBfbGVuMiAtIDEgOiAwKSwgX2tleTIgPSAxOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7XG4gICAgICAgIGFyZ3NbX2tleTIgLSAxXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgICB9XG5cbiAgICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSBudWxsO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgdmFyIGxpc3RlbmVyID0gYXJnc1swXTtcbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuICAgICAgfVxuXG4gICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgICAgaWYgKCFsaXN0ZW5lcnMgfHwgIWxpc3RlbmVycy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIHZhciBpbmRleE9mTGlzdGVuZXIgPSBsaXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcik7XG4gICAgICBpZiAoaW5kZXhPZkxpc3RlbmVyID09PSAtMSkge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgbGlzdGVuZXJzLnNwbGljZShpbmRleE9mTGlzdGVuZXIsIDEpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZW1pdCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICAgICAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBhcmdzID0gQXJyYXkoX2xlbjMgPiAxID8gX2xlbjMgLSAxIDogMCksIF9rZXkzID0gMTsgX2tleTMgPCBfbGVuMzsgX2tleTMrKykge1xuICAgICAgICBhcmdzW19rZXkzIC0gMV0gPSBhcmd1bWVudHNbX2tleTNdO1xuICAgICAgfVxuXG4gICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgICAgaWYgKCFsaXN0ZW5lcnMgfHwgIWxpc3RlbmVycy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMuZm9yRWFjaChmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NldE1heExpc3RlbmVycycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuZXdNYXhMaXN0ZW5lcnMpIHtcbiAgICAgIGlmIChwYXJzZUludChuZXdNYXhMaXN0ZW5lcnMsIDEwKSAhPT0gbmV3TWF4TGlzdGVuZXJzKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbmV3TWF4TGlzdGVuZXJzO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBFdmVudEVtaXR0ZXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBFdmVudEVtaXR0ZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vbGliL2V2ZW50LWVtaXR0ZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA3MlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiXCJ1c2Ugc3RyaWN0XCI7XG4vKiFcblxuU3RhY2tCbHVyIC0gYSBmYXN0IGFsbW9zdCBHYXVzc2lhbiBCbHVyIEZvciBDYW52YXNcblxuVmVyc2lvbjogIDAuNVxuQXV0aG9yOiAgIE1hcmlvIEtsaW5nZW1hbm5cbkNvbnRhY3Q6ICBtYXJpb0BxdWFzaW1vbmRvLmNvbVxuV2Vic2l0ZTogIGh0dHA6Ly93d3cucXVhc2ltb25kby5jb20vU3RhY2tCbHVyRm9yQ2FudmFzXG5Ud2l0dGVyOiAgQHF1YXNpbW9uZG9cblxuSW4gY2FzZSB5b3UgZmluZCB0aGlzIGNsYXNzIHVzZWZ1bCAtIGVzcGVjaWFsbHkgaW4gY29tbWVyY2lhbCBwcm9qZWN0cyAtXG5JIGFtIG5vdCB0b3RhbGx5IHVuaGFwcHkgZm9yIGEgc21hbGwgZG9uYXRpb24gdG8gbXkgUGF5UGFsIGFjY291bnRcbm1hcmlvQHF1YXNpbW9uZG8uZGVcblxuT3Igc3VwcG9ydCBtZSBvbiBmbGF0dHI6XG5odHRwczovL2ZsYXR0ci5jb20vdGhpbmcvNzI3OTEvU3RhY2tCbHVyLWEtZmFzdC1hbG1vc3QtR2F1c3NpYW4tQmx1ci1FZmZlY3QtZm9yLUNhbnZhc0phdmFzY3JpcHRcblxuQ29weXJpZ2h0IChjKSAyMDEwIE1hcmlvIEtsaW5nZW1hbm5cblxuUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbm9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG5maWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbnJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbmNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG5pbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbkVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbk5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG5IT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbldIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuKi9cblxudmFyIG11bF90YWJsZSA9IFs1MTIsIDUxMiwgNDU2LCA1MTIsIDMyOCwgNDU2LCAzMzUsIDUxMiwgNDA1LCAzMjgsIDI3MSwgNDU2LCAzODgsIDMzNSwgMjkyLCA1MTIsIDQ1NCwgNDA1LCAzNjQsIDMyOCwgMjk4LCAyNzEsIDQ5NiwgNDU2LCA0MjAsIDM4OCwgMzYwLCAzMzUsIDMxMiwgMjkyLCAyNzMsIDUxMiwgNDgyLCA0NTQsIDQyOCwgNDA1LCAzODMsIDM2NCwgMzQ1LCAzMjgsIDMxMiwgMjk4LCAyODQsIDI3MSwgMjU5LCA0OTYsIDQ3NSwgNDU2LCA0MzcsIDQyMCwgNDA0LCAzODgsIDM3NCwgMzYwLCAzNDcsIDMzNSwgMzIzLCAzMTIsIDMwMiwgMjkyLCAyODIsIDI3MywgMjY1LCA1MTIsIDQ5NywgNDgyLCA0NjgsIDQ1NCwgNDQxLCA0MjgsIDQxNywgNDA1LCAzOTQsIDM4MywgMzczLCAzNjQsIDM1NCwgMzQ1LCAzMzcsIDMyOCwgMzIwLCAzMTIsIDMwNSwgMjk4LCAyOTEsIDI4NCwgMjc4LCAyNzEsIDI2NSwgMjU5LCA1MDcsIDQ5NiwgNDg1LCA0NzUsIDQ2NSwgNDU2LCA0NDYsIDQzNywgNDI4LCA0MjAsIDQxMiwgNDA0LCAzOTYsIDM4OCwgMzgxLCAzNzQsIDM2NywgMzYwLCAzNTQsIDM0NywgMzQxLCAzMzUsIDMyOSwgMzIzLCAzMTgsIDMxMiwgMzA3LCAzMDIsIDI5NywgMjkyLCAyODcsIDI4MiwgMjc4LCAyNzMsIDI2OSwgMjY1LCAyNjEsIDUxMiwgNTA1LCA0OTcsIDQ4OSwgNDgyLCA0NzUsIDQ2OCwgNDYxLCA0NTQsIDQ0NywgNDQxLCA0MzUsIDQyOCwgNDIyLCA0MTcsIDQxMSwgNDA1LCAzOTksIDM5NCwgMzg5LCAzODMsIDM3OCwgMzczLCAzNjgsIDM2NCwgMzU5LCAzNTQsIDM1MCwgMzQ1LCAzNDEsIDMzNywgMzMyLCAzMjgsIDMyNCwgMzIwLCAzMTYsIDMxMiwgMzA5LCAzMDUsIDMwMSwgMjk4LCAyOTQsIDI5MSwgMjg3LCAyODQsIDI4MSwgMjc4LCAyNzQsIDI3MSwgMjY4LCAyNjUsIDI2MiwgMjU5LCAyNTcsIDUwNywgNTAxLCA0OTYsIDQ5MSwgNDg1LCA0ODAsIDQ3NSwgNDcwLCA0NjUsIDQ2MCwgNDU2LCA0NTEsIDQ0NiwgNDQyLCA0MzcsIDQzMywgNDI4LCA0MjQsIDQyMCwgNDE2LCA0MTIsIDQwOCwgNDA0LCA0MDAsIDM5NiwgMzkyLCAzODgsIDM4NSwgMzgxLCAzNzcsIDM3NCwgMzcwLCAzNjcsIDM2MywgMzYwLCAzNTcsIDM1NCwgMzUwLCAzNDcsIDM0NCwgMzQxLCAzMzgsIDMzNSwgMzMyLCAzMjksIDMyNiwgMzIzLCAzMjAsIDMxOCwgMzE1LCAzMTIsIDMxMCwgMzA3LCAzMDQsIDMwMiwgMjk5LCAyOTcsIDI5NCwgMjkyLCAyODksIDI4NywgMjg1LCAyODIsIDI4MCwgMjc4LCAyNzUsIDI3MywgMjcxLCAyNjksIDI2NywgMjY1LCAyNjMsIDI2MSwgMjU5XTtcblxudmFyIHNoZ190YWJsZSA9IFs5LCAxMSwgMTIsIDEzLCAxMywgMTQsIDE0LCAxNSwgMTUsIDE1LCAxNSwgMTYsIDE2LCAxNiwgMTYsIDE3LCAxNywgMTcsIDE3LCAxNywgMTcsIDE3LCAxOCwgMTgsIDE4LCAxOCwgMTgsIDE4LCAxOCwgMTgsIDE4LCAxOSwgMTksIDE5LCAxOSwgMTksIDE5LCAxOSwgMTksIDE5LCAxOSwgMTksIDE5LCAxOSwgMTksIDIwLCAyMCwgMjAsIDIwLCAyMCwgMjAsIDIwLCAyMCwgMjAsIDIwLCAyMCwgMjAsIDIwLCAyMCwgMjAsIDIwLCAyMCwgMjAsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIxLCAyMSwgMjEsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMiwgMjIsIDIyLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyMywgMjMsIDIzLCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjQsIDI0LCAyNCwgMjRdO1xuXG5mdW5jdGlvbiBzdGFja0JsdXJDYW52YXNSR0JBKGltYWdlRGF0YSwgdG9wX3gsIHRvcF95LCB3aWR0aCwgaGVpZ2h0LCByYWRpdXMpIHtcbiAgaWYgKGlzTmFOKHJhZGl1cykgfHwgcmFkaXVzIDwgMSkgcmV0dXJuO1xuICByYWRpdXMgfD0gMDtcblxuICB2YXIgcGl4ZWxzID0gaW1hZ2VEYXRhLmRhdGE7XG5cbiAgdmFyIHgsIHksIGksIHAsIHlwLCB5aSwgeXcsIHJfc3VtLCBnX3N1bSwgYl9zdW0sIGFfc3VtLCByX291dF9zdW0sIGdfb3V0X3N1bSwgYl9vdXRfc3VtLCBhX291dF9zdW0sIHJfaW5fc3VtLCBnX2luX3N1bSwgYl9pbl9zdW0sIGFfaW5fc3VtLCBwciwgcGcsIHBiLCBwYSwgcmJzO1xuXG4gIHZhciBkaXYgPSByYWRpdXMgKyByYWRpdXMgKyAxO1xuICB2YXIgd2lkdGhNaW51czEgPSB3aWR0aCAtIDE7XG4gIHZhciBoZWlnaHRNaW51czEgPSBoZWlnaHQgLSAxO1xuICB2YXIgcmFkaXVzUGx1czEgPSByYWRpdXMgKyAxO1xuICB2YXIgc3VtRmFjdG9yID0gcmFkaXVzUGx1czEgKiAocmFkaXVzUGx1czEgKyAxKSAvIDI7XG5cbiAgdmFyIHN0YWNrU3RhcnQgPSBuZXcgQmx1clN0YWNrKCk7XG4gIHZhciBzdGFja0VuZDtcbiAgdmFyIHN0YWNrID0gc3RhY2tTdGFydDtcbiAgZm9yIChpID0gMTsgaSA8IGRpdjsgaSsrKSB7XG4gICAgc3RhY2sgPSBzdGFjay5uZXh0ID0gbmV3IEJsdXJTdGFjaygpO1xuICAgIGlmIChpID09IHJhZGl1c1BsdXMxKSBzdGFja0VuZCA9IHN0YWNrO1xuICB9XG4gIHN0YWNrLm5leHQgPSBzdGFja1N0YXJ0O1xuICB2YXIgc3RhY2tJbiA9IG51bGw7XG4gIHZhciBzdGFja091dCA9IG51bGw7XG5cbiAgeXcgPSB5aSA9IDA7XG5cbiAgdmFyIG11bF9zdW0gPSBtdWxfdGFibGVbcmFkaXVzXTtcbiAgdmFyIHNoZ19zdW0gPSBzaGdfdGFibGVbcmFkaXVzXTtcblxuICBmb3IgKHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHtcbiAgICByX2luX3N1bSA9IGdfaW5fc3VtID0gYl9pbl9zdW0gPSBhX2luX3N1bSA9IHJfc3VtID0gZ19zdW0gPSBiX3N1bSA9IGFfc3VtID0gMDtcblxuICAgIHJfb3V0X3N1bSA9IHJhZGl1c1BsdXMxICogKHByID0gcGl4ZWxzW3lpXSk7XG4gICAgZ19vdXRfc3VtID0gcmFkaXVzUGx1czEgKiAocGcgPSBwaXhlbHNbeWkgKyAxXSk7XG4gICAgYl9vdXRfc3VtID0gcmFkaXVzUGx1czEgKiAocGIgPSBwaXhlbHNbeWkgKyAyXSk7XG4gICAgYV9vdXRfc3VtID0gcmFkaXVzUGx1czEgKiAocGEgPSBwaXhlbHNbeWkgKyAzXSk7XG5cbiAgICByX3N1bSArPSBzdW1GYWN0b3IgKiBwcjtcbiAgICBnX3N1bSArPSBzdW1GYWN0b3IgKiBwZztcbiAgICBiX3N1bSArPSBzdW1GYWN0b3IgKiBwYjtcbiAgICBhX3N1bSArPSBzdW1GYWN0b3IgKiBwYTtcblxuICAgIHN0YWNrID0gc3RhY2tTdGFydDtcblxuICAgIGZvciAoaSA9IDA7IGkgPCByYWRpdXNQbHVzMTsgaSsrKSB7XG4gICAgICBzdGFjay5yID0gcHI7XG4gICAgICBzdGFjay5nID0gcGc7XG4gICAgICBzdGFjay5iID0gcGI7XG4gICAgICBzdGFjay5hID0gcGE7XG4gICAgICBzdGFjayA9IHN0YWNrLm5leHQ7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMTsgaSA8IHJhZGl1c1BsdXMxOyBpKyspIHtcbiAgICAgIHAgPSB5aSArICgod2lkdGhNaW51czEgPCBpID8gd2lkdGhNaW51czEgOiBpKSA8PCAyKTtcbiAgICAgIHJfc3VtICs9IChzdGFjay5yID0gcHIgPSBwaXhlbHNbcF0pICogKHJicyA9IHJhZGl1c1BsdXMxIC0gaSk7XG4gICAgICBnX3N1bSArPSAoc3RhY2suZyA9IHBnID0gcGl4ZWxzW3AgKyAxXSkgKiByYnM7XG4gICAgICBiX3N1bSArPSAoc3RhY2suYiA9IHBiID0gcGl4ZWxzW3AgKyAyXSkgKiByYnM7XG4gICAgICBhX3N1bSArPSAoc3RhY2suYSA9IHBhID0gcGl4ZWxzW3AgKyAzXSkgKiByYnM7XG5cbiAgICAgIHJfaW5fc3VtICs9IHByO1xuICAgICAgZ19pbl9zdW0gKz0gcGc7XG4gICAgICBiX2luX3N1bSArPSBwYjtcbiAgICAgIGFfaW5fc3VtICs9IHBhO1xuXG4gICAgICBzdGFjayA9IHN0YWNrLm5leHQ7XG4gICAgfVxuXG4gICAgc3RhY2tJbiA9IHN0YWNrU3RhcnQ7XG4gICAgc3RhY2tPdXQgPSBzdGFja0VuZDtcbiAgICBmb3IgKHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xuICAgICAgcGl4ZWxzW3lpICsgM10gPSBwYSA9IGFfc3VtICogbXVsX3N1bSA+PiBzaGdfc3VtO1xuICAgICAgaWYgKHBhICE9PSAwKSB7XG4gICAgICAgIHBhID0gMjU1IC8gcGE7XG4gICAgICAgIHBpeGVsc1t5aV0gPSAocl9zdW0gKiBtdWxfc3VtID4+IHNoZ19zdW0pICogcGE7XG4gICAgICAgIHBpeGVsc1t5aSArIDFdID0gKGdfc3VtICogbXVsX3N1bSA+PiBzaGdfc3VtKSAqIHBhO1xuICAgICAgICBwaXhlbHNbeWkgKyAyXSA9IChiX3N1bSAqIG11bF9zdW0gPj4gc2hnX3N1bSkgKiBwYTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBpeGVsc1t5aV0gPSBwaXhlbHNbeWkgKyAxXSA9IHBpeGVsc1t5aSArIDJdID0gMDtcbiAgICAgIH1cblxuICAgICAgcl9zdW0gLT0gcl9vdXRfc3VtO1xuICAgICAgZ19zdW0gLT0gZ19vdXRfc3VtO1xuICAgICAgYl9zdW0gLT0gYl9vdXRfc3VtO1xuICAgICAgYV9zdW0gLT0gYV9vdXRfc3VtO1xuXG4gICAgICByX291dF9zdW0gLT0gc3RhY2tJbi5yO1xuICAgICAgZ19vdXRfc3VtIC09IHN0YWNrSW4uZztcbiAgICAgIGJfb3V0X3N1bSAtPSBzdGFja0luLmI7XG4gICAgICBhX291dF9zdW0gLT0gc3RhY2tJbi5hO1xuXG4gICAgICBwID0geXcgKyAoKHAgPSB4ICsgcmFkaXVzICsgMSkgPCB3aWR0aE1pbnVzMSA/IHAgOiB3aWR0aE1pbnVzMSkgPDwgMjtcblxuICAgICAgcl9pbl9zdW0gKz0gc3RhY2tJbi5yID0gcGl4ZWxzW3BdO1xuICAgICAgZ19pbl9zdW0gKz0gc3RhY2tJbi5nID0gcGl4ZWxzW3AgKyAxXTtcbiAgICAgIGJfaW5fc3VtICs9IHN0YWNrSW4uYiA9IHBpeGVsc1twICsgMl07XG4gICAgICBhX2luX3N1bSArPSBzdGFja0luLmEgPSBwaXhlbHNbcCArIDNdO1xuXG4gICAgICByX3N1bSArPSByX2luX3N1bTtcbiAgICAgIGdfc3VtICs9IGdfaW5fc3VtO1xuICAgICAgYl9zdW0gKz0gYl9pbl9zdW07XG4gICAgICBhX3N1bSArPSBhX2luX3N1bTtcblxuICAgICAgc3RhY2tJbiA9IHN0YWNrSW4ubmV4dDtcblxuICAgICAgcl9vdXRfc3VtICs9IHByID0gc3RhY2tPdXQucjtcbiAgICAgIGdfb3V0X3N1bSArPSBwZyA9IHN0YWNrT3V0Lmc7XG4gICAgICBiX291dF9zdW0gKz0gcGIgPSBzdGFja091dC5iO1xuICAgICAgYV9vdXRfc3VtICs9IHBhID0gc3RhY2tPdXQuYTtcblxuICAgICAgcl9pbl9zdW0gLT0gcHI7XG4gICAgICBnX2luX3N1bSAtPSBwZztcbiAgICAgIGJfaW5fc3VtIC09IHBiO1xuICAgICAgYV9pbl9zdW0gLT0gcGE7XG5cbiAgICAgIHN0YWNrT3V0ID0gc3RhY2tPdXQubmV4dDtcblxuICAgICAgeWkgKz0gNDtcbiAgICB9XG4gICAgeXcgKz0gd2lkdGg7XG4gIH1cblxuICBmb3IgKHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xuICAgIGdfaW5fc3VtID0gYl9pbl9zdW0gPSBhX2luX3N1bSA9IHJfaW5fc3VtID0gZ19zdW0gPSBiX3N1bSA9IGFfc3VtID0gcl9zdW0gPSAwO1xuXG4gICAgeWkgPSB4IDw8IDI7XG4gICAgcl9vdXRfc3VtID0gcmFkaXVzUGx1czEgKiAocHIgPSBwaXhlbHNbeWldKTtcbiAgICBnX291dF9zdW0gPSByYWRpdXNQbHVzMSAqIChwZyA9IHBpeGVsc1t5aSArIDFdKTtcbiAgICBiX291dF9zdW0gPSByYWRpdXNQbHVzMSAqIChwYiA9IHBpeGVsc1t5aSArIDJdKTtcbiAgICBhX291dF9zdW0gPSByYWRpdXNQbHVzMSAqIChwYSA9IHBpeGVsc1t5aSArIDNdKTtcblxuICAgIHJfc3VtICs9IHN1bUZhY3RvciAqIHByO1xuICAgIGdfc3VtICs9IHN1bUZhY3RvciAqIHBnO1xuICAgIGJfc3VtICs9IHN1bUZhY3RvciAqIHBiO1xuICAgIGFfc3VtICs9IHN1bUZhY3RvciAqIHBhO1xuXG4gICAgc3RhY2sgPSBzdGFja1N0YXJ0O1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHJhZGl1c1BsdXMxOyBpKyspIHtcbiAgICAgIHN0YWNrLnIgPSBwcjtcbiAgICAgIHN0YWNrLmcgPSBwZztcbiAgICAgIHN0YWNrLmIgPSBwYjtcbiAgICAgIHN0YWNrLmEgPSBwYTtcbiAgICAgIHN0YWNrID0gc3RhY2submV4dDtcbiAgICB9XG5cbiAgICB5cCA9IHdpZHRoO1xuXG4gICAgZm9yIChpID0gMTsgaSA8PSByYWRpdXM7IGkrKykge1xuICAgICAgeWkgPSB5cCArIHggPDwgMjtcblxuICAgICAgcl9zdW0gKz0gKHN0YWNrLnIgPSBwciA9IHBpeGVsc1t5aV0pICogKHJicyA9IHJhZGl1c1BsdXMxIC0gaSk7XG4gICAgICBnX3N1bSArPSAoc3RhY2suZyA9IHBnID0gcGl4ZWxzW3lpICsgMV0pICogcmJzO1xuICAgICAgYl9zdW0gKz0gKHN0YWNrLmIgPSBwYiA9IHBpeGVsc1t5aSArIDJdKSAqIHJicztcbiAgICAgIGFfc3VtICs9IChzdGFjay5hID0gcGEgPSBwaXhlbHNbeWkgKyAzXSkgKiByYnM7XG5cbiAgICAgIHJfaW5fc3VtICs9IHByO1xuICAgICAgZ19pbl9zdW0gKz0gcGc7XG4gICAgICBiX2luX3N1bSArPSBwYjtcbiAgICAgIGFfaW5fc3VtICs9IHBhO1xuXG4gICAgICBzdGFjayA9IHN0YWNrLm5leHQ7XG5cbiAgICAgIGlmIChpIDwgaGVpZ2h0TWludXMxKSB7XG4gICAgICAgIHlwICs9IHdpZHRoO1xuICAgICAgfVxuICAgIH1cblxuICAgIHlpID0geDtcbiAgICBzdGFja0luID0gc3RhY2tTdGFydDtcbiAgICBzdGFja091dCA9IHN0YWNrRW5kO1xuICAgIGZvciAoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xuICAgICAgcCA9IHlpIDw8IDI7XG4gICAgICBwaXhlbHNbcCArIDNdID0gcGEgPSBhX3N1bSAqIG11bF9zdW0gPj4gc2hnX3N1bTtcbiAgICAgIGlmIChwYSA+IDApIHtcbiAgICAgICAgcGEgPSAyNTUgLyBwYTtcbiAgICAgICAgcGl4ZWxzW3BdID0gKHJfc3VtICogbXVsX3N1bSA+PiBzaGdfc3VtKSAqIHBhO1xuICAgICAgICBwaXhlbHNbcCArIDFdID0gKGdfc3VtICogbXVsX3N1bSA+PiBzaGdfc3VtKSAqIHBhO1xuICAgICAgICBwaXhlbHNbcCArIDJdID0gKGJfc3VtICogbXVsX3N1bSA+PiBzaGdfc3VtKSAqIHBhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGl4ZWxzW3BdID0gcGl4ZWxzW3AgKyAxXSA9IHBpeGVsc1twICsgMl0gPSAwO1xuICAgICAgfVxuXG4gICAgICByX3N1bSAtPSByX291dF9zdW07XG4gICAgICBnX3N1bSAtPSBnX291dF9zdW07XG4gICAgICBiX3N1bSAtPSBiX291dF9zdW07XG4gICAgICBhX3N1bSAtPSBhX291dF9zdW07XG5cbiAgICAgIHJfb3V0X3N1bSAtPSBzdGFja0luLnI7XG4gICAgICBnX291dF9zdW0gLT0gc3RhY2tJbi5nO1xuICAgICAgYl9vdXRfc3VtIC09IHN0YWNrSW4uYjtcbiAgICAgIGFfb3V0X3N1bSAtPSBzdGFja0luLmE7XG5cbiAgICAgIHAgPSB4ICsgKChwID0geSArIHJhZGl1c1BsdXMxKSA8IGhlaWdodE1pbnVzMSA/IHAgOiBoZWlnaHRNaW51czEpICogd2lkdGggPDwgMjtcblxuICAgICAgcl9zdW0gKz0gcl9pbl9zdW0gKz0gc3RhY2tJbi5yID0gcGl4ZWxzW3BdO1xuICAgICAgZ19zdW0gKz0gZ19pbl9zdW0gKz0gc3RhY2tJbi5nID0gcGl4ZWxzW3AgKyAxXTtcbiAgICAgIGJfc3VtICs9IGJfaW5fc3VtICs9IHN0YWNrSW4uYiA9IHBpeGVsc1twICsgMl07XG4gICAgICBhX3N1bSArPSBhX2luX3N1bSArPSBzdGFja0luLmEgPSBwaXhlbHNbcCArIDNdO1xuXG4gICAgICBzdGFja0luID0gc3RhY2tJbi5uZXh0O1xuXG4gICAgICByX291dF9zdW0gKz0gcHIgPSBzdGFja091dC5yO1xuICAgICAgZ19vdXRfc3VtICs9IHBnID0gc3RhY2tPdXQuZztcbiAgICAgIGJfb3V0X3N1bSArPSBwYiA9IHN0YWNrT3V0LmI7XG4gICAgICBhX291dF9zdW0gKz0gcGEgPSBzdGFja091dC5hO1xuXG4gICAgICByX2luX3N1bSAtPSBwcjtcbiAgICAgIGdfaW5fc3VtIC09IHBnO1xuICAgICAgYl9pbl9zdW0gLT0gcGI7XG4gICAgICBhX2luX3N1bSAtPSBwYTtcblxuICAgICAgc3RhY2tPdXQgPSBzdGFja091dC5uZXh0O1xuXG4gICAgICB5aSArPSB3aWR0aDtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gQmx1clN0YWNrKCkge1xuICB0aGlzLnIgPSAwO1xuICB0aGlzLmcgPSAwO1xuICB0aGlzLmIgPSAwO1xuICB0aGlzLmEgPSAwO1xuICB0aGlzLm5leHQgPSBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc3RhY2tCbHVyQ2FudmFzUkdCQTogc3RhY2tCbHVyQ2FudmFzUkdCQVxufTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdmVuZG9yL3N0YWNrLWJsdXIuanNcbiAqKiBtb2R1bGUgaWQgPSA3M1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcbnZhciBxdWV1ZSA9IFtdO1xudmFyIGRyYWluaW5nID0gZmFsc2U7XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuICAgIHZhciBjdXJyZW50UXVldWU7XG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHZhciBpID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtpXSgpO1xuICAgICAgICB9XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbn1cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgcXVldWUucHVzaChmdW4pO1xuICAgIGlmICghZHJhaW5pbmcpIHtcbiAgICAgICAgc2V0VGltZW91dChkcmFpblF1ZXVlLCAwKTtcbiAgICB9XG59O1xuXG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxuLy8gVE9ETyhzaHR5bG1hbilcbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcblxuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogKHdlYnBhY2spL34vbm9kZS1saWJzLWJyb3dzZXIvfi9wcm9jZXNzL2Jyb3dzZXIuanNcbiAqKiBtb2R1bGUgaWQgPSA3NFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnLi4vLi4vbGliL2V2ZW50LWVtaXR0ZXInKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliRXZlbnRFbWl0dGVyKTtcblxudmFyIF9oZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cbnZhciBfaGVscGVyczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9oZWxwZXJzKTtcblxudmFyIEJhc2VVSSA9IChmdW5jdGlvbiAoX0V2ZW50RW1pdHRlcikge1xuICBmdW5jdGlvbiBCYXNlVUkoa2l0LCBvcHRpb25zKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEJhc2VVSSk7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihCYXNlVUkucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgIHRoaXMuX2tpdCA9IGtpdDtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLl9vcHRpb25zLnVpID0gdGhpcy5fb3B0aW9ucy51aSB8fCB7fTtcbiAgICB0aGlzLl9vcGVyYXRpb25zID0gW107XG4gICAgdGhpcy5faGVscGVycyA9IG5ldyBfaGVscGVyczJbJ2RlZmF1bHQnXSh0aGlzLmtpdCwgdGhpcywgb3B0aW9ucyk7XG4gICAgdGhpcy5fbGFuZ3VhZ2VzID0ge307XG4gICAgdGhpcy5zZWxlY3RPcGVyYXRpb25zKG51bGwpO1xuICB9XG5cbiAgX2luaGVyaXRzKEJhc2VVSSwgX0V2ZW50RW1pdHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEJhc2VVSSwgW3tcbiAgICBrZXk6ICdydW4nLFxuXG4gICAgLyoqXG4gICAgICogUHJlcGFyZXMgdGhlIFVJIGZvciB1c2VcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcnVuKCkge1xuICAgICAgdGhpcy5fYXR0YWNoKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVnaXN0ZXJMYW5ndWFnZScsXG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYSBsYW5ndWFnZVxuICAgICAqIEBwYXJhbSAge1N0cmluZ30gaWRlbnRpZmllclxuICAgICAqIEBwYXJhbSAge09iamVjdH0gb2JqZWN0XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlZ2lzdGVyTGFuZ3VhZ2UoaWRlbnRpZmllciwgb2JqZWN0KSB7XG4gICAgICB0aGlzLl9sYW5ndWFnZXNbaWRlbnRpZmllcl0gPSBvYmplY3Q7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAndHJhbnNsYXRlJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHRyYW5zbGF0aW9uIGZvciBga2V5YFxuICAgICAqIEBwYXJhbSAge1N0cmluZ30ga2V5XG4gICAgICogQHJldHVybiB7U3RyaW5nfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiB0cmFuc2xhdGUoa2V5KSB7XG4gICAgICByZXR1cm4gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmZldGNoKHRoaXMuX2xhbmd1YWdlLCBrZXksICd0cmFuc2xhdGlvbi1taXNzaW5nJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2F0dGFjaCcsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGFuZCBhdHRhY2hlcyB0aGUgVUkgSFRNTFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9hdHRhY2goKSB7XG4gICAgICBpZiAodGhpcy5fb3B0aW9ucy5jb250YWluZXIgPT09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCYXNlVUkjYXR0YWNoOiBObyBjb250YWluZXIgc2V0LicpO1xuICAgICAgfVxuXG4gICAgICB2YXIgaHRtbCA9IHRoaXMuX3JlbmRlcigpO1xuICAgICAgdGhpcy5fb3B0aW9ucy5jb250YWluZXIuaW5uZXJIVE1MID0gaHRtbDtcblxuICAgICAgLy8gQ29udGFpbmVyIGhhcyB0byBiZSBwb3NpdGlvbjogcmVsYXRpdmVcbiAgICAgIHRoaXMuX29wdGlvbnMuY29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHRlbXBsYXRlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlcigpIHtcbiAgICAgIGlmICh0eXBlb2YgdGhpcy5fdGVtcGxhdGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQmFzZVVJI19yZW5kZXI6IE5vIHRlbXBsYXRlIHNldC4nKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3RlbXBsYXRlKHRoaXMuY29udGV4dCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2VsZWN0T3BlcmF0aW9ucycsXG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIHRoZSBlbmFibGVkIG9wZXJhdGlvbnNcbiAgICAgKiBAcGFyYW0ge0ltZ2x5S2l0LlNlbGVjdG9yfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzZWxlY3RPcGVyYXRpb25zKHNlbGVjdG9yKSB7XG4gICAgICB2YXIgcmVnaXN0ZXJlZE9wZXJhdGlvbnMgPSB0aGlzLl9raXQucmVnaXN0ZXJlZE9wZXJhdGlvbnM7XG5cbiAgICAgIHZhciBvcGVyYXRpb25JZGVudGlmaWVycyA9IE9iamVjdC5rZXlzKHJlZ2lzdGVyZWRPcGVyYXRpb25zKTtcblxuICAgICAgdmFyIHNlbGVjdGVkT3BlcmF0aW9ucyA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5zZWxlY3Qob3BlcmF0aW9uSWRlbnRpZmllcnMsIHNlbGVjdG9yKTtcbiAgICAgIHRoaXMuX29wZXJhdGlvbnMgPSBzZWxlY3RlZE9wZXJhdGlvbnMubWFwKGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7XG4gICAgICAgIHJldHVybiByZWdpc3RlcmVkT3BlcmF0aW9uc1tpZGVudGlmaWVyXTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2FkZE9wZXJhdGlvbicsXG5cbiAgICAvKipcbiAgICAgKiBBZGRzIHRoZSBnaXZlbiBvcGVyYXRpb24gdG8gdGhlIGF2YWlsYWJsZSBvcGVyYXRpb25zXG4gICAgICogQHBhcmFtIHtPcGVyYXRpb259IG9wZXJhdGlvblxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBhZGRPcGVyYXRpb24ob3BlcmF0aW9uKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb25zLnB1c2gob3BlcmF0aW9uKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdpc09wZXJhdGlvblNlbGVjdGVkJyxcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHRoZSBvcGVyYXRpb24gd2l0aCB0aGUgZ2l2ZW4gaWRlbnRpZmllciBpcyBzZWxlY3RlZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICogQHJldHVybnMge0Jvb2xlYW59XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGlzT3BlcmF0aW9uU2VsZWN0ZWQoaWRlbnRpZmllcikge1xuICAgICAgdmFyIG9wZXJhdGlvbklkZW50aWZpZXJzID0gdGhpcy5fb3BlcmF0aW9ucy5tYXAoZnVuY3Rpb24gKG9wZXJhdGlvbikge1xuICAgICAgICByZXR1cm4gb3BlcmF0aW9uLnByb3RvdHlwZS5pZGVudGlmaWVyO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gb3BlcmF0aW9uSWRlbnRpZmllcnMuaW5kZXhPZihpZGVudGlmaWVyKSAhPT0gLTE7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIHRoaXMgVUlcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29udGV4dCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGF0YSB0aGF0IGlzIHBhc3NlZCB0byB0aGUgdGVtcGxhdGUgcmVuZGVyZXJcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3BlcmF0aW9uczogdGhpcy5fb3BlcmF0aW9ucyxcbiAgICAgICAgaGVscGVyczogdGhpcy5faGVscGVycyxcbiAgICAgICAgb3B0aW9uczogdGhpcy5fb3B0aW9uc1xuICAgICAgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250YWluZXInLFxuXG4gICAgLyoqXG4gICAgICogVGhlIERPTSBjb250YWluZXJcbiAgICAgKiBAdHlwZSB7RE9NRWxlbWVudH1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zLmNvbnRhaW5lcjtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdvcGVyYXRpb25zJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBzZWxlY3RlZCAvIGFjdGl2ZSBvcGVyYXRpb25zXG4gICAgICogQHR5cGUge0FycmF5LjxJbWdseUtpdC5PcGVyYXRpb24+fVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX29wZXJhdGlvbnM7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnb3B0aW9ucycsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3B0aW9uc1xuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGNhbnZhcyBvYmplY3RcbiAgICAgKiBAdHlwZSB7Q2FudmFzfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NhbnZhcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdoZWxwZXJzJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBoZWxwZXJzXG4gICAgICogQHR5cGUge0hlbHBlcnN9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5faGVscGVycztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdpbWFnZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW1hZ2VcbiAgICAgKiBAdHlwZSB7SW1hZ2V9XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5pbWFnZTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQmFzZVVJO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEJhc2VVSTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9iYXNlL3VpLmpzXG4gKiogbW9kdWxlIGlkID0gNzVcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDMsIF94NCwgX3g1KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MywgcHJvcGVydHkgPSBfeDQsIHJlY2VpdmVyID0gX3g1OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDMgPSBwYXJlbnQ7IF94NCA9IHByb3BlcnR5OyBfeDUgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfcmVuZGVyZXJzV2ViZ2xSZW5kZXJlciA9IHJlcXVpcmUoJy4uLy4uLy4uL3JlbmRlcmVycy93ZWJnbC1yZW5kZXJlcicpO1xuXG52YXIgX3JlbmRlcmVyc1dlYmdsUmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVuZGVyZXJzV2ViZ2xSZW5kZXJlcik7XG5cbnZhciBfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9yZW5kZXJlcnMvY2FudmFzLXJlbmRlcmVyJyk7XG5cbnZhciBfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXZlbnQtZW1pdHRlcicpO1xuXG52YXIgX2xpYkV2ZW50RW1pdHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFdmVudEVtaXR0ZXIpO1xuXG52YXIgX3ZlbmRvclByb21pc2UgPSByZXF1aXJlKCcuLi8uLi8uLi92ZW5kb3IvcHJvbWlzZScpO1xuXG52YXIgX3ZlbmRvclByb21pc2UyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdmVuZG9yUHJvbWlzZSk7XG5cbnZhciBDYW52YXMgPSAoZnVuY3Rpb24gKF9FdmVudEVtaXR0ZXIpIHtcbiAgZnVuY3Rpb24gQ2FudmFzKGtpdCwgdWksIG9wdGlvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ2FudmFzKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKENhbnZhcy5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5jYWxsKHRoaXMpO1xuXG4gICAgdGhpcy5fa2l0ID0ga2l0O1xuICAgIHRoaXMuX3VpID0gdWk7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fdWkuY29udGFpbmVyO1xuXG4gICAgdGhpcy5fY2FudmFzQ29udGFpbmVyID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jYW52YXMtY29udGFpbmVyJyk7XG4gICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNhbnZhcy1pbm5lci1jb250YWluZXInKTtcbiAgICB0aGlzLl9jYW52YXMgPSB0aGlzLl9jYW52YXNDb250YWluZXIucXVlcnlTZWxlY3RvcignY2FudmFzJyk7XG4gICAgdGhpcy5faW1hZ2UgPSB0aGlzLl9vcHRpb25zLmltYWdlO1xuICAgIHRoaXMuX3JvdW5kWm9vbUJ5ID0gMC4xO1xuICAgIHRoaXMuX2lzRmlyc3RSZW5kZXIgPSB0cnVlO1xuXG4gICAgLy8gTW91c2UgZXZlbnQgY2FsbGJhY2tzIGJvdW5kIHRvIHRoZSBjbGFzcyBjb250ZXh0XG4gICAgdGhpcy5fZHJhZ09uTW91c2Vkb3duID0gdGhpcy5fZHJhZ09uTW91c2Vkb3duLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fZHJhZ09uTW91c2Vtb3ZlID0gdGhpcy5fZHJhZ09uTW91c2Vtb3ZlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fZHJhZ09uTW91c2V1cCA9IHRoaXMuX2RyYWdPbk1vdXNldXAuYmluZCh0aGlzKTtcbiAgfVxuXG4gIF9pbmhlcml0cyhDYW52YXMsIF9FdmVudEVtaXR0ZXIpO1xuXG4gIF9jcmVhdGVDbGFzcyhDYW52YXMsIFt7XG4gICAga2V5OiAncnVuJyxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSByZW5kZXJlciwgc2V0cyB0aGUgem9vbSBsZXZlbCBhbmQgaW5pdGlhbGx5XG4gICAgICogcmVuZGVycyB0aGUgb3BlcmF0aW9ucyBzdGFja1xuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBydW4oKSB7XG4gICAgICB0aGlzLl9pbml0UmVuZGVyZXIoKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBpbml0aWFsIHpvb20gbGV2ZWxcbiAgICAgIHRoaXMuX3pvb21MZXZlbCA9IHRoaXMuX2dldEluaXRpYWxab29tTGV2ZWwoKTtcbiAgICAgIHRoaXMuX2luaXRpYWxab29tTGV2ZWwgPSB0aGlzLl96b29tTGV2ZWw7XG4gICAgICB0aGlzLl9pc0luaXRpYWxab29tID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3NpemUgPSBudWxsO1xuXG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgICAgdGhpcy5fY2VudGVyQ2FudmFzKCk7XG4gICAgICB0aGlzLl9oYW5kbGVEcmFnKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVuZGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIGN1cnJlbnQgb3BlcmF0aW9ucyBzdGFja1xuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB0aGlzLl9pbml0aWFsWm9vbUxldmVsID0gdGhpcy5fZ2V0SW5pdGlhbFpvb21MZXZlbCgpO1xuXG4gICAgICAvLyBSZXNldCB0aGUgem9vbSBsZXZlbCB0byBpbml0aWFsXG4gICAgICAvLyBTb21lIG9wZXJhdGlvbnMgY2hhbmdlIHRoZSB0ZXh0dXJlIHJlc29sdXRpb24gKGUuZy4gcm90YXRpb24pXG4gICAgICAvLyBJZiB3ZSdyZSBvbiBpbml0aWFsIHpvb20gbGV2ZWwsIHdlIHN0aWxsIHdhbnQgdG8gbWFrZSB0aGUgY2FudmFzXG4gICAgICAvLyBmaXQgaW50byB0aGUgY29udGFpbmVyLiBGaW5kIHRoZSBuZXcgaW5pdGlhbCB6b29tIGxldmVsIGFuZCBzZXQgaXQuXG4gICAgICBpZiAodGhpcy5faXNJbml0aWFsWm9vbSkge1xuICAgICAgICB0aGlzLnNldFpvb21MZXZlbCh0aGlzLl9pbml0aWFsWm9vbUxldmVsLCBmYWxzZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIENhbGN1bGF0ZSB0aGUgaW5pdGlhbCBzaXplXG4gICAgICB2YXIgaW1hZ2VTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9pbWFnZS53aWR0aCwgdGhpcy5faW1hZ2UuaGVpZ2h0KTtcbiAgICAgIHZhciBpbml0aWFsU2l6ZSA9IGltYWdlU2l6ZS5tdWx0aXBseSh0aGlzLl96b29tTGV2ZWwpO1xuICAgICAgdGhpcy5fc2V0Q2FudmFzU2l6ZShpbml0aWFsU2l6ZSk7XG5cbiAgICAgIC8vIFJlc2V0IGZyYW1lYnVmZmVyc1xuICAgICAgdGhpcy5fcmVuZGVyZXIucmVzZXQoKTtcblxuICAgICAgLy8gUnVuIHRoZSBvcGVyYXRpb25zIHN0YWNrXG4gICAgICB2YXIgc3RhY2sgPSB0aGlzLnNhbml0aXplZFN0YWNrO1xuICAgICAgdGhpcy5fdXBkYXRlU3RhY2tEaXJ0eVN0YXRlcyhzdGFjayk7XG5cbiAgICAgIHZhciB2YWxpZGF0aW9uUHJvbWlzZXMgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9wZXJhdGlvbiA9IHN0YWNrW2ldO1xuICAgICAgICB2YWxpZGF0aW9uUHJvbWlzZXMucHVzaChvcGVyYXRpb24udmFsaWRhdGVTZXR0aW5ncygpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF92ZW5kb3JQcm9taXNlMlsnZGVmYXVsdCddLmFsbCh2YWxpZGF0aW9uUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBXaGVuIHVzaW5nIFdlYkdMLCByZXNpemUgdGhlIGltYWdlIHRvIG1heCB0ZXh0dXJlIHNpemUgaWYgbmVjZXNzYXJ5XG4gICAgICAgIGlmIChfdGhpcy5faXNGaXJzdFJlbmRlciAmJiBfdGhpcy5fcmVuZGVyZXIuaWRlbnRpZmllciA9PT0gJ3dlYmdsJykge1xuXG4gICAgICAgICAgaWYgKF90aGlzLl9pbWFnZS53aWR0aCA+IF90aGlzLl9yZW5kZXJlci5tYXhUZXh0dXJlU2l6ZSB8fCBfdGhpcy5faW1hZ2UuaGVpZ2h0ID4gX3RoaXMuX3JlbmRlcmVyLm1heFRleHR1cmVTaXplKSB7XG4gICAgICAgICAgICBfdGhpcy5fdWkuZGlzcGxheUxvYWRpbmdNZXNzYWdlKCdSZXNpemluZy4uLicpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLl9yZW5kZXJlci5wcmVwYXJlSW1hZ2UoX3RoaXMuX2ltYWdlKS50aGVuKGZ1bmN0aW9uIChpbWFnZSkge1xuICAgICAgICAgICAgICAgICAgX3RoaXMuX3VpLmhpZGVMb2FkaW5nTWVzc2FnZSgpO1xuICAgICAgICAgICAgICAgICAgX3RoaXMuX29wdGlvbnMuaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICAgICAgICAgIF90aGlzLl9pbWFnZSA9IF90aGlzLl9vcHRpb25zLmltYWdlO1xuICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pWydjYXRjaCddKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH0sIDEwMCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBPbiBmaXJzdCByZW5kZXIsIGRyYXcgdGhlIGltYWdlIHRvIHRoZSBpbnB1dCB0ZXh0dXJlXG4gICAgICAgIGlmIChfdGhpcy5faXNGaXJzdFJlbmRlciB8fCBfdGhpcy5fcmVuZGVyZXIuY29uc3RydWN0b3IuaWRlbnRpZmllciA9PT0gJ2NhbnZhcycpIHtcbiAgICAgICAgICBfdGhpcy5faXNGaXJzdFJlbmRlciA9IGZhbHNlO1xuICAgICAgICAgIHJldHVybiBfdGhpcy5fcmVuZGVyZXIuZHJhd0ltYWdlKF90aGlzLl9pbWFnZSk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAvLyBSZW5kZXIgdGhlIG9wZXJhdGlvbnMgc3RhY2tcbiAgICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByb21pc2VzID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgb3BlcmF0aW9uID0gc3RhY2tbaV07XG4gICAgICAgICAgcHJvbWlzZXMucHVzaChvcGVyYXRpb24ucmVuZGVyKF90aGlzLl9yZW5kZXJlcikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfdmVuZG9yUHJvbWlzZTJbJ2RlZmF1bHQnXS5hbGwocHJvbWlzZXMpO1xuICAgICAgfSlcbiAgICAgIC8vIFJlbmRlciB0aGUgZmluYWwgaW1hZ2VcbiAgICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzLl9yZW5kZXJlci5yZW5kZXJGaW5hbCgpO1xuICAgICAgfSlcbiAgICAgIC8vIFVwZGF0ZSB0aGUgbWFyZ2lucyBhbmQgYm91bmRhcmllc1xuICAgICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy5fc3RvcmVDYW52YXNTaXplKCk7XG4gICAgICAgIF90aGlzLl91cGRhdGVDb250YWluZXJTaXplKCk7XG4gICAgICAgIF90aGlzLl91cGRhdGVDYW52YXNNYXJnaW5zKCk7XG4gICAgICAgIF90aGlzLl9hcHBseUJvdW5kYXJpZXMoKTtcbiAgICAgIH0pWydjYXRjaCddKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0SW1hZ2UnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaW1hZ2UgdG8gdGhlIGdpdmVuIG9uZVxuICAgICAqIEBwYXJhbSB7SW1hZ2V9IGltYWdlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldEltYWdlKGltYWdlKSB7XG4gICAgICB0aGlzLl9pbWFnZSA9IGltYWdlO1xuICAgICAgdGhpcy5yZXNldCgpO1xuICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgIHRoaXMuX2NlbnRlckNhbnZhcygpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3pvb21JbicsXG5cbiAgICAvKipcbiAgICAgKiBJbmNyZWFzZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHpvb21JbigpIHtcbiAgICAgIHRoaXMuX2lzSW5pdGlhbFpvb20gPSBmYWxzZTtcblxuICAgICAgdmFyIHpvb21MZXZlbCA9IE1hdGgucm91bmQodGhpcy5fem9vbUxldmVsICogMTAwKTtcbiAgICAgIHZhciByb3VuZFpvb21CeSA9IE1hdGgucm91bmQodGhpcy5fcm91bmRab29tQnkgKiAxMDApO1xuICAgICAgdmFyIGluaXRpYWxab29tTGV2ZWwgPSBNYXRoLnJvdW5kKHRoaXMuX2luaXRpYWxab29tTGV2ZWwgKiAxMDApO1xuXG4gICAgICAvLyBSb3VuZCB1cCBpZiBuZWVkZWRcbiAgICAgIGlmICh6b29tTGV2ZWwgJSByb3VuZFpvb21CeSAhPT0gMCkge1xuICAgICAgICB6b29tTGV2ZWwgPSBNYXRoLmNlaWwoem9vbUxldmVsIC8gcm91bmRab29tQnkpICogcm91bmRab29tQnk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB6b29tTGV2ZWwgKz0gcm91bmRab29tQnk7XG4gICAgICB9XG5cbiAgICAgIHpvb21MZXZlbCA9IE1hdGgubWluKGluaXRpYWxab29tTGV2ZWwgKiAyLCB6b29tTGV2ZWwpO1xuICAgICAgcmV0dXJuIHRoaXMuc2V0Wm9vbUxldmVsKHpvb21MZXZlbCAvIDEwMCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnem9vbU91dCcsXG5cbiAgICAvKipcbiAgICAgKiBEZWNyZWFzZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHpvb21PdXQoKSB7XG4gICAgICB0aGlzLl9pc0luaXRpYWxab29tID0gZmFsc2U7XG5cbiAgICAgIHZhciB6b29tTGV2ZWwgPSBNYXRoLnJvdW5kKHRoaXMuX3pvb21MZXZlbCAqIDEwMCk7XG4gICAgICB2YXIgcm91bmRab29tQnkgPSBNYXRoLnJvdW5kKHRoaXMuX3JvdW5kWm9vbUJ5ICogMTAwKTtcbiAgICAgIHZhciBpbml0aWFsWm9vbUxldmVsID0gTWF0aC5yb3VuZCh0aGlzLl9pbml0aWFsWm9vbUxldmVsICogMTAwKTtcblxuICAgICAgLy8gUm91bmQgdXAgaWYgbmVlZGVkXG4gICAgICBpZiAoem9vbUxldmVsICUgcm91bmRab29tQnkgIT09IDApIHtcbiAgICAgICAgem9vbUxldmVsID0gTWF0aC5mbG9vcih6b29tTGV2ZWwgLyByb3VuZFpvb21CeSkgKiByb3VuZFpvb21CeTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHpvb21MZXZlbCAtPSByb3VuZFpvb21CeTtcbiAgICAgIH1cblxuICAgICAgem9vbUxldmVsID0gTWF0aC5tYXgoaW5pdGlhbFpvb21MZXZlbCwgem9vbUxldmVsKTtcbiAgICAgIHJldHVybiB0aGlzLnNldFpvb21MZXZlbCh6b29tTGV2ZWwgLyAxMDApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19zZXRDYW52YXNTaXplJyxcblxuICAgIC8qKlxuICAgICAqIFJlc2l6ZXMgYW5kIHBvc2l0aW9ucyB0aGUgY2FudmFzXG4gICAgICogQHBhcmFtIHtWZWN0b3IyfSBbc2l6ZV1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0Q2FudmFzU2l6ZShzaXplKSB7XG4gICAgICBzaXplID0gc2l6ZSB8fCBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHRoaXMuX2NhbnZhcy53aWR0aCA9IHNpemUueDtcbiAgICAgIHRoaXMuX2NhbnZhcy5oZWlnaHQgPSBzaXplLnk7XG5cbiAgICAgIHRoaXMuX3N0b3JlQ2FudmFzU2l6ZSgpO1xuICAgICAgdGhpcy5fdXBkYXRlQ29udGFpbmVyU2l6ZSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191cGRhdGVDb250YWluZXJTaXplJyxcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIGNhbnZhcyBjb250YWluZXIgc2l6ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVDb250YWluZXJTaXplKCkge1xuICAgICAgdmFyIHNpemUgPSB0aGlzLl9zaXplO1xuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUud2lkdGggPSAnJyArIHNpemUueCArICdweCc7XG4gICAgICB0aGlzLl9jYW52YXNJbm5lckNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSAnJyArIHNpemUueSArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3N0b3JlQ2FudmFzU2l6ZScsXG5cbiAgICAvKipcbiAgICAgKiBSZW1lbWJlcnMgdGhlIGNhbnZhcyBzaXplXG4gICAgICogQGNvbW1lbnQgVGhpcyB3YXMgaW50cm9kdWNlZCBiZWNhdXNlIHRoZSBjYW52YXMgc2l6ZSB3YXMgbm90IGFsd2F5c1xuICAgICAqICAgICAgICAgIGNvcnJlY3QgZHVlIHRvIHNvbWUgcmFjZSBjb25kaXRpb25zLiBOb3cgdGhhdCBwcm9taXNlcyB3b3JrXG4gICAgICogICAgICAgICAgcHJvcGVybHksIGRvIHdlIHN0aWxsIG5lZWQgdGhpcz9cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc3RvcmVDYW52YXNTaXplKCkge1xuICAgICAgdGhpcy5fc2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10odGhpcy5fY2FudmFzLndpZHRoLCB0aGlzLl9jYW52YXMuaGVpZ2h0KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY2VudGVyQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIENlbnRlcnMgdGhlIGNhbnZhcyBpbnNpZGUgdGhlIGNvbnRhaW5lclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jZW50ZXJDYW52YXMoKSB7XG4gICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9tYXhTaXplLmRpdmlkZSgyKTtcblxuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUubGVmdCA9ICcnICsgcG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9jYW52YXNJbm5lckNvbnRhaW5lci5zdHlsZS50b3AgPSAnJyArIHBvc2l0aW9uLnkgKyAncHgnO1xuXG4gICAgICB0aGlzLl91cGRhdGVDYW52YXNNYXJnaW5zKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZUNhbnZhc01hcmdpbnMnLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgY2FudmFzIG1hcmdpbnMgc28gdGhhdCB0aGV5IGFyZSB0aGUgbmVnYXRpdmUgaGFsZiB3aWR0aFxuICAgICAqIGFuZCBoZWlnaHQgb2YgdGhlIGNhbnZhc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVDYW52YXNNYXJnaW5zKCkge1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgbWFyZ2luID0gY2FudmFzU2l6ZS5kaXZpZGUoMikubXVsdGlwbHkoLTEpO1xuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUubWFyZ2luTGVmdCA9ICcnICsgbWFyZ2luLnggKyAncHgnO1xuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUubWFyZ2luVG9wID0gJycgKyBtYXJnaW4ueSArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0Wm9vbUxldmVsJyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpvb20gbGV2ZWwsIHJlLXJlbmRlcnMgdGhlIGNhbnZhcyBhbmRcbiAgICAgKiByZXBvc2l0aW9ucyBpdFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB6b29tTGV2ZWxcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbmRlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgcmVuZGVyID0gYXJndW1lbnRzWzFdID09PSB1bmRlZmluZWQgPyB0cnVlIDogYXJndW1lbnRzWzFdO1xuXG4gICAgICB0aGlzLl96b29tTGV2ZWwgPSB6b29tTGV2ZWw7XG4gICAgICBpZiAocmVuZGVyKSB7XG4gICAgICAgIHRoaXMuc2V0QWxsT3BlcmF0aW9uc1RvRGlydHkoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMyLl91cGRhdGVDYW52YXNNYXJnaW5zKCk7XG4gICAgICAgICAgX3RoaXMyLl9hcHBseUJvdW5kYXJpZXMoKTtcbiAgICAgICAgICBfdGhpczIuZW1pdCgnem9vbScpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNhbnZhc01hcmdpbnMoKTtcbiAgICAgICAgdGhpcy5fYXBwbHlCb3VuZGFyaWVzKCk7XG4gICAgICAgIHRoaXMuZW1pdCgnem9vbScpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NldEFsbE9wZXJhdGlvbnNUb0RpcnR5JyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgYWxsIG9wZXJhdGlvbnMgdG8gZGlydHlcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0QWxsT3BlcmF0aW9uc1RvRGlydHkoKSB7XG4gICAgICB2YXIgb3BlcmF0aW9uc1N0YWNrID0gdGhpcy5fa2l0Lm9wZXJhdGlvbnNTdGFjaztcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvcGVyYXRpb25zU3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9wZXJhdGlvbiA9IG9wZXJhdGlvbnNTdGFja1tpXTtcbiAgICAgICAgaWYgKCFvcGVyYXRpb24pIGNvbnRpbnVlO1xuICAgICAgICBvcGVyYXRpb24uZGlydHkgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRJbml0aWFsWm9vbUxldmVsJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGluaXRpYWwgem9vbSBsZXZlbCBzbyB0aGF0IHRoZSBpbWFnZSBmaXRzIHRoZSBtYXhpbXVtXG4gICAgICogY2FudmFzIHNpemVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0SW5pdGlhbFpvb21MZXZlbCgpIHtcbiAgICAgIHZhciBpbnB1dFNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2ltYWdlLndpZHRoLCB0aGlzLl9pbWFnZS5oZWlnaHQpO1xuXG4gICAgICB2YXIgY3JvcE9wZXJhdGlvbiA9IHRoaXMuX3VpLm9wZXJhdGlvbnMuY3JvcDtcbiAgICAgIHZhciByb3RhdGlvbk9wZXJhdGlvbiA9IHRoaXMuX3VpLm9wZXJhdGlvbnMucm90YXRpb247XG5cbiAgICAgIHZhciBjcm9wU2l6ZSA9IHVuZGVmaW5lZCxcbiAgICAgICAgICBjcm9wcGVkU2l6ZSA9IHVuZGVmaW5lZCxcbiAgICAgICAgICBmaW5hbFNpemUgPSB1bmRlZmluZWQsXG4gICAgICAgICAgaW5pdGlhbFNpemUgPSB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChjcm9wT3BlcmF0aW9uKSB7XG4gICAgICAgIGNyb3BTaXplID0gY3JvcE9wZXJhdGlvbi5nZXRFbmQoKS5jbG9uZSgpLnN1YnRyYWN0KGNyb3BPcGVyYXRpb24uZ2V0U3RhcnQoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcm9wU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMSwgMSk7XG4gICAgICB9XG5cbiAgICAgIGNyb3BwZWRTaXplID0gaW5wdXRTaXplLmNsb25lKCkubXVsdGlwbHkoY3JvcFNpemUpO1xuXG4gICAgICAvLyBIYXMgdGhlIGltYWdlIGJlZW4gcm90YXRlZD9cbiAgICAgIGlmIChyb3RhdGlvbk9wZXJhdGlvbiAmJiByb3RhdGlvbk9wZXJhdGlvbi5nZXREZWdyZWVzKCkgJSAxODAgIT09IDApIHtcbiAgICAgICAgdmFyIHRlbXBYID0gY3JvcHBlZFNpemUueDtcbiAgICAgICAgY3JvcHBlZFNpemUueCA9IGNyb3BwZWRTaXplLnk7XG4gICAgICAgIGNyb3BwZWRTaXplLnkgPSB0ZW1wWDtcbiAgICAgIH1cblxuICAgICAgZmluYWxTaXplID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLnJlc2l6ZVZlY3RvclRvRml0KGNyb3BwZWRTaXplLCB0aGlzLl9tYXhTaXplKTtcblxuICAgICAgLy8gUm90YXRlIGJhY2sgdG8gYmUgYWJsZSB0byBmaW5kIHRoZSBmaW5hbCBzaXplXG4gICAgICBpZiAocm90YXRpb25PcGVyYXRpb24gJiYgcm90YXRpb25PcGVyYXRpb24uZ2V0RGVncmVlcygpICUgMTgwICE9PSAwKSB7XG4gICAgICAgIHZhciB0ZW1wWCA9IGZpbmFsU2l6ZS54O1xuICAgICAgICBmaW5hbFNpemUueCA9IGZpbmFsU2l6ZS55O1xuICAgICAgICBmaW5hbFNpemUueSA9IHRlbXBYO1xuICAgICAgfVxuXG4gICAgICBpbml0aWFsU2l6ZSA9IGZpbmFsU2l6ZS5jbG9uZSgpLmRpdmlkZShjcm9wU2l6ZSk7XG4gICAgICByZXR1cm4gaW5pdGlhbFNpemUueCAvIGlucHV0U2l6ZS54O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0UmVuZGVyZXInLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHJlbmRlcmVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRSZW5kZXJlcigpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICBpZiAoX3JlbmRlcmVyc1dlYmdsUmVuZGVyZXIyWydkZWZhdWx0J10uaXNTdXBwb3J0ZWQoKSAmJiB0aGlzLl9vcHRpb25zLnJlbmRlcmVyICE9PSAnY2FudmFzJykge1xuICAgICAgICB0aGlzLl9yZW5kZXJlciA9IG5ldyBfcmVuZGVyZXJzV2ViZ2xSZW5kZXJlcjJbJ2RlZmF1bHQnXShudWxsLCB0aGlzLl9jYW52YXMpO1xuICAgICAgICB0aGlzLl93ZWJnbEVuYWJsZWQgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIyWydkZWZhdWx0J10uaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICB0aGlzLl9yZW5kZXJlciA9IG5ldyBfcmVuZGVyZXJzQ2FudmFzUmVuZGVyZXIyWydkZWZhdWx0J10obnVsbCwgdGhpcy5fY2FudmFzKTtcbiAgICAgICAgdGhpcy5fd2ViZ2xFbmFibGVkID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9yZW5kZXJlciA9PT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05laXRoZXIgQ2FudmFzIG5vciBXZWJHTCByZW5kZXJlciBhcmUgc3VwcG9ydGVkLicpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9yZW5kZXJlci5vbignbmV3LWNhbnZhcycsIGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgX3RoaXMzLl9zZXRDYW52YXMoY2FudmFzKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19zZXRDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZXMgdGhlIGNhbnZhcyB3aXRoIHRoZSBnaXZlbiBjYW52YXMsIHVwZGF0ZXMgbWFyZ2lucyBldGNcbiAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGNhbnZhc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zZXRDYW52YXMoY2FudmFzKSB7XG4gICAgICB2YXIgY2FudmFzUGFyZW50ID0gdGhpcy5fY2FudmFzLnBhcmVudE5vZGU7XG4gICAgICBjYW52YXNQYXJlbnQucmVtb3ZlQ2hpbGQodGhpcy5fY2FudmFzKTtcbiAgICAgIHRoaXMuX2NhbnZhcyA9IGNhbnZhcztcbiAgICAgIGNhbnZhc1BhcmVudC5hcHBlbmRDaGlsZCh0aGlzLl9jYW52YXMpO1xuXG4gICAgICB0aGlzLl91cGRhdGVDYW52YXNNYXJnaW5zKCk7XG4gICAgICB0aGlzLl9hcHBseUJvdW5kYXJpZXMoKTtcbiAgICAgIHRoaXMuX3VwZGF0ZUNvbnRhaW5lclNpemUoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlRHJhZycsXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVEcmFnKCkge1xuICAgICAgdGhpcy5fY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX2RyYWdPbk1vdXNlZG93bik7XG4gICAgICB0aGlzLl9jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX2RyYWdPbk1vdXNlZG93bik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2RyYWdPbk1vdXNlZG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0YXJ0ZWQgdG91Y2hpbmcgLyBjbGlja2luZyB0aGUgY2FudmFzXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9kcmFnT25Nb3VzZWRvd24oZSkge1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ21vdXNlZG93bicgJiYgZS5idXR0b24gIT09IDApIHJldHVybjtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIHggPSBlLnBhZ2VYO1xuICAgICAgdmFyIHkgPSBlLnBhZ2VZO1xuXG4gICAgICBpZiAoZS50eXBlID09PSAndG91Y2hzdGFydCcpIHtcbiAgICAgICAgeCA9IGUudG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgeSA9IGUudG91Y2hlc1swXS5wYWdlWTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNhbnZhc1ggPSBwYXJzZUludCh0aGlzLl9jYW52YXNJbm5lckNvbnRhaW5lci5zdHlsZS5sZWZ0LCAxMCk7XG4gICAgICB2YXIgY2FudmFzWSA9IHBhcnNlSW50KHRoaXMuX2NhbnZhc0lubmVyQ29udGFpbmVyLnN0eWxlLnRvcCwgMTApO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9kcmFnT25Nb3VzZW1vdmUpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fZHJhZ09uTW91c2Vtb3ZlKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX2RyYWdPbk1vdXNldXApO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9kcmFnT25Nb3VzZXVwKTtcblxuICAgICAgLy8gUmVtZW1iZXIgaW5pdGlhbCBwb3NpdGlvblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHgsIHkpO1xuICAgICAgdGhpcy5faW5pdGlhbENhbnZhc1Bvc2l0aW9uID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXNYLCBjYW52YXNZKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZHJhZ09uTW91c2Vtb3ZlJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgdGhlIGNhbnZhc1xuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfZHJhZ09uTW91c2Vtb3ZlKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIHggPSBlLnBhZ2VYLFxuICAgICAgICAgIHkgPSBlLnBhZ2VZO1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ3RvdWNobW92ZScpIHtcbiAgICAgICAgeCA9IGUudG91Y2hlc1swXS5wYWdlWDtcbiAgICAgICAgeSA9IGUudG91Y2hlc1swXS5wYWdlWTtcbiAgICAgIH1cblxuICAgICAgdmFyIG5ld01vdXNlUG9zaXRpb24gPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHgsIHkpO1xuICAgICAgdmFyIG1vdXNlRGlmZiA9IG5ld01vdXNlUG9zaXRpb24uY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG4gICAgICB2YXIgbmV3UG9zaXRpb24gPSB0aGlzLl9pbml0aWFsQ2FudmFzUG9zaXRpb24uY2xvbmUoKS5hZGQobW91c2VEaWZmKTtcblxuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUubGVmdCA9ICcnICsgbmV3UG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9jYW52YXNJbm5lckNvbnRhaW5lci5zdHlsZS50b3AgPSAnJyArIG5ld1Bvc2l0aW9uLnkgKyAncHgnO1xuXG4gICAgICB0aGlzLl9hcHBseUJvdW5kYXJpZXMoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYXBwbHlCb3VuZGFyaWVzJyxcblxuICAgIC8qKlxuICAgICAqIE1ha2VzIHN1cmUgdGhlIGNhbnZhcyBwb3NpdGlvbnMgYXJlIHdpdGhpbiB0aGUgYm91bmRhcmllc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9hcHBseUJvdW5kYXJpZXMoKSB7XG4gICAgICB2YXIgeCA9IHBhcnNlSW50KHRoaXMuX2NhbnZhc0lubmVyQ29udGFpbmVyLnN0eWxlLmxlZnQsIDEwKTtcbiAgICAgIHZhciB5ID0gcGFyc2VJbnQodGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUudG9wLCAxMCk7XG4gICAgICB2YXIgY2FudmFzUG9zaXRpb24gPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHgsIHkpO1xuXG4gICAgICAvLyBCb3VuZGFyaWVzXG4gICAgICB2YXIgYm91bmRhcmllcyA9IHRoaXMuX2JvdW5kYXJpZXM7XG4gICAgICBjYW52YXNQb3NpdGlvbi54ID0gTWF0aC5taW4oYm91bmRhcmllcy5tYXgueCwgTWF0aC5tYXgoYm91bmRhcmllcy5taW4ueCwgY2FudmFzUG9zaXRpb24ueCkpO1xuICAgICAgY2FudmFzUG9zaXRpb24ueSA9IE1hdGgubWluKGJvdW5kYXJpZXMubWF4LnksIE1hdGgubWF4KGJvdW5kYXJpZXMubWluLnksIGNhbnZhc1Bvc2l0aW9uLnkpKTtcblxuICAgICAgdGhpcy5fY2FudmFzSW5uZXJDb250YWluZXIuc3R5bGUubGVmdCA9ICcnICsgY2FudmFzUG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9jYW52YXNJbm5lckNvbnRhaW5lci5zdHlsZS50b3AgPSAnJyArIGNhbnZhc1Bvc2l0aW9uLnkgKyAncHgnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19kcmFnT25Nb3VzZXVwJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgc3RvcHBlZCBkcmFnZ2luZyB0aGUgY2FudnNhXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9kcmFnT25Nb3VzZXVwKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fZHJhZ09uTW91c2Vtb3ZlKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX2RyYWdPbk1vdXNlbW92ZSk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9kcmFnT25Nb3VzZXVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fZHJhZ09uTW91c2V1cCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZVN0YWNrRGlydHlTdGF0ZXMnLFxuXG4gICAgLyoqXG4gICAgICogRmluZCB0aGUgZmlyc3QgZGlydHkgb3BlcmF0aW9uIG9mIHRoZSBzdGFjayBhbmQgc2V0cyBhbGwgZm9sbG93aW5nXG4gICAgICogb3BlcmF0aW9ucyB0byBkaXJ0eVxuICAgICAqIEBwYXJhbSB7QXJyYXkuPE9wZXJhdGlvbj59IHN0YWNrXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3VwZGF0ZVN0YWNrRGlydHlTdGF0ZXMoc3RhY2spIHtcbiAgICAgIHZhciBkaXJ0eUZvdW5kID0gZmFsc2U7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0YWNrLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSBzdGFja1tpXTtcbiAgICAgICAgaWYgKCFvcGVyYXRpb24pIGNvbnRpbnVlO1xuICAgICAgICBpZiAob3BlcmF0aW9uLmRpcnR5KSB7XG4gICAgICAgICAgZGlydHlGb3VuZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGlydHlGb3VuZCkge1xuICAgICAgICAgIG9wZXJhdGlvbi5kaXJ0eSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd6b29tVG9GaXQnLFxuXG4gICAgLyoqXG4gICAgICogWm9vbXMgdGhlIGNhbnZhcyBzbyB0aGF0IGl0IGZpdHMgdGhlIGNvbnRhaW5lclxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVuZGVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHpvb21Ub0ZpdCgpIHtcbiAgICAgIHZhciByZW5kZXIgPSBhcmd1bWVudHNbMF0gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhcmd1bWVudHNbMF07XG5cbiAgICAgIHZhciBpbml0aWFsWm9vbUxldmVsID0gdGhpcy5fZ2V0SW5pdGlhbFpvb21MZXZlbCgpO1xuICAgICAgcmV0dXJuIHRoaXMuc2V0Wm9vbUxldmVsKGluaXRpYWxab29tTGV2ZWwsIHJlbmRlcik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVzZXQnLFxuXG4gICAgLyoqXG4gICAgICogUmVzZXRzIHRoZSByZW5kZXJlclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnJlc2V0KHRydWUpO1xuICAgICAgdGhpcy5fa2l0Lm9wZXJhdGlvbnNTdGFjayA9IFtdO1xuICAgICAgdGhpcy5faXNGaXJzdFJlbmRlciA9IHRydWU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2JvdW5kYXJpZXMnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHBvc2l0aW9uIGJvdW5kYXJpZXMgZm9yIHRoZSBjYW52YXMgaW5zaWRlIHRoZSBjb250YWluZXJcbiAgICAgKiBAdHlwZSB7T2JqZWN0LjxWZWN0b3IyPn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgbWF4U2l6ZSA9IHRoaXMuX21heFNpemU7XG5cbiAgICAgIHZhciBkaWZmID0gY2FudmFzU2l6ZS5jbG9uZSgpLnN1YnRyYWN0KG1heFNpemUpLm11bHRpcGx5KC0xKTtcblxuICAgICAgdmFyIGJvdW5kYXJpZXMgPSB7XG4gICAgICAgIG1pbjogbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShkaWZmLngsIGRpZmYueSksXG4gICAgICAgIG1heDogbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKVxuICAgICAgfTtcblxuICAgICAgaWYgKGNhbnZhc1NpemUueCA8IG1heFNpemUueCkge1xuICAgICAgICBib3VuZGFyaWVzLm1pbi54ID0gZGlmZi54IC8gMjtcbiAgICAgICAgYm91bmRhcmllcy5tYXgueCA9IGRpZmYueCAvIDI7XG4gICAgICB9XG5cbiAgICAgIGlmIChjYW52YXNTaXplLnkgPCBtYXhTaXplLnkpIHtcbiAgICAgICAgYm91bmRhcmllcy5taW4ueSA9IGRpZmYueSAvIDI7XG4gICAgICAgIGJvdW5kYXJpZXMubWF4LnkgPSBkaWZmLnkgLyAyO1xuICAgICAgfVxuXG4gICAgICB2YXIgaGFsZkNhbnZhc1NpemUgPSBjYW52YXNTaXplLmNsb25lKCkuZGl2aWRlKDIpO1xuICAgICAgYm91bmRhcmllcy5taW4uYWRkKGhhbGZDYW52YXNTaXplKTtcbiAgICAgIGJvdW5kYXJpZXMubWF4LmFkZChoYWxmQ2FudmFzU2l6ZSk7XG4gICAgICByZXR1cm4gYm91bmRhcmllcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfbWF4U2l6ZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSBjYW52YXMgc2l6ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9jYW52YXNDb250YWluZXIub2Zmc2V0V2lkdGgsIHRoaXMuX2NhbnZhc0NvbnRhaW5lci5vZmZzZXRIZWlnaHQpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Nhbml0aXplZFN0YWNrJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG9wZXJhdGlvbnMgc3RhY2sgd2l0aG91dCBmYWxzeSB2YWx1ZXNcbiAgICAgKiBAdHlwZSB7QXJyYXkuPE9wZXJhdGlvbj59XG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgc2FuaXRpemVkU3RhY2sgPSBbXTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fa2l0Lm9wZXJhdGlvbnNTdGFjay5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3BlcmF0aW9uID0gdGhpcy5fa2l0Lm9wZXJhdGlvbnNTdGFja1tpXTtcbiAgICAgICAgaWYgKCFvcGVyYXRpb24pIGNvbnRpbnVlO1xuICAgICAgICBzYW5pdGl6ZWRTdGFjay5wdXNoKG9wZXJhdGlvbik7XG4gICAgICB9XG4gICAgICByZXR1cm4gc2FuaXRpemVkU3RhY2s7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnem9vbUxldmVsJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjdXJyZW50IHpvb20gbGV2ZWxcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3pvb21MZXZlbDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaXplJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBjYW52YXMgc2l6ZSBpbiBwaXhlbHNcbiAgICAgKiBAdHlwZSB7VmVjdG9yMn1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zaXplO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDYW52YXM7XG59KShfbGliRXZlbnRFbWl0dGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ2FudmFzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG4vLyB3aWxsIGJlIHJlZGlyZWN0ZWQgdG8gdG9wIGNvbnRyb2xzXG4vLyB3aWxsIGJlIHJlZGlyZWN0ZWQgdG8gdG9wIGNvbnRyb2xzXG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2xpYi9jYW52YXMuanNcbiAqKiBtb2R1bGUgaWQgPSA3NlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXZlbnQtZW1pdHRlcicpO1xuXG52YXIgX2xpYkV2ZW50RW1pdHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFdmVudEVtaXR0ZXIpO1xuXG52YXIgRmlsZUxvYWRlciA9IChmdW5jdGlvbiAoX0V2ZW50RW1pdHRlcikge1xuICBmdW5jdGlvbiBGaWxlTG9hZGVyKGtpdCwgdWkpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmlsZUxvYWRlcik7XG5cbiAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihGaWxlTG9hZGVyLnByb3RvdHlwZSksICdjb25zdHJ1Y3RvcicsIHRoaXMpLmNhbGwodGhpcyk7XG5cbiAgICB0aGlzLl9raXQgPSBraXQ7XG4gICAgdGhpcy5fdWkgPSB1aTtcblxuICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNzExMDM1My9odG1sNS1kcmFnbGVhdmUtZmlyZWQtd2hlbi1ob3ZlcmluZy1hLWNoaWxkLWVsZW1lbnRcbiAgICB0aGlzLl9kcmFnQ291bnRlciA9IDA7XG5cbiAgICB0aGlzLl9jb250YWluZXIgPSB0aGlzLl91aS5jb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNwbGFzaC1jb250YWluZXInKTtcblxuICAgIHRoaXMuX29uRHJvcEFyZWFEcmFnRW50ZXIgPSB0aGlzLl9vbkRyb3BBcmVhRHJhZ0VudGVyLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ecm9wQXJlYURyYWdPdmVyID0gdGhpcy5fb25Ecm9wQXJlYURyYWdPdmVyLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ecm9wQXJlYURyYWdMZWF2ZSA9IHRoaXMuX29uRHJvcEFyZWFEcmFnTGVhdmUuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkRyb3BBcmVhRHJvcCA9IHRoaXMuX29uRHJvcEFyZWFEcm9wLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ecm9wQXJlYUNsaWNrID0gdGhpcy5fb25Ecm9wQXJlYUNsaWNrLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25GaWxlSW5wdXRDaGFuZ2UgPSB0aGlzLl9vbkZpbGVJbnB1dENoYW5nZS5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5faGlkZGVuSW5wdXRGaWVsZCA9IHRoaXMuX3VpLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtdXBsb2FkLWhpZGRlbi1pbnB1dCcpO1xuICAgIHRoaXMuX2hpZGRlbklucHV0RmllbGQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25GaWxlSW5wdXRDaGFuZ2UpO1xuXG4gICAgdGhpcy5faGFuZGxlRHJvcEFyZWEoKTtcbiAgICBpZiAodGhpcy5fdWkub3B0aW9ucy5pbWFnZSkge1xuICAgICAgdGhpcy5yZW1vdmVET00oKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoRmlsZUxvYWRlciwgX0V2ZW50RW1pdHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKEZpbGVMb2FkZXIsIFt7XG4gICAga2V5OiAnb3BlbkZpbGVEaWFsb2cnLFxuXG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIGZpbGUgZGlhbG9nXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIG9wZW5GaWxlRGlhbG9nKCkge1xuICAgICAgdGhpcy5faGlkZGVuSW5wdXRGaWVsZC5jbGljaygpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVEcm9wQXJlYScsXG5cbiAgICAvKipcbiAgICAgKiBGaW5kcyB0aGUgZHJvcCBhcmVhLCBhZGRzIGV2ZW50IGxpc3RlbmVyc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVEcm9wQXJlYSgpIHtcbiAgICAgIHRoaXMuX2Ryb3BBcmVhID0gdGhpcy5fY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1zcGxhc2gtcm93LS11cGxvYWQnKTtcbiAgICAgIHRoaXMuX2Ryb3BBcmVhLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbnRlcicsIHRoaXMuX29uRHJvcEFyZWFEcmFnRW50ZXIpO1xuICAgICAgdGhpcy5fZHJvcEFyZWEuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ292ZXInLCB0aGlzLl9vbkRyb3BBcmVhRHJhZ092ZXIpO1xuICAgICAgdGhpcy5fZHJvcEFyZWEuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2xlYXZlJywgdGhpcy5fb25Ecm9wQXJlYURyYWdMZWF2ZSk7XG4gICAgICB0aGlzLl9kcm9wQXJlYS5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgdGhpcy5fb25Ecm9wQXJlYURyb3ApO1xuICAgICAgdGhpcy5fZHJvcEFyZWEuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2Ryb3AnLCB0aGlzLl9vbkRyb3BBcmVhRHJvcCk7XG4gICAgICB0aGlzLl9kcm9wQXJlYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uRHJvcEFyZWFDbGljayk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRHJvcEFyZWFDbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiB0aGUgZHJvcCBhcmVhLiBPcGVucyB0aGUgZmlsZVxuICAgICAqIGRpYWxvZyBieSB0cmlnZ2VyaW5nIGEgY2xpY2sgb24gdGhlIGhpZGRlbiBpbnB1dCBmaWVsZFxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Ecm9wQXJlYUNsaWNrKCkge1xuICAgICAgdGhpcy5vcGVuRmlsZURpYWxvZygpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkRyb3BBcmVhRHJhZ0VudGVyJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgYSBmaWxlIG92ZXIgdGhlIGRyb3AgYXJlYVxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Ecm9wQXJlYURyYWdFbnRlcihlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHRoaXMuX2RyYWdDb3VudGVyKys7XG4gICAgICB0aGlzLl9kcm9wQXJlYS5jbGFzc0xpc3QuYWRkKCdpbWdseWtpdC1zcGxhc2gtYWN0aXZlJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRHJvcEFyZWFEcmFnT3ZlcicsXG5cbiAgICAvKipcbiAgICAgKiBXZSBuZWVkIHRvIGNhbmNlbCB0aGlzIGV2ZW50IHRvIGdldCBhIGRyb3AgZXZlbnRcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRHJvcEFyZWFEcmFnT3ZlcihlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRHJvcEFyZWFEcmFnTGVhdmUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkb2VzIG5vIGxvbmdlciBkcmFnIGEgZmlsZSBvdmVyIHRoZSBkcm9wIGFyZWFcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRHJvcEFyZWFEcmFnTGVhdmUoZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB0aGlzLl9kcmFnQ291bnRlci0tO1xuXG4gICAgICBpZiAodGhpcy5fZHJhZ0NvdW50ZXIgPT09IDApIHtcbiAgICAgICAgdGhpcy5fZHJvcEFyZWEuY2xhc3NMaXN0LnJlbW92ZSgnaW1nbHlraXQtc3BsYXNoLWFjdGl2ZScpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkRyb3BBcmVhRHJvcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGRyb3BzIGEgZmlsZSBvbiB0aGUgZHJvcCBhcmVhXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRyb3BBcmVhRHJvcChlKSB7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlO1xuXG4gICAgICB0aGlzLl9kcm9wQXJlYS5jbGFzc0xpc3QucmVtb3ZlKCdpbWdseWtpdC1zcGxhc2gtYWN0aXZlJyk7XG5cbiAgICAgIGlmICghZS5kYXRhVHJhbnNmZXIpIHJldHVybjtcblxuICAgICAgdGhpcy5faGFuZGxlRmlsZShlLmRhdGFUcmFuc2Zlci5maWxlc1swXSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRmlsZUlucHV0Q2hhbmdlJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgc2VsZWN0ZWQgYSBmaWxlXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkZpbGVJbnB1dENoYW5nZSgpIHtcbiAgICAgIHRoaXMuX2hhbmRsZUZpbGUodGhpcy5faGlkZGVuSW5wdXRGaWVsZC5maWxlc1swXSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZUZpbGUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBzZWxlY3RlZCBhIGZpbGUuIEVtaXRzIGEgYGZpbGVgIGV2ZW50LlxuICAgICAqIEBwYXJhbSB7RmlsZX0gZmlsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVGaWxlKGZpbGUpIHtcbiAgICAgIHRoaXMuZW1pdCgnZmlsZScsIGZpbGUpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbW92ZURPTScsXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBhbmQgcmVtb3ZlcyB0aGUgY29udGFpbmVyIGZvcm0gdGhlIGRvbVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW1vdmVET00oKSB7XG4gICAgICB0aGlzLl9kcm9wQXJlYS5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnZW50ZXInLCB0aGlzLl9vbkRyb3BBcmVhRHJhZ0VudGVyKTtcbiAgICAgIHRoaXMuX2Ryb3BBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgdGhpcy5fb25Ecm9wQXJlYURyYWdPdmVyKTtcbiAgICAgIHRoaXMuX2Ryb3BBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdsZWF2ZScsIHRoaXMuX29uRHJvcEFyZWFEcmFnTGVhdmUpO1xuICAgICAgdGhpcy5fZHJvcEFyZWEucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJvcCcsIHRoaXMuX29uRHJvcEFyZWFEcm9wKTtcbiAgICAgIHRoaXMuX2Ryb3BBcmVhLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWdkcm9wJywgdGhpcy5fb25Ecm9wQXJlYURyb3ApO1xuICAgICAgdGhpcy5fZHJvcEFyZWEucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkRyb3BBcmVhQ2xpY2spO1xuXG4gICAgICBpZiAodGhpcy5fY29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgfVxuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBGaWxlTG9hZGVyO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEZpbGVMb2FkZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL2ZpbGUtbG9hZGVyLmpzXG4gKiogbW9kdWxlIGlkID0gNzdcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBJbWFnZSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXZlbnQtZW1pdHRlcicpO1xuXG52YXIgX2xpYkV2ZW50RW1pdHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFdmVudEVtaXR0ZXIpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIFdlYmNhbUhhbmRsZXIgPSAoZnVuY3Rpb24gKF9FdmVudEVtaXR0ZXIpIHtcbiAgZnVuY3Rpb24gV2ViY2FtSGFuZGxlcihraXQsIHVpKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFdlYmNhbUhhbmRsZXIpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoV2ViY2FtSGFuZGxlci5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5jYWxsKHRoaXMpO1xuICAgIHRoaXMuX2tpdCA9IGtpdDtcbiAgICB0aGlzLl91aSA9IHVpO1xuXG4gICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuX3VpLmNvbnRhaW5lcjtcblxuICAgIHRoaXMuX2NhbnZhc0NvbnRhaW5lciA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY2FudmFzLWNvbnRhaW5lcicpO1xuXG4gICAgdGhpcy5fdmlkZW8gPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXdlYmNhbS12aWRlbycpO1xuICAgIHRoaXMuX3dlYmNhbUJ1dHRvbiA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtd2ViY2FtLWJ1dHRvbicpO1xuICAgIHRoaXMuX3dlYmNhbUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uV2ViY2FtQnV0dG9uQ2xpY2suYmluZCh0aGlzKSk7XG4gICAgdGhpcy5faW5pdFZpZGVvU3RyZWFtKCk7XG4gIH1cblxuICBfaW5oZXJpdHMoV2ViY2FtSGFuZGxlciwgX0V2ZW50RW1pdHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKFdlYmNhbUhhbmRsZXIsIFt7XG4gICAga2V5OiAnX29uV2ViY2FtQnV0dG9uQ2xpY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBjbGlja2VkIHRoZSBzaHV0dGVyIGJ1dHRvbi4gRHJhd3MgdGhlIGN1cnJlbnRcbiAgICAgKiB2aWRlbyBmcmFtZSB0byBhIGNhbnZhcywgY3JlYXRlcyBhbiBpbWFnZSBmcm9tIGl0IGFuZCBlbWl0cyB0aGUgYGltYWdlYFxuICAgICAqIGV2ZW50XG4gICAgICogQHBhcmFtICB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25XZWJjYW1CdXR0b25DbGljayhlKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICBjYW52YXMud2lkdGggPSB0aGlzLl92aWRlby52aWRlb1dpZHRoO1xuICAgICAgY2FudmFzLmhlaWdodCA9IHRoaXMuX3ZpZGVvLnZpZGVvSGVpZ2h0O1xuICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgIGNvbnRleHQuZHJhd0ltYWdlKHRoaXMuX3ZpZGVvLCAwLCAwKTtcblxuICAgICAgdGhpcy5fc3RyZWFtLnN0b3AoKTtcbiAgICAgIHRoaXMuX3ZpZGVvLnBhdXNlKCk7XG5cbiAgICAgIGRlbGV0ZSB0aGlzLl9zdHJlYW07XG4gICAgICBkZWxldGUgdGhpcy5fdmlkZW87XG5cbiAgICAgIHZhciBpbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgaW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMuZW1pdCgnaW1hZ2UnLCBpbWFnZSk7XG4gICAgICB9KTtcbiAgICAgIGltYWdlLnNyYyA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0VmlkZW9TdHJlYW0nLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHZpZGVvIHN0cmVhbVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbml0VmlkZW9TdHJlYW0oKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIGdldFVzZXJNZWRpYSA9IG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgfHwgbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYSB8fCBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhIHx8IG5hdmlnYXRvci5tc0dldFVzZXJNZWRpYTtcbiAgICAgIGlmICghZ2V0VXNlck1lZGlhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2ViY2FtIGZlYXR1cmUgbm90IHN1cHBvcnRlZCEgOignKTtcbiAgICAgIH1cblxuICAgICAgZ2V0VXNlck1lZGlhLmNhbGwobmF2aWdhdG9yLCB7IHZpZGVvOiB0cnVlIH0sIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgX3RoaXMyLl9zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIF90aGlzMi5fdmlkZW8ub25sb2FkZWRtZXRhZGF0YSA9IF90aGlzMi5fb25WaWRlb1JlYWR5LmJpbmQoX3RoaXMyKTtcbiAgICAgICAgX3RoaXMyLl92aWRlby5zcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChzdHJlYW0pO1xuICAgICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25WaWRlb1JlYWR5JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uVmlkZW9SZWFkeSgpIHtcbiAgICAgIHRoaXMuX3Jlc2l6ZVZpZGVvKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3Jlc2l6ZVZpZGVvJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3Jlc2l6ZVZpZGVvKCkge1xuICAgICAgdmFyIF92aWRlbyA9IHRoaXMuX3ZpZGVvO1xuICAgICAgdmFyIHZpZGVvV2lkdGggPSBfdmlkZW8udmlkZW9XaWR0aDtcbiAgICAgIHZhciB2aWRlb0hlaWdodCA9IF92aWRlby52aWRlb0hlaWdodDtcblxuICAgICAgdmFyIHNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHZpZGVvV2lkdGgsIHZpZGVvSGVpZ2h0KTtcbiAgICAgIHZhciBtYXhTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9jYW52YXNDb250YWluZXIub2Zmc2V0V2lkdGgsIHRoaXMuX2NhbnZhc0NvbnRhaW5lci5vZmZzZXRIZWlnaHQpO1xuXG4gICAgICB2YXIgZmluYWxTaXplID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLnJlc2l6ZVZlY3RvclRvRml0KHNpemUsIG1heFNpemUpO1xuICAgICAgdGhpcy5fdmlkZW8uc3R5bGUud2lkdGggPSAnJyArIGZpbmFsU2l6ZS54ICsgJ3B4JztcbiAgICAgIHRoaXMuX3ZpZGVvLnN0eWxlLmhlaWdodCA9ICcnICsgZmluYWxTaXplLnkgKyAncHgnO1xuXG4gICAgICB2YXIgZGlmZiA9IG1heFNpemUuY2xvbmUoKS5zdWJ0cmFjdChmaW5hbFNpemUpLmRpdmlkZSgyKTtcblxuICAgICAgdGhpcy5fdmlkZW8uc3R5bGUubWFyZ2luTGVmdCA9ICcnICsgZGlmZi54ICsgJ3B4JztcbiAgICAgIHRoaXMuX3ZpZGVvLnN0eWxlLm1hcmdpblRvcCA9ICcnICsgZGlmZi55ICsgJ3B4JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRVc2VyTWVkaWEnLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBXZWJjYW1IYW5kbGVyO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFdlYmNhbUhhbmRsZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL3dlYmNhbS1oYW5kbGVyLmpzXG4gKiogbW9kdWxlIGlkID0gNzhcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL2V2ZW50LWVtaXR0ZXInKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliRXZlbnRFbWl0dGVyKTtcblxudmFyIFRvcENvbnRyb2xzID0gKGZ1bmN0aW9uIChfRXZlbnRFbWl0dGVyKSB7XG4gIGZ1bmN0aW9uIFRvcENvbnRyb2xzKGtpdCwgdWkpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVG9wQ29udHJvbHMpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoVG9wQ29udHJvbHMucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgIHRoaXMuX2tpdCA9IGtpdDtcbiAgICB0aGlzLl91aSA9IHVpO1xuICAgIHRoaXMuaW5pdCgpO1xuICB9XG5cbiAgX2luaGVyaXRzKFRvcENvbnRyb2xzLCBfRXZlbnRFbWl0dGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoVG9wQ29udHJvbHMsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgY29udHJvbHNcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgIHRoaXMuX2NhbnZhcyA9IHRoaXMuX3VpLmNhbnZhcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdydW4nLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIGNvbnRyb2xzXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJ1bigpIHtcbiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLl91aS5jb250YWluZXI7XG5cbiAgICAgIHRoaXMuX3JpZ2h0Q29udHJvbHMgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXRvcC1jb250cm9scy1yaWdodCcpO1xuICAgICAgdGhpcy5fbGVmdENvbnRyb2xzID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC10b3AtY29udHJvbHMtbGVmdCcpO1xuXG4gICAgICB0aGlzLl91bmRvQnV0dG9uID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC11bmRvJyk7XG4gICAgICB0aGlzLl96b29tSW4gPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXpvb20taW4nKTtcbiAgICAgIHRoaXMuX3pvb21PdXQgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXpvb20tb3V0Jyk7XG4gICAgICB0aGlzLl96b29tTGV2ZWwgPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXpvb20tbGV2ZWwtbnVtJyk7XG4gICAgICB0aGlzLl9uZXdCdXR0b24gPSBjb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LW5ldycpO1xuICAgICAgdGhpcy5fZXhwb3J0QnV0dG9uID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1leHBvcnQnKTtcbiAgICAgIHRoaXMuX2hhbmRsZVpvb20oKTtcbiAgICAgIHRoaXMuX2hhbmRsZVVuZG8oKTtcbiAgICAgIHRoaXMuX2hhbmRsZU5ldygpO1xuICAgICAgdGhpcy5faGFuZGxlRXhwb3J0KCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZVpvb20nLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgem9vbSBjb250cm9sc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVab29tKCkge1xuICAgICAgdGhpcy5fem9vbUluLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fb25ab29tSW5DbGljay5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX3pvb21PdXQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vblpvb21PdXRDbGljay5iaW5kKHRoaXMpKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlVW5kbycsXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSB1bmRvIGNvbnRyb2xcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlVW5kbygpIHtcbiAgICAgIHRoaXMuX3VuZG9CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl91bmRvLmJpbmQodGhpcykpO1xuICAgICAgdGhpcy5fdW5kbygpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVOZXcnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgbmV3IGJ1dHRvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVOZXcoKSB7XG4gICAgICBpZiAoIXRoaXMuX25ld0J1dHRvbikgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9uZXdCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbk5ld0NsaWNrLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVFeHBvcnQnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgZXhwb3J0IGJ1dHRvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVFeHBvcnQoKSB7XG4gICAgICBpZiAoIXRoaXMuX2V4cG9ydEJ1dHRvbikgcmV0dXJuO1xuXG4gICAgICB0aGlzLl9leHBvcnRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkV4cG9ydENsaWNrLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbk5ld0NsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBuZXcgYnV0dG9uXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbk5ld0NsaWNrKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMuZW1pdCgnbmV3Jyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRXhwb3J0Q2xpY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgdGhlIGV4cG9ydCBidXR0b25cbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRXhwb3J0Q2xpY2soZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB0aGlzLmVtaXQoJ2V4cG9ydCcpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191bmRvJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSB1bmRvIGJ1dHRvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91bmRvKCkge1xuICAgICAgdGhpcy5lbWl0KCd1bmRvJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAndXBkYXRlVW5kb0J1dHRvbicsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSB1bmRvIGJ1dHRvbiB2aXNpYmxlIHN0YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVVuZG9CdXR0b24oKSB7XG4gICAgICB2YXIgaGlzdG9yeSA9IHRoaXMuX3VpLmhpc3Rvcnk7XG5cbiAgICAgIGlmIChoaXN0b3J5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLl91bmRvQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl91bmRvQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnaW5saW5lLWJsb2NrJztcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd1cGRhdGVFeHBvcnRCdXR0b24nLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgZXhwb3J0IGJ1dHRvbiB2aXNpYmxlIHN0YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZUV4cG9ydEJ1dHRvbigpIHtcbiAgICAgIGlmICghdGhpcy5fZXhwb3J0QnV0dG9uKSByZXR1cm47XG5cbiAgICAgIHZhciBpbWFnZSA9IHRoaXMuX3VpLmltYWdlO1xuXG4gICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgdGhpcy5fZXhwb3J0QnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnaW5saW5lLWJsb2NrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2V4cG9ydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblpvb21JbkNsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tlZCB0aGUgem9vbSBpbiBidXR0b25cbiAgICAgKiBAcGFyYW0ge0V2ZW50fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblpvb21JbkNsaWNrKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5lbWl0KCd6b29tLWluJyk7XG4gICAgICB0aGlzLnVwZGF0ZVpvb21MZXZlbCgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblpvb21PdXRDbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrZWQgdGhlIHpvb20gb3V0IGJ1dHRvblxuICAgICAqIEBwYXJhbSB7RXZlbnR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uWm9vbU91dENsaWNrKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5lbWl0KCd6b29tLW91dCcpO1xuICAgICAgdGhpcy51cGRhdGVab29tTGV2ZWwoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG93Wm9vbScsXG5cbiAgICAvKipcbiAgICAgKiBTaG93cyB0aGUgem9vbSBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNob3dab29tKCkge1xuICAgICAgdGhpcy5fcmlnaHRDb250cm9scy5zdHlsZS5kaXNwbGF5ID0gJ2lubGluZS1ibG9jayc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaGlkZVpvb20nLFxuXG4gICAgLyoqXG4gICAgICogSGlkZXMgdGhlIHpvb20gY29udHJvbFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBoaWRlWm9vbSgpIHtcbiAgICAgIHRoaXMuX3JpZ2h0Q29udHJvbHMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd1cGRhdGVab29tTGV2ZWwnLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgem9vbSBsZXZlbCBkaXNwbGF5XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHVwZGF0ZVpvb21MZXZlbCgpIHtcbiAgICAgIHZhciB6b29tTGV2ZWwgPSB0aGlzLl9jYW52YXMuem9vbUxldmVsO1xuXG4gICAgICB0aGlzLl96b29tTGV2ZWwuaW5uZXJIVE1MID0gTWF0aC5yb3VuZCh6b29tTGV2ZWwgKiAxMDApO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBUb3BDb250cm9scztcbn0pKF9saWJFdmVudEVtaXR0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBUb3BDb250cm9scztcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9saWIvdG9wLWNvbnRyb2xzLmpzXG4gKiogbW9kdWxlIGlkID0gNzlcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIG1heFNjcm9sbGJhcldpZHRoID0gMTg7XG5cbi8qKlxuICogT3VyIGN1c3RvbSBzY3JvbGwgYmFyXG4gKi9cblxudmFyIFNjcm9sbGJhciA9IChmdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGNvbnRhaW5lclxuICAgKi9cblxuICBmdW5jdGlvbiBTY3JvbGxiYXIoY29udGFpbmVyKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFNjcm9sbGJhcik7XG5cbiAgICB0aGlzLl9jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgdGhpcy5faXNEcmFnZ2luZyA9IGZhbHNlO1xuICAgIHRoaXMuX2lzSG92ZXJpbmcgPSBmYWxzZTtcblxuICAgIHRoaXMuX2FwcGVuZERPTSgpO1xuICAgIHRoaXMuX3Jlc2l6ZUJ1dHRvbigpO1xuICAgIHRoaXMuX3VwZGF0ZVZhbHVlcygpO1xuXG4gICAgdGhpcy5fb25CdXR0b25Eb3duID0gdGhpcy5fb25CdXR0b25Eb3duLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25CdXR0b25Nb3ZlID0gdGhpcy5fb25CdXR0b25Nb3ZlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25CdXR0b25VcCA9IHRoaXMuX29uQnV0dG9uVXAuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX29uQ29udGFpbmVyRW50ZXIgPSB0aGlzLl9vbkNvbnRhaW5lckVudGVyLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Db250YWluZXJMZWF2ZSA9IHRoaXMuX29uQ29udGFpbmVyTGVhdmUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX29uQmFja2dyb3VuZENsaWNrID0gdGhpcy5fb25CYWNrZ3JvdW5kQ2xpY2suYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX2NvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgdGhpcy5fb25Db250YWluZXJFbnRlcik7XG4gICAgdGhpcy5fY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCB0aGlzLl9vbkNvbnRhaW5lckxlYXZlKTtcbiAgICB0aGlzLl9jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Db250YWluZXJFbnRlcik7XG4gICAgdGhpcy5fZG9tLmJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vbkJ1dHRvbkRvd24pO1xuICAgIHRoaXMuX2RvbS5idXR0b24uYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uQnV0dG9uRG93bik7XG4gICAgdGhpcy5fZG9tLmJhY2tncm91bmQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkJhY2tncm91bmRDbGljayk7XG4gICAgdGhpcy5fbGlzdC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLl9vbkxpc3RTY3JvbGwuYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLl9vbkxpc3RTY3JvbGwoKTtcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhTY3JvbGxiYXIsIFt7XG4gICAga2V5OiAnX29uQmFja2dyb3VuZENsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBzY3JvbGxiYXIgYmFja2dyb3VuZFxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CYWNrZ3JvdW5kQ2xpY2soZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKGUudGFyZ2V0ICE9PSB0aGlzLl9kb20uYmFja2dyb3VuZCkgcmV0dXJuO1xuXG4gICAgICB2YXIgcG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBiYWNrZ3JvdW5kT2Zmc2V0ID0gdGhpcy5fZG9tLmJhY2tncm91bmQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBiYWNrZ3JvdW5kT2Zmc2V0ID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShiYWNrZ3JvdW5kT2Zmc2V0LmxlZnQsIGJhY2tncm91bmRPZmZzZXQudG9wKTtcblxuICAgICAgdmFyIHJlbGF0aXZlUG9zaXRpb24gPSBwb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KGJhY2tncm91bmRPZmZzZXQpO1xuXG4gICAgICByZWxhdGl2ZVBvc2l0aW9uLnggLT0gdGhpcy5fdmFsdWVzLmJ1dHRvbi53aWR0aCAqIDAuNTtcblxuICAgICAgdGhpcy5fc2V0QnV0dG9uUG9zaXRpb24ocmVsYXRpdmVQb3NpdGlvbi54KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Db250YWluZXJFbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGVudGVycyB0aGUgbGlzdCB3aXRoIHRoZSBtb3VzZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkNvbnRhaW5lckVudGVyKCkge1xuICAgICAgdGhpcy5faXNIb3ZlcmluZyA9IHRydWU7XG4gICAgICB0aGlzLnNob3coKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Db250YWluZXJMZWF2ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGxlYXZlcyB0aGUgbGlzdCB3aXRoIHRoZSBtb3VzZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkNvbnRhaW5lckxlYXZlKCkge1xuICAgICAgdGhpcy5faXNIb3ZlcmluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5oaWRlKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2hvdycsXG5cbiAgICAvKipcbiAgICAgKiBTaG93cyB0aGUgc2Nyb2xsYmFyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNob3coKSB7XG4gICAgICBpZiAoIXRoaXMuX2lzU2Nyb2xsaW5nTmVjZXNzYXJ5KSByZXR1cm47XG4gICAgICB0aGlzLl9kb20uYmFja2dyb3VuZC5jbGFzc0xpc3QuYWRkKCd2aXNpYmxlJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaGlkZScsXG5cbiAgICAvKipcbiAgICAgKiBIaWRlcyB0aGUgc2Nyb2xsYmFyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICBpZiAodGhpcy5faXNEcmFnZ2luZykgcmV0dXJuO1xuICAgICAgdGhpcy5fZG9tLmJhY2tncm91bmQuY2xhc3NMaXN0LnJlbW92ZSgndmlzaWJsZScpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191cGRhdGVWYWx1ZXMnLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgc2l6ZSB2YWx1ZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfdXBkYXRlVmFsdWVzKCkge1xuICAgICAgdGhpcy5fdmFsdWVzID0ge1xuICAgICAgICBsaXN0OiB7XG4gICAgICAgICAgdG90YWxXaWR0aDogdGhpcy5fbGlzdC5zY3JvbGxXaWR0aCxcbiAgICAgICAgICB2aXNpYmxlV2lkdGg6IHRoaXMuX2xpc3Qub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgc2Nyb2xsYWJsZVdpZHRoOiB0aGlzLl9saXN0LnNjcm9sbFdpZHRoIC0gdGhpcy5fbGlzdC5vZmZzZXRXaWR0aFxuICAgICAgICB9LFxuICAgICAgICBidXR0b246IHtcbiAgICAgICAgICB3aWR0aDogdGhpcy5fZG9tLmJ1dHRvbi5vZmZzZXRXaWR0aCxcbiAgICAgICAgICBzY3JvbGxhYmxlV2lkdGg6IHRoaXMuX2RvbS5iYWNrZ3JvdW5kLm9mZnNldFdpZHRoIC0gdGhpcy5fZG9tLmJ1dHRvbi5vZmZzZXRXaWR0aFxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJ1dHRvbkRvd24nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIGJ1dHRvblxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQnV0dG9uRG93bihldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faXNEcmFnZ2luZyA9IHRydWU7XG5cbiAgICAgIHRoaXMuX2luaXRpYWxNb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZXZlbnQpO1xuICAgICAgdGhpcy5faW5pdGlhbEJ1dHRvblBvc2l0aW9uID0gdGhpcy5fYnV0dG9uUG9zaXRpb24gfHwgMDtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25CdXR0b25Nb3ZlKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uQnV0dG9uTW92ZSk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25CdXR0b25VcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uQnV0dG9uVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJ1dHRvbk1vdmUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgYnV0dG9uXG4gICAgICogQHBhcmFtIHtFdmVudH0gZXZlbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CdXR0b25Nb3ZlKGV2ZW50KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB2YXIgbW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGV2ZW50KTtcbiAgICAgIHZhciBkaWZmID0gbW91c2VQb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxNb3VzZVBvc2l0aW9uKTtcbiAgICAgIHZhciBuZXdCdXR0b25Qb3NpdGlvbiA9IHRoaXMuX2luaXRpYWxCdXR0b25Qb3NpdGlvbiArIGRpZmYueDtcblxuICAgICAgdGhpcy5fc2V0QnV0dG9uUG9zaXRpb24obmV3QnV0dG9uUG9zaXRpb24pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19zZXRCdXR0b25Qb3NpdGlvbicsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBidXR0b24gcG9zaXRpb24gdG8gdGhlIGdpdmVuIHZhbHVlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG5ld0J1dHRvblBvc2l0aW9uXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3NldEJ1dHRvblBvc2l0aW9uKG5ld0J1dHRvblBvc2l0aW9uKSB7XG4gICAgICAvLyBDbGFtcCBidXR0b24gcG9zaXRpb25cbiAgICAgIG5ld0J1dHRvblBvc2l0aW9uID0gTWF0aC5tYXgoMCwgbmV3QnV0dG9uUG9zaXRpb24pO1xuICAgICAgbmV3QnV0dG9uUG9zaXRpb24gPSBNYXRoLm1pbihuZXdCdXR0b25Qb3NpdGlvbiwgdGhpcy5fdmFsdWVzLmJ1dHRvbi5zY3JvbGxhYmxlV2lkdGgpO1xuXG4gICAgICAvLyBTZXQgYnV0dG9uIHBvc2l0aW9uXG4gICAgICB0aGlzLl9idXR0b25Qb3NpdGlvbiA9IG5ld0J1dHRvblBvc2l0aW9uO1xuICAgICAgdGhpcy5fZG9tLmJ1dHRvbi5zdHlsZS5sZWZ0ID0gJycgKyB0aGlzLl9idXR0b25Qb3NpdGlvbiArICdweCc7XG5cbiAgICAgIC8vIFVwZGF0ZSBsaXN0IHNjcm9sbCBwb3NpdGlvblxuICAgICAgdmFyIHByb2dyZXNzID0gbmV3QnV0dG9uUG9zaXRpb24gLyB0aGlzLl92YWx1ZXMuYnV0dG9uLnNjcm9sbGFibGVXaWR0aDtcbiAgICAgIHZhciBzY3JvbGxQb3NpdGlvbiA9IHRoaXMuX3ZhbHVlcy5saXN0LnNjcm9sbGFibGVXaWR0aCAqIHByb2dyZXNzO1xuICAgICAgdGhpcy5fbGlzdC5zY3JvbGxMZWZ0ID0gc2Nyb2xsUG9zaXRpb247XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQnV0dG9uVXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgYnV0dG9uXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQnV0dG9uVXAoKSB7XG4gICAgICB0aGlzLl9pc0RyYWdnaW5nID0gZmFsc2U7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQnV0dG9uTW92ZSk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkJ1dHRvbk1vdmUpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQnV0dG9uVXApO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbkJ1dHRvblVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25MaXN0U2Nyb2xsJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgc2Nyb2xscyB0aGUgbGlzdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkxpc3RTY3JvbGwoKSB7XG4gICAgICBpZiAodGhpcy5faXNEcmFnZ2luZykgcmV0dXJuO1xuXG4gICAgICB2YXIgbGlzdFNjcm9sbFdpZHRoID0gdGhpcy5fbGlzdC5zY3JvbGxXaWR0aCAtIHRoaXMuX2xpc3Qub2Zmc2V0V2lkdGg7XG4gICAgICB2YXIgbGlzdFNjcm9sbFBvc2l0aW9uID0gdGhpcy5fbGlzdC5zY3JvbGxMZWZ0O1xuXG4gICAgICB2YXIgYmFja2dyb3VuZFNjcm9sbFdpZHRoID0gdGhpcy5fZG9tLmJhY2tncm91bmQub2Zmc2V0V2lkdGggLSB0aGlzLl9kb20uYnV0dG9uLm9mZnNldFdpZHRoO1xuICAgICAgdmFyIHByb2dyZXNzID0gbGlzdFNjcm9sbFBvc2l0aW9uIC8gbGlzdFNjcm9sbFdpZHRoO1xuXG4gICAgICB0aGlzLl9idXR0b25Qb3NpdGlvbiA9IGJhY2tncm91bmRTY3JvbGxXaWR0aCAqIHByb2dyZXNzO1xuICAgICAgdGhpcy5fZG9tLmJ1dHRvbi5zdHlsZS5sZWZ0ID0gJycgKyB0aGlzLl9idXR0b25Qb3NpdGlvbiArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3Jlc2l6ZUJ1dHRvbicsXG5cbiAgICAvKipcbiAgICAgKiBSZXNpemVzIHRoZSBidXR0b24gdG8gcmVwcmVzZW50IHRoZSB2aXNpYmxlIHNpemUgb2YgdGhlIGNvbnRhaW5lclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZXNpemVCdXR0b24oKSB7XG4gICAgICB2YXIgbGlzdFNjcm9sbFdpZHRoID0gdGhpcy5fbGlzdC5zY3JvbGxXaWR0aDtcbiAgICAgIHZhciBsaXN0V2lkdGggPSB0aGlzLl9saXN0Lm9mZnNldFdpZHRoO1xuXG4gICAgICB0aGlzLl9idXR0b25XaWR0aCA9IGxpc3RXaWR0aCAvIGxpc3RTY3JvbGxXaWR0aCAqIGxpc3RXaWR0aDtcbiAgICAgIHRoaXMuX2RvbS5idXR0b24uc3R5bGUud2lkdGggPSAnJyArIHRoaXMuX2J1dHRvbldpZHRoICsgJ3B4JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYXBwZW5kRE9NJyxcblxuICAgIC8qKlxuICAgICAqIEFwcGVuZHMgdGhlIERPTSBlbGVtZW50cyB0byB0aGUgY29udGFpbmVyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FwcGVuZERPTSgpIHtcbiAgICAgIHZhciBiYWNrZ3JvdW5kID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBiYWNrZ3JvdW5kLmNsYXNzTGlzdC5hZGQoJ2ltZ2x5a2l0LXNjcm9sbGJhci1iYWNrZ3JvdW5kJyk7XG4gICAgICBiYWNrZ3JvdW5kLnN0eWxlLmJvdHRvbSA9ICcnICsgbWF4U2Nyb2xsYmFyV2lkdGggKyAncHgnO1xuXG4gICAgICB2YXIgYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBidXR0b24uY2xhc3NMaXN0LmFkZCgnaW1nbHlraXQtc2Nyb2xsYmFyLWJ1dHRvbicpO1xuXG4gICAgICBiYWNrZ3JvdW5kLmFwcGVuZENoaWxkKGJ1dHRvbik7XG4gICAgICB0aGlzLl9jb250YWluZXIuYXBwZW5kQ2hpbGQoYmFja2dyb3VuZCk7XG5cbiAgICAgIC8vIENvbnRhaW5lciBzaG91bGQgaGF2ZSBwb3NpdGlvbjogcmVsYXRpdmVcbiAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XG5cbiAgICAgIC8vIEZpbmQgdGhlIGxpc3RcbiAgICAgIHRoaXMuX2xpc3QgPSB0aGlzLl9jb250YWluZXIucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNvbnRyb2xzLWxpc3QnKTtcbiAgICAgIHRoaXMuX2RvbSA9IHsgYmFja2dyb3VuZDogYmFja2dyb3VuZCwgYnV0dG9uOiBidXR0b24gfTtcblxuICAgICAgLy8gUmVzaXplIHRoZSBsaXN0IGFuZCB0aGUgY29udGFpbmVyXG4gICAgICB0aGlzLl9saXN0LnN0eWxlLmhlaWdodCA9ICcnO1xuICAgICAgdmFyIGxpc3RIZWlnaHQgPSB0aGlzLl9saXN0Lm9mZnNldEhlaWdodDtcbiAgICAgIGxpc3RIZWlnaHQgKz0gbWF4U2Nyb2xsYmFyV2lkdGg7XG4gICAgICB0aGlzLl9jb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gJycgKyBsaXN0SGVpZ2h0ICsgJ3B4JztcbiAgICAgIHRoaXMuX2xpc3Quc3R5bGUuaGVpZ2h0ID0gJycgKyBsaXN0SGVpZ2h0ICsgJ3B4JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW1vdmUnLFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgRE9NIGVsZW1lbnRzIGFuZCBldmVudCBsaXN0ZW5lcnNcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVtb3ZlKCkge1xuICAgICAgdGhpcy5fZG9tLmJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vbkJ1dHRvbkRvd24pO1xuICAgICAgdGhpcy5fZG9tLmJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fb25CdXR0b25Eb3duKTtcblxuICAgICAgdGhpcy5fZG9tLmJhY2tncm91bmQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLl9kb20uYmFja2dyb3VuZCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2lzU2Nyb2xsaW5nTmVjZXNzYXJ5JyxcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHNjcm9sbGluZyBpcyBuZWNlc3NhcnlcbiAgICAgKiBAcmV0dXJucyB7Qm9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xpc3Quc2Nyb2xsV2lkdGggPiB0aGlzLl9saXN0Lm9mZnNldFdpZHRoO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBTY3JvbGxiYXI7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTY3JvbGxiYXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL3Njcm9sbGJhci5qc1xuICoqIG1vZHVsZSBpZCA9IDgwXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgX19ET1RKU19URU1QTEFURSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9jb250cm9sID0gcmVxdWlyZSgnLi9jb250cm9sJyk7XG5cbnZhciBfY29udHJvbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jb250cm9sKTtcblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIEZpbHRlcnNDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBGaWx0ZXJzQ29udHJvbCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmlsdGVyc0NvbnRyb2wpO1xuXG4gICAgaWYgKF9Db250cm9sICE9IG51bGwpIHtcbiAgICAgIF9Db250cm9sLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEZpbHRlcnNDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKEZpbHRlcnNDb250cm9sLCBbe1xuICAgIGtleTogJ2luaXQnLFxuXG4gICAgLyoqXG4gICAgICogRW50cnkgcG9pbnQgZm9yIHRoaXMgY29udHJvbFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgdmFyIGNvbnRyb2xzVGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWxpc3QtY29udGFpbmVyXCI+IDx1bCBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWxpc3QgaW1nbHktY29udHJvbHMtbGlzdC13aXRoLWJ1dHRvbnNcIj4gJzsgZm9yKHZhciBpZGVudGlmaWVyIGluIGl0LmZpbHRlcnMpIHsgb3V0Kz0nICc7IHZhciBmaWx0ZXIgPSBpdC5maWx0ZXJzW2lkZW50aWZpZXJdOyBvdXQrPScgJzsgdmFyIG5hbWUgPSBmaWx0ZXIucHJvdG90eXBlLm5hbWU7IG91dCs9JyAnOyB2YXIgZW5hYmxlZCA9IGl0LmFjdGl2ZUZpbHRlci5pZGVudGlmaWVyID09PSBpZGVudGlmaWVyOyBvdXQrPScgPGxpIGRhdGEtaWRlbnRpZmllcj1cIicrKCBpZGVudGlmaWVyKSsnXCIgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1pdGVtLXdpdGgtbGFiZWwnO2lmKGVuYWJsZWQpe291dCs9JyBpbWdseWtpdC1jb250cm9scy1pdGVtLWFjdGl2ZSc7fW91dCs9J1wiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9maWx0ZXJzLycgKyBpZGVudGlmaWVyICsgJy5wbmcnKSkrJ1wiIC8+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1pdGVtLWxhYmVsXCI+JysoIG5hbWUgKSsnPC9kaXY+IDwvbGk+ICc7IH0gb3V0Kz0nIDwvdWw+PC9kaXY+JztyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzVGVtcGxhdGUgPSBjb250cm9sc1RlbXBsYXRlO1xuXG4gICAgICB0aGlzLl9hdmFpbGFibGVGaWx0ZXJzID0ge307XG4gICAgICB0aGlzLl9maWx0ZXJzID0ge307XG5cbiAgICAgIHRoaXMuX2FkZERlZmF1bHRGaWx0ZXJzKCk7XG5cbiAgICAgIC8vIFNlbGVjdCBhbGwgZmlsdGVycyBwZXIgZGVmYXVsdFxuICAgICAgdGhpcy5zZWxlY3RGaWx0ZXJzKG51bGwpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJBbGxDb250cm9scycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBjb250cm9sc1xuICAgICAqIEBwcml2YXRlXG4gICAgICogQGludGVybmFsIFdlIG5lZWQgdG8gYWNjZXNzIGluZm9ybWF0aW9uIGZyb20gdGhlIG9wZXJhdGlvbiB3aGVuXG4gICAgICogICAgICAgICAgIHJlbmRlcmluZywgd2hpY2ggaXMgd2h5IHdlIGhhdmUgdG8gb3ZlcnJpZGUgdGhpcyBmdW5jdGlvblxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQWxsQ29udHJvbHMoKSB7XG4gICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgICAgICBhcmdzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLmZpbHRlcnM7XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbignZmlsdGVycycpO1xuXG4gICAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihGaWx0ZXJzQ29udHJvbC5wcm90b3R5cGUpLCAnX3JlbmRlckFsbENvbnRyb2xzJywgdGhpcykuYXBwbHkodGhpcywgYXJncyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRW50ZXInLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGlzIGNvbnRyb2wgaXMgYWN0aXZhdGVkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkVudGVyKCkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgdGhpcy5faW5pdGlhbEZpbHRlciA9IHRoaXMuX29wZXJhdGlvbi5nZXRGaWx0ZXIoKTtcbiAgICAgIHRoaXMuX2RlZmF1bHRGaWx0ZXIgPSB0aGlzLl9vcGVyYXRpb24uYXZhaWxhYmxlT3B0aW9ucy5maWx0ZXJbJ2RlZmF1bHQnXTtcblxuICAgICAgdmFyIGxpc3RJdGVtcyA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3JBbGwoJ2xpJyk7XG4gICAgICB0aGlzLl9saXN0SXRlbXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChsaXN0SXRlbXMpO1xuXG4gICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgbGlzdEl0ZW0gPSBfdGhpcy5fbGlzdEl0ZW1zW2ldO1xuICAgICAgICBsaXN0SXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5fb25MaXN0SXRlbUNsaWNrKGxpc3RJdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICAvLyBMaXN0ZW4gdG8gY2xpY2sgZXZlbnRzXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xpc3RJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbG9vcChpKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CYWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgaGl0cyB0aGUgYmFjayBidXR0b25cbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmFjaygpIHtcbiAgICAgIHZhciBjdXJyZW50RmlsdGVyID0gdGhpcy5fb3BlcmF0aW9uLmdldEZpbHRlcigpO1xuICAgICAgaWYgKGN1cnJlbnRGaWx0ZXIgIT09IHRoaXMuX2luaXRpYWxGaWx0ZXIpIHtcbiAgICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgICBmaWx0ZXI6IHRoaXMuX2luaXRpYWxGaWx0ZXJcbiAgICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgICB9XG4gICAgICBpZiAoY3VycmVudEZpbHRlciA9PT0gdGhpcy5fZGVmYXVsdEZpbHRlcikge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ2ZpbHRlcnMnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25MaXN0SXRlbUNsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tlZCBhIGxpc3QgaXRlbVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkxpc3RJdGVtQ2xpY2soaXRlbSkge1xuICAgICAgdGhpcy5fZGVhY3RpdmF0ZUFsbEl0ZW1zKCk7XG5cbiAgICAgIHZhciBpZGVudGlmaWVyID0gaXRlbS5kYXRhc2V0LmlkZW50aWZpZXI7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRGaWx0ZXIodGhpcy5fZmlsdGVyc1tpZGVudGlmaWVyXSk7XG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCk7XG5cbiAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZGVhY3RpdmF0ZUFsbEl0ZW1zJyxcblxuICAgIC8qKlxuICAgICAqIERlYWN0aXZhdGVzIGFsbCBsaXN0IGl0ZW1zXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2RlYWN0aXZhdGVBbGxJdGVtcygpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fbGlzdEl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBsaXN0SXRlbSA9IHRoaXMuX2xpc3RJdGVtc1tpXTtcbiAgICAgICAgbGlzdEl0ZW0uY2xhc3NMaXN0LnJlbW92ZSgnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYWRkRGVmYXVsdEZpbHRlcnMnLFxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGFsbCB0aGUga25vd24gZmlsdGVyc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9hZGREZWZhdWx0RmlsdGVycygpIHtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9pZGVudGl0eS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvazEtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2syLWZpbHRlcicpKTtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9rNi1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMva2R5bmFtaWMtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2ZyaWRnZS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvYnJlZXplLWZpbHRlcicpKTtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9vcmNoaWQtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2NoZXN0LWZpbHRlcicpKTtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9mcm9udC1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvZml4aWUtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL3g0MDAtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2J3LWZpbHRlcicpKTtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9id2hhcmQtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2xlbmluLWZpbHRlcicpKTtcbiAgICAgIHRoaXMuYWRkRmlsdGVyKHJlcXVpcmUoJy4uLy4uLy4uL29wZXJhdGlvbnMvZmlsdGVycy9xdW96aS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvcG9sYTY2OS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvcG9sYS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvZm9vZC1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvZ2xhbS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvY2Vsc2l1cy1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvdGV4YXMtZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL21vcm5pbmctZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2xvbW8tZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2dvYmJsaW4tZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL21lbGxvdy1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvc3VubnktZmlsdGVyJykpO1xuICAgICAgdGhpcy5hZGRGaWx0ZXIocmVxdWlyZSgnLi4vLi4vLi4vb3BlcmF0aW9ucy9maWx0ZXJzL2ExNS1maWx0ZXInKSk7XG4gICAgICB0aGlzLmFkZEZpbHRlcihyZXF1aXJlKCcuLi8uLi8uLi9vcGVyYXRpb25zL2ZpbHRlcnMvc2VtaXJlZC1maWx0ZXInKSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnYWRkRmlsdGVyJyxcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyB0aGUgZ2l2ZW4gZmlsdGVyXG4gICAgICogQHBhcmFtICB7Y2xhc3N9IGZpbHRlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZEZpbHRlcihmaWx0ZXIpIHtcbiAgICAgIHRoaXMuX2F2YWlsYWJsZUZpbHRlcnNbZmlsdGVyLmlkZW50aWZpZXJdID0gZmlsdGVyO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NlbGVjdEZpbHRlcnMnLFxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgZmlsdGVyc1xuICAgICAqIEBwYXJhbSB7U2VsZWN0b3J9IHNlbGVjdG9yXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHNlbGVjdEZpbHRlcnMoc2VsZWN0b3IpIHtcbiAgICAgIHRoaXMuX2ZpbHRlcnMgPSB7fTtcblxuICAgICAgdmFyIGZpbHRlcklkZW50aWZpZXJzID0gT2JqZWN0LmtleXModGhpcy5fYXZhaWxhYmxlRmlsdGVycyk7XG5cbiAgICAgIHZhciBzZWxlY3RlZEZpbHRlcnMgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uc2VsZWN0KGZpbHRlcklkZW50aWZpZXJzLCBzZWxlY3Rvcik7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGVjdGVkRmlsdGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWRlbnRpZmllciA9IHNlbGVjdGVkRmlsdGVyc1tpXTtcbiAgICAgICAgdGhpcy5fZmlsdGVyc1tpZGVudGlmaWVyXSA9IHRoaXMuX2F2YWlsYWJsZUZpbHRlcnNbaWRlbnRpZmllcl07XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9hY3RpdmUpIHtcbiAgICAgICAgdGhpcy5fcmVuZGVyQ29udHJvbHMoKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIHRoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSB0ZW1wbGF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBmaWx0ZXJzOiB0aGlzLl9maWx0ZXJzLFxuICAgICAgICBhY3RpdmVGaWx0ZXI6IHRoaXMuX29wZXJhdGlvbi5nZXRGaWx0ZXIoKVxuICAgICAgfTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRmlsdGVyc0NvbnRyb2w7XG59KShfY29udHJvbDJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5GaWx0ZXJzQ29udHJvbC5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdmaWx0ZXJzJztcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRmlsdGVyc0NvbnRyb2w7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvY29udHJvbHMvZmlsdGVycy1jb250cm9sLmpzXG4gKiogbW9kdWxlIGlkID0gODFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBfX0RPVEpTX1RFTVBMQVRFICovXG4vKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2NvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcblxudmFyIF9jb250cm9sMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NvbnRyb2wpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL21hdGgvdmVjdG9yMicpO1xuXG52YXIgX2xpYk1hdGhWZWN0b3IyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYk1hdGhWZWN0b3IyKTtcblxudmFyIFJvdGF0aW9uQ29udHJvbCA9IChmdW5jdGlvbiAoX0NvbnRyb2wpIHtcbiAgZnVuY3Rpb24gUm90YXRpb25Db250cm9sKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBSb3RhdGlvbkNvbnRyb2wpO1xuXG4gICAgaWYgKF9Db250cm9sICE9IG51bGwpIHtcbiAgICAgIF9Db250cm9sLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKFJvdGF0aW9uQ29udHJvbCwgX0NvbnRyb2wpO1xuXG4gIF9jcmVhdGVDbGFzcyhSb3RhdGlvbkNvbnRyb2wsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBFbnRyeSBwb2ludCBmb3IgdGhpcyBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICB2YXIgY29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2PiA8dWwgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1saXN0IGltZ2x5LWNvbnRyb2xzLWxpc3Qtd2l0aC1idXR0b25zXCI+IDxsaSBkYXRhLWRlZ3JlZXM9XCItOTBcIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvcm90YXRpb24vbGVmdC5wbmcnKSkrJ1wiIC8+IDwvbGk+IDxsaSBkYXRhLWRlZ3JlZXM9XCI5MFwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9yb3RhdGlvbi9yaWdodC5wbmcnKSkrJ1wiIC8+IDwvbGk+IDwvdWw+PC9kaXY+JztyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzVGVtcGxhdGUgPSBjb250cm9sc1RlbXBsYXRlO1xuXG4gICAgICB2YXIgY2FudmFzQ29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtY29udGFpbmVyIGltZ2x5a2l0LWNhbnZhcy1jcm9wLWNvbnRhaW5lci1oaWRkZW5cIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLXRvcFwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtdG9wLWxlZnRcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLXRvcC1jZW50ZXJcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLXRvcC1yaWdodFwiPjwvZGl2PiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLWNlbnRlclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtY2VudGVyLWxlZnRcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLWNlbnRlci1jZW50ZXIgaW1nbHlraXQtY2FudmFzLWNyb3AtY2VudGVyLWNlbnRlci1ub21vdmVcIj4gPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1jZW50ZXItcmlnaHRcIj48L2Rpdj4gPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1ib3R0b21cIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLWJvdHRvbS1sZWZ0XCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1ib3R0b20tY2VudGVyXCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1ib3R0b20tcmlnaHRcIj48L2Rpdj4gPC9kaXY+PC9kaXY+JztyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NhbnZhc0NvbnRyb2xzVGVtcGxhdGUgPSBjYW52YXNDb250cm9sc1RlbXBsYXRlO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkVudGVyJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhpcyBjb250cm9sIGlzIGFjdGl2YXRlZFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25FbnRlcigpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUgPSAhIXRoaXMuX3VpLm9wZXJhdGlvbnMucm90YXRpb247XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbigncm90YXRpb24nKTtcblxuICAgICAgdGhpcy5fY3JvcE9wZXJhdGlvbiA9IHRoaXMuX3VpLm9wZXJhdGlvbnMuY3JvcDtcblxuICAgICAgdGhpcy5faW5pdGlhbFpvb21MZXZlbCA9IHRoaXMuX3VpLmNhbnZhcy56b29tTGV2ZWw7XG4gICAgICB0aGlzLl91aS5jYW52YXMuem9vbVRvRml0KGZhbHNlKTtcblxuICAgICAgaWYgKHRoaXMuX2Nyb3BPcGVyYXRpb24pIHtcbiAgICAgICAgLy8gU3RvcmUgaW5pdGlhbCBzZXR0aW5ncyBmb3IgJ2JhY2snIGFuZCAnZG9uZScgYnV0dG9uc1xuICAgICAgICB0aGlzLl9pbml0aWFsU3RhcnQgPSB0aGlzLl9jcm9wT3BlcmF0aW9uLmdldFN0YXJ0KCkuY2xvbmUoKTtcbiAgICAgICAgdGhpcy5faW5pdGlhbEVuZCA9IHRoaXMuX2Nyb3BPcGVyYXRpb24uZ2V0RW5kKCkuY2xvbmUoKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgd2Ugc2VlIHRoZSB3aG9sZSBpbnB1dCBpbWFnZVxuICAgICAgICB0aGlzLl9jcm9wT3BlcmF0aW9uLnNldCh7XG4gICAgICAgICAgc3RhcnQ6IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMCwgMCksXG4gICAgICAgICAgZW5kOiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDEsIDEpXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pbml0aWFsRGVncmVlcyA9IHRoaXMuX29wZXJhdGlvbi5nZXREZWdyZWVzKCk7XG5cbiAgICAgIHZhciBsaXN0SXRlbXMgPSB0aGlzLl9jb250cm9scy5xdWVyeVNlbGVjdG9yQWxsKCdsaScpO1xuICAgICAgdGhpcy5fbGlzdEl0ZW1zID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobGlzdEl0ZW1zKTtcblxuICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgdmFyIGxpc3RJdGVtID0gX3RoaXMuX2xpc3RJdGVtc1tpXTtcbiAgICAgICAgbGlzdEl0ZW0uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMuX29uTGlzdEl0ZW1DbGljayhsaXN0SXRlbSk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgLy8gTGlzdGVuIHRvIGNsaWNrIGV2ZW50c1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9saXN0SXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgX2xvb3AoaSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEZpbmQgdGhlIGRpdiBhcmVhcyB0aGF0IGFmZmVjdCB0aGUgZGlzcGxheWVkIGNyb3Agc2l6ZVxuICAgICAgdmFyIHByZWZpeCA9ICcuaW1nbHlraXQtY2FudmFzLWNyb3AnO1xuICAgICAgdGhpcy5fY3JvcEFyZWFzID0ge1xuICAgICAgICB0b3BMZWZ0OiB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcnICsgcHJlZml4ICsgJy10b3AtbGVmdCcpLFxuICAgICAgICB0b3BDZW50ZXI6IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJycgKyBwcmVmaXggKyAnLXRvcC1jZW50ZXInKSxcbiAgICAgICAgY2VudGVyTGVmdDogdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignJyArIHByZWZpeCArICctY2VudGVyLWxlZnQnKSxcbiAgICAgICAgY2VudGVyQ2VudGVyOiB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcnICsgcHJlZml4ICsgJy1jZW50ZXItY2VudGVyJylcbiAgICAgIH07XG5cbiAgICAgIC8vIFJlc3VtZSB0aGUgcmVuZGVyaW5nXG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLl9zaG93Q3JvcENvbnRhaW5lcigpO1xuICAgICAgICBfdGhpcy5fdXBkYXRlQ3JvcERPTSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3Nob3dDcm9wQ29udGFpbmVyJyxcblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBjcm9wIGNvbnRhaW5lciB3aGljaCBpcyBoaWRkZW4gaW5pdGlhbGx5IHRvIGF2b2lkIGZsaWNrZXJpbmdcbiAgICAgKiB3aGVuIHJlc2l6aW5nIGFmdGVyIHRoZSByZW5kZXJpbmdcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2hvd0Nyb3BDb250YWluZXIoKSB7XG4gICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNhbnZhcy1jcm9wLWNvbnRhaW5lcicpO1xuICAgICAgY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoJ2ltZ2x5a2l0LWNhbnZhcy1jcm9wLWNvbnRhaW5lci1oaWRkZW4nKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25MaXN0SXRlbUNsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGdpdmVuIGl0ZW0gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBwYXJhbSB7RE9NT2JqZWN0fSBpdGVtXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTGlzdEl0ZW1DbGljayhpdGVtKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIGRlZ3JlZXMgPSBpdGVtLmRhdGFzZXQuZGVncmVlcztcblxuICAgICAgZGVncmVlcyA9IHBhcnNlSW50KGRlZ3JlZXMsIDEwKTtcblxuICAgICAgdmFyIGN1cnJlbnREZWdyZWVzID0gdGhpcy5fb3BlcmF0aW9uLmdldERlZ3JlZXMoKTtcbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXREZWdyZWVzKGN1cnJlbnREZWdyZWVzICsgZGVncmVlcyk7XG4gICAgICB0aGlzLl91aS5jYW52YXMuem9vbVRvRml0KCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzMi5fdXBkYXRlQ3JvcERPTSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnb25ab29tJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHpvb20gbGV2ZWwgaGFzIGJlZW4gY2hhbmdlZCB3aGlsZVxuICAgICAqIHRoaXMgY29udHJvbCBpcyBhY3RpdmVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gb25ab29tKCkge1xuICAgICAgdGhpcy5fdXBkYXRlQ3JvcERPTSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191cGRhdGVDcm9wRE9NJyxcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIGNyb3BwaW5nIGRpdnMgZm9yIHRoZSBjdXJyZW50IG9wZXJhdGlvbiBzZXR0aW5nc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVDcm9wRE9NKCkge1xuICAgICAgdmFyIHN0YXJ0ID0gdW5kZWZpbmVkLFxuICAgICAgICAgIGVuZCA9IHVuZGVmaW5lZDtcbiAgICAgIGlmICh0aGlzLl9jcm9wT3BlcmF0aW9uKSB7XG4gICAgICAgIHN0YXJ0ID0gdGhpcy5faW5pdGlhbFN0YXJ0LmNsb25lKCk7XG4gICAgICAgIGVuZCA9IHRoaXMuX2luaXRpYWxFbmQuY2xvbmUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXJ0ID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKTtcbiAgICAgICAgZW5kID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgxLCAxKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcblxuICAgICAgdmFyIHN0YXJ0QWJzb2x1dGUgPSBzdGFydC5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIHZhciBlbmRBYnNvbHV0ZSA9IGVuZC5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIHZhciBzaXplID0gZW5kQWJzb2x1dGUuY2xvbmUoKS5zdWJ0cmFjdChzdGFydEFic29sdXRlKTtcblxuICAgICAgdmFyIHRvcCA9IE1hdGgubWF4KDEsIHN0YXJ0QWJzb2x1dGUueSk7XG4gICAgICB2YXIgbGVmdCA9IE1hdGgubWF4KDEsIHN0YXJ0QWJzb2x1dGUueCk7XG4gICAgICB2YXIgd2lkdGggPSBNYXRoLm1heCgxLCBzaXplLngpO1xuICAgICAgdmFyIGhlaWdodCA9IE1hdGgubWF4KDEsIHNpemUueSk7XG5cbiAgICAgIC8vIHdpZHRocyBhcmUgZGVmaW5lZCBieSB0b3AgbGVmdCBhbmQgdG9wIGNlbnRlciBhcmVhc1xuICAgICAgdGhpcy5fY3JvcEFyZWFzLnRvcExlZnQuc3R5bGUud2lkdGggPSAnJyArIGxlZnQgKyAncHgnO1xuICAgICAgdGhpcy5fY3JvcEFyZWFzLnRvcENlbnRlci5zdHlsZS53aWR0aCA9ICcnICsgd2lkdGggKyAncHgnO1xuXG4gICAgICAvLyBoZWlnaHRzIGFyZSBkZWZpbmVkIGJ5IHRvcCBsZWZ0IGFuZCBjZW50ZXIgbGVmdCBhcmVhc1xuICAgICAgdGhpcy5fY3JvcEFyZWFzLnRvcExlZnQuc3R5bGUuaGVpZ2h0ID0gJycgKyB0b3AgKyAncHgnO1xuICAgICAgdGhpcy5fY3JvcEFyZWFzLmNlbnRlckxlZnQuc3R5bGUuaGVpZ2h0ID0gJycgKyBoZWlnaHQgKyAncHgnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJhY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgYmFjayBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CYWNrKCkge1xuICAgICAgdmFyIGN1cnJlbnREZWdyZWVzID0gdGhpcy5fb3BlcmF0aW9uLmdldERlZ3JlZXMoKTtcbiAgICAgIGlmICh0aGlzLl9pbml0aWFsRGVncmVlcyAhPT0gY3VycmVudERlZ3JlZXMpIHtcbiAgICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgICBkZWdyZWVzOiB0aGlzLl9pbml0aWFsRGVncmVlc1xuICAgICAgICB9LCB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGN1cnJlbnREZWdyZWVzID09PSAwKSB7XG4gICAgICAgIHRoaXMuX3VpLnJlbW92ZU9wZXJhdGlvbigncm90YXRpb24nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2Nyb3BPcGVyYXRpb24pIHtcbiAgICAgICAgdGhpcy5fY3JvcE9wZXJhdGlvbi5zZXQoe1xuICAgICAgICAgIHN0YXJ0OiB0aGlzLl9pbml0aWFsU3RhcnQsXG4gICAgICAgICAgZW5kOiB0aGlzLl9pbml0aWFsRW5kXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBSb3RhdGlvbkNvbnRyb2w7XG59KShfY29udHJvbDJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5Sb3RhdGlvbkNvbnRyb2wucHJvdG90eXBlLmlkZW50aWZpZXIgPSAncm90YXRpb24nO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBSb3RhdGlvbkNvbnRyb2w7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvY29udHJvbHMvcm90YXRpb24tY29udHJvbC5qc1xuICoqIG1vZHVsZSBpZCA9IDgyXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgX19ET1RKU19URU1QTEFURSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9jb250cm9sID0gcmVxdWlyZSgnLi9jb250cm9sJyk7XG5cbnZhciBfY29udHJvbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jb250cm9sKTtcblxudmFyIEZsaXBDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBGbGlwQ29udHJvbCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRmxpcENvbnRyb2wpO1xuXG4gICAgaWYgKF9Db250cm9sICE9IG51bGwpIHtcbiAgICAgIF9Db250cm9sLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEZsaXBDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKEZsaXBDb250cm9sLCBbe1xuICAgIGtleTogJ2luaXQnLFxuXG4gICAgLyoqXG4gICAgICogRW50cnkgcG9pbnQgZm9yIHRoaXMgY29udHJvbFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgdmFyIGNvbnRyb2xzVGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdj4gPHVsIGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtbGlzdCBpbWdseS1jb250cm9scy1saXN0LXdpdGgtYnV0dG9uc1wiPiA8bGkgZGF0YS1kaXJlY3Rpb249XCJob3Jpem9udGFsXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L2ZsaXAvaG9yaXpvbnRhbC5wbmcnKSkrJ1wiIC8+IDwvbGk+IDxsaSBkYXRhLWRpcmVjdGlvbj1cInZlcnRpY2FsXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L2ZsaXAvdmVydGljYWwucG5nJykpKydcIiAvPiA8L2xpPiA8L3VsPjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLmZsaXA7XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbignZmxpcCcpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsSG9yaXpvbnRhbCA9IHRoaXMuX29wZXJhdGlvbi5nZXRIb3Jpem9udGFsKCk7XG4gICAgICB0aGlzLl9pbml0aWFsVmVydGljYWwgPSB0aGlzLl9vcGVyYXRpb24uZ2V0VmVydGljYWwoKTtcblxuICAgICAgdmFyIGxpc3RJdGVtcyA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3JBbGwoJ2xpJyk7XG4gICAgICB0aGlzLl9saXN0SXRlbXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChsaXN0SXRlbXMpO1xuXG4gICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgbGlzdEl0ZW0gPSBfdGhpcy5fbGlzdEl0ZW1zW2ldO1xuICAgICAgICBsaXN0SXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5fb25MaXN0SXRlbUNsaWNrKGxpc3RJdGVtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IGxpc3RJdGVtLmRhdGFzZXQuZGlyZWN0aW9uO1xuXG4gICAgICAgIGlmIChkaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJyAmJiBfdGhpcy5fb3BlcmF0aW9uLmdldEhvcml6b250YWwoKSkge1xuICAgICAgICAgIF90aGlzLl90b2dnbGVJdGVtKGxpc3RJdGVtLCB0cnVlKTtcbiAgICAgICAgfSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCcgJiYgX3RoaXMuX29wZXJhdGlvbi5nZXRWZXJ0aWNhbCgpKSB7XG4gICAgICAgICAgX3RoaXMuX3RvZ2dsZUl0ZW0obGlzdEl0ZW0sIHRydWUpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvLyBMaXN0ZW4gdG8gY2xpY2sgZXZlbnRzXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xpc3RJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbG9vcChpKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25MaXN0SXRlbUNsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tlZCBhIGxpc3QgaXRlbVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkxpc3RJdGVtQ2xpY2soaXRlbSkge1xuICAgICAgdmFyIGRpcmVjdGlvbiA9IGl0ZW0uZGF0YXNldC5kaXJlY3Rpb247XG5cbiAgICAgIHZhciBhY3RpdmUgPSBmYWxzZTtcblxuICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgIHZhciBjdXJyZW50SG9yaXpvbnRhbCA9IHRoaXMuX29wZXJhdGlvbi5nZXRIb3Jpem9udGFsKCk7XG4gICAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRIb3Jpem9udGFsKCFjdXJyZW50SG9yaXpvbnRhbCk7XG4gICAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICAgICAgYWN0aXZlID0gIWN1cnJlbnRIb3Jpem9udGFsO1xuICAgICAgfSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgICAgdmFyIGN1cnJlbnRWZXJ0aWNhbCA9IHRoaXMuX29wZXJhdGlvbi5nZXRWZXJ0aWNhbCgpO1xuICAgICAgICB0aGlzLl9vcGVyYXRpb24uc2V0VmVydGljYWwoIWN1cnJlbnRWZXJ0aWNhbCk7XG4gICAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICAgICAgYWN0aXZlID0gIWN1cnJlbnRWZXJ0aWNhbDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdG9nZ2xlSXRlbShpdGVtLCBhY3RpdmUpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ190b2dnbGVJdGVtJyxcblxuICAgIC8qKlxuICAgICAqIFRvZ2dsZXMgdGhlIGFjdGl2ZSBzdGF0ZSBvZiB0aGUgZ2l2ZW4gaXRlbVxuICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gaXRlbVxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gYWN0aXZlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3RvZ2dsZUl0ZW0oaXRlbSwgYWN0aXZlKSB7XG4gICAgICB2YXIgYWN0aXZlQ2xhc3MgPSAnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnO1xuICAgICAgaWYgKGFjdGl2ZSkge1xuICAgICAgICBpdGVtLmNsYXNzTGlzdC5hZGQoYWN0aXZlQ2xhc3MpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaXRlbS5jbGFzc0xpc3QucmVtb3ZlKGFjdGl2ZUNsYXNzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CYWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGJhY2sgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmFjaygpIHtcbiAgICAgIHZhciBjdXJyZW50VmVydGljYWwgPSB0aGlzLl9vcGVyYXRpb24uZ2V0VmVydGljYWwoKTtcbiAgICAgIHZhciBjdXJyZW50SG9yaXpvbnRhbCA9IHRoaXMuX29wZXJhdGlvbi5nZXRIb3Jpem9udGFsKCk7XG5cbiAgICAgIGlmICh0aGlzLl9pbml0aWFsVmVydGljYWwgIT09IGN1cnJlbnRWZXJ0aWNhbCB8fCB0aGlzLl9pbml0aWFsSG9yaXpvbnRhbCAhPT0gY3VycmVudEhvcml6b250YWwpIHtcbiAgICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgICB2ZXJ0aWNhbDogdGhpcy5faW5pdGlhbFZlcnRpY2FsLFxuICAgICAgICAgIGhvcml6b250YWw6IHRoaXMuX2luaXRpYWxIb3Jpem9udGFsXG4gICAgICAgIH0sIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWN1cnJlbnRWZXJ0aWNhbCAmJiAhY3VycmVudEhvcml6b250YWwpIHtcbiAgICAgICAgdGhpcy5fdWkucmVtb3ZlT3BlcmF0aW9uKCdmbGlwJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gRmxpcENvbnRyb2w7XG59KShfY29udHJvbDJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5GbGlwQ29udHJvbC5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdmbGlwJztcblxuZXhwb3J0c1snZGVmYXVsdCddID0gRmxpcENvbnRyb2w7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvY29udHJvbHMvZmxpcC1jb250cm9sLmpzXG4gKiogbW9kdWxlIGlkID0gODNcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBfX0RPVEpTX1RFTVBMQVRFICovXG4vKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2NvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcblxudmFyIF9jb250cm9sMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NvbnRyb2wpO1xuXG52YXIgX2xpYlNsaWRlciA9IHJlcXVpcmUoJy4uL2xpYi9zbGlkZXInKTtcblxudmFyIF9saWJTbGlkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliU2xpZGVyKTtcblxudmFyIEJyaWdodG5lc3NDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBCcmlnaHRuZXNzQ29udHJvbCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQnJpZ2h0bmVzc0NvbnRyb2wpO1xuXG4gICAgaWYgKF9Db250cm9sICE9IG51bGwpIHtcbiAgICAgIF9Db250cm9sLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKEJyaWdodG5lc3NDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKEJyaWdodG5lc3NDb250cm9sLCBbe1xuICAgIGtleTogJ2luaXQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGVudHJ5IHBvaW50IGZvciB0aGlzIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgIHZhciBjb250cm9sc1RlbXBsYXRlID0gZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXY+ICcrKGl0LnBhcnRpYWxzLnNsaWRlcikrJzwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuc2xpZGVyID0gX2xpYlNsaWRlcjJbJ2RlZmF1bHQnXS50ZW1wbGF0ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLmJyaWdodG5lc3M7XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbignYnJpZ2h0bmVzcycpO1xuXG4gICAgICAvLyBJbml0aWFsbHkgc2V0IHZhbHVlXG4gICAgICB2YXIgYnJpZ2h0bmVzcyA9IHRoaXMuX29wZXJhdGlvbi5nZXRCcmlnaHRuZXNzKCk7XG4gICAgICB0aGlzLl9pbml0aWFsQnJpZ2h0bmVzcyA9IGJyaWdodG5lc3M7XG5cbiAgICAgIHZhciBzbGlkZXJFbGVtZW50ID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNsaWRlcicpO1xuICAgICAgdGhpcy5fc2xpZGVyID0gbmV3IF9saWJTbGlkZXIyWydkZWZhdWx0J10oc2xpZGVyRWxlbWVudCwge1xuICAgICAgICBtaW5WYWx1ZTogLTEsXG4gICAgICAgIG1heFZhbHVlOiAxLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IGJyaWdodG5lc3NcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fc2xpZGVyLm9uKCd1cGRhdGUnLCB0aGlzLl9vblVwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX3NsaWRlci5zZXRWYWx1ZSh0aGlzLl9pbml0aWFsQnJpZ2h0bmVzcyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICB2YXIgY3VycmVudEJyaWdodG5lc3MgPSB0aGlzLl9vcGVyYXRpb24uZ2V0QnJpZ2h0bmVzcygpO1xuXG4gICAgICBpZiAodGhpcy5faW5pdGlhbEJyaWdodG5lc3MgIT09IGN1cnJlbnRCcmlnaHRuZXNzKSB7XG4gICAgICAgIHRoaXMuX3VpLmFkZEhpc3RvcnkodGhpcy5fb3BlcmF0aW9uLCB7XG4gICAgICAgICAgYnJpZ2h0bmVzczogdGhpcy5faW5pdGlhbEJyaWdodG5lc3NcbiAgICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50QnJpZ2h0bmVzcyA9PT0gMSkge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ2JyaWdodG5lc3MnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblVwZGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB2YWx1ZSBoYXMgYmVlbiB1cGRhdGVkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblVwZGF0ZSh2YWx1ZSkge1xuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldEJyaWdodG5lc3ModmFsdWUpO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBCcmlnaHRuZXNzQ29udHJvbDtcbn0pKF9jb250cm9sMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgY29udHJvbC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cbkJyaWdodG5lc3NDb250cm9sLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ2JyaWdodG5lc3MnO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBCcmlnaHRuZXNzQ29udHJvbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9jb250cm9scy9icmlnaHRuZXNzLWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA4NFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfY29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbCcpO1xuXG52YXIgX2NvbnRyb2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY29udHJvbCk7XG5cbnZhciBfbGliU2xpZGVyID0gcmVxdWlyZSgnLi4vbGliL3NsaWRlcicpO1xuXG52YXIgX2xpYlNsaWRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJTbGlkZXIpO1xuXG52YXIgQ29udHJhc3RDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBDb250cmFzdENvbnRyb2woKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENvbnRyYXN0Q29udHJvbCk7XG5cbiAgICBpZiAoX0NvbnRyb2wgIT0gbnVsbCkge1xuICAgICAgX0NvbnRyb2wuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQ29udHJhc3RDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKENvbnRyYXN0Q29udHJvbCwgW3tcbiAgICBrZXk6ICdpbml0JyxcblxuICAgIC8qKlxuICAgICAqIEVudHJ5IHBvaW50IGZvciB0aGlzIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgIHZhciBjb250cm9sc1RlbXBsYXRlID0gZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXY+ICcrKGl0LnBhcnRpYWxzLnNsaWRlcikrJzwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuc2xpZGVyID0gX2xpYlNsaWRlcjJbJ2RlZmF1bHQnXS50ZW1wbGF0ZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLmNvbnRyYXN0O1xuICAgICAgdGhpcy5fb3BlcmF0aW9uID0gdGhpcy5fdWkuZ2V0T3JDcmVhdGVPcGVyYXRpb24oJ2NvbnRyYXN0Jyk7XG5cbiAgICAgIC8vIEluaXRpYWxseSBzZXQgdmFsdWVcbiAgICAgIHZhciBjb250cmFzdCA9IHRoaXMuX29wZXJhdGlvbi5nZXRDb250cmFzdCgpO1xuICAgICAgdGhpcy5faW5pdGlhbENvbnRyYXN0ID0gY29udHJhc3Q7XG5cbiAgICAgIHZhciBzbGlkZXJFbGVtZW50ID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNsaWRlcicpO1xuICAgICAgdGhpcy5fc2xpZGVyID0gbmV3IF9saWJTbGlkZXIyWydkZWZhdWx0J10oc2xpZGVyRWxlbWVudCwge1xuICAgICAgICBtaW5WYWx1ZTogMCxcbiAgICAgICAgbWF4VmFsdWU6IDIsXG4gICAgICAgIGRlZmF1bHRWYWx1ZTogY29udHJhc3RcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fc2xpZGVyLm9uKCd1cGRhdGUnLCB0aGlzLl9vblVwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX3NsaWRlci5zZXRWYWx1ZSh0aGlzLl9pbml0aWFsQ29udHJhc3QpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJhY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgYmFjayBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CYWNrKCkge1xuICAgICAgdmFyIGN1cnJlbnRDb250cmFzdCA9IHRoaXMuX29wZXJhdGlvbi5nZXRDb250cmFzdCgpO1xuXG4gICAgICBpZiAodGhpcy5faW5pdGlhbENvbnRyYXN0ICE9PSBjdXJyZW50Q29udHJhc3QpIHtcbiAgICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgICBjb250cmFzdDogdGhpcy5faW5pdGlhbENvbnRyYXN0XG4gICAgICAgIH0sIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY3VycmVudENvbnRyYXN0ID09PSAxKSB7XG4gICAgICAgIHRoaXMuX3VpLnJlbW92ZU9wZXJhdGlvbignY29udHJhc3QnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblVwZGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB2YWx1ZSBoYXMgYmVlbiB1cGRhdGVkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblVwZGF0ZSh2YWx1ZSkge1xuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldENvbnRyYXN0KHZhbHVlKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQ29udHJhc3RDb250cm9sO1xufSkoX2NvbnRyb2wyWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBjb250cm9sLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuQ29udHJhc3RDb250cm9sLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ2NvbnRyYXN0JztcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ29udHJhc3RDb250cm9sO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2NvbnRyb2xzL2NvbnRyYXN0LWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA4NVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliU2xpZGVyID0gcmVxdWlyZSgnLi4vbGliL3NsaWRlcicpO1xuXG52YXIgX2xpYlNsaWRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJTbGlkZXIpO1xuXG52YXIgX2NvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcblxudmFyIF9jb250cm9sMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NvbnRyb2wpO1xuXG52YXIgU2F0dXJhdGlvbkNvbnRyb2wgPSAoZnVuY3Rpb24gKF9Db250cm9sKSB7XG4gIGZ1bmN0aW9uIFNhdHVyYXRpb25Db250cm9sKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBTYXR1cmF0aW9uQ29udHJvbCk7XG5cbiAgICBpZiAoX0NvbnRyb2wgIT0gbnVsbCkge1xuICAgICAgX0NvbnRyb2wuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoU2F0dXJhdGlvbkNvbnRyb2wsIF9Db250cm9sKTtcblxuICBfY3JlYXRlQ2xhc3MoU2F0dXJhdGlvbkNvbnRyb2wsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBFbnRyeSBwb2ludCBmb3IgdGhpcyBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICB2YXIgY29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2PiAnKyhpdC5wYXJ0aWFscy5zbGlkZXIpKyc8L2Rpdj4nO3JldHVybiBvdXQ7XG59O1xuICAgICAgdGhpcy5fY29udHJvbHNUZW1wbGF0ZSA9IGNvbnRyb2xzVGVtcGxhdGU7XG4gICAgICB0aGlzLl9wYXJ0aWFsVGVtcGxhdGVzLnNsaWRlciA9IF9saWJTbGlkZXIyWydkZWZhdWx0J10udGVtcGxhdGU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRW50ZXInLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGlzIGNvbnRyb2wgaXMgYWN0aXZhdGVkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkVudGVyKCkge1xuICAgICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoU2F0dXJhdGlvbkNvbnRyb2wucHJvdG90eXBlKSwgJ19vbkVudGVyJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgICAgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSA9ICEhdGhpcy5fdWkub3BlcmF0aW9ucy5zYXR1cmF0aW9uO1xuICAgICAgdGhpcy5fb3BlcmF0aW9uID0gdGhpcy5fdWkuZ2V0T3JDcmVhdGVPcGVyYXRpb24oJ3NhdHVyYXRpb24nKTtcblxuICAgICAgLy8gSW5pdGlhbGx5IHNldCB2YWx1ZVxuICAgICAgdmFyIHNhdHVyYXRpb24gPSB0aGlzLl9vcGVyYXRpb24uZ2V0U2F0dXJhdGlvbigpO1xuICAgICAgdGhpcy5faW5pdGlhbFNhdHVyYXRpb24gPSBzYXR1cmF0aW9uO1xuXG4gICAgICB2YXIgc2xpZGVyRWxlbWVudCA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1zbGlkZXInKTtcbiAgICAgIHRoaXMuX3NsaWRlciA9IG5ldyBfbGliU2xpZGVyMlsnZGVmYXVsdCddKHNsaWRlckVsZW1lbnQsIHtcbiAgICAgICAgbWluVmFsdWU6IDAsXG4gICAgICAgIG1heFZhbHVlOiAyLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IHNhdHVyYXRpb25cbiAgICAgIH0pO1xuICAgICAgdGhpcy5fc2xpZGVyLm9uKCd1cGRhdGUnLCB0aGlzLl9vblVwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX3NsaWRlci5zZXRWYWx1ZSh0aGlzLl9pbml0aWFsU2F0dXJhdGlvbik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICB2YXIgY3VycmVudFNhdHVyYXRpb24gPSB0aGlzLl9vcGVyYXRpb24uZ2V0U2F0dXJhdGlvbigpO1xuXG4gICAgICBpZiAodGhpcy5faW5pdGlhbFNhdHVyYXRpb24gIT09IGN1cnJlbnRTYXR1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuX3VpLmFkZEhpc3RvcnkodGhpcy5fb3BlcmF0aW9uLCB7XG4gICAgICAgICAgc2F0dXJhdGlvbjogdGhpcy5faW5pdGlhbFNhdHVyYXRpb25cbiAgICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50U2F0dXJhdGlvbiA9PT0gMSkge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ3NhdHVyYXRpb24nKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblVwZGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB2YWx1ZSBoYXMgYmVlbiB1cGRhdGVkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblVwZGF0ZSh2YWx1ZSkge1xuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldFNhdHVyYXRpb24odmFsdWUpO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBTYXR1cmF0aW9uQ29udHJvbDtcbn0pKF9jb250cm9sMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgY29udHJvbC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cblNhdHVyYXRpb25Db250cm9sLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ3NhdHVyYXRpb24nO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTYXR1cmF0aW9uQ29udHJvbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9jb250cm9scy9zYXR1cmF0aW9uLWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA4NlxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDIsIF94MywgX3g0KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MiwgcHJvcGVydHkgPSBfeDMsIHJlY2VpdmVyID0gX3g0OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDIgPSBwYXJlbnQ7IF94MyA9IHByb3BlcnR5OyBfeDQgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfY29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbCcpO1xuXG52YXIgX2NvbnRyb2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY29udHJvbCk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgQ3JvcENvbnRyb2wgPSAoZnVuY3Rpb24gKF9Db250cm9sKSB7XG4gIGZ1bmN0aW9uIENyb3BDb250cm9sKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDcm9wQ29udHJvbCk7XG5cbiAgICBpZiAoX0NvbnRyb2wgIT0gbnVsbCkge1xuICAgICAgX0NvbnRyb2wuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoQ3JvcENvbnRyb2wsIF9Db250cm9sKTtcblxuICBfY3JlYXRlQ2xhc3MoQ3JvcENvbnRyb2wsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBFbnRyeSBwb2ludCBmb3IgdGhpcyBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICB0aGlzLl9hdmFpbGFibGVSYXRpb3MgPSB7fTtcbiAgICAgIHRoaXMuX3JhdGlvcyA9IHt9O1xuXG4gICAgICB2YXIgY29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2PiA8dWwgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1saXN0IGltZ2x5LWNvbnRyb2xzLWxpc3Qtd2l0aC1idXR0b25zXCI+ICc7IGZvcih2YXIgaWRlbnRpZmllciBpbiBpdC5yYXRpb3MpIHsgb3V0Kz0nICc7IHZhciByYXRpbyA9IGl0LnJhdGlvc1tpZGVudGlmaWVyXTsgb3V0Kz0nICc7IHZhciBlbmFibGVkID0gcmF0aW8uc2VsZWN0ZWQ7IG91dCs9JyA8bGkgZGF0YS1pZGVudGlmaWVyPVwiJysoIGlkZW50aWZpZXIpKydcIiBkYXRhLXJhdGlvPVwiJysoIHJhdGlvLnJhdGlvKSsnXCInO2lmKGVuYWJsZWQpe291dCs9JyBkYXRhLXNlbGVjdGVkJzt9b3V0Kz0nPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9jcm9wLycgKyBpZGVudGlmaWVyICsgJy5wbmcnKSkrJ1wiIC8+IDwvbGk+ICc7IH0gb3V0Kz0nIDwvdWw+PC9kaXY+JysoaXQucGFydGlhbHMuZG9uZUJ1dHRvbik7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcblxuICAgICAgdmFyIGNhbnZhc0NvbnRyb2xzVGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1jcm9wLWNvbnRhaW5lclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtdG9wXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC10b3AtbGVmdFwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtdG9wLWNlbnRlclwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtdG9wLXJpZ2h0XCI+PC9kaXY+IDwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtY2VudGVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1jZW50ZXItbGVmdFwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtY2VudGVyLWNlbnRlclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3Ata25vYnNcIj4gPGRpdiBkYXRhLWNvcm5lcj1cInRvcC1sZWZ0XCI+PC9kaXY+IDxkaXYgZGF0YS1jb3JuZXI9XCJ0b3AtcmlnaHRcIj48L2Rpdj4gPGRpdiBkYXRhLWNvcm5lcj1cImJvdHRvbS1sZWZ0XCI+PC9kaXY+IDxkaXYgZGF0YS1jb3JuZXI9XCJib3R0b20tcmlnaHRcIj48L2Rpdj4gPC9kaXY+IDwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtY2VudGVyLXJpZ2h0XCI+PC9kaXY+IDwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtYm90dG9tXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtY3JvcC1ib3R0b20tbGVmdFwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtYm90dG9tLWNlbnRlclwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLWNyb3AtYm90dG9tLXJpZ2h0XCI+PC9kaXY+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc1RlbXBsYXRlID0gY2FudmFzQ29udHJvbHNUZW1wbGF0ZTtcblxuICAgICAgLy8gTW91c2UgZXZlbnQgY2FsbGJhY2tzIGJvdW5kIHRvIHRoZSBjbGFzcyBjb250ZXh0XG4gICAgICB0aGlzLl9vbktub2JEb3duID0gdGhpcy5fb25Lbm9iRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Lbm9iRHJhZyA9IHRoaXMuX29uS25vYkRyYWcuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uS25vYlVwID0gdGhpcy5fb25Lbm9iVXAuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uQ2VudGVyRG93biA9IHRoaXMuX29uQ2VudGVyRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25DZW50ZXJEcmFnID0gdGhpcy5fb25DZW50ZXJEcmFnLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbkNlbnRlclVwID0gdGhpcy5fb25DZW50ZXJVcC5iaW5kKHRoaXMpO1xuXG4gICAgICB0aGlzLl9hZGREZWZhdWx0UmF0aW9zKCk7XG5cbiAgICAgIC8vIFNlbGVjdCBhbGwgcmF0aW9zIHBlciBkZWZhdWx0XG4gICAgICB0aGlzLnNlbGVjdFJhdGlvcyhudWxsKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzZWxlY3RSYXRpb3MnLFxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgcmF0aW9zXG4gICAgICogQHBhcmFtIHtTZWxlY3Rvcn0gc2VsZWN0b3JcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2VsZWN0UmF0aW9zKHNlbGVjdG9yKSB7XG4gICAgICB0aGlzLl9yYXRpb3MgPSB7fTtcblxuICAgICAgdmFyIHJhdGlvSWRlbnRpZmllcnMgPSBPYmplY3Qua2V5cyh0aGlzLl9hdmFpbGFibGVSYXRpb3MpO1xuXG4gICAgICB2YXIgc2VsZWN0ZWRSYXRpb3MgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uc2VsZWN0KHJhdGlvSWRlbnRpZmllcnMsIHNlbGVjdG9yKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZWN0ZWRSYXRpb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkZW50aWZpZXIgPSBzZWxlY3RlZFJhdGlvc1tpXTtcbiAgICAgICAgdGhpcy5fcmF0aW9zW2lkZW50aWZpZXJdID0gdGhpcy5fYXZhaWxhYmxlUmF0aW9zW2lkZW50aWZpZXJdO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fYWN0aXZlKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlckNvbnRyb2xzKCk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2FkZERlZmF1bHRSYXRpb3MnLFxuXG4gICAgLyoqXG4gICAgICogQWRkcyB0aGUgZGVmYXVsdCByYXRpb3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfYWRkRGVmYXVsdFJhdGlvcygpIHtcbiAgICAgIHRoaXMuYWRkUmF0aW8oJ2N1c3RvbScsICcqJywgdHJ1ZSk7XG4gICAgICB0aGlzLmFkZFJhdGlvKCdzcXVhcmUnLCAnMScpO1xuICAgICAgdGhpcy5hZGRSYXRpbygnNC0zJywgJzEuMzMnKTtcbiAgICAgIHRoaXMuYWRkUmF0aW8oJzE2LTknLCAnMS43NycpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2FkZFJhdGlvJyxcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSByYXRpbyB3aXRoIHRoZSBnaXZlbiBpZGVudGlmaWVyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gcmF0aW9cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHNlbGVjdGVkXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZFJhdGlvKGlkZW50aWZpZXIsIHJhdGlvLCBzZWxlY3RlZCkge1xuICAgICAgdGhpcy5fYXZhaWxhYmxlUmF0aW9zW2lkZW50aWZpZXJdID0geyByYXRpbzogcmF0aW8sIHNlbGVjdGVkOiBzZWxlY3RlZCB9O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkVudGVyJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhpcyBjb250cm9sIGlzIGFjdGl2YXRlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25FbnRlcigpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKENyb3BDb250cm9sLnByb3RvdHlwZSksICdfb25FbnRlcicsIHRoaXMpLmNhbGwodGhpcyk7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUgPSAhIXRoaXMuX3VpLm9wZXJhdGlvbnMuY3JvcDtcbiAgICAgIHRoaXMuX29wZXJhdGlvbiA9IHRoaXMuX3VpLmdldE9yQ3JlYXRlT3BlcmF0aW9uKCdjcm9wJyk7XG5cbiAgICAgIHRoaXMuX2RlZmF1bHRTdGFydCA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMC4xLCAwLjEpO1xuICAgICAgdGhpcy5fZGVmYXVsdEVuZCA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMC45LCAwLjkpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsT3B0aW9ucyA9IHtcbiAgICAgICAgc3RhcnQ6IHRoaXMuX29wZXJhdGlvbi5nZXRTdGFydCgpLFxuICAgICAgICBlbmQ6IHRoaXMuX29wZXJhdGlvbi5nZXRFbmQoKVxuICAgICAgfTtcblxuICAgICAgdGhpcy5fc3RhcnQgPSB0aGlzLl9pbml0aWFsT3B0aW9ucy5zdGFydCB8fCB0aGlzLl9kZWZhdWx0U3RhcnQ7XG4gICAgICB0aGlzLl9lbmQgPSB0aGlzLl9pbml0aWFsT3B0aW9ucy5lbmQgfHwgdGhpcy5fZGVmYXVsdEVuZDtcblxuICAgICAgLy8gTWluaW11bSBzaXplIGluIHBpeGVsc1xuICAgICAgdGhpcy5fbWluaW11bVNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDUwLCA1MCk7XG5cbiAgICAgIHRoaXMuX2luaXRpYWxab29tTGV2ZWwgPSB0aGlzLl91aS5jYW52YXMuem9vbUxldmVsO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnpvb21Ub0ZpdChmYWxzZSk7XG5cbiAgICAgIHZhciBwcmVmaXggPSAnLmltZ2x5a2l0LWNhbnZhcy1jcm9wJztcbiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLl9jYW52YXNDb250cm9scztcbiAgICAgIHZhciBrbm9ic0NvbnRhaW5lciA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcnICsgcHJlZml4ICsgJy1rbm9icycpO1xuXG4gICAgICAvLyBTdG9yZSBpbml0aWFsIHNldHRpbmdzIGZvciAnYmFjaycgYnV0dG9uXG4gICAgICB0aGlzLl9pbml0aWFsU3RhcnQgPSB0aGlzLl9vcGVyYXRpb24uZ2V0U3RhcnQoKS5jbG9uZSgpO1xuICAgICAgdGhpcy5faW5pdGlhbEVuZCA9IHRoaXMuX29wZXJhdGlvbi5nZXRFbmQoKS5jbG9uZSgpO1xuXG4gICAgICAvLyBNYWtlIHN1cmUgd2Ugc2VlIHRoZSB3aG9sZSBpbnB1dCBpbWFnZVxuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldCh7XG4gICAgICAgIHN0YXJ0OiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDApLFxuICAgICAgICBlbmQ6IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMSwgMSlcbiAgICAgIH0pO1xuXG4gICAgICAvLyBGaW5kIGFsbCA0IGtub2JzXG4gICAgICB0aGlzLl9rbm9icyA9IHtcbiAgICAgICAgdG9wTGVmdDoga25vYnNDb250YWluZXIucXVlcnlTZWxlY3RvcignW2RhdGEtY29ybmVyPXRvcC1sZWZ0XScpLFxuICAgICAgICB0b3BSaWdodDoga25vYnNDb250YWluZXIucXVlcnlTZWxlY3RvcignW2RhdGEtY29ybmVyPXRvcC1yaWdodF0nKSxcbiAgICAgICAgYm90dG9tTGVmdDoga25vYnNDb250YWluZXIucXVlcnlTZWxlY3RvcignW2RhdGEtY29ybmVyPWJvdHRvbS1sZWZ0XScpLFxuICAgICAgICBib3R0b21SaWdodDoga25vYnNDb250YWluZXIucXVlcnlTZWxlY3RvcignW2RhdGEtY29ybmVyPWJvdHRvbS1yaWdodF0nKVxuICAgICAgfTtcblxuICAgICAgLy8gRmluZCB0aGUgZGl2IGFyZWFzIHRoYXQgYWZmZWN0IHRoZSBkaXNwbGF5ZWQgY3JvcCBzaXplXG4gICAgICB0aGlzLl9hcmVhcyA9IHtcbiAgICAgICAgdG9wTGVmdDogdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignJyArIHByZWZpeCArICctdG9wLWxlZnQnKSxcbiAgICAgICAgdG9wQ2VudGVyOiB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcnICsgcHJlZml4ICsgJy10b3AtY2VudGVyJyksXG4gICAgICAgIGNlbnRlckxlZnQ6IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJycgKyBwcmVmaXggKyAnLWNlbnRlci1sZWZ0JyksXG4gICAgICAgIGNlbnRlckNlbnRlcjogdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignJyArIHByZWZpeCArICctY2VudGVyLWNlbnRlcicpXG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9oYW5kbGVDb250cm9scygpO1xuICAgICAgdGhpcy5faGFuZGxlS25vYnMoKTtcbiAgICAgIHRoaXMuX2hhbmRsZUNlbnRlcigpO1xuXG4gICAgICAvLyBSZXN1bWUgdGhlIHJlbmRlcmluZ1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlQ29udHJvbHMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgcmF0aW8gY29udHJvbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlQ29udHJvbHMoKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIGxpc3RJdGVtcyA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3JBbGwoJ3VsID4gbGknKTtcbiAgICAgIHRoaXMuX3JhdGlvSXRlbXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChsaXN0SXRlbXMpO1xuXG4gICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgaXRlbSA9IF90aGlzMi5fcmF0aW9JdGVtc1tpXTtcbiAgICAgICAgdmFyIF9pdGVtJGRhdGFzZXQgPSBpdGVtLmRhdGFzZXQ7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9IF9pdGVtJGRhdGFzZXQuc2VsZWN0ZWQ7XG4gICAgICAgIHZhciByYXRpbyA9IF9pdGVtJGRhdGFzZXQucmF0aW87XG4gICAgICAgIHZhciBpZGVudGlmaWVyID0gX2l0ZW0kZGF0YXNldC5pZGVudGlmaWVyO1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc2VsZWN0ZWQgIT09ICd1bmRlZmluZWQnICYmICFfdGhpczIuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUpIHtcbiAgICAgICAgICBfdGhpczIuX3NldFJhdGlvKGlkZW50aWZpZXIsIHJhdGlvLCBmYWxzZSk7XG4gICAgICAgICAgX3RoaXMyLl9zZWxlY3RSYXRpbyhpdGVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGl0ZW0uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICBfdGhpczIuX29uUmF0aW9DbGljayhpdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3JhdGlvSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgX2xvb3AoaSk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uUmF0aW9DbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBnaXZlbiByYXRpbyBoYXMgYmVlbiBzZWxlY3RlZFxuICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gaXRlbVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblJhdGlvQ2xpY2soaXRlbSkge1xuICAgICAgdGhpcy5fdW5zZWxlY3RBbGxSYXRpb3MoKTtcbiAgICAgIHRoaXMuX3NlbGVjdFJhdGlvKGl0ZW0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191bnNlbGVjdEFsbFJhdGlvcycsXG5cbiAgICAvKipcbiAgICAgKiBVbnNlbGVjdHMgYWxsIHJhdGlvIGNvbnRyb2wgaXRlbXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfdW5zZWxlY3RBbGxSYXRpb3MoKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3JhdGlvSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGl0ZW0gPSB0aGlzLl9yYXRpb0l0ZW1zW2ldO1xuICAgICAgICBpdGVtLmNsYXNzTGlzdC5yZW1vdmUoJ2ltZ2x5a2l0LWNvbnRyb2xzLWl0ZW0tYWN0aXZlJyk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3NlbGVjdFJhdGlvJyxcblxuICAgIC8qKlxuICAgICAqIEFjdGl2YXRlcyB0aGUgZ2l2ZW4gcmF0aW8gY29udHJvbCBpdGVtXG4gICAgICogQHBhcmFtIHtET01FbGVtZW50fSBpdGVtXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3NlbGVjdFJhdGlvKGl0ZW0pIHtcbiAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnKTtcbiAgICAgIHZhciBfaXRlbSRkYXRhc2V0MiA9IGl0ZW0uZGF0YXNldDtcbiAgICAgIHZhciByYXRpbyA9IF9pdGVtJGRhdGFzZXQyLnJhdGlvO1xuICAgICAgdmFyIGlkZW50aWZpZXIgPSBfaXRlbSRkYXRhc2V0Mi5pZGVudGlmaWVyO1xuXG4gICAgICB0aGlzLl9zZXRSYXRpbyhpZGVudGlmaWVyLCByYXRpbyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3NldFJhdGlvJyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGdpdmVuIHJhdGlvXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcmF0aW9cbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlc2l6ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9zZXRSYXRpbyhpZGVudGlmaWVyLCByYXRpbykge1xuICAgICAgdmFyIHJlc2l6ZSA9IGFyZ3VtZW50c1syXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1syXTtcblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcbiAgICAgIHRoaXMuX3NlbGVjdGVkUmF0aW8gPSBpZGVudGlmaWVyO1xuXG4gICAgICBpZiAocmF0aW8gPT09ICcqJykge1xuICAgICAgICB0aGlzLl9yYXRpbyA9IG51bGw7XG4gICAgICAgIHRoaXMuX3N0YXJ0ID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLjEsIDAuMSk7XG4gICAgICAgIHRoaXMuX2VuZCA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMC45LCAwLjkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHJhdGlvID09PSAnb3JpZ2luYWwnKSB7XG4gICAgICAgICAgdGhpcy5fcmF0aW8gPSBjYW52YXNTaXplLnggLyBjYW52YXNTaXplLnk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmF0aW8gPSBwYXJzZUZsb2F0KHJhdGlvKTtcbiAgICAgICAgICB0aGlzLl9yYXRpbyA9IHJhdGlvO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlc2l6ZSkge1xuICAgICAgICAgIGlmIChjYW52YXNTaXplLnggLyBjYW52YXNTaXplLnkgPD0gdGhpcy5fcmF0aW8pIHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnggPSAwLjE7XG4gICAgICAgICAgICB0aGlzLl9lbmQueCA9IDAuOTtcbiAgICAgICAgICAgIHZhciBoZWlnaHQgPSAxIC8gY2FudmFzU2l6ZS55ICogKGNhbnZhc1NpemUueCAvIHRoaXMuX3JhdGlvICogMC44KTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnkgPSAoMSAtIGhlaWdodCkgLyAyO1xuICAgICAgICAgICAgdGhpcy5fZW5kLnkgPSAxIC0gdGhpcy5fc3RhcnQueTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fc3RhcnQueSA9IDAuMTtcbiAgICAgICAgICAgIHRoaXMuX2VuZC55ID0gMC45O1xuICAgICAgICAgICAgdmFyIHdpZHRoID0gMSAvIGNhbnZhc1NpemUueCAqICh0aGlzLl9yYXRpbyAqIGNhbnZhc1NpemUueSAqIDAuOCk7XG4gICAgICAgICAgICB0aGlzLl9zdGFydC54ID0gKDEgLSB3aWR0aCkgLyAyO1xuICAgICAgICAgICAgdGhpcy5fZW5kLnggPSAxIC0gdGhpcy5fc3RhcnQueDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZURPTScsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBjcm9wcGluZyBkaXZzIGZvciB0aGUgY3VycmVudCBvcGVyYXRpb24gc2V0dGluZ3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfdXBkYXRlRE9NKCkge1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcbiAgICAgIHZhciBzdGFydEFic29sdXRlID0gdGhpcy5fc3RhcnQuY2xvbmUoKS5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIHZhciBlbmRBYnNvbHV0ZSA9IHRoaXMuX2VuZC5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgdmFyIHNpemUgPSBlbmRBYnNvbHV0ZS5jbG9uZSgpLnN1YnRyYWN0KHN0YXJ0QWJzb2x1dGUpO1xuXG4gICAgICB2YXIgdG9wID0gTWF0aC5tYXgoMSwgc3RhcnRBYnNvbHV0ZS55KTtcbiAgICAgIHZhciBsZWZ0ID0gTWF0aC5tYXgoMSwgc3RhcnRBYnNvbHV0ZS54KTtcbiAgICAgIHZhciB3aWR0aCA9IE1hdGgubWF4KDEsIHNpemUueCk7XG4gICAgICB2YXIgaGVpZ2h0ID0gTWF0aC5tYXgoMSwgc2l6ZS55KTtcblxuICAgICAgLy8gd2lkdGhzIGFyZSBkZWZpbmVkIGJ5IHRvcCBsZWZ0IGFuZCB0b3AgY2VudGVyIGFyZWFzXG4gICAgICB0aGlzLl9hcmVhcy50b3BMZWZ0LnN0eWxlLndpZHRoID0gJycgKyBsZWZ0ICsgJ3B4JztcbiAgICAgIHRoaXMuX2FyZWFzLnRvcENlbnRlci5zdHlsZS53aWR0aCA9ICcnICsgd2lkdGggKyAncHgnO1xuXG4gICAgICAvLyBoZWlnaHRzIGFyZSBkZWZpbmVkIGJ5IHRvcCBsZWZ0IGFuZCBjZW50ZXIgbGVmdCBhcmVhc1xuICAgICAgdGhpcy5fYXJlYXMudG9wTGVmdC5zdHlsZS5oZWlnaHQgPSAnJyArIHRvcCArICdweCc7XG4gICAgICB0aGlzLl9hcmVhcy5jZW50ZXJMZWZ0LnN0eWxlLmhlaWdodCA9ICcnICsgaGVpZ2h0ICsgJ3B4JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlS25vYnMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUga25vYiBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVLbm9icygpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgX2xvb3AyID0gZnVuY3Rpb24gKGlkZW50aWZpZXIpIHtcbiAgICAgICAgdmFyIGtub2IgPSBfdGhpczMuX2tub2JzW2lkZW50aWZpZXJdO1xuICAgICAgICBrbm9iLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgX3RoaXMzLl9vbktub2JEb3duKGUsIGtub2IpO1xuICAgICAgICB9KTtcbiAgICAgICAga25vYi5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICBfdGhpczMuX29uS25vYkRvd24oZSwga25vYik7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgZm9yICh2YXIgaWRlbnRpZmllciBpbiB0aGlzLl9rbm9icykge1xuICAgICAgICBfbG9vcDIoaWRlbnRpZmllcik7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uS25vYkRvd24nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBwcmVzc2VzIGEga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGtub2JcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Lbm9iRG93bihlLCBrbm9iKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICB0aGlzLl9jdXJyZW50S25vYiA9IGtub2I7XG4gICAgICB0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuXG4gICAgICAvLyBSZW1lbWJlciB0aGUgY3VycmVudCB2YWx1ZXNcbiAgICAgIHRoaXMuX3N0YXJ0QmVmb3JlRHJhZyA9IHRoaXMuX3N0YXJ0LmNsb25lKCk7XG4gICAgICB0aGlzLl9lbmRCZWZvcmVEcmFnID0gdGhpcy5fZW5kLmNsb25lKCk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uS25vYkRyYWcpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25Lbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Lbm9iVXApO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbktub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uS25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlIHRoZSB1c2VyIGRyYWdzIGEga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Lbm9iRHJhZyhlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgbW91c2VEaWZmID0gbW91c2VQb3NpdGlvbi5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG4gICAgICB2YXIgY29ybmVyID0gdGhpcy5fY3VycmVudEtub2IuZGF0YXNldC5jb3JuZXI7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuXG4gICAgICB2YXIgYWJzb2x1dGVTdGFydCA9IHRoaXMuX3N0YXJ0QmVmb3JlRHJhZy5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgdmFyIGFic29sdXRlRW5kID0gdGhpcy5fZW5kQmVmb3JlRHJhZy5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuXG4gICAgICB2YXIgd2lkdGggPSB1bmRlZmluZWQsXG4gICAgICAgICAgaGVpZ2h0ID0gdW5kZWZpbmVkLFxuICAgICAgICAgIG1heGltdW0gPSB1bmRlZmluZWQsXG4gICAgICAgICAgbWluaW11bSA9IHVuZGVmaW5lZDtcblxuICAgICAgc3dpdGNoIChjb3JuZXIpIHtcbiAgICAgICAgY2FzZSAndG9wLWxlZnQnOlxuICAgICAgICAgIGFic29sdXRlU3RhcnQuYWRkKG1vdXNlRGlmZik7XG4gICAgICAgICAgbWF4aW11bSA9IGFic29sdXRlRW5kLmNsb25lKCkuc3VidHJhY3QodGhpcy5fbWluaW11bVNpemUpO1xuICAgICAgICAgIGFic29sdXRlU3RhcnQuY2xhbXAobnVsbCwgbWF4aW11bSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3RvcC1yaWdodCc6XG4gICAgICAgICAgYWJzb2x1dGVFbmQueCArPSBtb3VzZURpZmYueDtcbiAgICAgICAgICBhYnNvbHV0ZVN0YXJ0LnkgKz0gbW91c2VEaWZmLnk7XG4gICAgICAgICAgYWJzb2x1dGVFbmQueCA9IE1hdGgubWF4KGFic29sdXRlU3RhcnQueCArIHRoaXMuX21pbmltdW1TaXplLngsIGFic29sdXRlRW5kLngpO1xuICAgICAgICAgIGFic29sdXRlU3RhcnQueSA9IE1hdGgubWluKGFic29sdXRlRW5kLnkgLSB0aGlzLl9taW5pbXVtU2l6ZS55LCBhYnNvbHV0ZVN0YXJ0LnkpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgIGFic29sdXRlRW5kLmFkZChtb3VzZURpZmYpO1xuICAgICAgICAgIG1pbmltdW0gPSBhYnNvbHV0ZVN0YXJ0LmNsb25lKCkuYWRkKHRoaXMuX21pbmltdW1TaXplKTtcbiAgICAgICAgICBhYnNvbHV0ZUVuZC5jbGFtcChtaW5pbXVtKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgIGFic29sdXRlU3RhcnQueCArPSBtb3VzZURpZmYueDtcbiAgICAgICAgICBhYnNvbHV0ZUVuZC55ICs9IG1vdXNlRGlmZi55O1xuICAgICAgICAgIGFic29sdXRlU3RhcnQueCA9IE1hdGgubWluKGFic29sdXRlRW5kLnggLSB0aGlzLl9taW5pbXVtU2l6ZS54LCBhYnNvbHV0ZVN0YXJ0LngpO1xuICAgICAgICAgIGFic29sdXRlRW5kLnkgPSBNYXRoLm1heChhYnNvbHV0ZVN0YXJ0LnkgKyB0aGlzLl9taW5pbXVtU2l6ZS55LCBhYnNvbHV0ZUVuZC55KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc3RhcnQuY29weShhYnNvbHV0ZVN0YXJ0KS5kaXZpZGUoY2FudmFzU2l6ZSk7XG4gICAgICB0aGlzLl9lbmQuY29weShhYnNvbHV0ZUVuZCkuZGl2aWRlKGNhbnZhc1NpemUpO1xuXG4gICAgICB0aGlzLl9zdGFydC5jbGFtcCgwLCAxKTtcbiAgICAgIHRoaXMuX2VuZC5jbGFtcCgwLCAxKTtcblxuICAgICAgLyoqXG4gICAgICAgKiBDYWxjdWxhdGUgYm91bmRhcmllc1xuICAgICAgICovXG4gICAgICBpZiAodGhpcy5fcmF0aW8gIT09IG51bGwpIHtcbiAgICAgICAgc3dpdGNoIChjb3JuZXIpIHtcbiAgICAgICAgICBjYXNlICd0b3AtbGVmdCc6XG4gICAgICAgICAgICB3aWR0aCA9ICh0aGlzLl9lbmQueCAtIHRoaXMuX3N0YXJ0LngpICogY2FudmFzU2l6ZS54O1xuICAgICAgICAgICAgaGVpZ2h0ID0gd2lkdGggLyB0aGlzLl9yYXRpbztcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnkgPSB0aGlzLl9lbmQueSAtIGhlaWdodCAvIGNhbnZhc1NpemUueTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX3N0YXJ0LnkgPD0gMCkge1xuICAgICAgICAgICAgICB0aGlzLl9zdGFydC55ID0gMDtcbiAgICAgICAgICAgICAgaGVpZ2h0ID0gKHRoaXMuX2VuZC55IC0gdGhpcy5fc3RhcnQueSkgKiBjYW52YXNTaXplLnk7XG4gICAgICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ICogdGhpcy5fcmF0aW87XG4gICAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnggPSB0aGlzLl9lbmQueCAtIHdpZHRoIC8gY2FudmFzU2l6ZS54O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndG9wLXJpZ2h0JzpcbiAgICAgICAgICAgIHdpZHRoID0gKHRoaXMuX2VuZC54IC0gdGhpcy5fc3RhcnQueCkgKiBjYW52YXNTaXplLng7XG4gICAgICAgICAgICBoZWlnaHQgPSB3aWR0aCAvIHRoaXMuX3JhdGlvO1xuICAgICAgICAgICAgdGhpcy5fc3RhcnQueSA9IHRoaXMuX2VuZC55IC0gaGVpZ2h0IC8gY2FudmFzU2l6ZS55O1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fc3RhcnQueSA8PSAwKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnkgPSAwO1xuICAgICAgICAgICAgICBoZWlnaHQgPSAodGhpcy5fZW5kLnkgLSB0aGlzLl9zdGFydC55KSAqIGNhbnZhc1NpemUueTtcbiAgICAgICAgICAgICAgd2lkdGggPSBoZWlnaHQgKiB0aGlzLl9yYXRpbztcbiAgICAgICAgICAgICAgdGhpcy5fZW5kLnggPSB0aGlzLl9zdGFydC54ICsgd2lkdGggLyBjYW52YXNTaXplLng7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdib3R0b20tcmlnaHQnOlxuICAgICAgICAgICAgd2lkdGggPSAodGhpcy5fZW5kLnggLSB0aGlzLl9zdGFydC54KSAqIGNhbnZhc1NpemUueDtcbiAgICAgICAgICAgIGhlaWdodCA9IHdpZHRoIC8gdGhpcy5fcmF0aW87XG4gICAgICAgICAgICB0aGlzLl9lbmQueSA9IHRoaXMuX3N0YXJ0LnkgKyBoZWlnaHQgLyBjYW52YXNTaXplLnk7XG5cbiAgICAgICAgICAgIC8vIElmIGJvdW5kYXJpZXMgYXJlIGV4Y2VlZGVkLCBjYWxjdWxhdGUgd2lkdGggYnkgbWF4aW11bSBoZWlnaHRcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbmQueSA+PSAxKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2VuZC55ID0gMTtcbiAgICAgICAgICAgICAgaGVpZ2h0ID0gKHRoaXMuX2VuZC55IC0gdGhpcy5fc3RhcnQueSkgKiBjYW52YXNTaXplLnk7XG4gICAgICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ICogdGhpcy5fcmF0aW87XG4gICAgICAgICAgICAgIHRoaXMuX2VuZC54ID0gdGhpcy5fc3RhcnQueCArIHdpZHRoIC8gY2FudmFzU2l6ZS54O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYm90dG9tLWxlZnQnOlxuICAgICAgICAgICAgd2lkdGggPSAodGhpcy5fZW5kLnggLSB0aGlzLl9zdGFydC54KSAqIGNhbnZhc1NpemUueDtcbiAgICAgICAgICAgIGhlaWdodCA9IHdpZHRoIC8gdGhpcy5fcmF0aW87XG4gICAgICAgICAgICB0aGlzLl9lbmQueSA9IHRoaXMuX3N0YXJ0LnkgKyBoZWlnaHQgLyBjYW52YXNTaXplLnk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLl9lbmQueSA+PSAxKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2VuZC55ID0gMTtcbiAgICAgICAgICAgICAgaGVpZ2h0ID0gKHRoaXMuX2VuZC55IC0gdGhpcy5fc3RhcnQueSkgKiBjYW52YXNTaXplLnk7XG4gICAgICAgICAgICAgIHdpZHRoID0gaGVpZ2h0ICogdGhpcy5fcmF0aW87XG4gICAgICAgICAgICAgIHRoaXMuX3N0YXJ0LnggPSB0aGlzLl9lbmQueCAtIHdpZHRoIC8gY2FudmFzU2l6ZS54O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uS25vYlVwJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZSB0aGUgdXNlciByZWxlYXNlcyBhIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uS25vYlVwKCkge1xuICAgICAgdGhpcy5fY3VycmVudEtub2IgPSBudWxsO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Lbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbktub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbktub2JVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uS25vYlVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlQ2VudGVyJyxcblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgdGhlIGNlbnRlciBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVDZW50ZXIoKSB7XG4gICAgICB0aGlzLl9hcmVhcy5jZW50ZXJDZW50ZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25DZW50ZXJEb3duKTtcbiAgICAgIHRoaXMuX2FyZWFzLmNlbnRlckNlbnRlci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fb25DZW50ZXJEb3duKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25DZW50ZXJEb3duJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyB0aGUgY2VudGVyIGFyZWFcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQ2VudGVyRG93bihlKSB7XG4gICAgICB0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuXG4gICAgICAvLyBSZW1lbWJlciB0aGUgY3VycmVudCB2YWx1ZXNcbiAgICAgIHRoaXMuX3N0YXJ0QmVmb3JlRHJhZyA9IHRoaXMuX3N0YXJ0LmNsb25lKCk7XG4gICAgICB0aGlzLl9lbmRCZWZvcmVEcmFnID0gdGhpcy5fZW5kLmNsb25lKCk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQ2VudGVyRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkNlbnRlckRyYWcpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQ2VudGVyVXApO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbkNlbnRlclVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25DZW50ZXJEcmFnJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyB0aGUgY2VudGVyIGFyZWEgYW5kIG1vdmVzIGhpcyBtb3VzZVxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25DZW50ZXJEcmFnKGUpIHtcbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgbW91c2VEaWZmID0gbW91c2VQb3NpdGlvbi5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuXG4gICAgICAvLyBHZXQgdGhlIGNyb3Agc2l6ZVxuICAgICAgdmFyIGNyb3BTaXplID0gdGhpcy5fZW5kQmVmb3JlRHJhZy5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX3N0YXJ0QmVmb3JlRHJhZyk7XG4gICAgICB2YXIgYWJzb2x1dGVDcm9wU2l6ZSA9IGNyb3BTaXplLmNsb25lKCkubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG5cbiAgICAgIC8vIEdldCB0aGUgYWJzb2x1dGUgaW5pdGlhbCB2YWx1ZXNcbiAgICAgIHZhciBhYnNvbHV0ZVN0YXJ0ID0gdGhpcy5fc3RhcnRCZWZvcmVEcmFnLmNsb25lKCkubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG4gICAgICB2YXIgYWJzb2x1dGVFbmQgPSB0aGlzLl9lbmRCZWZvcmVEcmFnLmNsb25lKCkubXVsdGlwbHkoY2FudmFzU2l6ZSk7XG5cbiAgICAgIC8vIEFkZCB0aGUgbW91c2UgcG9zaXRpb24gZGlmZmVyZW5jZVxuICAgICAgYWJzb2x1dGVTdGFydC5hZGQobW91c2VEaWZmKTtcblxuICAgICAgLy8gQ2xhbXAgdGhlIHZhbHVlXG4gICAgICB2YXIgbWF4U3RhcnQgPSBjYW52YXNTaXplLmNsb25lKCkuc3VidHJhY3QoYWJzb2x1dGVDcm9wU2l6ZSk7XG4gICAgICBhYnNvbHV0ZVN0YXJ0LmNsYW1wKG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMCwgMCksIG1heFN0YXJ0KTtcblxuICAgICAgLy8gRW5kIHBvc2l0aW9uIGRvZXMgbm90IGNoYW5nZSAocmVsYXRpdmUgdG8gc3RhcnQpXG4gICAgICBhYnNvbHV0ZUVuZC5jb3B5KGFic29sdXRlU3RhcnQpLmFkZChhYnNvbHV0ZUNyb3BTaXplKTtcblxuICAgICAgLy8gU2V0IHRoZSBmaW5hbCB2YWx1ZXNcbiAgICAgIHRoaXMuX3N0YXJ0LmNvcHkoYWJzb2x1dGVTdGFydCkuZGl2aWRlKGNhbnZhc1NpemUpO1xuICAgICAgdGhpcy5fZW5kLmNvcHkoYWJzb2x1dGVFbmQpLmRpdmlkZShjYW52YXNTaXplKTtcblxuICAgICAgdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQ2VudGVyVXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgY2VudGVyIGFyZWFcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQ2VudGVyVXAoKSB7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkNlbnRlckRyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25DZW50ZXJEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkNlbnRlclVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25DZW50ZXJVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICB0aGlzLl91aS5jYW52YXMuc2V0Wm9vbUxldmVsKHRoaXMuX2luaXRpYWxab29tTGV2ZWwsIGZhbHNlKTtcblxuICAgICAgaWYgKHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldCh7XG4gICAgICAgICAgc3RhcnQ6IHRoaXMuX2luaXRpYWxTdGFydCxcbiAgICAgICAgICBlbmQ6IHRoaXMuX2luaXRpYWxFbmRcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ2Nyb3AnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Eb25lJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGRvbmUgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWRcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRvbmUoKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb24uc2V0KHtcbiAgICAgICAgc3RhcnQ6IHRoaXMuX3N0YXJ0LFxuICAgICAgICBlbmQ6IHRoaXMuX2VuZFxuICAgICAgfSk7XG4gICAgICB0aGlzLl91aS5jYW52YXMuem9vbVRvRml0KHRydWUpO1xuXG4gICAgICB0aGlzLl91aS5hZGRIaXN0b3J5KHRoaXMuX29wZXJhdGlvbiwge1xuICAgICAgICBzdGFydDogdGhpcy5faW5pdGlhbFN0YXJ0LmNsb25lKCksXG4gICAgICAgIGVuZDogdGhpcy5faW5pdGlhbEVuZC5jbG9uZSgpXG4gICAgICB9LCB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIHRoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSB0ZW1wbGF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY29udGV4dCA9IF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKENyb3BDb250cm9sLnByb3RvdHlwZSksICdjb250ZXh0JywgdGhpcyk7XG4gICAgICBjb250ZXh0LnJhdGlvcyA9IHRoaXMuX3JhdGlvcztcbiAgICAgIHJldHVybiBjb250ZXh0O1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3NlbGVjdGVkUmF0aW8nLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHNlbGVjdGVkIHJhdGlvIGlkZW50aWZpZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkUmF0aW87XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIENyb3BDb250cm9sO1xufSkoX2NvbnRyb2wyWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBjb250cm9sLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuQ3JvcENvbnRyb2wucHJvdG90eXBlLmlkZW50aWZpZXIgPSAnY3JvcCc7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IENyb3BDb250cm9sO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2NvbnRyb2xzL2Nyb3AtY29udHJvbC5qc1xuICoqIG1vZHVsZSBpZCA9IDg3XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgX19ET1RKU19URU1QTEFURSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9jb250cm9sID0gcmVxdWlyZSgnLi9jb250cm9sJyk7XG5cbnZhciBfY29udHJvbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9jb250cm9sKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBfbGliU2ltcGxlU2xpZGVyID0gcmVxdWlyZSgnLi4vbGliL3NpbXBsZS1zbGlkZXInKTtcblxudmFyIF9saWJTaW1wbGVTbGlkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliU2ltcGxlU2xpZGVyKTtcblxudmFyIFJhZGlhbEJsdXJDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBSYWRpYWxCbHVyQ29udHJvbCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUmFkaWFsQmx1ckNvbnRyb2wpO1xuXG4gICAgaWYgKF9Db250cm9sICE9IG51bGwpIHtcbiAgICAgIF9Db250cm9sLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKFJhZGlhbEJsdXJDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKFJhZGlhbEJsdXJDb250cm9sLCBbe1xuICAgIGtleTogJ2luaXQnLFxuXG4gICAgLyoqXG4gICAgICogRW50cnkgcG9pbnQgZm9yIHRoaXMgY29udHJvbFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgdmFyIGNvbnRyb2xzVGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWljb25cIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvYmx1ci9ibHVyLnBuZycpKSsnXCIgLz48L2Rpdj48ZGl2PiAnKyggaXQucGFydGlhbHMuc2xpZGVyKSsnPC9kaXY+JysoIGl0LnBhcnRpYWxzLmRvbmVCdXR0b24pO3JldHVybiBvdXQ7XG59O1xuICAgICAgdGhpcy5fY29udHJvbHNUZW1wbGF0ZSA9IGNvbnRyb2xzVGVtcGxhdGU7XG5cbiAgICAgIHZhciBjYW52YXNDb250cm9sc1RlbXBsYXRlID0gZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtcmFkaWFsLWJsdXItY29udGFpbmVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtcmFkaWFsLWJsdXItZG90XCIgaWQ9XCJpbWdseWtpdC1yYWRpYWwtYmx1ci1wb3NpdGlvblwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXJhZGlhbC1ibHVyLWRvdFwiIGlkPVwiaW1nbHlraXQtcmFkaWFsLWJsdXItZ3JhZGllbnRcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy1yYWRpYWwtYmx1ci1jaXJjbGUtY29udGFpbmVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtcmFkaWFsLWJsdXItY2lyY2xlXCI+PC9kaXY+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc1RlbXBsYXRlID0gY2FudmFzQ29udHJvbHNUZW1wbGF0ZTtcblxuICAgICAgdGhpcy5fcGFydGlhbFRlbXBsYXRlcy5zbGlkZXIgPSBfbGliU2ltcGxlU2xpZGVyMlsnZGVmYXVsdCddLnRlbXBsYXRlO1xuICAgICAgdGhpcy5fcGFydGlhbFRlbXBsYXRlcy5zbGlkZXIuYWRkaXRpb25hbENvbnRleHQgPSB7XG4gICAgICAgIGlkOiAnaW1nbHlraXQtYmx1ci1yYWRpdXMtc2xpZGVyJ1xuICAgICAgfTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zWydyYWRpYWwtYmx1ciddO1xuICAgICAgdGhpcy5fb3BlcmF0aW9uID0gdGhpcy5fdWkuZ2V0T3JDcmVhdGVPcGVyYXRpb24oJ3JhZGlhbC1ibHVyJyk7XG5cbiAgICAgIC8vIFJlbWVtYmVyIGluaXRpYWwgaWRlbnRpdHkgc3RhdGVcbiAgICAgIHRoaXMuX2luaXRpYWxTZXR0aW5ncyA9IHtcbiAgICAgICAgcG9zaXRpb246IHRoaXMuX29wZXJhdGlvbi5nZXRQb3NpdGlvbigpLmNsb25lKCksXG4gICAgICAgIGdyYWRpZW50UmFkaXVzOiB0aGlzLl9vcGVyYXRpb24uZ2V0R3JhZGllbnRSYWRpdXMoKSxcbiAgICAgICAgYmx1clJhZGl1czogdGhpcy5fb3BlcmF0aW9uLmdldEJsdXJSYWRpdXMoKVxuICAgICAgfTtcblxuICAgICAgLy8gTW91c2UgZXZlbnQgY2FsbGJhY2tzIGJvdW5kIHRvIHRoZSBjbGFzcyBjb250ZXh0XG4gICAgICB0aGlzLl9vblBvc2l0aW9uS25vYkRvd24gPSB0aGlzLl9vblBvc2l0aW9uS25vYkRvd24uYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZyA9IHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZy5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Qb3NpdGlvbktub2JVcCA9IHRoaXMuX29uUG9zaXRpb25Lbm9iVXAuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uR3JhZGllbnRLbm9iRG93biA9IHRoaXMuX29uR3JhZGllbnRLbm9iRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25HcmFkaWVudEtub2JEcmFnID0gdGhpcy5fb25HcmFkaWVudEtub2JEcmFnLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbkdyYWRpZW50S25vYlVwID0gdGhpcy5fb25HcmFkaWVudEtub2JVcC5iaW5kKHRoaXMpO1xuXG4gICAgICB0aGlzLl9wb3NpdGlvbktub2IgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcjaW1nbHlraXQtcmFkaWFsLWJsdXItcG9zaXRpb24nKTtcbiAgICAgIHRoaXMuX2dyYWRpZW50S25vYiA9IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJyNpbWdseWtpdC1yYWRpYWwtYmx1ci1ncmFkaWVudCcpO1xuICAgICAgdGhpcy5fY2lyY2xlID0gdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNhbnZhcy1yYWRpYWwtYmx1ci1jaXJjbGUnKTtcbiAgICAgIHRoaXMuX2hhbmRsZUtub2JzKCk7XG4gICAgICB0aGlzLl9pbml0U2xpZGVycygpO1xuXG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLl91cGRhdGVET00oKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0U2xpZGVycycsXG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgc2xpZGVyIGNvbnRyb2xzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRTbGlkZXJzKCkge1xuICAgICAgdmFyIGJsdXJSYWRpdXNTbGlkZXIgPSB0aGlzLl9jb250cm9scy5xdWVyeVNlbGVjdG9yKCcjaW1nbHlraXQtYmx1ci1yYWRpdXMtc2xpZGVyJyk7XG4gICAgICB0aGlzLl9ibHVyUmFkaXVzU2xpZGVyID0gbmV3IF9saWJTaW1wbGVTbGlkZXIyWydkZWZhdWx0J10oYmx1clJhZGl1c1NsaWRlciwge1xuICAgICAgICBtaW5WYWx1ZTogMCxcbiAgICAgICAgbWF4VmFsdWU6IDQwXG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2JsdXJSYWRpdXNTbGlkZXIub24oJ3VwZGF0ZScsIHRoaXMuX29uQmx1clJhZGl1c1VwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX2JsdXJSYWRpdXNTbGlkZXIuc2V0VmFsdWUodGhpcy5faW5pdGlhbFNldHRpbmdzLmJsdXJSYWRpdXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJsdXJSYWRpdXNVcGRhdGUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdmFsdWUgb2YgdGhlIGJsdXIgcmFkaXVzIHNsaWRlciBoYXMgYmVlbiB1cGRhdGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmx1clJhZGl1c1VwZGF0ZSh2YWx1ZSkge1xuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldEJsdXJSYWRpdXModmFsdWUpO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVLbm9icycsXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSBrbm9iIGRyYWdnaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2hhbmRsZUtub2JzKCkge1xuICAgICAgLy8gSW5pdGlhbGx5IHNldCBncmFkaWVudCBrbm9iIHBvc2l0aW9uXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fb3BlcmF0aW9uLmdldFBvc2l0aW9uKCkuY2xvbmUoKS5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uID0gcG9zaXRpb24uY2xvbmUoKS5hZGQodGhpcy5faW5pdGlhbFNldHRpbmdzLmdyYWRpZW50UmFkaXVzLCAwKTtcblxuICAgICAgdGhpcy5fcG9zaXRpb25Lbm9iLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uUG9zaXRpb25Lbm9iRG93bik7XG4gICAgICB0aGlzLl9wb3NpdGlvbktub2IuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uUG9zaXRpb25Lbm9iRG93bik7XG4gICAgICB0aGlzLl9ncmFkaWVudEtub2IuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25HcmFkaWVudEtub2JEb3duKTtcbiAgICAgIHRoaXMuX2dyYWRpZW50S25vYi5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fb25HcmFkaWVudEtub2JEb3duKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Qb3NpdGlvbktub2JEb3duJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgc3RhcnRzIGRyYWdnaW5nIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblBvc2l0aW9uS25vYkRvd24oZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuXG4gICAgICB0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuICAgICAgdGhpcy5faW5pdGlhbFBvc2l0aW9uID0gdGhpcy5fb3BlcmF0aW9uLmdldFBvc2l0aW9uKCkuY2xvbmUoKTtcbiAgICAgIHRoaXMuX2dyYWRpZW50S25vYkRpc3RhbmNlID0gdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24uY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsUG9zaXRpb24uY2xvbmUoKS5tdWx0aXBseShjYW52YXNTaXplKSk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vblBvc2l0aW9uS25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Qb3NpdGlvbktub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uUG9zaXRpb25Lbm9iVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblBvc2l0aW9uS25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hpbGUgdGhlIHVzZXIgc3RhcnRzIGRyYWdzIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblBvc2l0aW9uS25vYkRyYWcoZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIG1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBkaWZmID0gbW91c2VQb3NpdGlvbi5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG5cbiAgICAgIHZhciBuZXdQb3NpdGlvbiA9IHRoaXMuX2luaXRpYWxQb3NpdGlvbi5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpLmFkZChkaWZmKTtcblxuICAgICAgdmFyIG1heFBvc2l0aW9uID0gY2FudmFzU2l6ZS5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2dyYWRpZW50S25vYkRpc3RhbmNlKTtcbiAgICAgIG5ld1Bvc2l0aW9uLmNsYW1wKG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oMCwgMCksIG1heFBvc2l0aW9uKTtcblxuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24uY29weShuZXdQb3NpdGlvbikuYWRkKHRoaXMuX2dyYWRpZW50S25vYkRpc3RhbmNlKTtcblxuICAgICAgLy8gVHJhbnNsYXRlIHRvIDAuLi4xXG4gICAgICBuZXdQb3NpdGlvbi5kaXZpZGUoY2FudmFzU2l6ZSk7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRQb3NpdGlvbihuZXdQb3NpdGlvbik7XG4gICAgICB0aGlzLl91cGRhdGVET00oKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Qb3NpdGlvbktub2JVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblBvc2l0aW9uS25vYlVwKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Qb3NpdGlvbktub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vblBvc2l0aW9uS25vYlVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25Qb3NpdGlvbktub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uR3JhZGllbnRLbm9iRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgcG9zaXRpb24ga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25HcmFkaWVudEtub2JEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHRoaXMuX2luaXRpYWxHcmFkaWVudEtub2JQb3NpdGlvbiA9IHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uLmNsb25lKCk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkdyYWRpZW50S25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25HcmFkaWVudEtub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uR3JhZGllbnRLbm9iVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkdyYWRpZW50S25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hpbGUgdGhlIHVzZXIgc3RhcnRzIGRyYWdzIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkdyYWRpZW50S25vYkRyYWcoZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIG1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBkaWZmID0gbW91c2VQb3NpdGlvbi5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG5cbiAgICAgIC8vIENhbGN1bGF0ZSBuZXcgZ3JhZGllbnQga25vYiBwb3NpdGlvblxuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24gPSB0aGlzLl9pbml0aWFsR3JhZGllbnRLbm9iUG9zaXRpb24uY2xvbmUoKS5hZGQoZGlmZik7XG4gICAgICB0aGlzLl9ncmFkaWVudEtub2JQb3NpdGlvbi5jbGFtcChuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDApLCBjYW52YXNTaXplKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIGRpc3RhbmNlIHRvIHBvc2l0aW9uXG4gICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9vcGVyYXRpb24uZ2V0UG9zaXRpb24oKS5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuICAgICAgdmFyIGRpc3RhbmNlID0gdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24uY2xvbmUoKS5zdWJ0cmFjdChwb3NpdGlvbik7XG4gICAgICB2YXIgZ3JhZGllbnRSYWRpdXMgPSBNYXRoLnNxcnQoTWF0aC5wb3coZGlzdGFuY2UueCwgMikgKyBNYXRoLnBvdyhkaXN0YW5jZS55LCAyKSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBvcGVyYXRpb25cbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRHcmFkaWVudFJhZGl1cyhncmFkaWVudFJhZGl1cyk7XG4gICAgICB0aGlzLl91cGRhdGVET00oKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25HcmFkaWVudEtub2JVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkdyYWRpZW50S25vYlVwKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25HcmFkaWVudEtub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkdyYWRpZW50S25vYlVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25HcmFkaWVudEtub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZURPTScsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBrbm9iXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3VwZGF0ZURPTSgpIHtcbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG4gICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9vcGVyYXRpb24uZ2V0UG9zaXRpb24oKS5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuXG4gICAgICB0aGlzLl9wb3NpdGlvbktub2Iuc3R5bGUubGVmdCA9ICcnICsgcG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9wb3NpdGlvbktub2Iuc3R5bGUudG9wID0gJycgKyBwb3NpdGlvbi55ICsgJ3B4JztcblxuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iLnN0eWxlLmxlZnQgPSAnJyArIHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uLnggKyAncHgnO1xuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iLnN0eWxlLnRvcCA9ICcnICsgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24ueSArICdweCc7XG5cbiAgICAgIHZhciBjaXJjbGVTaXplID0gdGhpcy5fb3BlcmF0aW9uLmdldEdyYWRpZW50UmFkaXVzKCkgKiAyO1xuICAgICAgdGhpcy5fY2lyY2xlLnN0eWxlLmxlZnQgPSAnJyArIHBvc2l0aW9uLnggKyAncHgnO1xuICAgICAgdGhpcy5fY2lyY2xlLnN0eWxlLnRvcCA9ICcnICsgcG9zaXRpb24ueSArICdweCc7XG4gICAgICB0aGlzLl9jaXJjbGUuc3R5bGUud2lkdGggPSAnJyArIGNpcmNsZVNpemUgKyAncHgnO1xuICAgICAgdGhpcy5fY2lyY2xlLnN0eWxlLmhlaWdodCA9ICcnICsgY2lyY2xlU2l6ZSArICdweCc7XG4gICAgICB0aGlzLl9jaXJjbGUuc3R5bGUubWFyZ2luTGVmdCA9ICctJyArIGNpcmNsZVNpemUgLyAyICsgJ3B4JztcbiAgICAgIHRoaXMuX2NpcmNsZS5zdHlsZS5tYXJnaW5Ub3AgPSAnLScgKyBjaXJjbGVTaXplIC8gMiArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICBpZiAodGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSkge1xuICAgICAgICB0aGlzLl9vcGVyYXRpb24uc2V0KHRoaXMuX2luaXRpYWxTZXR0aW5ncyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ3JhZGlhbC1ibHVyJyk7XG4gICAgICB9XG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRG9uZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBkb25lIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRvbmUoKSB7XG4gICAgICB0aGlzLl91aS5hZGRIaXN0b3J5KHRoaXMuX29wZXJhdGlvbiwge1xuICAgICAgICBwb3NpdGlvbjogdGhpcy5faW5pdGlhbFNldHRpbmdzLnBvc2l0aW9uLmNsb25lKCksXG4gICAgICAgIGdyYWRpZW50UmFkaXVzOiB0aGlzLl9pbml0aWFsU2V0dGluZ3MuZ3JhZGllbnRSYWRpdXMsXG4gICAgICAgIGJsdXJSYWRpdXM6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5ibHVyUmFkaXVzXG4gICAgICB9LCB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gUmFkaWFsQmx1ckNvbnRyb2w7XG59KShfY29udHJvbDJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5SYWRpYWxCbHVyQ29udHJvbC5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdyYWRpYWwtYmx1cic7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJhZGlhbEJsdXJDb250cm9sO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2NvbnRyb2xzL3JhZGlhbC1ibHVyLWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA4OFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfY29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbCcpO1xuXG52YXIgX2NvbnRyb2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY29udHJvbCk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX2xpYlNpbXBsZVNsaWRlciA9IHJlcXVpcmUoJy4uL2xpYi9zaW1wbGUtc2xpZGVyJyk7XG5cbnZhciBfbGliU2ltcGxlU2xpZGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlNpbXBsZVNsaWRlcik7XG5cbnZhciBUaWx0U2hpZnRDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBUaWx0U2hpZnRDb250cm9sKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUaWx0U2hpZnRDb250cm9sKTtcblxuICAgIGlmIChfQ29udHJvbCAhPSBudWxsKSB7XG4gICAgICBfQ29udHJvbC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhUaWx0U2hpZnRDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKFRpbHRTaGlmdENvbnRyb2wsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBFbnRyeSBwb2ludCBmb3IgdGhpcyBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICB2YXIgY29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtaWNvblwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9ibHVyL2JsdXIucG5nJykpKydcIiAvPjwvZGl2PjxkaXY+ICc7dmFyIHNsaWRlcklkID0gXCJpbWdseWtpdC1ibHVyLXJhZGl1cy1zbGlkZXJcIjtvdXQrPScgJysoIGl0LnBhcnRpYWxzLnNsaWRlcikrJzwvZGl2PicrKCBpdC5wYXJ0aWFscy5kb25lQnV0dG9uKTtyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzVGVtcGxhdGUgPSBjb250cm9sc1RlbXBsYXRlO1xuXG4gICAgICB2YXIgY2FudmFzQ29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXRpbHQtc2hpZnQtY29udGFpbmVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtdGlsdC1zaGlmdC1kb3RcIiBkYXRhLW9wdGlvbj1cInBvc2l0aW9uXCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtdGlsdC1zaGlmdC1kb3RcIiBkYXRhLW9wdGlvbj1cImdyYWRpZW50XCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtdGlsdC1zaGlmdC1yZWN0LWNvbnRhaW5lclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXRpbHQtc2hpZnQtcmVjdFwiPjwvZGl2PiA8L2Rpdj48L2Rpdj4nO3JldHVybiBvdXQ7XG59O1xuICAgICAgdGhpcy5fY2FudmFzQ29udHJvbHNUZW1wbGF0ZSA9IGNhbnZhc0NvbnRyb2xzVGVtcGxhdGU7XG5cbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuc2xpZGVyID0gX2xpYlNpbXBsZVNsaWRlcjJbJ2RlZmF1bHQnXS50ZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuc2xpZGVyLmFkZGl0aW9uYWxDb250ZXh0ID0geyBpZDogJ2ltZ2x5a2l0LWJsdXItcmFkaXVzLXNsaWRlcicgfTtcbiAgICAgIHRoaXMuX2N1cnJlbnRLbm9iID0gbnVsbDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zWyd0aWx0LXNoaWZ0J107XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbigndGlsdC1zaGlmdCcpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsU2V0dGluZ3MgPSB7XG4gICAgICAgIHN0YXJ0OiB0aGlzLl9vcGVyYXRpb24uZ2V0U3RhcnQoKS5jbG9uZSgpLFxuICAgICAgICBlbmQ6IHRoaXMuX29wZXJhdGlvbi5nZXRFbmQoKS5jbG9uZSgpLFxuICAgICAgICBncmFkaWVudFJhZGl1czogdGhpcy5fb3BlcmF0aW9uLmdldEdyYWRpZW50UmFkaXVzKCksXG4gICAgICAgIGJsdXJSYWRpdXM6IHRoaXMuX29wZXJhdGlvbi5nZXRCbHVyUmFkaXVzKClcbiAgICAgIH07XG5cbiAgICAgIC8vIE1vdXNlIGV2ZW50IGNhbGxiYWNrcyBib3VuZCB0byB0aGUgY2xhc3MgY29udGV4dFxuICAgICAgdGhpcy5fb25Qb3NpdGlvbktub2JEb3duID0gdGhpcy5fb25Qb3NpdGlvbktub2JEb3duLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vblBvc2l0aW9uS25vYkRyYWcgPSB0aGlzLl9vblBvc2l0aW9uS25vYkRyYWcuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uUG9zaXRpb25Lbm9iVXAgPSB0aGlzLl9vblBvc2l0aW9uS25vYlVwLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbkdyYWRpZW50S25vYkRvd24gPSB0aGlzLl9vbkdyYWRpZW50S25vYkRvd24uYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZyA9IHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZy5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25HcmFkaWVudEtub2JVcCA9IHRoaXMuX29uR3JhZGllbnRLbm9iVXAuYmluZCh0aGlzKTtcblxuICAgICAgLy8gRmluZCBET00gZWxlbWVudHNcbiAgICAgIHZhciBzZWxlY3RvciA9ICcuaW1nbHlraXQtY2FudmFzLXRpbHQtc2hpZnQtZG90JztcbiAgICAgIHRoaXMuX3Bvc2l0aW9uS25vYiA9IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJycgKyBzZWxlY3RvciArICdbZGF0YS1vcHRpb249XFwncG9zaXRpb25cXCddJyk7XG4gICAgICB0aGlzLl9ncmFkaWVudEtub2IgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcnICsgc2VsZWN0b3IgKyAnW2RhdGEtb3B0aW9uPVxcJ2dyYWRpZW50XFwnXScpO1xuICAgICAgdGhpcy5fcmVjdCA9IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jYW52YXMtdGlsdC1zaGlmdC1yZWN0Jyk7XG5cbiAgICAgIC8vIEluaXRpYWxpemF0aW9uXG4gICAgICB0aGlzLl9pbml0U2xpZGVycygpO1xuXG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzLl9oYW5kbGVLbm9icygpO1xuICAgICAgICBfdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaW5pdFNsaWRlcnMnLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHNsaWRlciBjb250cm9sc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9pbml0U2xpZGVycygpIHtcbiAgICAgIHZhciBibHVyUmFkaXVzU2xpZGVyID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignI2ltZ2x5a2l0LWJsdXItcmFkaXVzLXNsaWRlcicpO1xuICAgICAgdGhpcy5fYmx1clJhZGl1c1NsaWRlciA9IG5ldyBfbGliU2ltcGxlU2xpZGVyMlsnZGVmYXVsdCddKGJsdXJSYWRpdXNTbGlkZXIsIHtcbiAgICAgICAgbWluVmFsdWU6IDAsXG4gICAgICAgIG1heFZhbHVlOiA0MFxuICAgICAgfSk7XG4gICAgICB0aGlzLl9ibHVyUmFkaXVzU2xpZGVyLm9uKCd1cGRhdGUnLCB0aGlzLl9vbkJsdXJSYWRpdXNVcGRhdGUuYmluZCh0aGlzKSk7XG4gICAgICB0aGlzLl9ibHVyUmFkaXVzU2xpZGVyLnNldFZhbHVlKHRoaXMuX2luaXRpYWxTZXR0aW5ncy5ibHVyUmFkaXVzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CbHVyUmFkaXVzVXBkYXRlJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHZhbHVlIG9mIHRoZSBibHVyIHJhZGl1cyBzbGlkZXIgaGFzIGJlZW4gdXBkYXRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJsdXJSYWRpdXNVcGRhdGUodmFsdWUpIHtcbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRCbHVyUmFkaXVzKHZhbHVlKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICAgIHRoaXMuX2hpZ2hsaWdodERvbmVCdXR0b24oKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlS25vYnMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUga25vYiBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVLbm9icygpIHtcbiAgICAgIC8vIEFkZCBldmVudCBsaXN0ZW5lcnNcbiAgICAgIHRoaXMuX3Bvc2l0aW9uS25vYi5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vblBvc2l0aW9uS25vYkRvd24pO1xuICAgICAgdGhpcy5fcG9zaXRpb25Lbm9iLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblBvc2l0aW9uS25vYkRvd24pO1xuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uR3JhZGllbnRLbm9iRG93bik7XG4gICAgICB0aGlzLl9ncmFkaWVudEtub2IuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uR3JhZGllbnRLbm9iRG93bik7XG5cbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG4gICAgICB2YXIgX2luaXRpYWxTZXR0aW5ncyA9IHRoaXMuX2luaXRpYWxTZXR0aW5ncztcbiAgICAgIHZhciBzdGFydCA9IF9pbml0aWFsU2V0dGluZ3Muc3RhcnQ7XG4gICAgICB2YXIgZW5kID0gX2luaXRpYWxTZXR0aW5ncy5lbmQ7XG5cbiAgICAgIHN0YXJ0ID0gc3RhcnQuY2xvbmUoKS5tdWx0aXBseShjYW52YXNTaXplKTtcbiAgICAgIGVuZCA9IGVuZC5jbG9uZSgpLm11bHRpcGx5KGNhbnZhc1NpemUpO1xuXG4gICAgICB2YXIgZGlzdCA9IGVuZC5jbG9uZSgpLnN1YnRyYWN0KHN0YXJ0KTtcbiAgICAgIHZhciBtaWRkbGUgPSBzdGFydC5jbG9uZSgpLmFkZChkaXN0LmNsb25lKCkuZGl2aWRlKDIpKTtcblxuICAgICAgdmFyIHRvdGFsRGlzdCA9IE1hdGguc3FydChNYXRoLnBvdyhkaXN0LngsIDIpICsgTWF0aC5wb3coZGlzdC55LCAyKSk7XG4gICAgICB2YXIgZmFjdG9yID0gZGlzdC5jbG9uZSgpLmRpdmlkZSh0b3RhbERpc3QpLmRpdmlkZSgyKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIGluaXRpYWwga25vYiBwb3NpdGlvbiAobWlkZGxlIG9mIHN0YXJ0IGFuZCBlbmQpXG4gICAgICB0aGlzLl9rbm9iUG9zaXRpb24gPSBtaWRkbGUuY2xvbmUoKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIGluaXRpYWwgZ3JhZGllbnQga25vYiBwb3NpdGlvblxuICAgICAgdmFyIGdyYWRpZW50UmFkaXVzID0gdGhpcy5faW5pdGlhbFNldHRpbmdzLmdyYWRpZW50UmFkaXVzO1xuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24gPSBtaWRkbGUuY2xvbmUoKS5hZGQoLWdyYWRpZW50UmFkaXVzICogZmFjdG9yLnksIGdyYWRpZW50UmFkaXVzICogZmFjdG9yLngpO1xuXG4gICAgICB0aGlzLl91cGRhdGVTdGFydEFuZEVuZCgpO1xuICAgICAgdGhpcy5fdXBkYXRlRE9NKCk7XG5cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdXBkYXRlU3RhcnRBbmRFbmQnLFxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlIHN0YXJ0IGFuZCBlbmQgcG9zaXRpb25zIHVzaW5nIHRoZSBrbm9iIHBvc2l0aW9uc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVTdGFydEFuZEVuZCgpIHtcbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG5cbiAgICAgIC8vIENhbGN1bGF0ZSBkaXN0YW5jZSBiZXR3ZWVuIGdyYWRpZW50IGFuZCBwb3NpdGlvbiBrbm9iXG4gICAgICB2YXIgZGlmZiA9IHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uLmNsb25lKCkuc3VidHJhY3QodGhpcy5fa25vYlBvc2l0aW9uKTtcblxuICAgICAgdmFyIHN0YXJ0ID0gdGhpcy5fa25vYlBvc2l0aW9uLmNsb25lKCkuYWRkKC1kaWZmLnksIGRpZmYueCkuZGl2aWRlKGNhbnZhc1NpemUpO1xuICAgICAgdmFyIGVuZCA9IHRoaXMuX2tub2JQb3NpdGlvbi5jbG9uZSgpLmFkZChkaWZmLnksIC1kaWZmLngpLmRpdmlkZShjYW52YXNTaXplKTtcblxuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldCh7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uUG9zaXRpb25Lbm9iRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgcG9zaXRpb24ga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Qb3NpdGlvbktub2JEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHRoaXMuX2luaXRpYWxQb3NpdGlvbiA9IHRoaXMuX2tub2JQb3NpdGlvbi5jbG9uZSgpO1xuICAgICAgdGhpcy5faW5pdGlhbERpc3RhbmNlVG9HcmFkaWVudEtub2IgPSB0aGlzLl9ncmFkaWVudEtub2JQb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxQb3NpdGlvbik7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vblBvc2l0aW9uS25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Qb3NpdGlvbktub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uUG9zaXRpb25Lbm9iVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblBvc2l0aW9uS25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgcG9zaXRpb24ga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Qb3NpdGlvbktub2JEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgZGlmZiA9IG1vdXNlUG9zaXRpb24uc3VidHJhY3QodGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24pO1xuXG4gICAgICB2YXIgbmV3UG9zaXRpb24gPSB0aGlzLl9pbml0aWFsUG9zaXRpb24uY2xvbmUoKS5hZGQoZGlmZik7XG4gICAgICB0aGlzLl9rbm9iUG9zaXRpb24uY29weShuZXdQb3NpdGlvbik7XG5cbiAgICAgIHZhciBtaW5Qb3NpdGlvbiA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oKS5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsRGlzdGFuY2VUb0dyYWRpZW50S25vYik7XG4gICAgICBtaW5Qb3NpdGlvbi5jbGFtcChuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDApKTtcblxuICAgICAgdmFyIG1heFBvc2l0aW9uID0gY2FudmFzU2l6ZS5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxEaXN0YW5jZVRvR3JhZGllbnRLbm9iKTtcbiAgICAgIG1heFBvc2l0aW9uLmNsYW1wKG51bGwsIGNhbnZhc1NpemUpO1xuXG4gICAgICB0aGlzLl9rbm9iUG9zaXRpb24uY2xhbXAobWluUG9zaXRpb24sIG1heFBvc2l0aW9uKTtcblxuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24uY29weSh0aGlzLl9rbm9iUG9zaXRpb24pLmFkZCh0aGlzLl9pbml0aWFsRGlzdGFuY2VUb0dyYWRpZW50S25vYik7XG5cbiAgICAgIHRoaXMuX3VwZGF0ZVN0YXJ0QW5kRW5kKCk7XG4gICAgICB0aGlzLl91cGRhdGVET00oKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Qb3NpdGlvbktub2JVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIHRoZSBwb3NpdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblBvc2l0aW9uS25vYlVwKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25Qb3NpdGlvbktub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uUG9zaXRpb25Lbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vblBvc2l0aW9uS25vYlVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25Qb3NpdGlvbktub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uR3JhZGllbnRLbm9iRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgZ3JhZGllbnQga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25HcmFkaWVudEtub2JEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHRoaXMuX2luaXRpYWxHcmFkaWVudEtub2JQb3NpdGlvbiA9IHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uLmNsb25lKCk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkdyYWRpZW50S25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25HcmFkaWVudEtub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uR3JhZGllbnRLbm9iVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkdyYWRpZW50S25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgZ3JhZGllbnQga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25HcmFkaWVudEtub2JEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgZGlmZiA9IG1vdXNlUG9zaXRpb24uc3VidHJhY3QodGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24pO1xuXG4gICAgICB0aGlzLl9ncmFkaWVudEtub2JQb3NpdGlvbi5jb3B5KHRoaXMuX2luaXRpYWxHcmFkaWVudEtub2JQb3NpdGlvbikuYWRkKGRpZmYpO1xuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iUG9zaXRpb24uY2xhbXAobmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKSwgY2FudmFzU2l6ZSk7XG5cbiAgICAgIHZhciBkaXN0YW5jZSA9IHRoaXMuX2dyYWRpZW50S25vYlBvc2l0aW9uLmNsb25lKCkuc3VidHJhY3QodGhpcy5fa25vYlBvc2l0aW9uKTtcbiAgICAgIHZhciBuZXdHcmFkaWVudFJhZGl1cyA9IDIgKiBNYXRoLnNxcnQoTWF0aC5wb3coZGlzdGFuY2UueCwgMikgKyBNYXRoLnBvdyhkaXN0YW5jZS55LCAyKSk7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXRHcmFkaWVudFJhZGl1cyhuZXdHcmFkaWVudFJhZGl1cyk7XG4gICAgICB0aGlzLl91cGRhdGVTdGFydEFuZEVuZCgpO1xuICAgICAgdGhpcy5fdXBkYXRlRE9NKCk7XG4gICAgICB0aGlzLl91aS5jYW52YXMucmVuZGVyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uR3JhZGllbnRLbm9iVXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBzdG9wcyBkcmFnZ2luZyB0aGUgZ3JhZGllbnQga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25HcmFkaWVudEtub2JVcChlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uR3JhZGllbnRLbm9iRHJhZyk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkdyYWRpZW50S25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25HcmFkaWVudEtub2JVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uR3JhZGllbnRLbm9iVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ191cGRhdGVET00nLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUga25vYlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVET00oKSB7XG4gICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9rbm9iUG9zaXRpb247XG4gICAgICB0aGlzLl9wb3NpdGlvbktub2Iuc3R5bGUubGVmdCA9ICcnICsgcG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9wb3NpdGlvbktub2Iuc3R5bGUudG9wID0gJycgKyBwb3NpdGlvbi55ICsgJ3B4JztcblxuICAgICAgdmFyIGdyYWRpZW50UG9zaXRpb24gPSB0aGlzLl9ncmFkaWVudEtub2JQb3NpdGlvbjtcbiAgICAgIHRoaXMuX2dyYWRpZW50S25vYi5zdHlsZS5sZWZ0ID0gJycgKyBncmFkaWVudFBvc2l0aW9uLnggKyAncHgnO1xuICAgICAgdGhpcy5fZ3JhZGllbnRLbm9iLnN0eWxlLnRvcCA9ICcnICsgZ3JhZGllbnRQb3NpdGlvbi55ICsgJ3B4JztcblxuICAgICAgLy8gUmVzaXplIHJlY3RhbmdsZSB0byB3b3JzdCBjYXNlIHNpemVcbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG4gICAgICB2YXIgZ3JhZGllbnRSYWRpdXMgPSB0aGlzLl9vcGVyYXRpb24uZ2V0R3JhZGllbnRSYWRpdXMoKTtcbiAgICAgIHZhciByZWN0U2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oTWF0aC5zcXJ0KE1hdGgucG93KGNhbnZhc1NpemUueCwgMikgKyBNYXRoLnBvdyhjYW52YXNTaXplLnksIDIpKSAqIDIsIGdyYWRpZW50UmFkaXVzKTtcblxuICAgICAgdGhpcy5fcmVjdC5zdHlsZS53aWR0aCA9ICcnICsgcmVjdFNpemUueCArICdweCc7XG4gICAgICB0aGlzLl9yZWN0LnN0eWxlLmhlaWdodCA9ICcnICsgcmVjdFNpemUueSArICdweCc7XG4gICAgICB0aGlzLl9yZWN0LnN0eWxlLm1hcmdpbkxlZnQgPSAnLScgKyByZWN0U2l6ZS54IC8gMiArICdweCc7XG4gICAgICB0aGlzLl9yZWN0LnN0eWxlLm1hcmdpblRvcCA9ICctJyArIHJlY3RTaXplLnkgLyAyICsgJ3B4JztcbiAgICAgIHRoaXMuX3JlY3Quc3R5bGUubGVmdCA9ICcnICsgcG9zaXRpb24ueCArICdweCc7XG4gICAgICB0aGlzLl9yZWN0LnN0eWxlLnRvcCA9ICcnICsgcG9zaXRpb24ueSArICdweCc7XG5cbiAgICAgIC8vIFJvdGF0ZSByZWN0YW5nbGVcbiAgICAgIHZhciBkaXN0ID0gZ3JhZGllbnRQb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KHBvc2l0aW9uKTtcbiAgICAgIHZhciBkZWdyZWVzID0gTWF0aC5hdGFuMihkaXN0LngsIGRpc3QueSkgKiAoMTgwIC8gTWF0aC5QSSk7XG4gICAgICB0aGlzLl9yZWN0LnN0eWxlLnRyYW5zZm9ybSA9ICdyb3RhdGUoJyArICgtZGVncmVlcykudG9GaXhlZCgyKSArICdkZWcpJztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CYWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGJhY2sgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmFjaygpIHtcbiAgICAgIGlmICh0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKSB7XG4gICAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXQodGhpcy5faW5pdGlhbFNldHRpbmdzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3VpLnJlbW92ZU9wZXJhdGlvbigndGlsdC1zaGlmdCcpO1xuICAgICAgfVxuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkRvbmUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgZG9uZSBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Eb25lKCkge1xuICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgc3RhcnQ6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5zdGFydC5jbG9uZSgpLFxuICAgICAgICBlbmQ6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5lbmQuY2xvbmUoKSxcbiAgICAgICAgYmx1clJhZGl1czogdGhpcy5faW5pdGlhbFNldHRpbmdzLmJsdXJSYWRpdXMsXG4gICAgICAgIGdyYWRpZW50UmFkaXVzOiB0aGlzLl9pbml0aWFsU2V0dGluZ3MuZ3JhZGllbnRSYWRpdXNcbiAgICAgIH0sIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUpO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBUaWx0U2hpZnRDb250cm9sO1xufSkoX2NvbnRyb2wyWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBjb250cm9sLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuVGlsdFNoaWZ0Q29udHJvbC5wcm90b3R5cGUuaWRlbnRpZmllciA9ICd0aWx0LXNoaWZ0JztcblxuZXhwb3J0c1snZGVmYXVsdCddID0gVGlsdFNoaWZ0Q29udHJvbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9jb250cm9scy90aWx0LXNoaWZ0LWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA4OVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfY29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbCcpO1xuXG52YXIgX2NvbnRyb2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY29udHJvbCk7XG5cbnZhciBfbGliU2ltcGxlU2xpZGVyID0gcmVxdWlyZSgnLi4vbGliL3NpbXBsZS1zbGlkZXInKTtcblxudmFyIF9saWJTaW1wbGVTbGlkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliU2ltcGxlU2xpZGVyKTtcblxudmFyIF9saWJDb2xvclBpY2tlciA9IHJlcXVpcmUoJy4uL2xpYi9jb2xvci1waWNrZXInKTtcblxudmFyIF9saWJDb2xvclBpY2tlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJDb2xvclBpY2tlcik7XG5cbnZhciBGcmFtZXNDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBGcmFtZXNDb250cm9sKCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGcmFtZXNDb250cm9sKTtcblxuICAgIGlmIChfQ29udHJvbCAhPSBudWxsKSB7XG4gICAgICBfQ29udHJvbC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhGcmFtZXNDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKEZyYW1lc0NvbnRyb2wsIFt7XG4gICAga2V5OiAnaW5pdCcsXG5cbiAgICAvKipcbiAgICAgKiBFbnRyeSBwb2ludCBmb3IgdGhpcyBjb250cm9sXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgICB2YXIgY29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2PiAnKyggaXQucGFydGlhbHMuc2xpZGVyKSsnPC9kaXY+PGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWJ1dHRvblwiPiAnKyggaXQucGFydGlhbHMuY29sb3JQaWNrZXIpKyc8L2Rpdj4nKyggaXQucGFydGlhbHMuZG9uZUJ1dHRvbik7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuc2xpZGVyID0gX2xpYlNpbXBsZVNsaWRlcjJbJ2RlZmF1bHQnXS50ZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuY29sb3JQaWNrZXIgPSBfbGliQ29sb3JQaWNrZXIyWydkZWZhdWx0J10udGVtcGxhdGU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNvbnRyb2xzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNvbnRyb2xzKCkge1xuICAgICAgdGhpcy5fcGFydGlhbFRlbXBsYXRlcy5jb2xvclBpY2tlci5hZGRpdGlvbmFsQ29udGV4dCA9IHsgbGFiZWw6IHRoaXMuX3VpLnRyYW5zbGF0ZSgnY29udHJvbHMuZnJhbWVzLmNvbG9yJykgfTtcblxuICAgICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoRnJhbWVzQ29udHJvbC5wcm90b3R5cGUpLCAnX3JlbmRlckNvbnRyb2xzJywgdGhpcykuY2FsbCh0aGlzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLmZyYW1lcztcbiAgICAgIHRoaXMuX29wZXJhdGlvbiA9IHRoaXMuX3VpLmdldE9yQ3JlYXRlT3BlcmF0aW9uKCdmcmFtZXMnKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE9wdGlvbnMgPSB7XG4gICAgICAgIHRoaWNrbmVzczogdGhpcy5fb3BlcmF0aW9uLmdldFRoaWNrbmVzcygpLFxuICAgICAgICBjb2xvcjogdGhpcy5fb3BlcmF0aW9uLmdldENvbG9yKClcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcblxuICAgICAgLy8gSW5pdCBzbGlkZXJcbiAgICAgIHZhciBzbGlkZXJFbGVtZW50ID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNsaWRlcicpO1xuICAgICAgdGhpcy5fc2xpZGVyID0gbmV3IF9saWJTaW1wbGVTbGlkZXIyWydkZWZhdWx0J10oc2xpZGVyRWxlbWVudCwge1xuICAgICAgICBtaW5WYWx1ZTogMCxcbiAgICAgICAgbWF4VmFsdWU6IDAuNVxuICAgICAgfSk7XG4gICAgICB0aGlzLl9zbGlkZXIub24oJ3VwZGF0ZScsIHRoaXMuX29uVGhpY2tuZXNzVXBkYXRlLmJpbmQodGhpcykpO1xuICAgICAgdGhpcy5fc2xpZGVyLnNldFZhbHVlKHRoaXMuX2luaXRpYWxPcHRpb25zLnRoaWNrbmVzcyk7XG5cbiAgICAgIC8vIEluaXQgY29sb3JwaWNrZXJcbiAgICAgIHZhciBjb2xvclBpY2tlckVsZW1lbnQgPSB0aGlzLl9jb250cm9scy5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY29sb3ItcGlja2VyJyk7XG4gICAgICB0aGlzLl9jb2xvclBpY2tlciA9IG5ldyBfbGliQ29sb3JQaWNrZXIyWydkZWZhdWx0J10odGhpcy5fdWksIGNvbG9yUGlja2VyRWxlbWVudCk7XG4gICAgICB0aGlzLl9jb2xvclBpY2tlci5vbigndXBkYXRlJywgdGhpcy5fb25Db2xvclVwZGF0ZS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuX2NvbG9yUGlja2VyLnNldFZhbHVlKHRoaXMuX2luaXRpYWxPcHRpb25zLmNvbG9yKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CYWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGJhY2sgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmFjaygpIHtcbiAgICAgIGlmICh0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKSB7XG4gICAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXQodGhpcy5faW5pdGlhbE9wdGlvbnMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fdWkucmVtb3ZlT3BlcmF0aW9uKCdmcmFtZXMnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25UaGlja25lc3NVcGRhdGUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdGhpY2tuZXNzIGhhcyBiZWVuIGNoYW5nZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uVGhpY2tuZXNzVXBkYXRlKHZhbHVlKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb24uc2V0VGhpY2tuZXNzKHZhbHVlKTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcbiAgICAgIHRoaXMuX2hpZ2hsaWdodERvbmVCdXR0b24oKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Db2xvclVwZGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBjb2xvciBoYXMgYmVlbiBjaGFuZ2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkNvbG9yVXBkYXRlKHZhbHVlKSB7XG4gICAgICB0aGlzLl9vcGVyYXRpb24uc2V0Q29sb3IodmFsdWUpO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkRvbmUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgZG9uZSBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Eb25lKCkge1xuICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLl9vcGVyYXRpb24sIHtcbiAgICAgICAgY29sb3I6IHRoaXMuX2luaXRpYWxPcHRpb25zLmNvbG9yLFxuICAgICAgICB0aGlja25lc3M6IHRoaXMuX2luaXRpYWxPcHRpb25zLnRoaWNrbmVzc1xuICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEZyYW1lc0NvbnRyb2w7XG59KShfY29udHJvbDJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5GcmFtZXNDb250cm9sLnByb3RvdHlwZS5pZGVudGlmaWVyID0gJ2ZyYW1lcyc7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IEZyYW1lc0NvbnRyb2w7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvY29udHJvbHMvZnJhbWVzLWNvbnRyb2wuanNcbiAqKiBtb2R1bGUgaWQgPSA5MFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeDIsIF94MywgX3g0KSB7IHZhciBfYWdhaW4gPSB0cnVlOyBfZnVuY3Rpb246IHdoaWxlIChfYWdhaW4pIHsgdmFyIG9iamVjdCA9IF94MiwgcHJvcGVydHkgPSBfeDMsIHJlY2VpdmVyID0gX3g0OyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeDIgPSBwYXJlbnQ7IF94MyA9IHByb3BlcnR5OyBfeDQgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfY29udHJvbCA9IHJlcXVpcmUoJy4vY29udHJvbCcpO1xuXG52YXIgX2NvbnRyb2wyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY29udHJvbCk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgU3RpY2tlcnNDb250cm9sID0gKGZ1bmN0aW9uIChfQ29udHJvbCkge1xuICBmdW5jdGlvbiBTdGlja2Vyc0NvbnRyb2woKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFN0aWNrZXJzQ29udHJvbCk7XG5cbiAgICBpZiAoX0NvbnRyb2wgIT0gbnVsbCkge1xuICAgICAgX0NvbnRyb2wuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBfaW5oZXJpdHMoU3RpY2tlcnNDb250cm9sLCBfQ29udHJvbCk7XG5cbiAgX2NyZWF0ZUNsYXNzKFN0aWNrZXJzQ29udHJvbCwgW3tcbiAgICBrZXk6ICdpbml0JyxcblxuICAgIC8qKlxuICAgICAqIEVudHJ5IHBvaW50IGZvciB0aGlzIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgIHZhciBjb250cm9sc1RlbXBsYXRlID0gZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXY+IDx1bCBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWxpc3QgaW1nbHktY29udHJvbHMtbGlzdC13aXRoLWJ1dHRvbnNcIj4gJzsgZm9yKHZhciBpZGVudGlmaWVyIGluIGl0LnN0aWNrZXJzKSB7IG91dCs9JyAnOyB2YXIgc3RpY2tlclBhdGggPSBpdC5zdGlja2Vyc1tpZGVudGlmaWVyXTsgb3V0Kz0nICc7IHZhciBlbmFibGVkID0gaXQuYWN0aXZlU3RpY2tlciA9PT0gaWRlbnRpZmllcjsgb3V0Kz0nIDxsaSBkYXRhLWlkZW50aWZpZXI9XCInKyggaWRlbnRpZmllcikrJ1wiJztpZihlbmFibGVkKXtvdXQrPScgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1pdGVtLWFjdGl2ZVwiJzt9b3V0Kz0nPiA8Y2FudmFzIGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtaXRlbS1jYW52YXNcIiBkYXRhLWltYWdlPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoc3RpY2tlclBhdGgpKSsnXCI+PC9jYW52YXM+IDwvbGk+ICc7IH0gb3V0Kz0nIDwvdWw+PC9kaXY+JysoIGl0LnBhcnRpYWxzLmRvbmVCdXR0b24gKTtyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzVGVtcGxhdGUgPSBjb250cm9sc1RlbXBsYXRlO1xuXG4gICAgICB2YXIgY2FudmFzQ29udHJvbHNUZW1wbGF0ZSA9IGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXN0aWNrZXJzLWNvbnRhaW5lclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXN0aWNrZXJzXCI+IDxpbWcgY2xhc3M9XCJpbWdseWtpdC1jYW52YXMtc3RpY2tlci1pbWFnZVwiIC8+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1rbm9iXCI+PC9kaXY+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc1RlbXBsYXRlID0gY2FudmFzQ29udHJvbHNUZW1wbGF0ZTtcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgcmVnaXN0ZXJlZCBzdGlja2Vyc1xuICAgICAgICogQHR5cGUge09iamVjdC48c3RyaW5nLCBjbGFzcz59XG4gICAgICAgKi9cbiAgICAgIHRoaXMuX2F2YWlsYWJsZVN0aWNrZXJzID0ge307XG4gICAgICB0aGlzLl9zdGlja2VycyA9IHt9O1xuICAgICAgdGhpcy5fYWRkRGVmYXVsdFN0aWNrZXJzKCk7XG4gICAgICB0aGlzLnNlbGVjdFN0aWNrZXJzKG51bGwpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19hZGREZWZhdWx0U3RpY2tlcnMnLFxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIHRoZSBkZWZhdWx0IHN0aWNrZXJzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FkZERlZmF1bHRTdGlja2VycygpIHtcbiAgICAgIHRoaXMuYWRkU3RpY2tlcignZ2xhc3Nlcy1uZXJkJywgJ3N0aWNrZXJzL3N0aWNrZXItZ2xhc3Nlcy1uZXJkLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdnbGFzc2VzLW5vcm1hbCcsICdzdGlja2Vycy9zdGlja2VyLWdsYXNzZXMtbm9ybWFsLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdnbGFzc2VzLXNodXR0ZXItZ3JlZW4nLCAnc3RpY2tlcnMvc3RpY2tlci1nbGFzc2VzLXNodXR0ZXItZ3JlZW4ucG5nJyk7XG4gICAgICB0aGlzLmFkZFN0aWNrZXIoJ2dsYXNzZXMtc2h1dHRlci15ZWxsb3cnLCAnc3RpY2tlcnMvc3RpY2tlci1nbGFzc2VzLXNodXR0ZXIteWVsbG93LnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdnbGFzc2VzLXN1bicsICdzdGlja2Vycy9zdGlja2VyLWdsYXNzZXMtc3VuLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdoYXQtY2FwJywgJ3N0aWNrZXJzL3N0aWNrZXItaGF0LWNhcC5wbmcnKTtcbiAgICAgIHRoaXMuYWRkU3RpY2tlcignaGF0LWN5bGluZGVyJywgJ3N0aWNrZXJzL3N0aWNrZXItaGF0LWN5bGluZGVyLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdoYXQtcGFydHknLCAnc3RpY2tlcnMvc3RpY2tlci1oYXQtcGFydHkucG5nJyk7XG4gICAgICB0aGlzLmFkZFN0aWNrZXIoJ2hhdC1zaGVyaWZmJywgJ3N0aWNrZXJzL3N0aWNrZXItaGF0LXNoZXJpZmYucG5nJyk7XG4gICAgICB0aGlzLmFkZFN0aWNrZXIoJ2hlYXJ0JywgJ3N0aWNrZXJzL3N0aWNrZXItaGVhcnQucG5nJyk7XG4gICAgICB0aGlzLmFkZFN0aWNrZXIoJ211c3RhY2hlLWxvbmcnLCAnc3RpY2tlcnMvc3RpY2tlci1tdXN0YWNoZS1sb25nLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdtdXN0YWNoZTEnLCAnc3RpY2tlcnMvc3RpY2tlci1tdXN0YWNoZTEucG5nJyk7XG4gICAgICB0aGlzLmFkZFN0aWNrZXIoJ211c3RhY2hlMicsICdzdGlja2Vycy9zdGlja2VyLW11c3RhY2hlMi5wbmcnKTtcbiAgICAgIHRoaXMuYWRkU3RpY2tlcignbXVzdGFjaGUzJywgJ3N0aWNrZXJzL3N0aWNrZXItbXVzdGFjaGUzLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdwaXBlJywgJ3N0aWNrZXJzL3N0aWNrZXItcGlwZS5wbmcnKTtcbiAgICAgIHRoaXMuYWRkU3RpY2tlcignc25vd2ZsYWtlJywgJ3N0aWNrZXJzL3N0aWNrZXItc25vd2ZsYWtlLnBuZycpO1xuICAgICAgdGhpcy5hZGRTdGlja2VyKCdzdGFyJywgJ3N0aWNrZXJzL3N0aWNrZXItc3Rhci5wbmcnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdhZGRTdGlja2VyJyxcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyB0aGUgc3RpY2tlciB3aXRoIHRoZSBnaXZlbiBpZGVudGlmaWVyIGFuZCBwYXRoXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gYWRkU3RpY2tlcihpZGVudGlmaWVyLCBwYXRoKSB7XG4gICAgICB0aGlzLl9hdmFpbGFibGVTdGlja2Vyc1tpZGVudGlmaWVyXSA9IHBhdGg7XG4gICAgICB0aGlzLl9zdGlja2Vyc1tpZGVudGlmaWVyXSA9IHRoaXMuX2F2YWlsYWJsZVN0aWNrZXJzW2lkZW50aWZpZXJdO1xuXG4gICAgICBpZiAodGhpcy5fYWN0aXZlKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlckNvbnRyb2xzKCk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2VsZWN0U3RpY2tlcnMnLFxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0cyB0aGUgc3RpY2tlcnNcbiAgICAgKiBAcGFyYW0ge1NlbGVjdG9yfSBzZWxlY3RvclxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzZWxlY3RTdGlja2VycyhzZWxlY3Rvcikge1xuICAgICAgdGhpcy5fc3RpY2tlcnMgPSB7fTtcblxuICAgICAgdmFyIHN0aWNrZXJJZGVudGlmaWVycyA9IE9iamVjdC5rZXlzKHRoaXMuX2F2YWlsYWJsZVN0aWNrZXJzKTtcblxuICAgICAgdmFyIHNlbGVjdGVkU3RpY2tlcnMgPSBfbGliVXRpbHMyWydkZWZhdWx0J10uc2VsZWN0KHN0aWNrZXJJZGVudGlmaWVycywgc2VsZWN0b3IpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxlY3RlZFN0aWNrZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZGVudGlmaWVyID0gc2VsZWN0ZWRTdGlja2Vyc1tpXTtcbiAgICAgICAgdGhpcy5fc3RpY2tlcnNbaWRlbnRpZmllcl0gPSB0aGlzLl9hdmFpbGFibGVTdGlja2Vyc1tpZGVudGlmaWVyXTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2FjdGl2ZSkge1xuICAgICAgICB0aGlzLl9yZW5kZXJDb250cm9scygpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkVudGVyJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhpcyBjb250cm9sIGlzIGFjdGl2YXRlZFxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25FbnRlcigpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHRoaXMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUgPSAhIXRoaXMuX3VpLm9wZXJhdGlvbnMuc3RpY2tlcnM7XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbignc3RpY2tlcnMnKTtcblxuICAgICAgLy8gRG9uJ3QgcmVuZGVyIGluaXRpYWxseVxuICAgICAgdGhpcy5fdWkucmVtb3ZlT3BlcmF0aW9uKCdzdGlja2VycycpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsU2V0dGluZ3MgPSB7XG4gICAgICAgIHN0aWNrZXI6IHRoaXMuX29wZXJhdGlvbi5nZXRTdGlja2VyKCksXG4gICAgICAgIHBvc2l0aW9uOiB0aGlzLl9vcGVyYXRpb24uZ2V0UG9zaXRpb24oKS5jbG9uZSgpLFxuICAgICAgICBzaXplOiB0aGlzLl9vcGVyYXRpb24uZ2V0U2l6ZSgpLmNsb25lKClcbiAgICAgIH07XG5cbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG5cbiAgICAgIHRoaXMuX3NpemUgPSB0aGlzLl9pbml0aWFsU2V0dGluZ3Muc2l6ZS5jbG9uZSgpO1xuICAgICAgdGhpcy5fcG9zaXRpb24gPSB0aGlzLl9pbml0aWFsU2V0dGluZ3MucG9zaXRpb24uY2xvbmUoKS5tdWx0aXBseShjYW52YXNTaXplKTtcblxuICAgICAgLy8gUmVtZW1iZXIgem9vbSBsZXZlbCBhbmQgem9vbSB0byBmaXQgdGhlIGNhbnZhc1xuICAgICAgdGhpcy5faW5pdGlhbFpvb21MZXZlbCA9IHRoaXMuX3VpLmNhbnZhcy56b29tTGV2ZWw7XG4gICAgICB0aGlzLl91aS5jYW52YXMuem9vbVRvRml0KCk7XG5cbiAgICAgIC8vIEZpbmQgRE9NIGVsZW1lbnRzXG4gICAgICB0aGlzLl9jb250YWluZXIgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY2FudmFzLXN0aWNrZXJzJyk7XG4gICAgICB0aGlzLl9zdGlja2VySW1hZ2UgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCdpbWcnKTtcbiAgICAgIHRoaXMuX3N0aWNrZXJJbWFnZS5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy5fc3RpY2tlclNpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKF90aGlzLl9zdGlja2VySW1hZ2Uud2lkdGgsIF90aGlzLl9zdGlja2VySW1hZ2UuaGVpZ2h0KTtcbiAgICAgICAgX3RoaXMuX29uU3RpY2tlckxvYWQoKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fa25vYiA9IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJ2Rpdi5pbWdseWtpdC1rbm9iJyk7XG5cbiAgICAgIC8vIE1vdXNlIGV2ZW50IGNhbGxiYWNrcyBib3VuZCB0byB0aGUgY2xhc3MgY29udGV4dFxuICAgICAgdGhpcy5fb25JbWFnZURvd24gPSB0aGlzLl9vbkltYWdlRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25JbWFnZURyYWcgPSB0aGlzLl9vbkltYWdlRHJhZy5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25JbWFnZVVwID0gdGhpcy5fb25JbWFnZVVwLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbktub2JEb3duID0gdGhpcy5fb25Lbm9iRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Lbm9iRHJhZyA9IHRoaXMuX29uS25vYkRyYWcuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uS25vYlVwID0gdGhpcy5fb25Lbm9iVXAuYmluZCh0aGlzKTtcblxuICAgICAgdGhpcy5fcmVuZGVyTGlzdEl0ZW1zKCk7XG4gICAgICB0aGlzLl9oYW5kbGVMaXN0SXRlbXMoKTtcbiAgICAgIHRoaXMuX2hhbmRsZUltYWdlKCk7XG4gICAgICB0aGlzLl9oYW5kbGVLbm9iKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckxpc3RJdGVtcycsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBzdGlja2VycyBvbiB0aGUgbGlzdCBpdGVtIGNhbnZhcyBlbGVtZW50c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJMaXN0SXRlbXMoKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIGNhbnZhc0l0ZW1zID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvckFsbCgnbGkgY2FudmFzJyk7XG4gICAgICB0aGlzLl9jYW52YXNJdGVtcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNhbnZhc0l0ZW1zKTtcblxuICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IF90aGlzMi5fY2FudmFzSXRlbXNbaV07XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhcy5vZmZzZXRXaWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGNhbnZhcy5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgdmFyIGltYWdlID0gY2FudmFzLmRhdGFzZXQuaW1hZ2U7XG5cbiAgICAgICAgdmFyIGltYWdlRWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcblxuICAgICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgICBpbWFnZUVsLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIGltYWdlU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oaW1hZ2VFbC53aWR0aCwgaW1hZ2VFbC5oZWlnaHQpO1xuICAgICAgICAgIHZhciBuZXdTaXplID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLnJlc2l6ZVZlY3RvclRvRml0KGltYWdlU2l6ZSwgY2FudmFzU2l6ZSk7XG5cbiAgICAgICAgICB2YXIgb2Zmc2V0ID0gY2FudmFzU2l6ZS5jbG9uZSgpLmRpdmlkZSgyKS5zdWJ0cmFjdChuZXdTaXplLmNsb25lKCkuZGl2aWRlKDIpKTtcblxuICAgICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGltYWdlRWwsIDAsIDAsIGltYWdlU2l6ZS54LCBpbWFnZVNpemUueSwgb2Zmc2V0LngsIG9mZnNldC55LCBuZXdTaXplLngsIG5ld1NpemUueSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGltYWdlRWwuc3JjID0gaW1hZ2U7XG4gICAgICB9O1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2NhbnZhc0l0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIF9sb29wKGkpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVMaXN0SXRlbXMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgbGlzdCBpdGVtIGNsaWNrIGV2ZW50c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVMaXN0SXRlbXMoKSB7XG4gICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgdmFyIGxpc3RJdGVtcyA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3JBbGwoJ2xpJyk7XG4gICAgICB0aGlzLl9saXN0SXRlbXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChsaXN0SXRlbXMpO1xuXG4gICAgICB2YXIgX2xvb3AyID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgdmFyIGxpc3RJdGVtID0gX3RoaXMzLl9saXN0SXRlbXNbaV07XG4gICAgICAgIHZhciBpZGVudGlmaWVyID0gbGlzdEl0ZW0uZGF0YXNldC5pZGVudGlmaWVyO1xuXG4gICAgICAgIGxpc3RJdGVtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzMy5fb25MaXN0SXRlbUNsaWNrKGxpc3RJdGVtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFfdGhpczMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUgJiYgaSA9PT0gMCB8fCBfdGhpczMuX29wZXJhdGlvbkV4aXN0ZWRCZWZvcmUgJiYgX3RoaXMzLl9zdGlja2Vyc1tpZGVudGlmaWVyXSA9PT0gX3RoaXMzLl9pbml0aWFsU2V0dGluZ3Muc3RpY2tlcikge1xuICAgICAgICAgIF90aGlzMy5fb25MaXN0SXRlbUNsaWNrKGxpc3RJdGVtLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vIExpc3RlbiB0byBjbGljayBldmVudHNcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fbGlzdEl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIF9sb29wMihpKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfYXBwbHlTZXR0aW5ncycsXG5cbiAgICAvKipcbiAgICAgKiBSZXNpemVzIGFuZCBwb3NpdGlvbnMgdGhlIHN0aWNrZXIgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IHNldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FwcGx5U2V0dGluZ3MoKSB7XG4gICAgICB2YXIgcmF0aW8gPSB0aGlzLl9zdGlja2VyU2l6ZS55IC8gdGhpcy5fc3RpY2tlclNpemUueDtcbiAgICAgIHRoaXMuX3NpemUueSA9IHRoaXMuX3NpemUueCAqIHJhdGlvO1xuXG4gICAgICB0aGlzLl9zdGlja2VySW1hZ2Uuc3R5bGUud2lkdGggPSAnJyArIHRoaXMuX3NpemUueCArICdweCc7XG4gICAgICB0aGlzLl9zdGlja2VySW1hZ2Uuc3R5bGUuaGVpZ2h0ID0gJycgKyB0aGlzLl9zaXplLnkgKyAncHgnO1xuICAgICAgdGhpcy5fY29udGFpbmVyLnN0eWxlLmxlZnQgPSAnJyArIHRoaXMuX3Bvc2l0aW9uLnggKyAncHgnO1xuICAgICAgdGhpcy5fY29udGFpbmVyLnN0eWxlLnRvcCA9ICcnICsgdGhpcy5fcG9zaXRpb24ueSArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGhpdHMgdGhlIGJhY2sgYnV0dG9uXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICBpZiAodGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSkge1xuICAgICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbignc3RpY2tlcnMnKTtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldCh0aGlzLl9pbml0aWFsU2V0dGluZ3MpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fdWkucmVtb3ZlT3BlcmF0aW9uKCdzdGlja2VycycpO1xuICAgICAgfVxuICAgICAgdGhpcy5fdWkuY2FudmFzLnNldFpvb21MZXZlbCh0aGlzLl9pbml0aWFsWm9vbUxldmVsKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Eb25lJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIGRvbmUgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWRcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRvbmUoKSB7XG4gICAgICAvLyBNYXAgdGhlIHBvc2l0aW9uIGFuZCBzaXplIG9wdGlvbnMgdG8gMC4uLjEgdmFsdWVzXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fcG9zaXRpb24uY2xvbmUoKS5kaXZpZGUoY2FudmFzU2l6ZSk7XG4gICAgICB2YXIgc2l6ZSA9IHRoaXMuX3NpemUuY2xvbmUoKS5kaXZpZGUoY2FudmFzU2l6ZSk7XG5cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5zZXRab29tTGV2ZWwodGhpcy5faW5pdGlhbFpvb21MZXZlbCwgZmFsc2UpO1xuXG4gICAgICAvLyBDcmVhdGUgYSBuZXcgb3BlcmF0aW9uIGFuZCByZW5kZXIgaXRcbiAgICAgIHRoaXMuX29wZXJhdGlvbiA9IHRoaXMuX3VpLmdldE9yQ3JlYXRlT3BlcmF0aW9uKCdzdGlja2VycycpO1xuICAgICAgdGhpcy5fb3BlcmF0aW9uLnNldCh7XG4gICAgICAgIHN0aWNrZXI6IHRoaXMuX2F2YWlsYWJsZVN0aWNrZXJzW3RoaXMuX3N0aWNrZXJdLFxuICAgICAgICBwb3NpdGlvbjogcG9zaXRpb24sXG4gICAgICAgIHNpemU6IHNpemVcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fdWkuY2FudmFzLnJlbmRlcigpO1xuXG4gICAgICB0aGlzLl91aS5hZGRIaXN0b3J5KHRoaXMsIHtcbiAgICAgICAgc3RpY2tlcjogdGhpcy5faW5pdGlhbFNldHRpbmdzLnN0aWNrZXIsXG4gICAgICAgIHBvc2l0aW9uOiB0aGlzLl9pbml0aWFsU2V0dGluZ3MucG9zaXRpb24uY2xvbmUoKSxcbiAgICAgICAgc2l6ZTogdGhpcy5faW5pdGlhbFNldHRpbmdzLnNpemUuY2xvbmUoKVxuICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZUtub2InLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUga25vYiBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVLbm9iKCkge1xuICAgICAgdGhpcy5fa25vYi5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vbktub2JEb3duKTtcbiAgICAgIHRoaXMuX2tub2IuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uS25vYkRvd24pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbktub2JEb3duJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbktub2JEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHRoaXMuX2luaXRpYWxTaXplID0gdGhpcy5fc2l6ZS5jbG9uZSgpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbktub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uS25vYkRyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25Lbm9iVXApO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbktub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uS25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25Lbm9iRHJhZyhlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgZGlmZiA9IG1vdXNlUG9zaXRpb24uY2xvbmUoKS5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG5cbiAgICAgIHZhciBzaXplID0gdGhpcy5faW5pdGlhbFNpemUuY2xvbmUoKTtcbiAgICAgIHZhciByYXRpbyA9IHRoaXMuX3N0aWNrZXJJbWFnZS5oZWlnaHQgLyB0aGlzLl9zdGlja2VySW1hZ2Uud2lkdGg7XG4gICAgICBzaXplLnggKz0gZGlmZi54O1xuICAgICAgc2l6ZS55ID0gc2l6ZS54ICogcmF0aW87XG5cbiAgICAgIHRoaXMuX3NpemUuY29weShzaXplKTtcblxuICAgICAgdGhpcy5fYXBwbHlTZXR0aW5ncygpO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbktub2JVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHJlbGVhc2VzIHRoZSBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbktub2JVcCgpIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uS25vYkRyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25Lbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbktub2JVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uS25vYlVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlSW1hZ2UnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgaW1hZ2UgZHJhZ2dpbmdcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlSW1hZ2UoKSB7XG4gICAgICB0aGlzLl9zdGlja2VySW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25JbWFnZURvd24pO1xuICAgICAgdGhpcy5fc3RpY2tlckltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLl9vbkltYWdlRG93bik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uSW1hZ2VEb3duJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBpbWFnZVxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25JbWFnZURvd24oZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuICAgICAgdGhpcy5faW5pdGlhbFBvc2l0aW9uID0gdGhpcy5fcG9zaXRpb24uY2xvbmUoKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25JbWFnZURyYWcpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25JbWFnZURyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25JbWFnZVVwKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25JbWFnZVVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25JbWFnZURyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgaW1hZ2VcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uSW1hZ2VEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIG1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBkaWZmID0gbW91c2VQb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxNb3VzZVBvc2l0aW9uKTtcblxuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5faW5pdGlhbFBvc2l0aW9uLmNsb25lKCk7XG4gICAgICBwb3NpdGlvbi5hZGQoZGlmZik7XG5cbiAgICAgIHRoaXMuX3Bvc2l0aW9uLmNvcHkocG9zaXRpb24pO1xuXG4gICAgICB0aGlzLl9hcHBseVNldHRpbmdzKCk7XG4gICAgICB0aGlzLl9oaWdobGlnaHREb25lQnV0dG9uKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uSW1hZ2VVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHJlbGVhc2VzIHRoZSBpbWFnZVxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25JbWFnZVVwKCkge1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25JbWFnZURyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25JbWFnZURyYWcpO1xuXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25JbWFnZVVwKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25JbWFnZVVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25TdGlja2VyTG9hZCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCBhcyBzb29uIGFzIHRoZSBzdGlja2VyIGltYWdlIGhhcyBiZWVuIGxvYWRlZFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblN0aWNrZXJMb2FkKCkge1xuICAgICAgdGhpcy5fc2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10odGhpcy5fc3RpY2tlckltYWdlLndpZHRoLCB0aGlzLl9zdGlja2VySW1hZ2UuaGVpZ2h0KTtcblxuICAgICAgaWYgKHR5cGVvZiB0aGlzLl9wb3NpdGlvbiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhpcy5fcG9zaXRpb24gPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDAsIDApO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9hcHBseVNldHRpbmdzKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uTGlzdEl0ZW1DbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrZWQgYSBsaXN0IGl0ZW1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25MaXN0SXRlbUNsaWNrKGl0ZW0pIHtcbiAgICAgIHZhciBtYW51YWxseSA9IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgdGhpcy5fZGVhY3RpdmF0ZUFsbEl0ZW1zKCk7XG5cbiAgICAgIHZhciBpZGVudGlmaWVyID0gaXRlbS5kYXRhc2V0LmlkZW50aWZpZXI7XG5cbiAgICAgIHZhciBzdGlja2VyUGF0aCA9IHRoaXMuX2F2YWlsYWJsZVN0aWNrZXJzW2lkZW50aWZpZXJdO1xuICAgICAgc3RpY2tlclBhdGggPSB0aGlzLl9raXQuZ2V0QXNzZXRQYXRoKHN0aWNrZXJQYXRoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5fc3RpY2tlckltYWdlLmF0dHJpYnV0ZXMucmVtb3ZlTmFtZWRJdGVtKCdzdHlsZScpO1xuICAgICAgfSBjYXRjaCAoZSkge31cblxuICAgICAgdGhpcy5fc3RpY2tlciA9IGlkZW50aWZpZXI7XG4gICAgICB0aGlzLl9zdGlja2VySW1hZ2Uuc3JjID0gc3RpY2tlclBhdGg7XG5cbiAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnKTtcblxuICAgICAgaWYgKG1hbnVhbGx5KSB7XG4gICAgICAgIHRoaXMuX2hpZ2hsaWdodERvbmVCdXR0b24oKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZGVhY3RpdmF0ZUFsbEl0ZW1zJyxcblxuICAgIC8qKlxuICAgICAqIERlYWN0aXZhdGVzIGFsbCBsaXN0IGl0ZW1zXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2RlYWN0aXZhdGVBbGxJdGVtcygpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fbGlzdEl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBsaXN0SXRlbSA9IHRoaXMuX2xpc3RJdGVtc1tpXTtcbiAgICAgICAgbGlzdEl0ZW0uY2xhc3NMaXN0LnJlbW92ZSgnaW1nbHlraXQtY29udHJvbHMtaXRlbS1hY3RpdmUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIHRoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSB0ZW1wbGF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY29udGV4dCA9IF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFN0aWNrZXJzQ29udHJvbC5wcm90b3R5cGUpLCAnY29udGV4dCcsIHRoaXMpO1xuICAgICAgY29udGV4dC5zdGlja2VycyA9IHRoaXMuX3N0aWNrZXJzO1xuICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFN0aWNrZXJzQ29udHJvbDtcbn0pKF9jb250cm9sMlsnZGVmYXVsdCddKTtcblxuLyoqXG4gKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgY29udHJvbC5cbiAqIEB0eXBlIHtTdHJpbmd9XG4gKi9cblN0aWNrZXJzQ29udHJvbC5wcm90b3R5cGUuaWRlbnRpZmllciA9ICdzdGlja2Vycyc7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFN0aWNrZXJzQ29udHJvbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9jb250cm9scy9zdGlja2Vycy1jb250cm9sLmpzXG4gKiogbW9kdWxlIGlkID0gOTFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBfX0RPVEpTX1RFTVBMQVRFICovXG4vKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IChmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoJ3ZhbHVlJyBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSkoKTtcblxudmFyIF9nZXQgPSBmdW5jdGlvbiBnZXQoX3gyLCBfeDMsIF94NCkgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeDIsIHByb3BlcnR5ID0gX3gzLCByZWNlaXZlciA9IF94NDsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3gyID0gcGFyZW50OyBfeDMgPSBwcm9wZXJ0eTsgX3g0ID0gcmVjZWl2ZXI7IF9hZ2FpbiA9IHRydWU7IGNvbnRpbnVlIF9mdW5jdGlvbjsgfSB9IGVsc2UgaWYgKCd2YWx1ZScgaW4gZGVzYykgeyByZXR1cm4gZGVzYy52YWx1ZTsgfSBlbHNlIHsgdmFyIGdldHRlciA9IGRlc2MuZ2V0OyBpZiAoZ2V0dGVyID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSByZXR1cm4gZ2V0dGVyLmNhbGwocmVjZWl2ZXIpOyB9IH0gfTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgJ2RlZmF1bHQnOiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2NvbnRyb2wgPSByZXF1aXJlKCcuL2NvbnRyb2wnKTtcblxudmFyIF9jb250cm9sMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2NvbnRyb2wpO1xuXG52YXIgX2xpYkNvbG9yUGlja2VyID0gcmVxdWlyZSgnLi4vbGliL2NvbG9yLXBpY2tlcicpO1xuXG52YXIgX2xpYkNvbG9yUGlja2VyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkNvbG9yUGlja2VyKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBUZXh0Q29udHJvbCA9IChmdW5jdGlvbiAoX0NvbnRyb2wpIHtcbiAgZnVuY3Rpb24gVGV4dENvbnRyb2woKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFRleHRDb250cm9sKTtcblxuICAgIGlmIChfQ29udHJvbCAhPSBudWxsKSB7XG4gICAgICBfQ29udHJvbC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIF9pbmhlcml0cyhUZXh0Q29udHJvbCwgX0NvbnRyb2wpO1xuXG4gIF9jcmVhdGVDbGFzcyhUZXh0Q29udHJvbCwgW3tcbiAgICBrZXk6ICdpbml0JyxcblxuICAgIC8qKlxuICAgICAqIEVudHJ5IHBvaW50IGZvciB0aGlzIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHtcbiAgICAgIHZhciBjb250cm9sc1RlbXBsYXRlID0gZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXY+IDx1bCBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWxpc3QgaW1nbHktY29udHJvbHMtbGlzdC13aXRoLWJ1dHRvbnNcIj4gJzt2YXIgYXJyMT1pdC5mb250cztpZihhcnIxKXt2YXIgdmFsdWUsaW5kZXg9LTEsbDE9YXJyMS5sZW5ndGgtMTt3aGlsZShpbmRleDxsMSl7dmFsdWU9YXJyMVtpbmRleCs9MV07b3V0Kz0nIDxsaSBkYXRhLW5hbWU9XCInKyggdmFsdWUubmFtZSkrJ1wiIGRhdGEtd2VpZ2h0PVwiJysoIHZhbHVlLndlaWdodCkrJ1wiPiA8Y2FudmFzIGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtaXRlbS1jYW52YXNcIj48L2NhbnZhcz4gPC9saT4gJzt9IH0gb3V0Kz0nIDwvdWw+PC9kaXY+PGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWJ1dHRvblwiPiAnKyggaXQucGFydGlhbHMuZmdDb2xvclBpY2tlcikrJzwvZGl2PjxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1idXR0b25cIj4gJysoIGl0LnBhcnRpYWxzLmJnQ29sb3JQaWNrZXIpKyc8L2Rpdj4nKyggaXQucGFydGlhbHMuZG9uZUJ1dHRvbik7cmV0dXJuIG91dDtcbn07XG4gICAgICB0aGlzLl9jb250cm9sc1RlbXBsYXRlID0gY29udHJvbHNUZW1wbGF0ZTtcblxuICAgICAgdmFyIGNhbnZhc0NvbnRyb2xzVGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy10ZXh0LWNvbnRhaW5lclwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY2FudmFzLXRleHRcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNyb3NzaGFpclwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9jcm9zc2hhaXIucG5nJykpKydcIiAvPiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNhbnZhcy10ZXh0LXRleHRhcmVhXCI+IDx0ZXh0YXJlYT48L3RleHRhcmVhPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQta25vYlwiPjwvZGl2PiA8L2Rpdj4gPC9kaXY+PC9kaXY+JztyZXR1cm4gb3V0O1xufTtcbiAgICAgIHRoaXMuX2NhbnZhc0NvbnRyb2xzVGVtcGxhdGUgPSBjYW52YXNDb250cm9sc1RlbXBsYXRlO1xuXG4gICAgICB0aGlzLl9wYXJ0aWFsVGVtcGxhdGVzLmZnQ29sb3JQaWNrZXIgPSBfbGliQ29sb3JQaWNrZXIyWydkZWZhdWx0J10udGVtcGxhdGU7XG4gICAgICB0aGlzLl9wYXJ0aWFsVGVtcGxhdGVzLmZnQ29sb3JQaWNrZXIuYWRkaXRpb25hbENvbnRleHQgPSB7XG4gICAgICAgIGlkOiAnaW1nbHlraXQtdGV4dC1mb3JlZ3JvdW5kLWNvbG9yLXBpY2tlcidcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuYmdDb2xvclBpY2tlciA9IF9saWJDb2xvclBpY2tlcjJbJ2RlZmF1bHQnXS50ZW1wbGF0ZTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuYmdDb2xvclBpY2tlci5hZGRpdGlvbmFsQ29udGV4dCA9IHtcbiAgICAgICAgaWQ6ICdpbWdseWtpdC10ZXh0LWJhY2tncm91bmQtY29sb3ItcGlja2VyJ1xuICAgICAgfTtcblxuICAgICAgdGhpcy5fZm9udHMgPSBbXTtcbiAgICAgIHRoaXMuX2FkZEZvbnRzKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckNvbnRyb2xzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNvbnRyb2xzKCkge1xuICAgICAgdGhpcy5fcGFydGlhbFRlbXBsYXRlcy5mZ0NvbG9yUGlja2VyLmFkZGl0aW9uYWxDb250ZXh0LmxhYmVsID0gdGhpcy5fdWkudHJhbnNsYXRlKCdjb250cm9scy50ZXh0LmZvcmVncm91bmQnKTtcbiAgICAgIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMuYmdDb2xvclBpY2tlci5hZGRpdGlvbmFsQ29udGV4dC5sYWJlbCA9IHRoaXMuX3VpLnRyYW5zbGF0ZSgnY29udHJvbHMudGV4dC5iYWNrZ3JvdW5kJyk7XG4gICAgICBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihUZXh0Q29udHJvbC5wcm90b3R5cGUpLCAnX3JlbmRlckNvbnRyb2xzJywgdGhpcykuY2FsbCh0aGlzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRW50ZXIoKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICB0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlID0gISF0aGlzLl91aS5vcGVyYXRpb25zLnRleHQ7XG4gICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbigndGV4dCcpO1xuXG4gICAgICAvLyBEb24ndCByZW5kZXIgaW5pdGlhbGx5XG4gICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ3RleHQnKTtcblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcblxuICAgICAgdGhpcy5faW5pdGlhbFNldHRpbmdzID0ge1xuICAgICAgICBsaW5lSGVpZ2h0OiB0aGlzLl9vcGVyYXRpb24uZ2V0TGluZUhlaWdodCgpLFxuICAgICAgICBmb250U2l6ZTogdGhpcy5fb3BlcmF0aW9uLmdldEZvbnRTaXplKCksXG4gICAgICAgIGZvbnRGYW1pbHk6IHRoaXMuX29wZXJhdGlvbi5nZXRGb250RmFtaWx5KCksXG4gICAgICAgIGZvbnRXZWlnaHQ6IHRoaXMuX29wZXJhdGlvbi5nZXRGb250V2VpZ2h0KCksXG4gICAgICAgIGNvbG9yOiB0aGlzLl9vcGVyYXRpb24uZ2V0Q29sb3IoKSxcbiAgICAgICAgcG9zaXRpb246IHRoaXMuX29wZXJhdGlvbi5nZXRQb3NpdGlvbigpLFxuICAgICAgICB0ZXh0OiB0aGlzLl9vcGVyYXRpb24uZ2V0VGV4dCgpIHx8ICcnLFxuICAgICAgICBtYXhXaWR0aDogdGhpcy5fb3BlcmF0aW9uLmdldE1heFdpZHRoKCksXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5fb3BlcmF0aW9uLmdldEJhY2tncm91bmRDb2xvcigpXG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9zZXR0aW5ncyA9IHtcbiAgICAgICAgbGluZUhlaWdodDogdGhpcy5faW5pdGlhbFNldHRpbmdzLmxpbmVIZWlnaHQsXG4gICAgICAgIGZvbnRTaXplOiB0aGlzLl9pbml0aWFsU2V0dGluZ3MuZm9udFNpemUsXG4gICAgICAgIGZvbnRGYW1pbHk6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5mb250RmFtaWx5LFxuICAgICAgICBmb250V2VpZ2h0OiB0aGlzLl9pbml0aWFsU2V0dGluZ3MuZm9udFdlaWdodCxcbiAgICAgICAgY29sb3I6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5jb2xvci5jbG9uZSgpLFxuICAgICAgICBwb3NpdGlvbjogdGhpcy5faW5pdGlhbFNldHRpbmdzLnBvc2l0aW9uLmNsb25lKCkubXVsdGlwbHkoY2FudmFzU2l6ZSksXG4gICAgICAgIHRleHQ6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy50ZXh0LFxuICAgICAgICBtYXhXaWR0aDogdGhpcy5faW5pdGlhbFNldHRpbmdzLm1heFdpZHRoICogY2FudmFzU2l6ZS54LFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5iYWNrZ3JvdW5kQ29sb3IuY2xvbmUoKVxuICAgICAgfTtcblxuICAgICAgLy8gUmVtZW1iZXIgem9vbSBsZXZlbCBhbmQgem9vbSB0byBmaXQgdGhlIGNhbnZhc1xuICAgICAgdGhpcy5faW5pdGlhbFpvb21MZXZlbCA9IHRoaXMuX3VpLmNhbnZhcy56b29tTGV2ZWw7XG5cbiAgICAgIHRoaXMuX2NvbnRhaW5lciA9IHRoaXMuX2NhbnZhc0NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jYW52YXMtdGV4dCcpO1xuICAgICAgdGhpcy5fdGV4dGFyZWEgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCd0ZXh0YXJlYScpO1xuICAgICAgdGhpcy5fdGV4dGFyZWEuZm9jdXMoKTtcblxuICAgICAgdGhpcy5fbW92ZUtub2IgPSB0aGlzLl9jYW52YXNDb250cm9scy5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY3Jvc3NoYWlyJyk7XG4gICAgICB0aGlzLl9yZXNpemVLbm9iID0gdGhpcy5fY2FudmFzQ29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWtub2InKTtcblxuICAgICAgLy8gSWYgdGhlIHRleHQgaGFzIGJlZW4gZWRpdGVkIGJlZm9yZSwgc3VidHJhY3QgdGhlIGtub2Igd2lkdGggYW5kIHBhZGRpbmdcbiAgICAgIGlmICh0aGlzLl9vcGVyYXRpb25FeGlzdGVkQmVmb3JlKSB7XG4gICAgICAgIHRoaXMuX3NldHRpbmdzLnBvc2l0aW9uLnggLT0gMjtcbiAgICAgICAgdGhpcy5fc2V0dGluZ3MucG9zaXRpb24ueSAtPSAyO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9vblRleHRhcmVhS2V5VXAgPSB0aGlzLl9vblRleHRhcmVhS2V5VXAuYmluZCh0aGlzKTtcbiAgICAgIHRoaXMuX29uUmVzaXplS25vYkRvd24gPSB0aGlzLl9vblJlc2l6ZUtub2JEb3duLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vblJlc2l6ZUtub2JEcmFnID0gdGhpcy5fb25SZXNpemVLbm9iRHJhZy5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25SZXNpemVLbm9iVXAgPSB0aGlzLl9vblJlc2l6ZUtub2JVcC5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Nb3ZlS25vYkRvd24gPSB0aGlzLl9vbk1vdmVLbm9iRG93bi5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Nb3ZlS25vYkRyYWcgPSB0aGlzLl9vbk1vdmVLbm9iRHJhZy5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5fb25Nb3ZlS25vYlVwID0gdGhpcy5fb25Nb3ZlS25vYlVwLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbkZvcmVncm91bmRDb2xvclVwZGF0ZSA9IHRoaXMuX29uRm9yZWdyb3VuZENvbG9yVXBkYXRlLmJpbmQodGhpcyk7XG4gICAgICB0aGlzLl9vbkJhY2tncm91bmRDb2xvclVwZGF0ZSA9IHRoaXMuX29uQmFja2dyb3VuZENvbG9yVXBkYXRlLmJpbmQodGhpcyk7XG5cbiAgICAgIHRoaXMuX2luaXRDb2xvclBpY2tlcnMoKTtcbiAgICAgIHRoaXMuX3JlbmRlckxpc3RJdGVtcygpO1xuICAgICAgdGhpcy5faGFuZGxlTGlzdEl0ZW1zKCk7XG4gICAgICB0aGlzLl9oYW5kbGVUZXh0YXJlYSgpO1xuICAgICAgdGhpcy5faGFuZGxlUmVzaXplS25vYigpO1xuICAgICAgdGhpcy5faGFuZGxlTW92ZUtub2IoKTtcblxuICAgICAgLy8gUmVzaXplIGFzeW5jaHJvbm91c2x5IHRvIHJlbmRlciBhIGZyYW1lXG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMuX3Jlc2l6ZVRleHRhcmVhKCk7XG4gICAgICB9LCAxKTtcblxuICAgICAgdGhpcy5fdWkuY2FudmFzLnpvb21Ub0ZpdCgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy5fYXBwbHlTZXR0aW5ncygpO1xuICAgICAgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2luaXRDb2xvclBpY2tlcnMnLFxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIGNvbG9yIHBpY2tlcnNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaW5pdENvbG9yUGlja2VycygpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgZm9yZWdyb3VuZENvbG9yUGlja2VyID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignI2ltZ2x5a2l0LXRleHQtZm9yZWdyb3VuZC1jb2xvci1waWNrZXInKTtcbiAgICAgIHRoaXMuX2ZvcmVncm91bmRDb2xvclBpY2tlciA9IG5ldyBfbGliQ29sb3JQaWNrZXIyWydkZWZhdWx0J10odGhpcy5fdWksIGZvcmVncm91bmRDb2xvclBpY2tlcik7XG4gICAgICB0aGlzLl9mb3JlZ3JvdW5kQ29sb3JQaWNrZXIuc2V0VmFsdWUodGhpcy5fb3BlcmF0aW9uLmdldENvbG9yKCkpO1xuICAgICAgdGhpcy5fZm9yZWdyb3VuZENvbG9yUGlja2VyLm9uKCd1cGRhdGUnLCB0aGlzLl9vbkZvcmVncm91bmRDb2xvclVwZGF0ZSk7XG4gICAgICB0aGlzLl9mb3JlZ3JvdW5kQ29sb3JQaWNrZXIub24oJ3Nob3cnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF90aGlzMi5fYmFja2dyb3VuZENvbG9yUGlja2VyLmhpZGUoKTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgYmFja2dyb3VuZENvbG9yUGlja2VyID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignI2ltZ2x5a2l0LXRleHQtYmFja2dyb3VuZC1jb2xvci1waWNrZXInKTtcbiAgICAgIHRoaXMuX2JhY2tncm91bmRDb2xvclBpY2tlciA9IG5ldyBfbGliQ29sb3JQaWNrZXIyWydkZWZhdWx0J10odGhpcy5fdWksIGJhY2tncm91bmRDb2xvclBpY2tlcik7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kQ29sb3JQaWNrZXIuc2V0VmFsdWUodGhpcy5fb3BlcmF0aW9uLmdldEJhY2tncm91bmRDb2xvcigpKTtcbiAgICAgIHRoaXMuX2JhY2tncm91bmRDb2xvclBpY2tlci5vbigndXBkYXRlJywgdGhpcy5fb25CYWNrZ3JvdW5kQ29sb3JVcGRhdGUpO1xuICAgICAgdGhpcy5fYmFja2dyb3VuZENvbG9yUGlja2VyLm9uKCdzaG93JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpczIuX2ZvcmVncm91bmRDb2xvclBpY2tlci5oaWRlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyTGlzdEl0ZW1zJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHRleHQgb24gdGhlIGxpc3QgaXRlbSBjYW52YXMgZWxlbWVudHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyTGlzdEl0ZW1zKCkge1xuICAgICAgdmFyIGNhbnZhc0l0ZW1zID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvckFsbCgnbGkgY2FudmFzJyk7XG4gICAgICB0aGlzLl9jYW52YXNJdGVtcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGNhbnZhc0l0ZW1zKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9jYW52YXNJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzSXRlbXNbaV07XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhcy5vZmZzZXRXaWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGNhbnZhcy5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgdmFyIGxpc3RJdGVtID0gY2FudmFzLnBhcmVudE5vZGU7XG5cbiAgICAgICAgdmFyIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgdmFyIGZvbnRGYW1pbHkgPSBsaXN0SXRlbS5kYXRhc2V0Lm5hbWU7XG4gICAgICAgIHZhciBmb250V2VpZ2h0ID0gbGlzdEl0ZW0uZGF0YXNldC53ZWlnaHQ7XG5cbiAgICAgICAgY29udGV4dC5mb250ID0gJycgKyBmb250V2VpZ2h0ICsgJyAzMHB4ICcgKyBmb250RmFtaWx5O1xuICAgICAgICBjb250ZXh0LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnO1xuICAgICAgICBjb250ZXh0LnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICd3aGl0ZSc7XG5cbiAgICAgICAgY29udGV4dC5maWxsVGV4dChmb250RmFtaWx5LnN1YnN0cigwLCAyKSwgY2FudmFzLndpZHRoIC8gMiwgY2FudmFzLmhlaWdodCAvIDIpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVMaXN0SXRlbXMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgbGlzdCBpdGVtIGNsaWNrIGV2ZW50c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVMaXN0SXRlbXMoKSB7XG4gICAgICB2YXIgX3RoaXMzID0gdGhpcztcblxuICAgICAgdmFyIGxpc3RJdGVtcyA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3JBbGwoJ2xpJyk7XG4gICAgICB0aGlzLl9saXN0SXRlbXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChsaXN0SXRlbXMpO1xuXG4gICAgICB2YXIgX2xvb3AgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgbGlzdEl0ZW0gPSBfdGhpczMuX2xpc3RJdGVtc1tpXTtcbiAgICAgICAgdmFyIG5hbWUgPSBsaXN0SXRlbS5kYXRhc2V0Lm5hbWU7XG5cbiAgICAgICAgbGlzdEl0ZW0uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMzLl9vbkxpc3RJdGVtQ2xpY2sobGlzdEl0ZW0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoIV90aGlzMy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSAmJiBpID09PSAwIHx8IF90aGlzMy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSAmJiBuYW1lID09PSBfdGhpczMuX2luaXRpYWxTZXR0aW5ncy5mb250RmFtaWx5KSB7XG4gICAgICAgICAgX3RoaXMzLl9vbkxpc3RJdGVtQ2xpY2sobGlzdEl0ZW0sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgLy8gTGlzdGVuIHRvIGNsaWNrIGV2ZW50c1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9saXN0SXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgX2xvb3AoaSk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZVRleHRhcmVhJyxcblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgdGhlIHRleHQgYXJlYSBrZXkgZXZlbnRzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2hhbmRsZVRleHRhcmVhKCkge1xuICAgICAgdGhpcy5fdGV4dGFyZWEuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vblRleHRhcmVhS2V5VXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vblRleHRhcmVhS2V5VXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyBhIGtleSBpbnNpZGUgdGhlIHRleHQgYXJlYVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblRleHRhcmVhS2V5VXAoKSB7XG4gICAgICB0aGlzLl9yZXNpemVUZXh0YXJlYSgpO1xuICAgICAgdGhpcy5fc2V0dGluZ3MudGV4dCA9IHRoaXMuX3RleHRhcmVhLnZhbHVlO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZXNpemVUZXh0YXJlYScsXG5cbiAgICAvKipcbiAgICAgKiBSZXNpemVzIHRoZSB0ZXh0IGFyZWEgdG8gZml0IHRoZSB0ZXh0IGluc2lkZSBvZiBpdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZXNpemVUZXh0YXJlYSgpIHtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSB0aGlzLl90ZXh0YXJlYS5zY3JvbGxUb3A7XG5cbiAgICAgIGlmICghc2Nyb2xsVG9wKSB7XG4gICAgICAgIHZhciBfc2Nyb2xsSGVpZ2h0ID0gdW5kZWZpbmVkLFxuICAgICAgICAgICAgaGVpZ2h0ID0gdW5kZWZpbmVkO1xuICAgICAgICBkbyB7XG4gICAgICAgICAgX3Njcm9sbEhlaWdodCA9IHRoaXMuX3RleHRhcmVhLnNjcm9sbEhlaWdodDtcbiAgICAgICAgICBoZWlnaHQgPSB0aGlzLl90ZXh0YXJlYS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgICAgdGhpcy5fdGV4dGFyZWEuc3R5bGUuaGVpZ2h0ID0gJycgKyAoaGVpZ2h0IC0gNSkgKyAncHgnO1xuICAgICAgICB9IHdoaWxlIChfc2Nyb2xsSGVpZ2h0ICYmIF9zY3JvbGxIZWlnaHQgIT09IHRoaXMuX3RleHRhcmVhLnNjcm9sbEhlaWdodCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSB0aGlzLl90ZXh0YXJlYS5zY3JvbGxIZWlnaHQ7XG4gICAgICB0aGlzLl90ZXh0YXJlYS5zdHlsZS5oZWlnaHQgPSAnJyArIChzY3JvbGxIZWlnaHQgKyAyMCkgKyAncHgnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVNb3ZlS25vYicsXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSBtb3ZlIGtub2IgZHJhZ2dpbmdcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlTW92ZUtub2IoKSB7XG4gICAgICB0aGlzLl9tb3ZlS25vYi5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLl9vbk1vdmVLbm9iRG93bik7XG4gICAgICB0aGlzLl9tb3ZlS25vYi5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5fb25Nb3ZlS25vYkRvd24pO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbk1vdmVLbm9iRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0aGUgbW92ZSBrbm9iXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTW92ZUtub2JEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHRoaXMuX2luaXRpYWxQb3NpdGlvbiA9IHRoaXMuX3NldHRpbmdzLnBvc2l0aW9uLmNsb25lKCk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uTW92ZUtub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uTW92ZUtub2JEcmFnKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uTW92ZUtub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b2NoZW5kJywgdGhpcy5fb25Nb3ZlS25vYlVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Nb3ZlS25vYkRyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgbW92ZSBrbm9iXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTW92ZUtub2JEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIGNhbnZhc1NpemUgPSB0aGlzLl91aS5jYW52YXMuc2l6ZTtcblxuICAgICAgdmFyIG1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBkaWZmID0gbW91c2VQb3NpdGlvbi5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxNb3VzZVBvc2l0aW9uKTtcblxuICAgICAgdmFyIG1pblBvc2l0aW9uID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKTtcbiAgICAgIHZhciBjb250YWluZXJTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSh0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGgsIHRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQpO1xuICAgICAgdmFyIG1heFBvc2l0aW9uID0gY2FudmFzU2l6ZS5jbG9uZSgpLnN1YnRyYWN0KGNvbnRhaW5lclNpemUpO1xuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5faW5pdGlhbFBvc2l0aW9uLmNsb25lKCkuYWRkKGRpZmYpLmNsYW1wKG1pblBvc2l0aW9uLCBtYXhQb3NpdGlvbik7XG5cbiAgICAgIHRoaXMuX3NldHRpbmdzLnBvc2l0aW9uID0gcG9zaXRpb247XG5cbiAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJycgKyBwb3NpdGlvbi54ICsgJ3B4JztcbiAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS50b3AgPSAnJyArIHBvc2l0aW9uLnkgKyAncHgnO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbk1vdmVLbm9iVXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgbW92ZSBrbm9iXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTW92ZUtub2JVcCgpIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uTW92ZUtub2JEcmFnKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uTW92ZUtub2JEcmFnKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uTW92ZUtub2JVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uTW92ZUtub2JVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hhbmRsZVJlc2l6ZUtub2InLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgcmVzaXplIGtub2IgZHJhZ2dpbmdcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlUmVzaXplS25vYigpIHtcbiAgICAgIHRoaXMuX3Jlc2l6ZUtub2IuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25SZXNpemVLbm9iRG93bik7XG4gICAgICB0aGlzLl9yZXNpemVLbm9iLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblJlc2l6ZUtub2JEb3duKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25SZXNpemVLbm9iRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0aGUgcmVzaXplIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uUmVzaXplS25vYkRvd24oZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuICAgICAgdGhpcy5faW5pdGlhbE1heFdpZHRoID0gdGhpcy5fc2V0dGluZ3MubWF4V2lkdGg7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uUmVzaXplS25vYkRyYWcpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25SZXNpemVLbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vblJlc2l6ZUtub2JVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uUmVzaXplS25vYlVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25SZXNpemVLbm9iRHJhZycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGRyYWdzIHRoZSByZXNpemUga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25SZXNpemVLbm9iRHJhZyhlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBjYW52YXNTaXplID0gdGhpcy5fdWkuY2FudmFzLnNpemU7XG4gICAgICB2YXIgbW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuICAgICAgdmFyIGRpZmYgPSBtb3VzZVBvc2l0aW9uLnN1YnRyYWN0KHRoaXMuX2luaXRpYWxNb3VzZVBvc2l0aW9uKTtcblxuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fc2V0dGluZ3MucG9zaXRpb24uY2xvbmUoKTtcbiAgICAgIHZhciBtYXhXaWR0aEFsbG93ZWQgPSBjYW52YXNTaXplLnggLSBwb3NpdGlvbi54O1xuXG4gICAgICB2YXIgbWF4V2lkdGggPSB0aGlzLl9pbml0aWFsTWF4V2lkdGggKyBkaWZmLng7XG4gICAgICBtYXhXaWR0aCA9IE1hdGgubWF4KDEwMCwgTWF0aC5taW4obWF4V2lkdGhBbGxvd2VkLCBtYXhXaWR0aCkpO1xuICAgICAgdGhpcy5fc2V0dGluZ3MubWF4V2lkdGggPSBtYXhXaWR0aDtcbiAgICAgIHRoaXMuX3RleHRhcmVhLnN0eWxlLndpZHRoID0gJycgKyBtYXhXaWR0aCArICdweCc7XG5cbiAgICAgIHRoaXMuX3Jlc2l6ZVRleHRhcmVhKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uUmVzaXplS25vYlVwJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgcmVsZWFzZXMgdGhlIHJlc2l6ZSBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblJlc2l6ZUtub2JVcCgpIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uUmVzaXplS25vYkRyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25SZXNpemVLbm9iRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vblJlc2l6ZUtub2JVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uUmVzaXplS25vYlVwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Gb3JlZ3JvdW5kQ29sb3JVcGRhdGUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBzZWxlY3RzIGFub3RoZXIgY29sb3IgdXNpbmdcbiAgICAgKiB0aGUgY29sb3IgcGlja2VyLlxuICAgICAqIEBwYXJhbSB7Q29sb3J9IHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRm9yZWdyb3VuZENvbG9yVXBkYXRlKHZhbHVlKSB7XG4gICAgICB0aGlzLl9zZXR0aW5ncy5jb2xvciA9IHZhbHVlO1xuICAgICAgdGhpcy5fYXBwbHlTZXR0aW5ncygpO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJhY2tncm91bmRDb2xvclVwZGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHNlbGVjdHMgYW5vdGhlciBjb2xvciB1c2luZ1xuICAgICAqIHRoZSBjb2xvciBwaWNrZXIuXG4gICAgICogQHBhcmFtIHtDb2xvcn0gdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CYWNrZ3JvdW5kQ29sb3JVcGRhdGUodmFsdWUpIHtcbiAgICAgIHRoaXMuX3NldHRpbmdzLmJhY2tncm91bmRDb2xvciA9IHZhbHVlO1xuICAgICAgdGhpcy5fYXBwbHlTZXR0aW5ncygpO1xuICAgICAgdGhpcy5faGlnaGxpZ2h0RG9uZUJ1dHRvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19hcHBseVNldHRpbmdzJyxcblxuICAgIC8qKlxuICAgICAqIFN0eWxlcyB0aGUgdGV4dGFyZWEgdG8gcmVwcmVzZW50IHRoZSBjdXJyZW50IHNldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2FwcGx5U2V0dGluZ3MoKSB7XG4gICAgICB2YXIgdGV4dGFyZWEgPSB0aGlzLl90ZXh0YXJlYTtcbiAgICAgIHZhciBzZXR0aW5ncyA9IHRoaXMuX3NldHRpbmdzO1xuXG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIGFjdHVhbEZvbnRTaXplID0gc2V0dGluZ3MuZm9udFNpemUgKiBjYW52YXNTaXplLnk7XG5cbiAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJycgKyBzZXR0aW5ncy5wb3NpdGlvbi54ICsgJ3B4JztcbiAgICAgIHRoaXMuX2NvbnRhaW5lci5zdHlsZS50b3AgPSAnJyArIHNldHRpbmdzLnBvc2l0aW9uLnkgKyAncHgnO1xuXG4gICAgICB0ZXh0YXJlYS52YWx1ZSA9IHNldHRpbmdzLnRleHQ7XG4gICAgICB0ZXh0YXJlYS5zdHlsZS5mb250RmFtaWx5ID0gc2V0dGluZ3MuZm9udEZhbWlseTtcbiAgICAgIHRleHRhcmVhLnN0eWxlLmZvbnRTaXplID0gJycgKyBhY3R1YWxGb250U2l6ZSArICdweCc7XG4gICAgICB0ZXh0YXJlYS5zdHlsZS5mb250V2VpZ2h0ID0gc2V0dGluZ3MuZm9udFdlaWdodDtcbiAgICAgIHRleHRhcmVhLnN0eWxlLmxpbmVIZWlnaHQgPSBzZXR0aW5ncy5saW5lSGVpZ2h0O1xuICAgICAgdGV4dGFyZWEuc3R5bGUuY29sb3IgPSBzZXR0aW5ncy5jb2xvci50b1JHQkEoKTtcbiAgICAgIHRleHRhcmVhLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHNldHRpbmdzLmJhY2tncm91bmRDb2xvci50b1JHQkEoKTtcbiAgICAgIHRleHRhcmVhLnN0eWxlLndpZHRoID0gJycgKyBzZXR0aW5ncy5tYXhXaWR0aCArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uTGlzdEl0ZW1DbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrZWQgYSBsaXN0IGl0ZW1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25MaXN0SXRlbUNsaWNrKGl0ZW0pIHtcbiAgICAgIHZhciBtYW51YWxseSA9IGFyZ3VtZW50c1sxXSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IGFyZ3VtZW50c1sxXTtcblxuICAgICAgdGhpcy5fZGVhY3RpdmF0ZUFsbEl0ZW1zKCk7XG5cbiAgICAgIHZhciBfaXRlbSRkYXRhc2V0ID0gaXRlbS5kYXRhc2V0O1xuICAgICAgdmFyIG5hbWUgPSBfaXRlbSRkYXRhc2V0Lm5hbWU7XG4gICAgICB2YXIgd2VpZ2h0ID0gX2l0ZW0kZGF0YXNldC53ZWlnaHQ7XG5cbiAgICAgIHRoaXMuX3NldHRpbmdzLmZvbnRGYW1pbHkgPSBuYW1lO1xuICAgICAgdGhpcy5fc2V0dGluZ3MuZm9udFdlaWdodCA9IHdlaWdodDtcblxuICAgICAgdGhpcy5fYXBwbHlTZXR0aW5ncygpO1xuXG4gICAgICBpdGVtLmNsYXNzTGlzdC5hZGQoJ2ltZ2x5a2l0LWNvbnRyb2xzLWl0ZW0tYWN0aXZlJyk7XG5cbiAgICAgIGlmIChtYW51YWxseSkge1xuICAgICAgICB0aGlzLl9oaWdobGlnaHREb25lQnV0dG9uKCk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2RlYWN0aXZhdGVBbGxJdGVtcycsXG5cbiAgICAvKipcbiAgICAgKiBEZWFjdGl2YXRlcyBhbGwgbGlzdCBpdGVtc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9kZWFjdGl2YXRlQWxsSXRlbXMoKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xpc3RJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGlzdEl0ZW0gPSB0aGlzLl9saXN0SXRlbXNbaV07XG4gICAgICAgIGxpc3RJdGVtLmNsYXNzTGlzdC5yZW1vdmUoJ2ltZ2x5a2l0LWNvbnRyb2xzLWl0ZW0tYWN0aXZlJyk7XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2FkZEZvbnRzJyxcblxuICAgIC8qKlxuICAgICAqIEFkZHMgdGhlIGRlZmF1bHQgZm9udHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfYWRkRm9udHMoKSB7XG4gICAgICB0aGlzLmFkZEZvbnQoJ0hlbHZldGljYScsICdub3JtYWwnKTtcbiAgICAgIHRoaXMuYWRkRm9udCgnTHVjaWRhIEdyYW5kZScsICdub3JtYWwnKTtcbiAgICAgIHRoaXMuYWRkRm9udCgnVGltZXMgTmV3IFJvbWFuJywgJ25vcm1hbCcpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2FkZEZvbnQnLFxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGZvbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgd2VpZ2h0XG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gd2VpZ2h0XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFkZEZvbnQobmFtZSwgd2VpZ2h0KSB7XG4gICAgICB0aGlzLl9mb250cy5wdXNoKHsgbmFtZTogbmFtZSwgd2VpZ2h0OiB3ZWlnaHQgfSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uRG9uZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBkb25lIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRvbmUoKSB7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IHRoaXMuX3VpLmNhbnZhcy5zaXplO1xuICAgICAgdmFyIHBhZGRpbmcgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKDIsIDIpO1xuICAgICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fc2V0dGluZ3MucG9zaXRpb24uY2xvbmUoKS5hZGQocGFkZGluZykuZGl2aWRlKGNhbnZhc1NpemUpO1xuXG4gICAgICB0aGlzLl91aS5jYW52YXMuc2V0Wm9vbUxldmVsKHRoaXMuX2luaXRpYWxab29tTGV2ZWwsIGZhbHNlKTtcblxuICAgICAgdGhpcy5fb3BlcmF0aW9uID0gdGhpcy5fdWkuZ2V0T3JDcmVhdGVPcGVyYXRpb24oJ3RleHQnKTtcbiAgICAgIHRoaXMuX29wZXJhdGlvbi5zZXQoe1xuICAgICAgICBmb250U2l6ZTogdGhpcy5fc2V0dGluZ3MuZm9udFNpemUsXG4gICAgICAgIGZvbnRGYW1pbHk6IHRoaXMuX3NldHRpbmdzLmZvbnRGYW1pbHksXG4gICAgICAgIGZvbnRXZWlnaHQ6IHRoaXMuX3NldHRpbmdzLmZvbnRXZWlnaHQsXG4gICAgICAgIGNvbG9yOiB0aGlzLl9zZXR0aW5ncy5jb2xvcixcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLl9zZXR0aW5ncy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAgIHBvc2l0aW9uOiBwb3NpdGlvbixcbiAgICAgICAgdGV4dDogdGhpcy5fc2V0dGluZ3MudGV4dCxcbiAgICAgICAgbWF4V2lkdGg6IHRoaXMuX3NldHRpbmdzLm1heFdpZHRoIC8gY2FudmFzU2l6ZS54XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5yZW5kZXIoKTtcblxuICAgICAgdGhpcy5fdWkuYWRkSGlzdG9yeSh0aGlzLCB7XG4gICAgICAgIGZvbnRGYW1pbHk6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5mb250RmFtaWx5LFxuICAgICAgICBmb250V2VpZ2h0OiB0aGlzLl9pbml0aWFsU2V0dGluZ3MuZm9udFdlaWdodCxcbiAgICAgICAgY29sb3I6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5jb2xvci5jbG9uZSgpLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5iYWNrZ3JvdW5kQ29sb3IuY2xvbmUoKSxcbiAgICAgICAgcG9zaXRpb246IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5wb3NpdGlvbi5jbG9uZSgpLFxuICAgICAgICB0ZXh0OiB0aGlzLl9pbml0aWFsU2V0dGluZ3MudGV4dCxcbiAgICAgICAgbWF4V2lkdGg6IHRoaXMuX2luaXRpYWxTZXR0aW5ncy5tYXhXaWR0aFxuICAgICAgfSwgdGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQG92ZXJyaWRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2soKSB7XG4gICAgICBpZiAodGhpcy5fb3BlcmF0aW9uRXhpc3RlZEJlZm9yZSkge1xuICAgICAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLl91aS5nZXRPckNyZWF0ZU9wZXJhdGlvbigndGV4dCcpO1xuICAgICAgICB0aGlzLl9vcGVyYXRpb24uc2V0KHRoaXMuX2luaXRpYWxTZXR0aW5ncyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl91aS5yZW1vdmVPcGVyYXRpb24oJ3RleHQnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3VpLmNhbnZhcy5zZXRab29tTGV2ZWwodGhpcy5faW5pdGlhbFpvb21MZXZlbCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnY29udGV4dCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGF0YSB0aGF0IGlzIGF2YWlsYWJsZSB0byB0aGUgdGVtcGxhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBvdmVycmlkZVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGNvbnRleHQgPSBfZ2V0KE9iamVjdC5nZXRQcm90b3R5cGVPZihUZXh0Q29udHJvbC5wcm90b3R5cGUpLCAnY29udGV4dCcsIHRoaXMpO1xuICAgICAgY29udGV4dC5mb250cyA9IHRoaXMuX2ZvbnRzO1xuICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFRleHRDb250cm9sO1xufSkoX2NvbnRyb2wyWydkZWZhdWx0J10pO1xuXG4vKipcbiAqIEEgdW5pcXVlIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyBjb250cm9sLlxuICogQHR5cGUge1N0cmluZ31cbiAqL1xuVGV4dENvbnRyb2wucHJvdG90eXBlLmlkZW50aWZpZXIgPSAndGV4dCc7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFRleHRDb250cm9sO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2NvbnRyb2xzL3RleHQtY29udHJvbC5qc1xuICoqIG1vZHVsZSBpZCA9IDkyXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKiBnbG9iYWwgX19ET1RKU19URU1QTEFURSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9iYXNlSGVscGVycyA9IHJlcXVpcmUoJy4uLy4uL2Jhc2UvaGVscGVycycpO1xuXG52YXIgX2Jhc2VIZWxwZXJzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2Jhc2VIZWxwZXJzKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvZXZlbnQtZW1pdHRlcicpO1xuXG52YXIgX2xpYkV2ZW50RW1pdHRlcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFdmVudEVtaXR0ZXIpO1xuXG52YXIgX2xpYlV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL3V0aWxzJyk7XG5cbnZhciBfbGliVXRpbHMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliVXRpbHMpO1xuXG52YXIgX2xpYlNjcm9sbGJhciA9IHJlcXVpcmUoJy4uL2xpYi9zY3JvbGxiYXInKTtcblxudmFyIF9saWJTY3JvbGxiYXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliU2Nyb2xsYmFyKTtcblxuLyoqXG4gKiBUbyBjcmVhdGUgYW4ge0BsaW5rIEltZ2x5S2l0Lk5pZ2h0VUkuQ29udHJvbH0gY2xhc3Mgb2YgeW91ciBvd24sIGNhbGxcbiAqIHRoaXMgbWV0aG9kIGFuZCBwcm92aWRlIGluc3RhbmNlIHByb3BlcnRpZXMgYW5kIGZ1bmN0aW9ucy5cbiAqIEBmdW5jdGlvblxuICovXG5cbnZhciBfbGliRXh0ZW5kID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL2V4dGVuZCcpO1xuXG52YXIgX2xpYkV4dGVuZDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJFeHRlbmQpO1xuXG52YXIgQ29udHJvbCA9IChmdW5jdGlvbiAoX0V2ZW50RW1pdHRlcikge1xuICBmdW5jdGlvbiBDb250cm9sKGtpdCwgdWksIG9wZXJhdGlvbikge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBDb250cm9sKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKENvbnRyb2wucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgIHRoaXMuX2tpdCA9IGtpdDtcbiAgICB0aGlzLl91aSA9IHVpO1xuICAgIHRoaXMuX29wZXJhdGlvbiA9IG9wZXJhdGlvbjtcbiAgICB0aGlzLl9oZWxwZXJzID0gbmV3IF9iYXNlSGVscGVyczJbJ2RlZmF1bHQnXSh0aGlzLl9raXQsIHRoaXMuX3VpLCB0aGlzLl91aS5vcHRpb25zKTtcbiAgICB0aGlzLl9wYXJ0aWFsVGVtcGxhdGVzID0ge1xuICAgICAgZG9uZUJ1dHRvbjogZnVuY3Rpb24oaXRcbi8qKi8pIHtcbnZhciBvdXQ9JzxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb250cm9scy1idXR0b24gaW1nbHlraXQtY29udHJvbHMtZG9uZVwiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9idXR0b25zL2RvbmUucG5nJykgKSsnXCIgLz4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWRvbmUtaGlnaGxpZ2h0ZWRcIj4gPGltZyBzcmM9XCInKyhpdC5oZWxwZXJzLmFzc2V0UGF0aCgndWkvbmlnaHQvYnV0dG9ucy9kb25lLWhpZ2hsaWdodGVkLnBuZycpICkrJ1wiIC8+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn1cbiAgICB9O1xuXG4gICAgdGhpcy5fdGVtcGxhdGUgPSBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLScrKGl0LmlkZW50aWZpZXIpKydcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbnRyb2xzLWJ1dHRvbiBpbWdseWtpdC1jb250cm9scy1iYWNrXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L2J1dHRvbnMvYmFjay5wbmcnKSApKydcIiAvPiA8L2Rpdj4gJysoaXQucGFydGlhbHMuY29udHJvbCkrJzwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgdGhpcy5fYWN0aXZlID0gZmFsc2U7XG5cbiAgICB0aGlzLmluaXQoKTtcbiAgfVxuXG4gIF9pbmhlcml0cyhDb250cm9sLCBfRXZlbnRFbWl0dGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQ29udHJvbCwgW3tcbiAgICBrZXk6ICdzZXRDb250YWluZXJzJyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGNvbnRhaW5lcnMgdGhhdCB0aGUgY29udHJvbCB3aWxsIGJlIHJlbmRlcmVkIHRvXG4gICAgICogQHBhcmFtIHtET01FbGVtZW50fSBjb250cm9sc0NvbnRhaW5lclxuICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gY2FudmFzQ29udHJvbHNDb250YWluZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0Q29udGFpbmVycyhjb250cm9sc0NvbnRhaW5lciwgY2FudmFzQ29udHJvbHNDb250YWluZXIpIHtcbiAgICAgIHRoaXMuX2NvbnRyb2xzQ29udGFpbmVyID0gY29udHJvbHNDb250YWluZXI7XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc0NvbnRhaW5lciA9IGNhbnZhc0NvbnRyb2xzQ29udGFpbmVyO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2luaXQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGVudHJ5IHBvaW50IGZvciB0aGlzIGNvbnRyb2xcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gaW5pdCgpIHt9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQWxsQ29udHJvbHMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY29udHJvbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQWxsQ29udHJvbHMoKSB7XG4gICAgICB0aGlzLl9yZW5kZXJDb250cm9scygpO1xuICAgICAgdGhpcy5fcmVuZGVyQ2FudmFzQ29udHJvbHMoKTtcbiAgICAgIHRoaXMuX2luaXRTY3JvbGxiYXIoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ29udHJvbHMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY29udHJvbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ29udHJvbHMoKSB7XG4gICAgICBpZiAodHlwZW9mIHRoaXMuX2NvbnRyb2xzVGVtcGxhdGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29udHJvbCNfcmVuZGVyT3ZlcnZpZXdDb250cm9sczogQ29udHJvbCBuZWVkcyB0byBkZWZpbmUgdGhpcy5fY29udHJvbHNUZW1wbGF0ZS4nKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVuZGVyIHRoZSB0ZW1wbGF0ZVxuICAgICAgdmFyIGh0bWwgPSB0aGlzLl90ZW1wbGF0ZSh0aGlzLl9jb250ZXh0KTtcblxuICAgICAgaWYgKHR5cGVvZiB0aGlzLl9jb250cm9scyAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5fY29udHJvbHMucGFyZW50Tm9kZSAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9jb250cm9scy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRyb2xzKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIGEgd3JhcHBlclxuICAgICAgdGhpcy5fY29udHJvbHMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzLmlubmVySFRNTCA9IGh0bWw7XG5cbiAgICAgIC8vIEFwcGVuZCB0byBET01cbiAgICAgIHRoaXMuX2NvbnRyb2xzQ29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRyb2xzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyQ2FudmFzQ29udHJvbHMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY2FudmFzIGNvbnRyb2xzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckNhbnZhc0NvbnRyb2xzKCkge1xuICAgICAgaWYgKHR5cGVvZiB0aGlzLl9jYW52YXNDb250cm9sc1RlbXBsYXRlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm47IC8vIENhbnZhcyBjb250cm9scyBhcmUgb3B0aW9uYWxcbiAgICAgIH1cblxuICAgICAgLy8gUmVuZGVyIHRoZSB0ZW1wbGF0ZVxuICAgICAgdmFyIGh0bWwgPSB0aGlzLl9jYW52YXNDb250cm9sc1RlbXBsYXRlKHRoaXMuX2NvbnRleHQpO1xuXG4gICAgICAvLyBDcmVhdGUgYSB3cmFwcGVyXG4gICAgICB0aGlzLl9jYW52YXNDb250cm9scyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgdGhpcy5fY2FudmFzQ29udHJvbHMuaW5uZXJIVE1MID0gaHRtbDtcblxuICAgICAgLy8gQXBwZW5kIHRvIERPTVxuICAgICAgdGhpcy5fY2FudmFzQ29udHJvbHNDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5fY2FudmFzQ29udHJvbHMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19pbml0U2Nyb2xsYmFyJyxcblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBjdXN0b20gc2Nyb2xsYmFyXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2luaXRTY3JvbGxiYXIoKSB7XG4gICAgICB2YXIgbGlzdCA9IHRoaXMuX2NvbnRyb2xzLnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1jb250cm9scy1saXN0Jyk7XG4gICAgICBpZiAobGlzdCkge1xuICAgICAgICB0aGlzLl9zY3JvbGxiYXIgPSBuZXcgX2xpYlNjcm9sbGJhcjJbJ2RlZmF1bHQnXShsaXN0LnBhcmVudE5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW1vdmVDb250cm9scycsXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBjb250cm9scyBmcm9tIHRoZSBET01cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVtb3ZlQ29udHJvbHMoKSB7XG4gICAgICB0aGlzLl9jb250cm9scy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NvbnRyb2xzKTtcbiAgICAgIGlmICh0aGlzLl9jYW52YXNDb250cm9scykge1xuICAgICAgICB0aGlzLl9jYW52YXNDb250cm9scy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX2NhbnZhc0NvbnRyb2xzKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX3Njcm9sbGJhcikgdGhpcy5fc2Nyb2xsYmFyLnJlbW92ZSgpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVCYWNrQW5kRG9uZUJ1dHRvbnMnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgYmFjayBhbmQgZG9uZSBidXR0b25zXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX2hhbmRsZUJhY2tBbmREb25lQnV0dG9ucygpIHtcbiAgICAgIC8vIEJhY2sgYnV0dG9uXG4gICAgICB0aGlzLl9iYWNrQnV0dG9uID0gdGhpcy5fY29udHJvbHMucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNvbnRyb2xzLWJhY2snKTtcbiAgICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uKSB7XG4gICAgICAgIHRoaXMuX2JhY2tCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkJhY2tCdXR0b25DbGljay5iaW5kKHRoaXMpKTtcbiAgICAgIH1cblxuICAgICAgLy8gRG9uZSBidXR0b25cbiAgICAgIHRoaXMuX2RvbmVCdXR0b24gPSB0aGlzLl9jb250cm9scy5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY29udHJvbHMtZG9uZScpO1xuICAgICAgaWYgKHRoaXMuX2RvbmVCdXR0b24pIHtcbiAgICAgICAgdGhpcy5fZG9uZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uRG9uZUJ1dHRvbkNsaWNrLmJpbmQodGhpcykpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkJhY2tCdXR0b25DbGljaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQmFja0J1dHRvbkNsaWNrKCkge1xuICAgICAgdGhpcy5fb25CYWNrKCk7XG4gICAgICB0aGlzLmVtaXQoJ2JhY2snKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Eb25lQnV0dG9uQ2xpY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgZG9uZSBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkRvbmVCdXR0b25DbGljaygpIHtcbiAgICAgIHRoaXMuX29uRG9uZSgpO1xuICAgICAgdGhpcy5lbWl0KCdiYWNrJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2hpZ2hsaWdodERvbmVCdXR0b24nLFxuXG4gICAgLyoqXG4gICAgICogSGlnaGxpZ2h0cyB0aGUgZG9uZSBidXR0b25cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGlnaGxpZ2h0RG9uZUJ1dHRvbigpIHtcbiAgICAgIHRoaXMuX2RvbmVCdXR0b24uY2xhc3NMaXN0LmFkZCgnaGlnaGxpZ2h0ZWQnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdlbnRlcicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWRcbiAgICAgKiBAaW50ZXJuYWwgVXNlZCBieSB0aGUgU0RLLCBkb24ndCBvdmVycmlkZS5cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZW50ZXIoKSB7XG4gICAgICB0aGlzLl9hY3RpdmUgPSB0cnVlO1xuXG4gICAgICB0aGlzLl91aS5oaWRlWm9vbSgpO1xuXG4gICAgICB0aGlzLl9yZW5kZXJBbGxDb250cm9scygpO1xuICAgICAgdGhpcy5faGFuZGxlQmFja0FuZERvbmVCdXR0b25zKCk7XG4gICAgICB0aGlzLl9lbmFibGVDYW52YXNDb250cm9scygpO1xuICAgICAgdGhpcy5fb25FbnRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2xlYXZlJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhpcyBjb250cm9sIGlzIGRlYWN0aXZhdGVkXG4gICAgICogQGludGVybmFsIFVzZWQgYnkgdGhlIFNESywgZG9uJ3Qgb3ZlcnJpZGUuXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGxlYXZlKCkge1xuICAgICAgdGhpcy5fYWN0aXZlID0gZmFsc2U7XG5cbiAgICAgIHRoaXMuX3VpLnNob3dab29tKCk7XG5cbiAgICAgIHRoaXMuX3JlbW92ZUNvbnRyb2xzKCk7XG4gICAgICB0aGlzLl9kaXNhYmxlQ2FudmFzQ29udHJvbHMoKTtcbiAgICAgIHRoaXMuX29uTGVhdmUoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZW5hYmxlQ2FudmFzQ29udHJvbHMnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfZW5hYmxlQ2FudmFzQ29udHJvbHMoKSB7XG4gICAgICB0aGlzLl9jYW52YXNDb250cm9sc0NvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKCdpbWdseWtpdC1jYW52YXMtY29udHJvbHMtZGlzYWJsZWQnKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZGlzYWJsZUNhbnZhc0NvbnRyb2xzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2Rpc2FibGVDYW52YXNDb250cm9scygpIHtcbiAgICAgIHRoaXMuX2NhbnZhc0NvbnRyb2xzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ2ltZ2x5a2l0LWNhbnZhcy1jb250cm9scy1kaXNhYmxlZCcpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkVudGVyJyxcblxuICAgIC8vIFByb3RlY3RlZCBtZXRob2RzXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBhY3RpdmF0ZWQuXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25FbnRlcigpIHt9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25MZWF2ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoaXMgY29udHJvbCBpcyBkZWFjdGl2YXRlZFxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTGVhdmUoKSB7fVxuICB9LCB7XG4gICAga2V5OiAnX29uQmFjaycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBiYWNrIGJ1dHRvbiBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25CYWNrKCkge31cbiAgfSwge1xuICAgIGtleTogJ19vbkRvbmUnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgZG9uZSBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uRG9uZSgpIHt9XG4gIH0sIHtcbiAgICBrZXk6ICdvblpvb20nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgem9vbSBsZXZlbCBoYXMgYmVlbiBjaGFuZ2VkIHdoaWxlXG4gICAgICogdGhpcyBjb250cm9sIGlzIGFjdGl2ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBvblpvb20oKSB7fVxuICB9LCB7XG4gICAga2V5OiAnX2NvbnRleHQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIGRhdGEgdGhhdCBpcyBhdmFpbGFibGUgdG8gdGhlIHRlbXBsYXRlXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuXG4gICAgICBjb250ZXh0ID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmV4dGVuZChjb250ZXh0LCB7XG4gICAgICAgIGhlbHBlcnM6IHRoaXMuX2hlbHBlcnMsXG4gICAgICAgIGlkZW50aWZpZXI6IHRoaXMuaWRlbnRpZmllclxuICAgICAgfSk7XG5cbiAgICAgIC8vIFJlbmRlciBwYXJ0aWFscyBiZWZvcmUgcmVuZGVyaW5nIGNvbnRyb2xcbiAgICAgIGNvbnRleHQucGFydGlhbHMgPSB7fTtcbiAgICAgIGZvciAodmFyIF9uYW1lIGluIHRoaXMuX3BhcnRpYWxUZW1wbGF0ZXMpIHtcbiAgICAgICAgdmFyIHRlbXBsYXRlID0gdGhpcy5fcGFydGlhbFRlbXBsYXRlc1tfbmFtZV07XG4gICAgICAgIHZhciBwYXJ0aWFsQ29udGV4dCA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5leHRlbmQoe30sIGNvbnRleHQsIHRlbXBsYXRlLmFkZGl0aW9uYWxDb250ZXh0IHx8IHt9KTtcbiAgICAgICAgY29udGV4dC5wYXJ0aWFsc1tfbmFtZV0gPSB0ZW1wbGF0ZShwYXJ0aWFsQ29udGV4dCk7XG4gICAgICB9XG4gICAgICBjb250ZXh0LnBhcnRpYWxzLmNvbnRyb2wgPSB0aGlzLl9jb250cm9sc1RlbXBsYXRlKGNvbnRleHQpO1xuXG4gICAgICByZXR1cm4gY29udGV4dDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdjb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFRoZSBkYXRhIHRoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSB0ZW1wbGF0ZVxuICAgICAqIEBhYnN0cmFjdFxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBDb250cm9sO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbi8qKlxuICogQSB1bmlxdWUgc3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGlzIGNvbnRyb2wuXG4gKiBAdHlwZSB7U3RyaW5nfVxuICovXG5Db250cm9sLnByb3RvdHlwZS5pZGVudGlmaWVyID0gbnVsbDtcbkNvbnRyb2wuZXh0ZW5kID0gX2xpYkV4dGVuZDJbJ2RlZmF1bHQnXTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ29udHJvbDtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi91aS9uaWdodC9jb250cm9scy9jb250cm9sLmpzXG4gKiogbW9kdWxlIGlkID0gOTNcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIm1vZHVsZS5leHBvcnRzID0ge1xuXHRcIm9wZXJhdGlvbnNcIjoge1xuXHRcdFwiYnJpZ2h0bmVzc1wiOiBcIkJyaWdodG5lc3NcIixcblx0XHRcImNvbnRyYXN0XCI6IFwiQ29udHJhc3RcIixcblx0XHRcImZpbHRlcnNcIjogXCJGaWx0ZXJzXCIsXG5cdFx0XCJmbGlwXCI6IFwiRmxpcFwiLFxuXHRcdFwiZnJhbWVzXCI6IFwiRnJhbWVzXCIsXG5cdFx0XCJyYWRpYWwtYmx1clwiOiBcIlJhZGlhbCBCbHVyXCIsXG5cdFx0XCJyb3RhdGlvblwiOiBcIlJvdGF0aW9uXCIsXG5cdFx0XCJzYXR1cmF0aW9uXCI6IFwiU2F0dXJhdGlvblwiLFxuXHRcdFwic3RpY2tlcnNcIjogXCJTdGlja2Vyc1wiLFxuXHRcdFwidGV4dFwiOiBcIlRleHRcIixcblx0XHRcInRpbHQtc2hpZnRcIjogXCJUaWx0LVNoaWZ0XCIsXG5cdFx0XCJjcm9wXCI6IFwiQ3JvcFwiXG5cdH0sXG5cdFwidG9wLWNvbnRyb2xzXCI6IHtcblx0XHRcIm5ld1wiOiBcIk5ld1wiLFxuXHRcdFwidW5kb1wiOiBcIlVuZG9cIixcblx0XHRcImV4cG9ydFwiOiBcIkV4cG9ydFwiLFxuXHRcdFwiem9vbVwiOiBcIlpvb21cIlxuXHR9LFxuXHRcInNwbGFzaFwiOiB7XG5cdFx0XCJ1cGxvYWRcIjoge1xuXHRcdFx0XCJoZWFkbGluZVwiOiBcIlVwbG9hZCBhIHBpY3R1cmVcIixcblx0XHRcdFwiZGVzY3JpcHRpb25cIjogXCJDbGljayBoZXJlIHRvIHVwbG9hZCBhIHBpY3R1cmUgZnJvbSB5b3VyIGxpYnJhcnkgb3IganVzdCBkcmFnIGFuZCBkcm9wXCJcblx0XHR9LFxuXHRcdFwib3JcIjogXCJvclwiLFxuXHRcdFwid2ViY2FtXCI6IHtcblx0XHRcdFwiaGVhZGxpbmVcIjogXCJUYWtlIGEgcGljdHVyZVwiLFxuXHRcdFx0XCJkZXNjcmlwdGlvblwiOiBcIkNsaWNrIGhlcmUgdG8gdGFrZSBhIHBpY3R1cmUgd2l0aCB5b3VyIHdlYmNhbSBvciBwaG9uZVwiXG5cdFx0fVxuXHR9LFxuXHRcImdlbmVyaWNcIjoge1xuXHRcdFwibG9hZGluZ1wiOiBcIkxvYWRpbmdcIixcblx0XHRcImV4cG9ydGluZ1wiOiBcIkV4cG9ydGluZ1wiLFxuXHRcdFwiY29sb3JcIjogXCJDb2xvclwiXG5cdH0sXG5cdFwiY29udHJvbHNcIjoge1xuXHRcdFwiZnJhbWVzXCI6IHtcblx0XHRcdFwiY29sb3JcIjogXCJDb2xvclwiXG5cdFx0fSxcblx0XHRcInRleHRcIjoge1xuXHRcdFx0XCJmb3JlZ3JvdW5kXCI6IFwiRm9yZWdyb3VuZFwiLFxuXHRcdFx0XCJiYWNrZ3JvdW5kXCI6IFwiQmFja2dyb3VuZFwiXG5cdFx0fVxuXHR9XG59XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL25pZ2h0L2xhbmcvZW4uanNvblxuICoqIG1vZHVsZSBpZCA9IDk0XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCJtb2R1bGUuZXhwb3J0cyA9IHtcblx0XCJvcGVyYXRpb25zXCI6IHtcblx0XHRcImJyaWdodG5lc3NcIjogXCJIZWxsaWdrZWl0XCIsXG5cdFx0XCJjb250cmFzdFwiOiBcIktvbnRyYXN0XCIsXG5cdFx0XCJmaWx0ZXJzXCI6IFwiRmlsdGVyXCIsXG5cdFx0XCJmbGlwXCI6IFwiU3BpZWdlbG5cIixcblx0XHRcImZyYW1lc1wiOiBcIlJhaG1lblwiLFxuXHRcdFwicmFkaWFsLWJsdXJcIjogXCJSYWRpYWwgQmx1clwiLFxuXHRcdFwicm90YXRpb25cIjogXCJEcmVodW5nXCIsXG5cdFx0XCJzYXR1cmF0aW9uXCI6IFwiU8OkdHRpZ3VuZ1wiLFxuXHRcdFwic3RpY2tlcnNcIjogXCJTdGlja2VyXCIsXG5cdFx0XCJ0ZXh0XCI6IFwiVGV4dFwiLFxuXHRcdFwidGlsdC1zaGlmdFwiOiBcIlRpbHQtU2hpZnRcIixcblx0XHRcImNyb3BcIjogXCJadXNjaG5laWRlblwiXG5cdH0sXG5cdFwidG9wLWNvbnRyb2xzXCI6IHtcblx0XHRcIm5ld1wiOiBcIk5ldVwiLFxuXHRcdFwidW5kb1wiOiBcIlLDvGNrZ8OkbmdpZ1wiLFxuXHRcdFwiZXhwb3J0XCI6IFwiRXhwb3J0aWVyZW5cIixcblx0XHRcInpvb21cIjogXCJab29tXCJcblx0fSxcblx0XCJzcGxhc2hcIjoge1xuXHRcdFwidXBsb2FkXCI6IHtcblx0XHRcdFwiaGVhZGxpbmVcIjogXCJCaWxkIGhvY2hsYWRlblwiLFxuXHRcdFx0XCJkZXNjcmlwdGlvblwiOiBcIktsaWNrZSBoaWVyLCB1bSBlaW4gQmlsZCBob2NoenVsYWRlbiBvZGVyIHppZWhlIGVpbmUgQmlsZGRhdGVpIGhpZXIgaGVyXCJcblx0XHR9LFxuXHRcdFwib3JcIjogXCJvZGVyXCIsXG5cdFx0XCJ3ZWJjYW1cIjoge1xuXHRcdFx0XCJoZWFkbGluZVwiOiBcIkZvdG8gbWFjaGVuXCIsXG5cdFx0XHRcImRlc2NyaXB0aW9uXCI6IFwiS2xpY2tlIGhpZXIsIHVtIGVpbiBGb3RvIG1pdCBkZWluZXIgV2ViY2FtIG9kZXIgZGVpbmVtIFNtYXJ0cGhvbmUgenUgbWFjaGVuXCJcblx0XHR9XG5cdH0sXG5cdFwiZ2VuZXJpY1wiOiB7XG5cdFx0XCJsb2FkaW5nXCI6IFwiTGFkZW5cIixcblx0XHRcImV4cG9ydGluZ1wiOiBcIkV4cG9ydGllcmVcIlxuXHR9LFxuXHRcImNvbnRyb2xzXCI6IHtcblx0XHRcImZyYW1lc1wiOiB7XG5cdFx0XHRcImNvbG9yXCI6IFwiRmFyYmVcIlxuXHRcdH0sXG5cdFx0XCJ0ZXh0XCI6IHtcblx0XHRcdFwiZm9yZWdyb3VuZFwiOiBcIlRleHRcIixcblx0XHRcdFwiYmFja2dyb3VuZFwiOiBcIkhpbnRlcmdydW5kXCJcblx0XHR9XG5cdH1cbn1cblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGFuZy9kZS5qc29uXG4gKiogbW9kdWxlIGlkID0gOTVcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qanNoaW50IHVudXNlZDpmYWxzZSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94MiwgX3gzLCBfeDQpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gyLCBwcm9wZXJ0eSA9IF94MywgcmVjZWl2ZXIgPSBfeDQ7IGRlc2MgPSBwYXJlbnQgPSBnZXR0ZXIgPSB1bmRlZmluZWQ7IF9hZ2FpbiA9IGZhbHNlOyB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7IGlmIChkZXNjID09PSB1bmRlZmluZWQpIHsgdmFyIHBhcmVudCA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmplY3QpOyBpZiAocGFyZW50ID09PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gZWxzZSB7IF94MiA9IHBhcmVudDsgX3gzID0gcHJvcGVydHk7IF94NCA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24nKTsgfSB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90ICcgKyB0eXBlb2Ygc3VwZXJDbGFzcyk7IH0gc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBzdWJDbGFzcywgZW51bWVyYWJsZTogZmFsc2UsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUgfSB9KTsgaWYgKHN1cGVyQ2xhc3MpIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnLi4vbGliL2V2ZW50LWVtaXR0ZXInKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliRXZlbnRFbWl0dGVyKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5SZW5kZXJlclxuICogQHBhcmFtIHtWZWN0b3IyfSBkaW1lbnNpb25zXG4gKiBAcHJpdmF0ZVxuICovXG5cbnZhciBSZW5kZXJlciA9IChmdW5jdGlvbiAoX0V2ZW50RW1pdHRlcikge1xuICBmdW5jdGlvbiBSZW5kZXJlcihkaW1lbnNpb25zLCBjYW52YXMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUmVuZGVyZXIpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoUmVuZGVyZXIucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtDYW52YXN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9jYW52YXMgPSBjYW52YXMgfHwgdGhpcy5jcmVhdGVDYW52YXMoKTtcblxuICAgIGlmICghY2FudmFzKSB7XG4gICAgICB0aGlzLnNldFNpemUoZGltZW5zaW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHR5cGUge1JlbmRlcmluZ0NvbnRleHR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9jb250ZXh0ID0gdGhpcy5fZ2V0Q29udGV4dCgpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHRleHR1cmUgLyBpbWFnZSBkYXRhIGNhY2hlXG4gICAgICogQHR5cGUge09iamVjdC48U3RyaW5nLCAqPn1cbiAgICAgKi9cbiAgICB0aGlzLl9jYWNoZSA9IHt9O1xuICB9XG5cbiAgX2luaGVyaXRzKFJlbmRlcmVyLCBfRXZlbnRFbWl0dGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoUmVuZGVyZXIsIFt7XG4gICAga2V5OiAnY2FjaGUnLFxuXG4gICAgLyoqXG4gICAgICogQ2FjaGVzIHRoZSBjdXJyZW50IGNhbnZhcyBjb250ZW50IGZvciB0aGUgZ2l2ZW4gaWRlbnRpZmllclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpZGVudGlmaWVyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGNhY2hlKGlkZW50aWZpZXIpIHt9XG4gIH0sIHtcbiAgICBrZXk6ICdkcmF3Q2FjaGVkJyxcblxuICAgIC8qKlxuICAgICAqIERyYXdzIHRoZSBzdG9yZWQgdGV4dHVyZSAvIGltYWdlIGRhdGEgZm9yIHRoZSBnaXZlbiBpZGVudGlmaWVyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGlkZW50aWZpZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZHJhd0NhY2hlZChpZGVudGlmaWVyKSB7fVxuICB9LCB7XG4gICAga2V5OiAnY3JlYXRlQ2FudmFzJyxcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgY2FudmFzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFt3aWR0aF1cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW2hlaWdodF1cbiAgICAgKiBAcmV0dXJuIHtDYW52YXN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gY3JlYXRlQ2FudmFzKHdpZHRoLCBoZWlnaHQpIHtcbiAgICAgIHZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJztcbiAgICAgIHZhciBjYW52YXM7XG4gICAgICBpZiAoaXNCcm93c2VyKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIENhbnZhcyA9IHJlcXVpcmUoJ2NhbnZhcycpO1xuICAgICAgICBjYW52YXMgPSBuZXcgQ2FudmFzKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFwcGx5IHdpZHRoXG4gICAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgIH1cblxuICAgICAgLy8gQXBwbHkgaGVpZ2h0XG4gICAgICBpZiAodHlwZW9mIGhlaWdodCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNhbnZhcztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRTaXplJyxcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgc2l6ZSBvZiB0aGUgY2FudmFzXG4gICAgICogQHJldHVybiB7VmVjdG9yMn1cbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0U2l6ZSgpIHtcbiAgICAgIHJldHVybiBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKHRoaXMuX2NhbnZhcy53aWR0aCwgdGhpcy5fY2FudmFzLmhlaWdodCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0U2l6ZScsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjYW52YXMgZGltZW5zaW9uc1xuICAgICAqIEBwYXJhbSB7VmVjdG9yMn0gZGltZW5zaW9uc1xuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRTaXplKGRpbWVuc2lvbnMpIHtcbiAgICAgIHRoaXMuX2NhbnZhcy53aWR0aCA9IGRpbWVuc2lvbnMueDtcbiAgICAgIHRoaXMuX2NhbnZhcy5oZWlnaHQgPSBkaW1lbnNpb25zLnk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2dldENvbnRleHQnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcmVuZGVyaW5nIGNvbnRleHQgZnJvbSB0aGUgQ2FudmFcbiAgICAgKiBAcmV0dXJuIHtSZW5kZXJpbmdDb250ZXh0fVxuICAgICAqIEBhYnN0cmFjdFxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfZ2V0Q29udGV4dCgpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlbmRlcmVyI19nZXRDb250ZXh0IGlzIGFic3RyYWN0IGFuZCBub3QgaW1wbGVtZW50ZWQgaW4gaW5oZXJpdGVkIGNsYXNzLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3Jlc2l6ZVRvJyxcblxuICAgIC8qKlxuICAgICAqIFJlc2l6ZXMgdGhlIGN1cnJlbnQgY2FudmFzIHBpY3R1cmUgdG8gdGhlIGdpdmVuIGRpbWVuc2lvbnNcbiAgICAgKiBAcGFyYW0gIHtWZWN0b3IyfSBkaW1lbnNpb25zXG4gICAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICAgKiBAYWJzdHJhY3RcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzaXplVG8oZGltZW5zaW9ucykge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVuZGVyZXIjcmVzaXplVG8gaXMgYWJzdHJhY3QgYW5kIG5vdCBpbXBsZW1lbnRlZCBpbiBpbmhlcml0ZWQgY2xhc3MuJyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZHJhd0ltYWdlJyxcblxuICAgIC8qKlxuICAgICAqIERyYXdzIHRoZSBnaXZlbiBpbWFnZSBvbiB0aGUgY2FudmFzXG4gICAgICogQHBhcmFtICB7SW1hZ2V9IGltYWdlXG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGRyYXdJbWFnZShpbWFnZSkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVuZGVyZXIjZHJhd0ltYWdlIGlzIGFic3RyYWN0IGFuZCBub3QgaW1wbGVtZW50ZWQgaW4gaW5oZXJpdGVkIGNsYXNzLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlckZpbmFsJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIGFmdGVyIHRoZSBzdGFjayBoYXMgYmVlbiByZW5kZXJlZFxuICAgICAqIEBwYXJhbSAge0ltYWdlfSBpbWFnZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXJGaW5hbCgpIHt9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY2FudmFzXG4gICAgICogQHJldHVybiB7Q2FudmFzfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRDYW52YXMoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY2FudmFzO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2dldENvbnRleHQnLFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29udGV4dFxuICAgICAqIEByZXR1cm4ge1JlbmRlcmluZ0NvbnRleHR9XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGdldENvbnRleHQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY29udGV4dDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzZXRDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCBjYW52YXMgdG8gdGhlIGdpdmVuIG9uZVxuICAgICAqIEBwYXJhbSB7Q2FudmFzfSBjYW52YXNcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0Q2FudmFzKGNhbnZhcykge1xuICAgICAgdGhpcy5fY2FudmFzID0gY2FudmFzO1xuICAgICAgdGhpcy5fY29udGV4dCA9IHRoaXMuX2dldENvbnRleHQoKTtcblxuICAgICAgdGhpcy5lbWl0KCduZXctY2FudmFzJywgdGhpcy5fY2FudmFzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzZXRDb250ZXh0JyxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGN1cnJlbnQgY29udGV4dCB0byB0aGUgZ2l2ZW4gb25lXG4gICAgICogQHBhcmFtIHtSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHRcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0Q29udGV4dChjb250ZXh0KSB7XG4gICAgICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZXNldCcsXG5cbiAgICAvKipcbiAgICAgKiBSZXNldHMgdGhlIHJlbmRlcmVyXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZXNldENhY2hlID0gZmFsc2VcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICB2YXIgcmVzZXRDYWNoZSA9IGFyZ3VtZW50c1swXSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBhcmd1bWVudHNbMF07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaWRlbnRpZmllcicsXG5cbiAgICAvKipcbiAgICAgKiBBIHVuaXF1ZSBzdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoaXMgcmVuZGVyZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICdpc1N1cHBvcnRlZCcsXG5cbiAgICAvKipcbiAgICAgKiBDaGVja3Mgd2hldGhlciB0aGlzIHR5cGUgb2YgcmVuZGVyZXIgaXMgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50XG4gICAgICogQGFic3RyYWN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGlzU3VwcG9ydGVkKCkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVuZGVyZXIjaXNTdXBwb3J0ZWQgaXMgYWJzdHJhY3QgYW5kIG5vdCBpbXBsZW1lbnRlZCBpbiBpbmhlcml0ZWQgY2xhc3MuJyk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFJlbmRlcmVyO1xufSkoX2xpYkV2ZW50RW1pdHRlcjJbJ2RlZmF1bHQnXSk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFJlbmRlcmVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3JlbmRlcmVycy9yZW5kZXJlci5qc1xuICoqIG1vZHVsZSBpZCA9IDk2XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iLCIvKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKlxuICogRXh0cmFjdGVkIGZyb20gTWluaWZ5SnBlZyAoQ29weXJpZ2h0IChjKSAyMDE0IEhpcm9ha2kgTWF0b2JhLCBNSVQgTGljZW5zZSk6XG4gKiBodHRwczovL2dpdGh1Yi5jb20vaE1hdG9iYS9NaW5pZnlKcGVnXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbnZhciBLRVlfU1RSID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky89JztcblxuZXhwb3J0c1snZGVmYXVsdCddID0ge1xuICBlbmNvZGU6IGZ1bmN0aW9uIGVuY29kZShpbnB1dCkge1xuICAgIHZhciBvdXRwdXQgPSAnJyxcbiAgICAgICAgY2hyMSA9IHVuZGVmaW5lZCxcbiAgICAgICAgY2hyMiA9IHVuZGVmaW5lZCxcbiAgICAgICAgY2hyMyA9ICcnLFxuICAgICAgICBlbmMxID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmMyID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmMzID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmM0ID0gJycsXG4gICAgICAgIGkgPSAwO1xuXG4gICAgZG8ge1xuICAgICAgY2hyMSA9IGlucHV0W2krK107XG4gICAgICBjaHIyID0gaW5wdXRbaSsrXTtcbiAgICAgIGNocjMgPSBpbnB1dFtpKytdO1xuXG4gICAgICBlbmMxID0gY2hyMSA+PiAyO1xuICAgICAgZW5jMiA9IChjaHIxICYgMykgPDwgNCB8IGNocjIgPj4gNDtcbiAgICAgIGVuYzMgPSAoY2hyMiAmIDE1KSA8PCAyIHwgY2hyMyA+PiA2O1xuICAgICAgZW5jNCA9IGNocjMgJiA2MztcblxuICAgICAgaWYgKGlzTmFOKGNocjIpKSB7XG4gICAgICAgIGVuYzMgPSBlbmM0ID0gNjQ7XG4gICAgICB9IGVsc2UgaWYgKGlzTmFOKGNocjMpKSB7XG4gICAgICAgIGVuYzQgPSA2NDtcbiAgICAgIH1cblxuICAgICAgb3V0cHV0ID0gb3V0cHV0ICsgS0VZX1NUUi5jaGFyQXQoZW5jMSkgKyBLRVlfU1RSLmNoYXJBdChlbmMyKSArIEtFWV9TVFIuY2hhckF0KGVuYzMpICsgS0VZX1NUUi5jaGFyQXQoZW5jNCk7XG4gICAgICBjaHIxID0gY2hyMiA9IGNocjMgPSAnJztcbiAgICAgIGVuYzEgPSBlbmMyID0gZW5jMyA9IGVuYzQgPSAnJztcbiAgICB9IHdoaWxlIChpIDwgaW5wdXQubGVuZ3RoKTtcblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0sXG5cbiAgZGVjb2RlOiBmdW5jdGlvbiBkZWNvZGUoaW5wdXQpIHtcbiAgICB2YXIgY2hyMSA9IHVuZGVmaW5lZCxcbiAgICAgICAgY2hyMiA9IHVuZGVmaW5lZCxcbiAgICAgICAgY2hyMyA9ICcnLFxuICAgICAgICBlbmMxID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmMyID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmMzID0gdW5kZWZpbmVkLFxuICAgICAgICBlbmM0ID0gJycsXG4gICAgICAgIGkgPSAwLFxuICAgICAgICBidWYgPSBbXTtcblxuICAgIC8vIHJlbW92ZSBhbGwgY2hhcmFjdGVycyB0aGF0IGFyZSBub3QgQS1aLCBhLXosIDAtOSwgKywgLywgb3IgPVxuICAgIHZhciBiYXNlNjR0ZXN0ID0gL1teQS1aYS16MC05XFwrXFwvXFw9XS9nO1xuICAgIGlmIChiYXNlNjR0ZXN0LmV4ZWMoaW5wdXQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIHdlcmUgaW52YWxpZCBiYXNlNjQgY2hhcmFjdGVycyBpbiB0aGUgaW5wdXQgdGV4dC5cXG4nICsgJ1ZhbGlkIGJhc2U2NCBjaGFyYWN0ZXJzIGFyZSBBLVosIGEteiwgMC05LCBcXCcrXFwnLCBcXCcvXFwnLGFuZCBcXCc9XFwnXFxuJyArICdFeHBlY3QgZXJyb3JzIGluIGRlY29kaW5nLicpO1xuICAgIH1cbiAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoL1teQS1aYS16MC05XFwrXFwvXFw9XS9nLCAnJyk7XG5cbiAgICBkbyB7XG4gICAgICBlbmMxID0gS0VZX1NUUi5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcbiAgICAgIGVuYzIgPSBLRVlfU1RSLmluZGV4T2YoaW5wdXQuY2hhckF0KGkrKykpO1xuICAgICAgZW5jMyA9IEtFWV9TVFIuaW5kZXhPZihpbnB1dC5jaGFyQXQoaSsrKSk7XG4gICAgICBlbmM0ID0gS0VZX1NUUi5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcblxuICAgICAgY2hyMSA9IGVuYzEgPDwgMiB8IGVuYzIgPj4gNDtcbiAgICAgIGNocjIgPSAoZW5jMiAmIDE1KSA8PCA0IHwgZW5jMyA+PiAyO1xuICAgICAgY2hyMyA9IChlbmMzICYgMykgPDwgNiB8IGVuYzQ7XG5cbiAgICAgIGJ1Zi5wdXNoKGNocjEpO1xuXG4gICAgICBpZiAoZW5jMyAhPT0gNjQpIHtcbiAgICAgICAgYnVmLnB1c2goY2hyMik7XG4gICAgICB9XG4gICAgICBpZiAoZW5jNCAhPT0gNjQpIHtcbiAgICAgICAgYnVmLnB1c2goY2hyMyk7XG4gICAgICB9XG5cbiAgICAgIGNocjEgPSBjaHIyID0gY2hyMyA9ICcnO1xuICAgICAgZW5jMSA9IGVuYzIgPSBlbmMzID0gZW5jNCA9ICcnO1xuICAgIH0gd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpO1xuXG4gICAgcmV0dXJuIGJ1ZjtcbiAgfVxufTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9saWIvYmFzZTY0LmpzXG4gKiogbW9kdWxlIGlkID0gOTdcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGpzaGludCB1bnVzZWQ6IGZhbHNlICovXG4vKlxuICogUGhvdG8gRWRpdG9yIFNESyAtIHBob3RvZWRpdG9yc2RrLmNvbVxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTUgOWVsZW1lbnRzIEdtYkhcbiAqXG4gKiBSZWxlYXNlZCB1bmRlciBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBVbnBvcnRlZFxuICogaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMvMy4wL1xuICpcbiAqIEZvciBjb21tZXJjaWFsIHVzZSwgcGxlYXNlIGNvbnRhY3QgdXMgYXQgY29udGFjdEA5ZWxlbWVudHMuY29tXG4gKi9cblxuLyoqXG4gKiBCYXNlIGNsYXNzIGZvciBwcmltaXRpdmVzLiBFeHRlbmRhYmxlIHZpYSB7QGxpbmsgSW1nbHlLaXQuRmlsdGVyLlByaW1pdGl2ZSNleHRlbmR9XG4gKiBAY2xhc3NcbiAqIEBhbGlhcyBJbWdseUtpdC5GaWx0ZXIuUHJpbWl0aXZlXG4gKi9cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG52YXIgUHJpbWl0aXZlID0gKGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gUHJpbWl0aXZlKG9wdGlvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHJpbWl0aXZlKTtcblxuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgdGhpcy5fZ2xzbFByb2dyYW1zID0ge307XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICBfY3JlYXRlQ2xhc3MoUHJpbWl0aXZlLCBbe1xuICAgIGtleTogJ3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwcmltaXRpdmVcbiAgICAgKiBAcGFyYW0gIHtSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiByZW5kZXIocmVuZGVyZXIpIHtcbiAgICAgIGlmIChyZW5kZXJlci5pZGVudGlmaWVyID09PSAnd2ViZ2wnKSB7XG4gICAgICAgIHRoaXMucmVuZGVyV2ViR0wocmVuZGVyZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZW5kZXJDYW52YXMocmVuZGVyZXIpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcldlYkdMJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHByaW1pdGl2ZSAoV2ViR0wpXG4gICAgICogQHBhcmFtICB7Q2FudmFzUmVuZGVyZXJ9IHJlbmRlcmVyXG4gICAgICovXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyV2ViR0wocmVuZGVyZXIpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ByaW1pdGl2ZSNyZW5kZXJXZWJHTCBpcyBhYnN0cmFjdCBhbmQgbm90IGltcGxlbWVudGVkIGluIGluaGVyaXRlZCBjbGFzcy4nKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdyZW5kZXJDYW52YXMnLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcHJpbWl0aXZlIChDYW52YXMyRClcbiAgICAgKiBAcGFyYW0gIHtDYW52YXNSZW5kZXJlcn0gcmVuZGVyZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gcmVuZGVyQ2FudmFzKHJlbmRlcmVyKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQcmltaXRpdmUjcmVuZGVyQ2FudmFzIGlzIGFic3RyYWN0IGFuZCBub3QgaW1wbGVtZW50ZWQgaW4gaW5oZXJpdGVkIGNsYXNzLicpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ29wdGlvbnMnLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFByaW1pdGl2ZTtcbn0pKCk7XG5cbmV4cG9ydHNbJ2RlZmF1bHQnXSA9IFByaW1pdGl2ZTtcbm1vZHVsZS5leHBvcnRzID0gZXhwb3J0c1snZGVmYXVsdCddO1xuXG5cbi8qKioqKioqKioqKioqKioqKlxuICoqIFdFQlBBQ0sgRk9PVEVSXG4gKiogLi9vcGVyYXRpb25zL2ZpbHRlcnMvcHJpbWl0aXZlcy9wcmltaXRpdmUuanNcbiAqKiBtb2R1bGUgaWQgPSA5OFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyohXG4gKiBOYXRpdmUgUHJvbWlzZSBPbmx5XG4gKiB2MC44LjAtYSAoYykgS3lsZSBTaW1wc29uXG4gKiBNSVQgTGljZW5zZTogaHR0cDovL2dldGlmeS5taXQtbGljZW5zZS5vcmdcbiAqIEBsaWNlbnNlXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiBVTUQobmFtZSwgY29udGV4dCwgZGVmaW5pdGlvbikge1xuICAvLyBzcGVjaWFsIGZvcm0gb2YgVU1EIGZvciBwb2x5ZmlsbGluZyBhY3Jvc3MgZXZpcm9ubWVudHNcbiAgY29udGV4dFtuYW1lXSA9IGNvbnRleHRbbmFtZV0gfHwgZGVmaW5pdGlvbigpO1xuICBpZiAodHlwZW9mIG1vZHVsZSAhPSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBjb250ZXh0W25hbWVdO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICBkZWZpbmUoZnVuY3Rpb24gJEFNRCQoKSB7XG4gICAgICByZXR1cm4gY29udGV4dFtuYW1lXTtcbiAgICB9KTtcbiAgfVxufSkoXCJQcm9taXNlXCIsIHR5cGVvZiBnbG9iYWwgIT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHVuZGVmaW5lZCwgZnVuY3Rpb24gREVGKCkge1xuICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICBcInVzZSBzdHJpY3RcIjtcblxuICB2YXIgYnVpbHRJblByb3AsXG4gICAgICBjeWNsZSxcbiAgICAgIHNjaGVkdWxpbmdfcXVldWUsXG4gICAgICBUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcsXG4gICAgICB0aW1lciA9IHR5cGVvZiBzZXRJbW1lZGlhdGUgIT0gXCJ1bmRlZmluZWRcIiA/IGZ1bmN0aW9uIHRpbWVyKGZuKSB7XG4gICAgcmV0dXJuIHNldEltbWVkaWF0ZShmbik7XG4gIH0gOiBzZXRUaW1lb3V0O1xuXG4gIC8vIGRhbW1pdCwgSUU4LlxuICB0cnkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgXCJ4XCIsIHt9KTtcbiAgICBidWlsdEluUHJvcCA9IGZ1bmN0aW9uIGJ1aWx0SW5Qcm9wKG9iaiwgbmFtZSwgdmFsLCBjb25maWcpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBuYW1lLCB7XG4gICAgICAgIHZhbHVlOiB2YWwsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IGNvbmZpZyAhPT0gZmFsc2VcbiAgICAgIH0pO1xuICAgIH07XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGJ1aWx0SW5Qcm9wID0gZnVuY3Rpb24gYnVpbHRJblByb3Aob2JqLCBuYW1lLCB2YWwpIHtcbiAgICAgIG9ialtuYW1lXSA9IHZhbDtcbiAgICAgIHJldHVybiBvYmo7XG4gICAgfTtcbiAgfVxuXG4gIC8vIE5vdGU6IHVzaW5nIGEgcXVldWUgaW5zdGVhZCBvZiBhcnJheSBmb3IgZWZmaWNpZW5jeVxuICBzY2hlZHVsaW5nX3F1ZXVlID0gKGZ1bmN0aW9uIFF1ZXVlKCkge1xuICAgIHZhciBmaXJzdCwgbGFzdCwgaXRlbTtcblxuICAgIGZ1bmN0aW9uIEl0ZW0oZm4sIHNlbGYpIHtcbiAgICAgIHRoaXMuZm4gPSBmbjtcbiAgICAgIHRoaXMuc2VsZiA9IHNlbGY7XG4gICAgICB0aGlzLm5leHQgPSB2b2lkIDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFkZDogZnVuY3Rpb24gYWRkKGZuLCBzZWxmKSB7XG4gICAgICAgIGl0ZW0gPSBuZXcgSXRlbShmbiwgc2VsZik7XG4gICAgICAgIGlmIChsYXN0KSB7XG4gICAgICAgICAgbGFzdC5uZXh0ID0gaXRlbTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaXJzdCA9IGl0ZW07XG4gICAgICAgIH1cbiAgICAgICAgbGFzdCA9IGl0ZW07XG4gICAgICAgIGl0ZW0gPSB2b2lkIDA7XG4gICAgICB9LFxuICAgICAgZHJhaW46IGZ1bmN0aW9uIGRyYWluKCkge1xuICAgICAgICB2YXIgZiA9IGZpcnN0O1xuICAgICAgICBmaXJzdCA9IGxhc3QgPSBjeWNsZSA9IHZvaWQgMDtcblxuICAgICAgICB3aGlsZSAoZikge1xuICAgICAgICAgIGYuZm4uY2FsbChmLnNlbGYpO1xuICAgICAgICAgIGYgPSBmLm5leHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9KSgpO1xuXG4gIGZ1bmN0aW9uIHNjaGVkdWxlKGZuLCBzZWxmKSB7XG4gICAgc2NoZWR1bGluZ19xdWV1ZS5hZGQoZm4sIHNlbGYpO1xuICAgIGlmICghY3ljbGUpIHtcbiAgICAgIGN5Y2xlID0gdGltZXIoc2NoZWR1bGluZ19xdWV1ZS5kcmFpbik7XG4gICAgfVxuICB9XG5cbiAgLy8gcHJvbWlzZSBkdWNrIHR5cGluZ1xuICBmdW5jdGlvbiBpc1RoZW5hYmxlKG8pIHtcbiAgICB2YXIgX3RoZW4sXG4gICAgICAgIG9fdHlwZSA9IHR5cGVvZiBvO1xuXG4gICAgaWYgKG8gIT0gbnVsbCAmJiAob190eXBlID09IFwib2JqZWN0XCIgfHwgb190eXBlID09IFwiZnVuY3Rpb25cIikpIHtcbiAgICAgIF90aGVuID0gby50aGVuO1xuICAgIH1cbiAgICByZXR1cm4gdHlwZW9mIF90aGVuID09IFwiZnVuY3Rpb25cIiA/IF90aGVuIDogZmFsc2U7XG4gIH1cblxuICBmdW5jdGlvbiBub3RpZnkoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNoYWluLmxlbmd0aDsgaSsrKSB7XG4gICAgICBub3RpZnlJc29sYXRlZCh0aGlzLCB0aGlzLnN0YXRlID09PSAxID8gdGhpcy5jaGFpbltpXS5zdWNjZXNzIDogdGhpcy5jaGFpbltpXS5mYWlsdXJlLCB0aGlzLmNoYWluW2ldKTtcbiAgICB9XG4gICAgdGhpcy5jaGFpbi5sZW5ndGggPSAwO1xuICB9XG5cbiAgLy8gTk9URTogVGhpcyBpcyBhIHNlcGFyYXRlIGZ1bmN0aW9uIHRvIGlzb2xhdGVcbiAgLy8gdGhlIGB0cnkuLmNhdGNoYCBzbyB0aGF0IG90aGVyIGNvZGUgY2FuIGJlXG4gIC8vIG9wdGltaXplZCBiZXR0ZXJcbiAgZnVuY3Rpb24gbm90aWZ5SXNvbGF0ZWQoc2VsZiwgY2IsIGNoYWluKSB7XG4gICAgdmFyIHJldCwgX3RoZW47XG4gICAgdHJ5IHtcbiAgICAgIGlmIChjYiA9PT0gZmFsc2UpIHtcbiAgICAgICAgY2hhaW4ucmVqZWN0KHNlbGYubXNnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjYiA9PT0gdHJ1ZSkge1xuICAgICAgICAgIHJldCA9IHNlbGYubXNnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldCA9IGNiLmNhbGwodm9pZCAwLCBzZWxmLm1zZyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmV0ID09PSBjaGFpbi5wcm9taXNlKSB7XG4gICAgICAgICAgY2hhaW4ucmVqZWN0KFR5cGVFcnJvcihcIlByb21pc2UtY2hhaW4gY3ljbGVcIikpO1xuICAgICAgICB9IGVsc2UgaWYgKF90aGVuID0gaXNUaGVuYWJsZShyZXQpKSB7XG4gICAgICAgICAgX3RoZW4uY2FsbChyZXQsIGNoYWluLnJlc29sdmUsIGNoYWluLnJlamVjdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2hhaW4ucmVzb2x2ZShyZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjaGFpbi5yZWplY3QoZXJyKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZXNvbHZlKG1zZykge1xuICAgIHZhciBfdGhlbixcbiAgICAgICAgc2VsZiA9IHRoaXM7XG5cbiAgICAvLyBhbHJlYWR5IHRyaWdnZXJlZD9cbiAgICBpZiAoc2VsZi50cmlnZ2VyZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzZWxmLnRyaWdnZXJlZCA9IHRydWU7XG5cbiAgICAvLyB1bndyYXBcbiAgICBpZiAoc2VsZi5kZWYpIHtcbiAgICAgIHNlbGYgPSBzZWxmLmRlZjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgaWYgKF90aGVuID0gaXNUaGVuYWJsZShtc2cpKSB7XG4gICAgICAgIHNjaGVkdWxlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgZGVmX3dyYXBwZXIgPSBuZXcgTWFrZURlZldyYXBwZXIoc2VsZik7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIF90aGVuLmNhbGwobXNnLCBmdW5jdGlvbiAkcmVzb2x2ZSQoKSB7XG4gICAgICAgICAgICAgIHJlc29sdmUuYXBwbHkoZGVmX3dyYXBwZXIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAkcmVqZWN0JCgpIHtcbiAgICAgICAgICAgICAgcmVqZWN0LmFwcGx5KGRlZl93cmFwcGVyLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICByZWplY3QuY2FsbChkZWZfd3JhcHBlciwgZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VsZi5tc2cgPSBtc2c7XG4gICAgICAgIHNlbGYuc3RhdGUgPSAxO1xuICAgICAgICBpZiAoc2VsZi5jaGFpbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc2NoZWR1bGUobm90aWZ5LCBzZWxmKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmVqZWN0LmNhbGwobmV3IE1ha2VEZWZXcmFwcGVyKHNlbGYpLCBlcnIpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJlamVjdChtc2cpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAvLyBhbHJlYWR5IHRyaWdnZXJlZD9cbiAgICBpZiAoc2VsZi50cmlnZ2VyZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzZWxmLnRyaWdnZXJlZCA9IHRydWU7XG5cbiAgICAvLyB1bndyYXBcbiAgICBpZiAoc2VsZi5kZWYpIHtcbiAgICAgIHNlbGYgPSBzZWxmLmRlZjtcbiAgICB9XG5cbiAgICBzZWxmLm1zZyA9IG1zZztcbiAgICBzZWxmLnN0YXRlID0gMjtcbiAgICBpZiAoc2VsZi5jaGFpbi5sZW5ndGggPiAwKSB7XG4gICAgICBzY2hlZHVsZShub3RpZnksIHNlbGYpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGl0ZXJhdGVQcm9taXNlcyhDb25zdHJ1Y3RvciwgYXJyLCByZXNvbHZlciwgcmVqZWN0ZXIpIHtcbiAgICBmb3IgKHZhciBpZHggPSAwOyBpZHggPCBhcnIubGVuZ3RoOyBpZHgrKykge1xuICAgICAgKGZ1bmN0aW9uIElJRkUoaWR4KSB7XG4gICAgICAgIENvbnN0cnVjdG9yLnJlc29sdmUoYXJyW2lkeF0pLnRoZW4oZnVuY3Rpb24gJHJlc29sdmVyJChtc2cpIHtcbiAgICAgICAgICByZXNvbHZlcihpZHgsIG1zZyk7XG4gICAgICAgIH0sIHJlamVjdGVyKTtcbiAgICAgIH0pKGlkeCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gTWFrZURlZldyYXBwZXIoc2VsZikge1xuICAgIHRoaXMuZGVmID0gc2VsZjtcbiAgICB0aGlzLnRyaWdnZXJlZCA9IGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gTWFrZURlZihzZWxmKSB7XG4gICAgdGhpcy5wcm9taXNlID0gc2VsZjtcbiAgICB0aGlzLnN0YXRlID0gMDtcbiAgICB0aGlzLnRyaWdnZXJlZCA9IGZhbHNlO1xuICAgIHRoaXMuY2hhaW4gPSBbXTtcbiAgICB0aGlzLm1zZyA9IHZvaWQgMDtcbiAgfVxuXG4gIGZ1bmN0aW9uIFByb21pc2UoZXhlY3V0b3IpIHtcbiAgICBpZiAodHlwZW9mIGV4ZWN1dG9yICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiTm90IGEgZnVuY3Rpb25cIik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX19OUE9fXyAhPT0gMCkge1xuICAgICAgdGhyb3cgVHlwZUVycm9yKFwiTm90IGEgcHJvbWlzZVwiKTtcbiAgICB9XG5cbiAgICAvLyBpbnN0YW5jZSBzaGFkb3dpbmcgdGhlIGluaGVyaXRlZCBcImJyYW5kXCJcbiAgICAvLyB0byBzaWduYWwgYW4gYWxyZWFkeSBcImluaXRpYWxpemVkXCIgcHJvbWlzZVxuICAgIHRoaXMuX19OUE9fXyA9IDE7XG5cbiAgICB2YXIgZGVmID0gbmV3IE1ha2VEZWYodGhpcyk7XG5cbiAgICB0aGlzW1widGhlblwiXSA9IGZ1bmN0aW9uIHRoZW4oc3VjY2VzcywgZmFpbHVyZSkge1xuICAgICAgdmFyIG8gPSB7XG4gICAgICAgIHN1Y2Nlc3M6IHR5cGVvZiBzdWNjZXNzID09IFwiZnVuY3Rpb25cIiA/IHN1Y2Nlc3MgOiB0cnVlLFxuICAgICAgICBmYWlsdXJlOiB0eXBlb2YgZmFpbHVyZSA9PSBcImZ1bmN0aW9uXCIgPyBmYWlsdXJlIDogZmFsc2VcbiAgICAgIH07XG4gICAgICAvLyBOb3RlOiBgdGhlbiguLilgIGl0c2VsZiBjYW4gYmUgYm9ycm93ZWQgdG8gYmUgdXNlZCBhZ2FpbnN0XG4gICAgICAvLyBhIGRpZmZlcmVudCBwcm9taXNlIGNvbnN0cnVjdG9yIGZvciBtYWtpbmcgdGhlIGNoYWluZWQgcHJvbWlzZSxcbiAgICAgIC8vIGJ5IHN1YnN0aXR1dGluZyBhIGRpZmZlcmVudCBgdGhpc2AgYmluZGluZy5cbiAgICAgIG8ucHJvbWlzZSA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKGZ1bmN0aW9uIGV4dHJhY3RDaGFpbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZlICE9IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgcmVqZWN0ICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIk5vdCBhIGZ1bmN0aW9uXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgby5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgby5yZWplY3QgPSByZWplY3Q7XG4gICAgICB9KTtcbiAgICAgIGRlZi5jaGFpbi5wdXNoKG8pO1xuXG4gICAgICBpZiAoZGVmLnN0YXRlICE9PSAwKSB7XG4gICAgICAgIHNjaGVkdWxlKG5vdGlmeSwgZGVmKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG8ucHJvbWlzZTtcbiAgICB9O1xuICAgIHRoaXNbXCJjYXRjaFwiXSA9IGZ1bmN0aW9uICRjYXRjaCQoZmFpbHVyZSkge1xuICAgICAgcmV0dXJuIHRoaXMudGhlbih2b2lkIDAsIGZhaWx1cmUpO1xuICAgIH07XG5cbiAgICB0cnkge1xuICAgICAgZXhlY3V0b3IuY2FsbCh2b2lkIDAsIGZ1bmN0aW9uIHB1YmxpY1Jlc29sdmUobXNnKSB7XG4gICAgICAgIHJlc29sdmUuY2FsbChkZWYsIG1zZyk7XG4gICAgICB9LCBmdW5jdGlvbiBwdWJsaWNSZWplY3QobXNnKSB7XG4gICAgICAgIHJlamVjdC5jYWxsKGRlZiwgbXNnKTtcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmVqZWN0LmNhbGwoZGVmLCBlcnIpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBQcm9taXNlUHJvdG90eXBlID0gYnVpbHRJblByb3Aoe30sIFwiY29uc3RydWN0b3JcIiwgUHJvbWlzZSxcbiAgLypjb25maWd1cmFibGU9Ki9mYWxzZSk7XG5cbiAgLy8gTm90ZTogQW5kcm9pZCA0IGNhbm5vdCB1c2UgYE9iamVjdC5kZWZpbmVQcm9wZXJ0eSguLilgIGhlcmVcbiAgUHJvbWlzZS5wcm90b3R5cGUgPSBQcm9taXNlUHJvdG90eXBlO1xuXG4gIC8vIGJ1aWx0LWluIFwiYnJhbmRcIiB0byBzaWduYWwgYW4gXCJ1bmluaXRpYWxpemVkXCIgcHJvbWlzZVxuICBidWlsdEluUHJvcChQcm9taXNlUHJvdG90eXBlLCBcIl9fTlBPX19cIiwgMCxcbiAgLypjb25maWd1cmFibGU9Ki9mYWxzZSk7XG5cbiAgYnVpbHRJblByb3AoUHJvbWlzZSwgXCJyZXNvbHZlXCIsIGZ1bmN0aW9uIFByb21pc2UkcmVzb2x2ZShtc2cpIHtcbiAgICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuXG4gICAgLy8gc3BlYyBtYW5kYXRlZCBjaGVja3NcbiAgICAvLyBub3RlOiBiZXN0IFwiaXNQcm9taXNlXCIgY2hlY2sgdGhhdCdzIHByYWN0aWNhbCBmb3Igbm93XG4gICAgaWYgKG1zZyAmJiB0eXBlb2YgbXNnID09IFwib2JqZWN0XCIgJiYgbXNnLl9fTlBPX18gPT09IDEpIHtcbiAgICAgIHJldHVybiBtc2c7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiBleGVjdXRvcihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmICh0eXBlb2YgcmVzb2x2ZSAhPSBcImZ1bmN0aW9uXCIgfHwgdHlwZW9mIHJlamVjdCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiTm90IGEgZnVuY3Rpb25cIik7XG4gICAgICB9XG5cbiAgICAgIHJlc29sdmUobXNnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgYnVpbHRJblByb3AoUHJvbWlzZSwgXCJyZWplY3RcIiwgZnVuY3Rpb24gUHJvbWlzZSRyZWplY3QobXNnKSB7XG4gICAgcmV0dXJuIG5ldyB0aGlzKGZ1bmN0aW9uIGV4ZWN1dG9yKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiByZXNvbHZlICE9IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgcmVqZWN0ICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJOb3QgYSBmdW5jdGlvblwiKTtcbiAgICAgIH1cblxuICAgICAgcmVqZWN0KG1zZyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGJ1aWx0SW5Qcm9wKFByb21pc2UsIFwiYWxsXCIsIGZ1bmN0aW9uIFByb21pc2UkYWxsKGFycikge1xuICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7XG5cbiAgICAvLyBzcGVjIG1hbmRhdGVkIGNoZWNrc1xuICAgIGlmIChUb1N0cmluZy5jYWxsKGFycikgIT0gXCJbb2JqZWN0IEFycmF5XVwiKSB7XG4gICAgICByZXR1cm4gQ29uc3RydWN0b3IucmVqZWN0KFR5cGVFcnJvcihcIk5vdCBhbiBhcnJheVwiKSk7XG4gICAgfVxuICAgIGlmIChhcnIubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gQ29uc3RydWN0b3IucmVzb2x2ZShbXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBDb25zdHJ1Y3RvcihmdW5jdGlvbiBleGVjdXRvcihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGlmICh0eXBlb2YgcmVzb2x2ZSAhPSBcImZ1bmN0aW9uXCIgfHwgdHlwZW9mIHJlamVjdCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiTm90IGEgZnVuY3Rpb25cIik7XG4gICAgICB9XG5cbiAgICAgIHZhciBsZW4gPSBhcnIubGVuZ3RoLFxuICAgICAgICAgIG1zZ3MgPSBBcnJheShsZW4pLFxuICAgICAgICAgIGNvdW50ID0gMDtcblxuICAgICAgaXRlcmF0ZVByb21pc2VzKENvbnN0cnVjdG9yLCBhcnIsIGZ1bmN0aW9uIHJlc29sdmVyKGlkeCwgbXNnKSB7XG4gICAgICAgIG1zZ3NbaWR4XSA9IG1zZztcbiAgICAgICAgaWYgKCsrY291bnQgPT09IGxlbikge1xuICAgICAgICAgIHJlc29sdmUobXNncyk7XG4gICAgICAgIH1cbiAgICAgIH0sIHJlamVjdCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGJ1aWx0SW5Qcm9wKFByb21pc2UsIFwicmFjZVwiLCBmdW5jdGlvbiBQcm9taXNlJHJhY2UoYXJyKSB7XG4gICAgdmFyIENvbnN0cnVjdG9yID0gdGhpcztcblxuICAgIC8vIHNwZWMgbWFuZGF0ZWQgY2hlY2tzXG4gICAgaWYgKFRvU3RyaW5nLmNhbGwoYXJyKSAhPSBcIltvYmplY3QgQXJyYXldXCIpIHtcbiAgICAgIHJldHVybiBDb25zdHJ1Y3Rvci5yZWplY3QoVHlwZUVycm9yKFwiTm90IGFuIGFycmF5XCIpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvbnN0cnVjdG9yKGZ1bmN0aW9uIGV4ZWN1dG9yKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgaWYgKHR5cGVvZiByZXNvbHZlICE9IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgcmVqZWN0ICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJOb3QgYSBmdW5jdGlvblwiKTtcbiAgICAgIH1cblxuICAgICAgaXRlcmF0ZVByb21pc2VzKENvbnN0cnVjdG9yLCBhcnIsIGZ1bmN0aW9uIHJlc29sdmVyKGlkeCwgbXNnKSB7XG4gICAgICAgIHJlc29sdmUobXNnKTtcbiAgICAgIH0sIHJlamVjdCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIHJldHVybiBQcm9taXNlO1xufSk7XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3ZlbmRvci9uYXRpdmUtcHJvbWlzZS1vbmx5LmpzXG4gKiogbW9kdWxlIGlkID0gOTlcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxudmFyIEhlbHBlcnMgPSAoZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBIZWxwZXJzKGtpdCwgdWksIG9wdGlvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgSGVscGVycyk7XG5cbiAgICB0aGlzLl9raXQgPSBraXQ7XG4gICAgdGhpcy5fdWkgPSB1aTtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhIZWxwZXJzLCBbe1xuICAgIGtleTogJ2Fzc2V0UGF0aCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGFzc2V0UGF0aChhc3NldCkge1xuICAgICAgdmFyIHBhdGggPSB0aGlzLl9vcHRpb25zLmFzc2V0c1VybCArICcvJyArIGFzc2V0O1xuXG4gICAgICB2YXIgYXNzZXRQYXRoUmVzb2x2ZXIgPSB0aGlzLl91aS5vcHRpb25zLnVpLmFzc2V0UGF0aFJlc29sdmVyO1xuICAgICAgaWYgKHR5cGVvZiBhc3NldFBhdGhSZXNvbHZlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcGF0aCA9IGFzc2V0UGF0aFJlc29sdmVyKHBhdGgpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGF0aDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICd0cmFuc2xhdGUnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiB0cmFuc2xhdGUoa2V5KSB7XG4gICAgICByZXR1cm4gdGhpcy5fdWkudHJhbnNsYXRlKGtleSk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEhlbHBlcnM7XG59KSgpO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBIZWxwZXJzO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzWydkZWZhdWx0J107XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL3VpL2Jhc2UvaGVscGVycy5qc1xuICoqIG1vZHVsZSBpZCA9IDEwMFxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG52YXIgX2dldCA9IGZ1bmN0aW9uIGdldChfeCwgX3gyLCBfeDMpIHsgdmFyIF9hZ2FpbiA9IHRydWU7IF9mdW5jdGlvbjogd2hpbGUgKF9hZ2FpbikgeyB2YXIgb2JqZWN0ID0gX3gsIHByb3BlcnR5ID0gX3gyLCByZWNlaXZlciA9IF94MzsgZGVzYyA9IHBhcmVudCA9IGdldHRlciA9IHVuZGVmaW5lZDsgX2FnYWluID0gZmFsc2U7IHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTsgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkgeyB2YXIgcGFyZW50ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iamVjdCk7IGlmIChwYXJlbnQgPT09IG51bGwpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSBlbHNlIHsgX3ggPSBwYXJlbnQ7IF94MiA9IHByb3BlcnR5OyBfeDMgPSByZWNlaXZlcjsgX2FnYWluID0gdHJ1ZTsgY29udGludWUgX2Z1bmN0aW9uOyB9IH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBkZXNjKSB7IHJldHVybiBkZXNjLnZhbHVlOyB9IGVsc2UgeyB2YXIgZ2V0dGVyID0gZGVzYy5nZXQ7IGlmIChnZXR0ZXIgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7IH0gfSB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnLi4vLi4vLi4vbGliL2V2ZW50LWVtaXR0ZXInKTtcblxudmFyIF9saWJFdmVudEVtaXR0ZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliRXZlbnRFbWl0dGVyKTtcblxudmFyIF9saWJVdGlscyA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi91dGlscycpO1xuXG52YXIgX2xpYlV0aWxzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYlV0aWxzKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMiA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9tYXRoL3ZlY3RvcjInKTtcblxudmFyIF9saWJNYXRoVmVjdG9yMjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJNYXRoVmVjdG9yMik7XG5cbnZhciBTbGlkZXIgPSAoZnVuY3Rpb24gKF9FdmVudEVtaXR0ZXIpIHtcbiAgZnVuY3Rpb24gU2xpZGVyKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU2xpZGVyKTtcblxuICAgIF9nZXQoT2JqZWN0LmdldFByb3RvdHlwZU9mKFNsaWRlci5wcm90b3R5cGUpLCAnY29uc3RydWN0b3InLCB0aGlzKS5jYWxsKHRoaXMpO1xuXG4gICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgdGhpcy5fb3B0aW9ucyA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5kZWZhdWx0cyhvcHRpb25zLCB7XG4gICAgICBtaW5WYWx1ZTogMCxcbiAgICAgIG1heFZhbHVlOiAxLFxuICAgICAgZGVmYXVsdFZhbHVlOiAwXG4gICAgfSk7XG5cbiAgICB0aGlzLl92YWx1ZSA9IHRoaXMuX29wdGlvbnMuZGVmYXVsdFZhbHVlO1xuXG4gICAgdGhpcy5fc2xpZGVyRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNsaWRlci1zbGlkZXInKTtcbiAgICB0aGlzLl9kb3RFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtc2xpZGVyLWRvdCcpO1xuICAgIHRoaXMuX2NlbnRlckRvdEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5pbWdseWtpdC1zbGlkZXItY2VudGVyLWRvdCcpO1xuICAgIHRoaXMuX2ZpbGxFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtc2xpZGVyLWZpbGwnKTtcbiAgICB0aGlzLl9iYWNrZ3JvdW5kRWxlbWVudCA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LXNsaWRlci1iYWNrZ3JvdW5kJyk7XG5cbiAgICAvLyBNb3VzZSBldmVudCBjYWxsYmFja3MgYm91bmQgdG8gY2xhc3MgY29udGV4dFxuICAgIHRoaXMuX29uTW91c2VEb3duID0gdGhpcy5fb25Nb3VzZURvd24uYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbk1vdXNlTW92ZSA9IHRoaXMuX29uTW91c2VNb3ZlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Nb3VzZVVwID0gdGhpcy5fb25Nb3VzZVVwLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25DZW50ZXJEb3RDbGljayA9IHRoaXMuX29uQ2VudGVyRG90Q2xpY2suYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkJhY2tncm91bmRDbGljayA9IHRoaXMuX29uQmFja2dyb3VuZENsaWNrLmJpbmQodGhpcyk7XG5cbiAgICB0aGlzLl9iYWNrZ3JvdW5kRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQmFja2dyb3VuZENsaWNrKTtcbiAgICB0aGlzLl9maWxsRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQmFja2dyb3VuZENsaWNrKTtcblxuICAgIHRoaXMuX2hhbmRsZURvdCgpO1xuICB9XG5cbiAgX2luaGVyaXRzKFNsaWRlciwgX0V2ZW50RW1pdHRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKFNsaWRlciwgW3tcbiAgICBrZXk6ICdzZXRWYWx1ZScsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBnaXZlbiB2YWx1ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRWYWx1ZSh2YWx1ZSkge1xuICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcblxuICAgICAgdmFyIF9vcHRpb25zID0gdGhpcy5fb3B0aW9ucztcbiAgICAgIHZhciBtYXhWYWx1ZSA9IF9vcHRpb25zLm1heFZhbHVlO1xuICAgICAgdmFyIG1pblZhbHVlID0gX29wdGlvbnMubWluVmFsdWU7XG5cbiAgICAgIC8vIENhbGN1bGF0ZSB0aGUgWCBwb3NpdGlvblxuICAgICAgdmFyIHZhbHVlUmFuZ2UgPSBtYXhWYWx1ZSAtIG1pblZhbHVlO1xuICAgICAgdmFyIHBlcmNlbnRhZ2UgPSAodmFsdWUgLSBtaW5WYWx1ZSkgLyB2YWx1ZVJhbmdlO1xuICAgICAgdmFyIHNsaWRlcldpZHRoID0gdGhpcy5fc2xpZGVyRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgIHRoaXMuX3NldFgoc2xpZGVyV2lkdGggKiBwZXJjZW50YWdlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfc2V0WCcsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzbGlkZXIgcG9zaXRpb24gdG8gdGhlIGdpdmVuIFggdmFsdWUgYW5kIHJlc2l6ZXNcbiAgICAgKiB0aGUgZmlsbCBkaXZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0WCh4KSB7XG4gICAgICB0aGlzLl94UG9zaXRpb24gPSB4O1xuICAgICAgdGhpcy5fZG90RWxlbWVudC5zdHlsZS5sZWZ0ID0gJycgKyB4ICsgJ3B4JztcblxuICAgICAgLy8gWCBwb3NpdGlvbiByZWxhdGl2ZSB0byBjZW50ZXIgdG8gc2ltcGxpZnkgY2FsY3VsYXRpb25zXG4gICAgICB2YXIgaGFsZlNsaWRlcldpZHRoID0gdGhpcy5fc2xpZGVyRWxlbWVudC5vZmZzZXRXaWR0aCAvIDI7XG4gICAgICB2YXIgcmVsYXRpdmVYID0geCAtIGhhbGZTbGlkZXJXaWR0aDtcblxuICAgICAgLy8gVXBkYXRlIHN0eWxlXG4gICAgICB0aGlzLl9maWxsRWxlbWVudC5zdHlsZS53aWR0aCA9ICcnICsgTWF0aC5hYnMocmVsYXRpdmVYKSArICdweCc7XG4gICAgICBpZiAocmVsYXRpdmVYIDwgMCkge1xuICAgICAgICB0aGlzLl9maWxsRWxlbWVudC5zdHlsZS5sZWZ0ID0gaGFsZlNsaWRlcldpZHRoIC0gTWF0aC5hYnMocmVsYXRpdmVYKSArICdweCc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9maWxsRWxlbWVudC5zdHlsZS5sZWZ0ID0gaGFsZlNsaWRlcldpZHRoICsgJ3B4JztcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlRG90JyxcblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgdGhlIGRvdCBkcmFnZ2luZ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVEb3QoKSB7XG4gICAgICB0aGlzLl9kb3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duKTtcbiAgICAgIHRoaXMuX2RvdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uTW91c2VEb3duKTtcblxuICAgICAgaWYgKHRoaXMuX2NlbnRlckRvdEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fY2VudGVyRG90RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2VudGVyRG90Q2xpY2spO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkNlbnRlckRvdENsaWNrJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIHRoZSBjZW50ZXIgYnV0dG9uLiBSZXNldHMgdG8gZGVmYXVsdFxuICAgICAqIHNldHRpbmdzLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkNlbnRlckRvdENsaWNrKCkge1xuICAgICAgdGhpcy5zZXRWYWx1ZSh0aGlzLl9vcHRpb25zLmRlZmF1bHRWYWx1ZSk7XG4gICAgICB0aGlzLmVtaXQoJ3VwZGF0ZScsIHRoaXMuX3ZhbHVlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25CYWNrZ3JvdW5kQ2xpY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gdGhlIHNsaWRlciBiYWNrZ3JvdW5kXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkJhY2tncm91bmRDbGljayhlKSB7XG4gICAgICB2YXIgcG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcbiAgICAgIHZhciBzbGlkZXJPZmZzZXQgPSB0aGlzLl9zbGlkZXJFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgc2xpZGVyT2Zmc2V0ID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShzbGlkZXJPZmZzZXQubGVmdCwgc2xpZGVyT2Zmc2V0LnkpO1xuXG4gICAgICB2YXIgcmVsYXRpdmVQb3NpdGlvbiA9IHBvc2l0aW9uLmNsb25lKCkuc3VidHJhY3Qoc2xpZGVyT2Zmc2V0KTtcblxuICAgICAgdGhpcy5fc2V0WChyZWxhdGl2ZVBvc2l0aW9uLngpO1xuICAgICAgdGhpcy5fdXBkYXRlVmFsdWUoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Nb3VzZURvd24nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBwcmVzc2VzIGEgbW91c2UgYnV0dG9uIG9uIHRoZSBzbGlkZXIgZG90XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTW91c2VEb3duKGUpIHtcbiAgICAgIGlmIChlLnR5cGUgPT09ICdtb3VzZWRvd24nICYmIGUuYnV0dG9uICE9PSAwKSByZXR1cm47XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uTW91c2VNb3ZlKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uTW91c2VNb3ZlKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uTW91c2VVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uTW91c2VVcCk7XG5cbiAgICAgIC8vIFJlbWVtYmVyIGluaXRpYWwgcG9zaXRpb25cbiAgICAgIHZhciBkb3RQb3NpdGlvbiA9IHRoaXMuX2RvdEVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB2YXIgc2xpZGVyUG9zaXRpb24gPSB0aGlzLl9zbGlkZXJFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICB0aGlzLl9pbml0aWFsU2xpZGVyWCA9IGRvdFBvc2l0aW9uLmxlZnQgLSBzbGlkZXJQb3NpdGlvbi5sZWZ0O1xuICAgICAgdGhpcy5faW5pdGlhbE1vdXNlUG9zaXRpb24gPSBtb3VzZVBvc2l0aW9uO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbk1vdXNlTW92ZScsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGRyYWdzIHRoZSBtb3VzZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbk1vdXNlTW92ZShlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBtb3VzZVBvc2l0aW9uID0gX2xpYlV0aWxzMlsnZGVmYXVsdCddLmdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICB2YXIgbW91c2VEaWZmID0gbW91c2VQb3NpdGlvbi5zdWJ0cmFjdCh0aGlzLl9pbml0aWFsTW91c2VQb3NpdGlvbik7XG5cbiAgICAgIC8vIEFkZCBoYWxmIHdpZHRoIG9mIHRoZSBkb3QgZm9yIG5lZ2F0aXZlIG1hcmdpbiBjb21wZW5zYXRpb25cbiAgICAgIHZhciBoYWxmRG90V2lkdGggPSB0aGlzLl9kb3RFbGVtZW50Lm9mZnNldFdpZHRoICogMC41O1xuICAgICAgdmFyIG5ld1NsaWRlclggPSB0aGlzLl9pbml0aWFsU2xpZGVyWCArIG1vdXNlRGlmZi54ICsgaGFsZkRvdFdpZHRoO1xuXG4gICAgICAvLyBYIGJvdW5kYXJpZXNcbiAgICAgIHZhciBzbGlkZXJXaWR0aCA9IHRoaXMuX3NsaWRlckVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgICBuZXdTbGlkZXJYID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obmV3U2xpZGVyWCwgc2xpZGVyV2lkdGgpKTtcblxuICAgICAgdGhpcy5fc2V0WChuZXdTbGlkZXJYKTtcbiAgICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3VwZGF0ZVZhbHVlJyxcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIHZhbHVlIHVzaW5nIHRoZSBzbGlkZXIgcG9zaXRpb25cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfdXBkYXRlVmFsdWUoKSB7XG4gICAgICB2YXIgc2xpZGVyV2lkdGggPSB0aGlzLl9zbGlkZXJFbGVtZW50Lm9mZnNldFdpZHRoO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgdGhlIG5ldyB2YWx1ZVxuICAgICAgdmFyIF9vcHRpb25zMiA9IHRoaXMuX29wdGlvbnM7XG4gICAgICB2YXIgbWluVmFsdWUgPSBfb3B0aW9uczIubWluVmFsdWU7XG4gICAgICB2YXIgbWF4VmFsdWUgPSBfb3B0aW9uczIubWF4VmFsdWU7XG5cbiAgICAgIHZhciBwZXJjZW50YWdlID0gdGhpcy5feFBvc2l0aW9uIC8gc2xpZGVyV2lkdGg7XG4gICAgICB2YXIgdmFsdWUgPSBtaW5WYWx1ZSArIChtYXhWYWx1ZSAtIG1pblZhbHVlKSAqIHBlcmNlbnRhZ2U7XG4gICAgICB0aGlzLmVtaXQoJ3VwZGF0ZScsIHZhbHVlKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25Nb3VzZVVwJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgZG9lcyBub3QgcHJlc3MgdGhlIG1vdXNlIGJ1dHRvbiBhbnltb3JlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uTW91c2VVcCgpIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uTW91c2VNb3ZlKTtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uTW91c2VNb3ZlKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uTW91c2VVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uTW91c2VVcCk7XG4gICAgfVxuICB9XSwgW3tcbiAgICBrZXk6ICd0ZW1wbGF0ZScsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGFydGlhbCB0ZW1wbGF0ZSBzdHJpbmdcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqL1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGl0XG4vKiovKSB7XG52YXIgb3V0PSc8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc2xpZGVyXCIgaWQ9XCInKygodHlwZW9mIGl0LmlkID09PSBcInVuZGVmaW5lZFwiPycnOml0LmlkKSkrJ1wiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc2xpZGVyLW1pbnVzXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L3NsaWRlci9taW51cy5wbmcnKSApKydcIiAvPiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1zbGlkZXJcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1jb250ZW50XCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zbGlkZXItYmFja2dyb3VuZFwiPjwvZGl2PiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc2xpZGVyLWZpbGxcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1jZW50ZXItZG90XCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zbGlkZXItZG90XCI+PC9kaXY+IDwvZGl2PiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1wbHVzXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L3NsaWRlci9wbHVzLnBuZycpICkrJ1wiIC8+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFNsaWRlcjtcbn0pKF9saWJFdmVudEVtaXR0ZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTbGlkZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL3NsaWRlci5qc1xuICoqIG1vZHVsZSBpZCA9IDEwMVxuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwiLyogZ2xvYmFsIF9fRE9USlNfVEVNUExBVEUgKi9cbi8qXG4gKiBQaG90byBFZGl0b3IgU0RLIC0gcGhvdG9lZGl0b3JzZGsuY29tXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAxNSA5ZWxlbWVudHMgR21iSFxuICpcbiAqIFJlbGVhc2VkIHVuZGVyIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFVucG9ydGVkXG4gKiBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvXG4gKlxuICogRm9yIGNvbW1lcmNpYWwgdXNlLCBwbGVhc2UgY29udGFjdCB1cyBhdCBjb250YWN0QDllbGVtZW50cy5jb21cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gKGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmICgndmFsdWUnIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KSgpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyAnZGVmYXVsdCc6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJyk7IH0gfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSAnZnVuY3Rpb24nICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcignU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBzdWJDbGFzcy5fX3Byb3RvX18gPSBzdXBlckNsYXNzOyB9XG5cbnZhciBfc2xpZGVyID0gcmVxdWlyZSgnLi9zbGlkZXInKTtcblxudmFyIF9zbGlkZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfc2xpZGVyKTtcblxudmFyIFNpbXBsZVNsaWRlciA9IChmdW5jdGlvbiAoX1NsaWRlcikge1xuICBmdW5jdGlvbiBTaW1wbGVTbGlkZXIoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFNpbXBsZVNsaWRlcik7XG5cbiAgICBpZiAoX1NsaWRlciAhPSBudWxsKSB7XG4gICAgICBfU2xpZGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgX2luaGVyaXRzKFNpbXBsZVNsaWRlciwgX1NsaWRlcik7XG5cbiAgX2NyZWF0ZUNsYXNzKFNpbXBsZVNsaWRlciwgW3tcbiAgICBrZXk6ICdfc2V0WCcsXG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzbGlkZXIgcG9zaXRpb24gdG8gdGhlIGdpdmVuIFggdmFsdWUgYW5kIHJlc2l6ZXNcbiAgICAgKiB0aGUgZmlsbCBkaXZcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfc2V0WCh4KSB7XG4gICAgICB0aGlzLl94UG9zaXRpb24gPSB4O1xuXG4gICAgICB0aGlzLl9kb3RFbGVtZW50LnN0eWxlLmxlZnQgPSAnJyArIHggKyAncHgnO1xuICAgICAgdGhpcy5fZmlsbEVsZW1lbnQuc3R5bGUud2lkdGggPSAnJyArIHggKyAncHgnO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAndGVtcGxhdGUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHBhcnRpYWwgdGVtcGxhdGUgc3RyaW5nXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlclwiIGlkPVwiJysoKHR5cGVvZiBpdC5pZCA9PT0gXCJ1bmRlZmluZWRcIj8nJzppdC5pZCkpKydcIj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1taW51c1wiPiA8aW1nIHNyYz1cIicrKGl0LmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC9zbGlkZXIvbWludXMucG5nJykgKSsnXCIgLz4gPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zbGlkZXItc2xpZGVyXCI+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zbGlkZXItY29udGVudFwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtc2xpZGVyLWJhY2tncm91bmRcIj48L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1maWxsXCI+PC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1zbGlkZXItZG90XCI+PC9kaXY+IDwvZGl2PiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LXNsaWRlci1wbHVzXCI+IDxpbWcgc3JjPVwiJysoaXQuaGVscGVycy5hc3NldFBhdGgoJ3VpL25pZ2h0L3NsaWRlci9wbHVzLnBuZycpICkrJ1wiIC8+IDwvZGl2PjwvZGl2Pic7cmV0dXJuIG91dDtcbn07XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIFNpbXBsZVNsaWRlcjtcbn0pKF9zbGlkZXIyWydkZWZhdWx0J10pO1xuXG5leHBvcnRzWydkZWZhdWx0J10gPSBTaW1wbGVTbGlkZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL3NpbXBsZS1zbGlkZXIuanNcbiAqKiBtb2R1bGUgaWQgPSAxMDJcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8qIGdsb2JhbCBfX0RPVEpTX1RFTVBMQVRFLCBJbWFnZSAqL1xuLypcbiAqIFBob3RvIEVkaXRvciBTREsgLSBwaG90b2VkaXRvcnNkay5jb21cbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE1IDllbGVtZW50cyBHbWJIXG4gKlxuICogUmVsZWFzZWQgdW5kZXIgQXR0cmlidXRpb24tTm9uQ29tbWVyY2lhbCAzLjAgVW5wb3J0ZWRcbiAqIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC9cbiAqXG4gKiBGb3IgY29tbWVyY2lhbCB1c2UsIHBsZWFzZSBjb250YWN0IHVzIGF0IGNvbnRhY3RAOWVsZW1lbnRzLmNvbVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSAoZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKCd2YWx1ZScgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0pKCk7XG5cbnZhciBfZ2V0ID0gZnVuY3Rpb24gZ2V0KF94LCBfeDIsIF94MykgeyB2YXIgX2FnYWluID0gdHJ1ZTsgX2Z1bmN0aW9uOiB3aGlsZSAoX2FnYWluKSB7IHZhciBvYmplY3QgPSBfeCwgcHJvcGVydHkgPSBfeDIsIHJlY2VpdmVyID0gX3gzOyBkZXNjID0gcGFyZW50ID0gZ2V0dGVyID0gdW5kZWZpbmVkOyBfYWdhaW4gPSBmYWxzZTsgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpOyBpZiAoZGVzYyA9PT0gdW5kZWZpbmVkKSB7IHZhciBwYXJlbnQgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqZWN0KTsgaWYgKHBhcmVudCA9PT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGVsc2UgeyBfeCA9IHBhcmVudDsgX3gyID0gcHJvcGVydHk7IF94MyA9IHJlY2VpdmVyOyBfYWdhaW4gPSB0cnVlOyBjb250aW51ZSBfZnVuY3Rpb247IH0gfSBlbHNlIGlmICgndmFsdWUnIGluIGRlc2MpIHsgcmV0dXJuIGRlc2MudmFsdWU7IH0gZWxzZSB7IHZhciBnZXR0ZXIgPSBkZXNjLmdldDsgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gcmV0dXJuIGdldHRlci5jYWxsKHJlY2VpdmVyKTsgfSB9IH07XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7ICdkZWZhdWx0Jzogb2JqIH07IH1cblxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHsgcmV0dXJuIGFycjsgfSBlbHNlIGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGFycikpIHsgdmFyIF9hcnIgPSBbXTsgdmFyIF9uID0gdHJ1ZTsgdmFyIF9kID0gZmFsc2U7IHZhciBfZSA9IHVuZGVmaW5lZDsgdHJ5IHsgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkgeyBfYXJyLnB1c2goX3MudmFsdWUpOyBpZiAoaSAmJiBfYXJyLmxlbmd0aCA9PT0gaSkgYnJlYWs7IH0gfSBjYXRjaCAoZXJyKSB7IF9kID0gdHJ1ZTsgX2UgPSBlcnI7IH0gZmluYWxseSB7IHRyeSB7IGlmICghX24gJiYgX2lbJ3JldHVybiddKSBfaVsncmV0dXJuJ10oKTsgfSBmaW5hbGx5IHsgaWYgKF9kKSB0aHJvdyBfZTsgfSB9IHJldHVybiBfYXJyOyB9IGVsc2UgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlJyk7IH0gfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvbicpOyB9IH1cblxuZnVuY3Rpb24gX2luaGVyaXRzKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7IGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gJ2Z1bmN0aW9uJyAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoJ1N1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLCBub3QgJyArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgX2xpYkV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJy4uLy4uLy4uL2xpYi9ldmVudC1lbWl0dGVyJyk7XG5cbnZhciBfbGliRXZlbnRFbWl0dGVyMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2xpYkV2ZW50RW1pdHRlcik7XG5cbnZhciBfbGliVXRpbHMgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvdXRpbHMnKTtcblxudmFyIF9saWJVdGlsczIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJVdGlscyk7XG5cbnZhciBfbGliQ29sb3IgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvY29sb3InKTtcblxudmFyIF9saWJDb2xvcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9saWJDb2xvcik7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIgPSByZXF1aXJlKCcuLi8uLi8uLi9saWIvbWF0aC92ZWN0b3IyJyk7XG5cbnZhciBfbGliTWF0aFZlY3RvcjIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbGliTWF0aFZlY3RvcjIpO1xuXG52YXIgQ29sb3JQaWNrZXIgPSAoZnVuY3Rpb24gKF9FdmVudEVtaXR0ZXIpIHtcbiAgZnVuY3Rpb24gQ29sb3JQaWNrZXIodWksIGVsZW1lbnQpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ29sb3JQaWNrZXIpO1xuXG4gICAgX2dldChPYmplY3QuZ2V0UHJvdG90eXBlT2YoQ29sb3JQaWNrZXIucHJvdG90eXBlKSwgJ2NvbnN0cnVjdG9yJywgdGhpcykuY2FsbCh0aGlzKTtcblxuICAgIHRoaXMuX3VpID0gdWk7XG4gICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuX2xvYWRlZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5fb3ZlcmxheSA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNvbG9yLXBpY2tlci1vdmVybGF5Jyk7XG4gICAgdGhpcy5fY3VycmVudENvbG9yQ2FudmFzID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY29sb3ItcGlja2VyLWNvbG9yJyk7XG5cbiAgICB0aGlzLl9hbHBoYUNhbnZhcyA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignY2FudmFzLmltZ2x5a2l0LWNvbG9yLXBpY2tlci1hbHBoYScpO1xuICAgIHRoaXMuX2FscGhhS25vYiA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignLmltZ2x5a2l0LWNvbG9yLXBpY2tlci1hbHBoYS1jb250YWluZXIgLmltZ2x5a2l0LXRyYW5zcGFyZW50LWtub2InKTtcblxuICAgIHRoaXMuX2h1ZUNhbnZhcyA9IHRoaXMuX2VsZW1lbnQucXVlcnlTZWxlY3RvcignY2FudmFzLmltZ2x5a2l0LWNvbG9yLXBpY2tlci1odWUnKTtcbiAgICB0aGlzLl9odWVLbm9iID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY29sb3ItcGlja2VyLWh1ZS1jb250YWluZXIgLmltZ2x5a2l0LXRyYW5zcGFyZW50LWtub2InKTtcblxuICAgIHRoaXMuX3NhdHVyYXRpb25DYW52YXMgPSB0aGlzLl9lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ2NhbnZhcy5pbWdseWtpdC1jb2xvci1waWNrZXItc2F0dXJhdGlvbicpO1xuICAgIHRoaXMuX3NhdHVyYXRpb25Lbm9iID0gdGhpcy5fZWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuaW1nbHlraXQtY29sb3ItcGlja2VyLXNhdHVyYXRpb24tY29udGFpbmVyIC5pbWdseWtpdC10cmFuc3BhcmVudC1rbm9iJyk7XG5cbiAgICB0aGlzLl90cmFuc3BhcmVuY3lJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgIHRoaXMuX3RyYW5zcGFyZW5jeUltYWdlLnNyYyA9IHVpLmhlbHBlcnMuYXNzZXRQYXRoKCd1aS9uaWdodC90cmFuc3BhcmVuY3kucG5nJyk7XG4gICAgdGhpcy5fdHJhbnNwYXJlbmN5SW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHRoaXMuX29uVHJhbnNwYXJlbmN5SW1hZ2VMb2FkLmJpbmQodGhpcykpO1xuXG4gICAgdGhpcy5fb25BbHBoYUNhbnZhc0Rvd24gPSB0aGlzLl9vbkFscGhhQ2FudmFzRG93bi5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uQWxwaGFDYW52YXNEcmFnID0gdGhpcy5fb25BbHBoYUNhbnZhc0RyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkFscGhhQ2FudmFzVXAgPSB0aGlzLl9vbkFscGhhQ2FudmFzVXAuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkh1ZUNhbnZhc0Rvd24gPSB0aGlzLl9vbkh1ZUNhbnZhc0Rvd24uYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkh1ZUNhbnZhc0RyYWcgPSB0aGlzLl9vbkh1ZUNhbnZhc0RyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkh1ZUNhbnZhc1VwID0gdGhpcy5fb25IdWVDYW52YXNVcC5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzRG93biA9IHRoaXMuX29uU2F0dXJhdGlvbkNhbnZhc0Rvd24uYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNEcmFnID0gdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzRHJhZy5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uU2F0dXJhdGlvbkNhbnZhc1VwID0gdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzVXAuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX29uRWxlbWVudENsaWNrID0gdGhpcy5fb25FbGVtZW50Q2xpY2suYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX2hhbmRsZVRvZ2dsZSgpO1xuICAgIHRoaXMuX2hhbmRsZUFscGhhS25vYigpO1xuICAgIHRoaXMuX2hhbmRsZUh1ZUtub2IoKTtcbiAgICB0aGlzLl9oYW5kbGVTYXR1cmF0aW9uS25vYigpO1xuICB9XG5cbiAgX2luaGVyaXRzKENvbG9yUGlja2VyLCBfRXZlbnRFbWl0dGVyKTtcblxuICBfY3JlYXRlQ2xhc3MoQ29sb3JQaWNrZXIsIFt7XG4gICAga2V5OiAnX29uVHJhbnNwYXJlbmN5SW1hZ2VMb2FkJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uVHJhbnNwYXJlbmN5SW1hZ2VMb2FkKCkge1xuICAgICAgdGhpcy5fbG9hZGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3JlbmRlcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVUb2dnbGUnLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgdG9nZ2xpbmcgb2YgdGhlIG92ZXJsYXlcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlVG9nZ2xlKCkge1xuICAgICAgdGhpcy5fZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uRWxlbWVudENsaWNrKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25FbGVtZW50Q2xpY2snLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgZWxlbWVudCBoYXMgYmVlbiBjbGlja2VkXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkVsZW1lbnRDbGljayhlKSB7XG4gICAgICBpZiAoZS50YXJnZXQgPT09IHRoaXMuX2VsZW1lbnQgfHwgZS50YXJnZXQgPT09IHRoaXMuX2N1cnJlbnRDb2xvckNhbnZhcykge1xuICAgICAgICBpZiAodGhpcy5fdmlzaWJsZSkge1xuICAgICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICAgIHRoaXMuZW1pdCgnaGlkZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgIHRoaXMuZW1pdCgnc2hvdycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnaGlkZScsXG5cbiAgICAvKipcbiAgICAgKiBIaWRlcyB0aGUgY29sb3IgcGlja2VyXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICB0aGlzLl9vdmVybGF5LmNsYXNzTGlzdC5yZW1vdmUoJ2ltZ2x5a2l0LXZpc2libGUnKTtcbiAgICAgIHRoaXMuX3Zpc2libGUgPSBmYWxzZTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdzaG93JyxcblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBjb2xvciBwaWNrZXJcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgIHRoaXMuX292ZXJsYXkuY2xhc3NMaXN0LmFkZCgnaW1nbHlraXQtdmlzaWJsZScpO1xuICAgICAgdGhpcy5fdmlzaWJsZSA9IHRydWU7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnc2V0VmFsdWUnLFxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZ2l2ZW4gdmFsdWVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gc2V0VmFsdWUodmFsdWUpIHtcbiAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWUuY2xvbmUoKTtcblxuICAgICAgdmFyIF92YWx1ZSR0b0hTViA9IHRoaXMuX3ZhbHVlLnRvSFNWKCk7XG5cbiAgICAgIHZhciBfdmFsdWUkdG9IU1YyID0gX3NsaWNlZFRvQXJyYXkoX3ZhbHVlJHRvSFNWLCAzKTtcblxuICAgICAgdmFyIGggPSBfdmFsdWUkdG9IU1YyWzBdO1xuICAgICAgdmFyIHMgPSBfdmFsdWUkdG9IU1YyWzFdO1xuICAgICAgdmFyIHYgPSBfdmFsdWUkdG9IU1YyWzJdO1xuXG4gICAgICB0aGlzLl9oc3ZDb2xvciA9IHsgaDogaCwgczogcywgdjogdiB9O1xuICAgICAgdGhpcy5fcG9zaXRpb25Lbm9icygpO1xuICAgICAgdGhpcy5fcmVuZGVyKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3Bvc2l0aW9uS25vYnMnLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUga25vYiBwb3NpdGlvbnMgdG8gcmVwcmVzZW50IHRoZSBjdXJyZW50IEhTViBjb2xvclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9wb3NpdGlvbktub2JzKCkge1xuICAgICAgdGhpcy5fcG9zaXRpb25BbHBoYUtub2IoKTtcbiAgICAgIHRoaXMuX3Bvc2l0aW9uSHVlS25vYigpO1xuICAgICAgdGhpcy5fcG9zaXRpb25TYXR1cmF0aW9uS25vYigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19wb3NpdGlvbkFscGhhS25vYicsXG5cbiAgICAvKipcbiAgICAgKiBQb3NpdGlvbnMgdGhlIGFscGhhIGtub2IgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IGFscGhhIHZhbHVlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3Bvc2l0aW9uQWxwaGFLbm9iKCkge1xuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2FscGhhQ2FudmFzO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHZhciBsZWZ0ID0gdGhpcy5fdmFsdWUuYSAqIGNhbnZhc1NpemUueDtcbiAgICAgIHRoaXMuX2FscGhhS25vYi5zdHlsZS5sZWZ0ID0gJycgKyBsZWZ0ICsgJ3B4JztcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcG9zaXRpb25IdWVLbm9iJyxcblxuICAgIC8qKlxuICAgICAqIFBvc2l0aW9ucyB0aGUgaHVlIGtub2IgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IGh1ZSB2YWx1ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9wb3NpdGlvbkh1ZUtub2IoKSB7XG4gICAgICB2YXIgY2FudmFzID0gdGhpcy5faHVlQ2FudmFzO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHZhciB0b3AgPSB0aGlzLl9oc3ZDb2xvci5oICogY2FudmFzU2l6ZS55O1xuICAgICAgdGhpcy5faHVlS25vYi5zdHlsZS50b3AgPSAnJyArIHRvcCArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3Bvc2l0aW9uU2F0dXJhdGlvbktub2InLFxuXG4gICAgLyoqXG4gICAgICogUG9zaXRpb25zIHRoZSBzYXR1cmF0aW9uIGtub2IgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IHNhdHVyYXRpb24gdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcG9zaXRpb25TYXR1cmF0aW9uS25vYigpIHtcbiAgICAgIHZhciBjYW52YXMgPSB0aGlzLl9zYXR1cmF0aW9uQ2FudmFzO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHZhciBsZWZ0ID0gdGhpcy5faHN2Q29sb3IucyAqIGNhbnZhc1NpemUueDtcbiAgICAgIHRoaXMuX3NhdHVyYXRpb25Lbm9iLnN0eWxlLmxlZnQgPSAnJyArIGxlZnQgKyAncHgnO1xuICAgICAgdmFyIHRvcCA9ICgxIC0gdGhpcy5faHN2Q29sb3IudikgKiBjYW52YXNTaXplLnk7XG4gICAgICB0aGlzLl9zYXR1cmF0aW9uS25vYi5zdHlsZS50b3AgPSAnJyArIHRvcCArICdweCc7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlcicsXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIGFuZCByZW5kZXJzIGFsbCBjb250cm9scyB0byByZXByZXNlbnQgdGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyKCkge1xuICAgICAgaWYgKCF0aGlzLl9sb2FkZWQpIHJldHVybjtcbiAgICAgIHRoaXMuX3JlbmRlckN1cnJlbnRDb2xvcigpO1xuICAgICAgdGhpcy5fcmVuZGVyQWxwaGEoKTtcbiAgICAgIHRoaXMuX3JlbmRlckh1ZSgpO1xuICAgICAgdGhpcy5fcmVuZGVyU2F0dXJhdGlvbigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDdXJyZW50Q29sb3InLFxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGNvbG9yIG9uIHRoZSBjb250cm9scyBjYW52YXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfcmVuZGVyQ3VycmVudENvbG9yKCkge1xuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2N1cnJlbnRDb2xvckNhbnZhcztcbiAgICAgIHZhciBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIHZhciBwYXR0ZXJuID0gY29udGV4dC5jcmVhdGVQYXR0ZXJuKHRoaXMuX3RyYW5zcGFyZW5jeUltYWdlLCAncmVwZWF0Jyk7XG4gICAgICBjb250ZXh0LnJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gcGF0dGVybjtcbiAgICAgIGNvbnRleHQuZmlsbCgpO1xuXG4gICAgICBjb250ZXh0LmZpbGxTdHlsZSA9IHRoaXMuX3ZhbHVlLnRvUkdCQSgpO1xuICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckFscGhhJyxcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHRyYW5zcGFyZW5jeSBjYW52YXMgd2l0aCB0aGUgY3VycmVudCBjb2xvclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJBbHBoYSgpIHtcbiAgICAgIHZhciBjYW52YXMgPSB0aGlzLl9hbHBoYUNhbnZhcztcbiAgICAgIHZhciBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAgIHZhciBwYXR0ZXJuID0gY29udGV4dC5jcmVhdGVQYXR0ZXJuKHRoaXMuX3RyYW5zcGFyZW5jeUltYWdlLCAncmVwZWF0Jyk7XG4gICAgICBjb250ZXh0LnJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gcGF0dGVybjtcbiAgICAgIGNvbnRleHQuZmlsbCgpO1xuXG4gICAgICB2YXIgZ3JhZGllbnQgPSBjb250ZXh0LmNyZWF0ZUxpbmVhckdyYWRpZW50KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cbiAgICAgIHZhciBjb2xvciA9IHRoaXMuX3ZhbHVlLmNsb25lKCk7XG4gICAgICBjb2xvci5hID0gMDtcbiAgICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgwLCBjb2xvci50b1JHQkEoKSk7XG4gICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMSwgdGhpcy5fdmFsdWUudG9IZXgoKSk7XG4gICAgICBjb250ZXh0LmZpbGxTdHlsZSA9IGdyYWRpZW50O1xuICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX3JlbmRlckh1ZScsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBodWUgY2FudmFzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX3JlbmRlckh1ZSgpIHtcbiAgICAgIHZhciBjYW52YXMgPSB0aGlzLl9odWVDYW52YXM7XG4gICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICB2YXIgY29sb3IgPSBuZXcgX2xpYkNvbG9yMlsnZGVmYXVsdCddKCk7XG4gICAgICBmb3IgKHZhciB5ID0gMDsgeSA8IGNhbnZhcy5oZWlnaHQ7IHkrKykge1xuICAgICAgICB2YXIgcmF0aW8gPSB5IC8gY2FudmFzLmhlaWdodDtcbiAgICAgICAgY29sb3IuZnJvbUhTVihyYXRpbywgMSwgMSk7XG5cbiAgICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9IGNvbG9yLnRvUkdCQSgpO1xuICAgICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgICAgICBjb250ZXh0Lm1vdmVUbygwLCB5KTtcbiAgICAgICAgY29udGV4dC5saW5lVG8oY2FudmFzLndpZHRoLCB5KTtcbiAgICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfcmVuZGVyU2F0dXJhdGlvbicsXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBzYXR1cmF0aW9uIGNhbnZhc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJTYXR1cmF0aW9uKCkge1xuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX3NhdHVyYXRpb25DYW52YXM7XG4gICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICB2YXIgaW1hZ2VEYXRhID0gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgdmFyIGNvbG9yID0gbmV3IF9saWJDb2xvcjJbJ2RlZmF1bHQnXSgxLCAwLCAwLCAxKTtcbiAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgY2FudmFzLmhlaWdodDsgeSsrKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IChjYW52YXMuaGVpZ2h0IC0geSkgLyBjYW52YXMuaGVpZ2h0O1xuICAgICAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGNhbnZhcy53aWR0aDsgeCsrKSB7XG4gICAgICAgICAgdmFyIHNhdHVyYXRpb24gPSB4IC8gY2FudmFzLndpZHRoO1xuICAgICAgICAgIGNvbG9yLmZyb21IU1YodGhpcy5faHN2Q29sb3IuaCwgc2F0dXJhdGlvbiwgdmFsdWUpO1xuICAgICAgICAgIHZhciByID0gY29sb3IucjtcbiAgICAgICAgICB2YXIgZyA9IGNvbG9yLmc7XG4gICAgICAgICAgdmFyIGIgPSBjb2xvci5iO1xuICAgICAgICAgIHZhciBhID0gY29sb3IuYTtcblxuICAgICAgICAgIHZhciBpbmRleCA9ICh5ICogY2FudmFzLndpZHRoICsgeCkgKiA0O1xuXG4gICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXhdID0gciAqIDI1NTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdID0gZyAqIDI1NTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gYiAqIDI1NTtcbiAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDNdID0gYSAqIDI1NTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVBbHBoYUtub2InLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgZHJhZ2dpbmcgb2YgdGhlIGFscGhhIGtub2JcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfaGFuZGxlQWxwaGFLbm9iKCkge1xuICAgICAgdGhpcy5fYWxwaGFDYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25BbHBoYUNhbnZhc0Rvd24pO1xuICAgICAgdGhpcy5fYWxwaGFDYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uQWxwaGFDYW52YXNEb3duKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25BbHBoYUNhbnZhc0Rvd24nLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgdGhlIGFscGhhIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQWxwaGFDYW52YXNEb3duKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdGhpcy5fb25BbHBoYUNhbnZhc0RyYWcoZSk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uQWxwaGFDYW52YXNEcmFnKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uQWxwaGFDYW52YXNEcmFnKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uQWxwaGFDYW52YXNVcCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uQWxwaGFDYW52YXNVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQWxwaGFDYW52YXNEcmFnJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgdGhlIGFscGhhIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uQWxwaGFDYW52YXNEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIHJlbGF0aXZlIG1vdXNlIHBvc2l0aW9uIG9uIGNhbnZhc1xuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2FscGhhQ2FudmFzO1xuICAgICAgdmFyIGNhbnZhc1NpemUgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICB2YXIgbW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuXG4gICAgICB2YXIgX2NhbnZhcyRnZXRCb3VuZGluZ0NsaWVudFJlY3QgPSBjYW52YXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgIHZhciBsZWZ0ID0gX2NhbnZhcyRnZXRCb3VuZGluZ0NsaWVudFJlY3QubGVmdDtcbiAgICAgIHZhciB0b3AgPSBfY2FudmFzJGdldEJvdW5kaW5nQ2xpZW50UmVjdC50b3A7XG5cbiAgICAgIHZhciBvZmZzZXQgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGxlZnQsIHRvcCk7XG4gICAgICB2YXIgcmVsYXRpdmVQb3NpdGlvbiA9IG1vdXNlUG9zaXRpb24uc3VidHJhY3Qob2Zmc2V0KTtcbiAgICAgIHJlbGF0aXZlUG9zaXRpb24uY2xhbXAobmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKSwgY2FudmFzU2l6ZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBrbm9iIGNzcyBwb3NpdGlvbmluZ1xuICAgICAgdGhpcy5fYWxwaGFLbm9iLnN0eWxlLmxlZnQgPSAnJyArIHJlbGF0aXZlUG9zaXRpb24ueCArICdweCc7XG5cbiAgICAgIC8vIFVwZGF0ZSBhbHBoYSB2YWx1ZVxuICAgICAgdGhpcy5fdmFsdWUuYSA9IHJlbGF0aXZlUG9zaXRpb24ueCAvIGNhbnZhc1NpemUueDtcbiAgICAgIHRoaXMuX3VwZGF0ZUNvbG9yKCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uQWxwaGFDYW52YXNVcCcsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIHRoZSBhbHBoYSBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vbkFscGhhQ2FudmFzVXAoKSB7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkFscGhhQ2FudmFzRHJhZyk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLl9vbkFscGhhQ2FudmFzRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkFscGhhQ2FudmFzVXApO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbkFscGhhQ2FudmFzVXApO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19oYW5kbGVIdWVLbm9iJyxcblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgdGhlIGRyYWdnaW5nIG9mIHRoZSBodWUga25vYlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVIdWVLbm9iKCkge1xuICAgICAgdGhpcy5faHVlQ2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMuX29uSHVlQ2FudmFzRG93bik7XG4gICAgICB0aGlzLl9odWVDYW52YXMuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMuX29uSHVlQ2FudmFzRG93bik7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uSHVlQ2FudmFzRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0aGUgY2FudmFzIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uSHVlQ2FudmFzRG93bihlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHRoaXMuX29uSHVlQ2FudmFzRHJhZyhlKTtcblxuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5fb25IdWVDYW52YXNEcmFnKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uSHVlQ2FudmFzRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vbkh1ZUNhbnZhc1VwKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5fb25IdWVDYW52YXNVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uSHVlQ2FudmFzRHJhZycsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGRyYWdzIHRoZSBodWUga25vYlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHZhbHVlOiBmdW5jdGlvbiBfb25IdWVDYW52YXNEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2h1ZUNhbnZhcztcbiAgICAgIHZhciBjYW52YXNTaXplID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgcmVsYXRpdmUgbW91c2UgcG9zaXRpb24gb24gY2FudmFzXG4gICAgICB2YXIgbW91c2VQb3NpdGlvbiA9IF9saWJVdGlsczJbJ2RlZmF1bHQnXS5nZXRFdmVudFBvc2l0aW9uKGUpO1xuXG4gICAgICB2YXIgX2NhbnZhcyRnZXRCb3VuZGluZ0NsaWVudFJlY3QyID0gY2FudmFzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICB2YXIgbGVmdCA9IF9jYW52YXMkZ2V0Qm91bmRpbmdDbGllbnRSZWN0Mi5sZWZ0O1xuICAgICAgdmFyIHRvcCA9IF9jYW52YXMkZ2V0Qm91bmRpbmdDbGllbnRSZWN0Mi50b3A7XG5cbiAgICAgIHZhciBvZmZzZXQgPSBuZXcgX2xpYk1hdGhWZWN0b3IyMlsnZGVmYXVsdCddKGxlZnQsIHRvcCk7XG4gICAgICB2YXIgcmVsYXRpdmVQb3NpdGlvbiA9IG1vdXNlUG9zaXRpb24uc3VidHJhY3Qob2Zmc2V0KTtcbiAgICAgIHJlbGF0aXZlUG9zaXRpb24uY2xhbXAobmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXSgwLCAwKSwgY2FudmFzU2l6ZSk7XG5cbiAgICAgIC8vIFVwZGF0ZSBzYXR1cmFpdG9uIGtub2IgY3NzIHBvc2l0aW9uaW5nXG4gICAgICB0aGlzLl9odWVLbm9iLnN0eWxlLnRvcCA9ICcnICsgcmVsYXRpdmVQb3NpdGlvbi55ICsgJ3B4JztcblxuICAgICAgLy8gVXBkYXRlIHNhdHVyYXRpb24gYW5kIHZhbHVlXG4gICAgICByZWxhdGl2ZVBvc2l0aW9uLmRpdmlkZShjYW52YXNTaXplKTtcbiAgICAgIHRoaXMuX2hzdkNvbG9yLmggPSByZWxhdGl2ZVBvc2l0aW9uLnk7XG4gICAgICB0aGlzLl91cGRhdGVDb2xvcigpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19vbkh1ZUNhbnZhc1VwJyxcblxuICAgIC8qKlxuICAgICAqIEdldHMgY2FsbGVkIHdoZW4gdGhlIHVzZXIgc3RvcHMgZHJhZ2dpbmcgdGhlIGFscGhhIGtub2JcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uSHVlQ2FudmFzVXAoKSB7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vbkh1ZUNhbnZhc0RyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25IdWVDYW52YXNEcmFnKTtcblxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMuX29uSHVlQ2FudmFzVXApO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vbkh1ZUNhbnZhc1VwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfaGFuZGxlU2F0dXJhdGlvbktub2InLFxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgZHJhZ2dpbmcgb2YgdGhlIHNhdHVyYXRpb24ga25vYlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9oYW5kbGVTYXR1cmF0aW9uS25vYigpIHtcbiAgICAgIHRoaXMuX3NhdHVyYXRpb25DYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzRG93bik7XG4gICAgICB0aGlzLl9zYXR1cmF0aW9uQ2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNEb3duKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25TYXR1cmF0aW9uQ2FudmFzRG93bicsXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0aGUgc2F0dXJhdGlvbiBjYW52YXNcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YWx1ZTogZnVuY3Rpb24gX29uU2F0dXJhdGlvbkNhbnZhc0Rvd24oZSkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNEcmFnKGUpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNEcmFnKTtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHRoaXMuX29uU2F0dXJhdGlvbkNhbnZhc0RyYWcpO1xuXG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzVXApO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNVcCk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX29uU2F0dXJhdGlvbkNhbnZhc0RyYWcnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgc2F0dXJhdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNhdHVyYXRpb25DYW52YXNEcmFnKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX3NhdHVyYXRpb25DYW52YXM7XG4gICAgICB2YXIgY2FudmFzU2l6ZSA9IG5ldyBfbGliTWF0aFZlY3RvcjIyWydkZWZhdWx0J10oY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIHJlbGF0aXZlIG1vdXNlIHBvc2l0aW9uIG9uIGNhbnZhc1xuICAgICAgdmFyIG1vdXNlUG9zaXRpb24gPSBfbGliVXRpbHMyWydkZWZhdWx0J10uZ2V0RXZlbnRQb3NpdGlvbihlKTtcblxuICAgICAgdmFyIF9jYW52YXMkZ2V0Qm91bmRpbmdDbGllbnRSZWN0MyA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgdmFyIGxlZnQgPSBfY2FudmFzJGdldEJvdW5kaW5nQ2xpZW50UmVjdDMubGVmdDtcbiAgICAgIHZhciB0b3AgPSBfY2FudmFzJGdldEJvdW5kaW5nQ2xpZW50UmVjdDMudG9wO1xuXG4gICAgICB2YXIgb2Zmc2V0ID0gbmV3IF9saWJNYXRoVmVjdG9yMjJbJ2RlZmF1bHQnXShsZWZ0LCB0b3ApO1xuICAgICAgdmFyIHJlbGF0aXZlUG9zaXRpb24gPSBtb3VzZVBvc2l0aW9uLnN1YnRyYWN0KG9mZnNldCk7XG4gICAgICByZWxhdGl2ZVBvc2l0aW9uLmNsYW1wKDAsIGNhbnZhcy53aWR0aCk7XG5cbiAgICAgIC8vIFVwZGF0ZSBzYXR1cmFpdG9uIGtub2IgY3NzIHBvc2l0aW9uaW5nXG4gICAgICB0aGlzLl9zYXR1cmF0aW9uS25vYi5zdHlsZS5sZWZ0ID0gJycgKyByZWxhdGl2ZVBvc2l0aW9uLnggKyAncHgnO1xuICAgICAgdGhpcy5fc2F0dXJhdGlvbktub2Iuc3R5bGUudG9wID0gJycgKyByZWxhdGl2ZVBvc2l0aW9uLnkgKyAncHgnO1xuXG4gICAgICAvLyBVcGRhdGUgc2F0dXJhdGlvbiBhbmQgdmFsdWVcbiAgICAgIHJlbGF0aXZlUG9zaXRpb24uZGl2aWRlKGNhbnZhc1NpemUpO1xuICAgICAgdGhpcy5faHN2Q29sb3IucyA9IHJlbGF0aXZlUG9zaXRpb24ueDtcbiAgICAgIHRoaXMuX2hzdkNvbG9yLnYgPSAxIC0gcmVsYXRpdmVQb3NpdGlvbi55O1xuICAgICAgdGhpcy5fdXBkYXRlQ29sb3IoKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfb25TYXR1cmF0aW9uQ2FudmFzVXAnLFxuXG4gICAgLyoqXG4gICAgICogR2V0cyBjYWxsZWQgd2hlbiB0aGUgdXNlciBzdG9wcyBkcmFnZ2luZyB0aGUgc2F0dXJhdGlvbiBrbm9iXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9vblNhdHVyYXRpb25DYW52YXNVcCgpIHtcbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuX29uU2F0dXJhdGlvbkNhbnZhc0RyYWcpO1xuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5fb25TYXR1cmF0aW9uQ2FudmFzRHJhZyk7XG5cbiAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9vblNhdHVyYXRpb25DYW52YXNVcCk7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIHRoaXMuX29uU2F0dXJhdGlvbkNhbnZhc1VwKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfdXBkYXRlQ29sb3InLFxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgYXR0YWNoZWQgY29sb3IsIGVtaXRzIHRoZSBgdXBkYXRlYCBldmVudCBhbmQgdHJpZ2dlcnNcbiAgICAgKiBhIHJlbmRlclxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF91cGRhdGVDb2xvcigpIHtcbiAgICAgIHRoaXMuX3ZhbHVlLmZyb21IU1YodGhpcy5faHN2Q29sb3IuaCwgdGhpcy5faHN2Q29sb3IucywgdGhpcy5faHN2Q29sb3Iudik7XG4gICAgICB0aGlzLmVtaXQoJ3VwZGF0ZScsIHRoaXMuX3ZhbHVlKTtcbiAgICAgIHRoaXMuX3JlbmRlcigpO1xuICAgIH1cbiAgfV0sIFt7XG4gICAga2V5OiAndGVtcGxhdGUnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHBhcnRpYWwgdGVtcGxhdGUgc3RyaW5nXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihpdFxuLyoqLykge1xudmFyIG91dD0nPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbG9yLXBpY2tlclwiIGlkPVwiJysoKHR5cGVvZiBpdC5pZCA9PT0gXCJ1bmRlZmluZWRcIj8nJzppdC5pZCkpKydcIj4gPGNhbnZhcyBjbGFzcz1cImltZ2x5a2l0LWNvbG9yLXBpY2tlci1jb2xvclwiIHdpZHRoPVwiMzRcIiBoZWlnaHQ9XCIzNFwiPjwvY2FudmFzPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY29udHJvbHMtaXRlbS1sYWJlbFwiPicrKCh0eXBlb2YgaXQubGFiZWwgPT09IFwidW5kZWZpbmVkXCI/Jyc6aXQubGFiZWwpKSsnPC9kaXY+IDxkaXYgY2xhc3M9XCJpbWdseWtpdC1jb2xvci1waWNrZXItb3ZlcmxheVwiPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtY29sb3ItcGlja2VyLWFscGhhLWNvbnRhaW5lclwiPiA8Y2FudmFzIGNsYXNzPVwiaW1nbHlraXQtY29sb3ItcGlja2VyLWFscGhhXCIgd2lkdGg9XCIyMDBcIiBoZWlnaHQ9XCIzMFwiPjwvY2FudmFzPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtdHJhbnNwYXJlbnQta25vYlwiPjwvZGl2PiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbG9yLXBpY2tlci1zYXR1cmF0aW9uLWNvbnRhaW5lclwiPiA8Y2FudmFzIGNsYXNzPVwiaW1nbHlraXQtY29sb3ItcGlja2VyLXNhdHVyYXRpb25cIiB3aWR0aD1cIjE2MFwiIGhlaWdodD1cIjE2MFwiPjwvY2FudmFzPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtdHJhbnNwYXJlbnQta25vYlwiPjwvZGl2PiA8L2Rpdj4gPGRpdiBjbGFzcz1cImltZ2x5a2l0LWNvbG9yLXBpY2tlci1odWUtY29udGFpbmVyXCI+IDxjYW52YXMgY2xhc3M9XCJpbWdseWtpdC1jb2xvci1waWNrZXItaHVlXCIgd2lkdGg9XCIzMFwiIGhlaWdodD1cIjE2MFwiPjwvY2FudmFzPiA8ZGl2IGNsYXNzPVwiaW1nbHlraXQtdHJhbnNwYXJlbnQta25vYlwiPjwvZGl2PiA8L2Rpdj4gPC9kaXY+PC9kaXY+JztyZXR1cm4gb3V0O1xufTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gQ29sb3JQaWNrZXI7XG59KShfbGliRXZlbnRFbWl0dGVyMlsnZGVmYXVsdCddKTtcblxuZXhwb3J0c1snZGVmYXVsdCddID0gQ29sb3JQaWNrZXI7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vdWkvbmlnaHQvbGliL2NvbG9yLXBpY2tlci5qc1xuICoqIG1vZHVsZSBpZCA9IDEwM1xuICoqIG1vZHVsZSBjaHVua3MgPSAwXG4gKiovIiwidmFyIG5leHRUaWNrID0gcmVxdWlyZSgncHJvY2Vzcy9icm93c2VyLmpzJykubmV4dFRpY2s7XG52YXIgYXBwbHkgPSBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHk7XG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG52YXIgaW1tZWRpYXRlSWRzID0ge307XG52YXIgbmV4dEltbWVkaWF0ZUlkID0gMDtcblxuLy8gRE9NIEFQSXMsIGZvciBjb21wbGV0ZW5lc3NcblxuZXhwb3J0cy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldFRpbWVvdXQsIHdpbmRvdywgYXJndW1lbnRzKSwgY2xlYXJUaW1lb3V0KTtcbn07XG5leHBvcnRzLnNldEludGVydmFsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldEludGVydmFsLCB3aW5kb3csIGFyZ3VtZW50cyksIGNsZWFySW50ZXJ2YWwpO1xufTtcbmV4cG9ydHMuY2xlYXJUaW1lb3V0ID1cbmV4cG9ydHMuY2xlYXJJbnRlcnZhbCA9IGZ1bmN0aW9uKHRpbWVvdXQpIHsgdGltZW91dC5jbG9zZSgpOyB9O1xuXG5mdW5jdGlvbiBUaW1lb3V0KGlkLCBjbGVhckZuKSB7XG4gIHRoaXMuX2lkID0gaWQ7XG4gIHRoaXMuX2NsZWFyRm4gPSBjbGVhckZuO1xufVxuVGltZW91dC5wcm90b3R5cGUudW5yZWYgPSBUaW1lb3V0LnByb3RvdHlwZS5yZWYgPSBmdW5jdGlvbigpIHt9O1xuVGltZW91dC5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fY2xlYXJGbi5jYWxsKHdpbmRvdywgdGhpcy5faWQpO1xufTtcblxuLy8gRG9lcyBub3Qgc3RhcnQgdGhlIHRpbWUsIGp1c3Qgc2V0cyB1cCB0aGUgbWVtYmVycyBuZWVkZWQuXG5leHBvcnRzLmVucm9sbCA9IGZ1bmN0aW9uKGl0ZW0sIG1zZWNzKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcbiAgaXRlbS5faWRsZVRpbWVvdXQgPSBtc2Vjcztcbn07XG5cbmV4cG9ydHMudW5lbnJvbGwgPSBmdW5jdGlvbihpdGVtKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcbiAgaXRlbS5faWRsZVRpbWVvdXQgPSAtMTtcbn07XG5cbmV4cG9ydHMuX3VucmVmQWN0aXZlID0gZXhwb3J0cy5hY3RpdmUgPSBmdW5jdGlvbihpdGVtKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcblxuICB2YXIgbXNlY3MgPSBpdGVtLl9pZGxlVGltZW91dDtcbiAgaWYgKG1zZWNzID49IDApIHtcbiAgICBpdGVtLl9pZGxlVGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiBvblRpbWVvdXQoKSB7XG4gICAgICBpZiAoaXRlbS5fb25UaW1lb3V0KVxuICAgICAgICBpdGVtLl9vblRpbWVvdXQoKTtcbiAgICB9LCBtc2Vjcyk7XG4gIH1cbn07XG5cbi8vIFRoYXQncyBub3QgaG93IG5vZGUuanMgaW1wbGVtZW50cyBpdCBidXQgdGhlIGV4cG9zZWQgYXBpIGlzIHRoZSBzYW1lLlxuZXhwb3J0cy5zZXRJbW1lZGlhdGUgPSB0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSBcImZ1bmN0aW9uXCIgPyBzZXRJbW1lZGlhdGUgOiBmdW5jdGlvbihmbikge1xuICB2YXIgaWQgPSBuZXh0SW1tZWRpYXRlSWQrKztcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGZhbHNlIDogc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXG4gIGltbWVkaWF0ZUlkc1tpZF0gPSB0cnVlO1xuXG4gIG5leHRUaWNrKGZ1bmN0aW9uIG9uTmV4dFRpY2soKSB7XG4gICAgaWYgKGltbWVkaWF0ZUlkc1tpZF0pIHtcbiAgICAgIC8vIGZuLmNhbGwoKSBpcyBmYXN0ZXIgc28gd2Ugb3B0aW1pemUgZm9yIHRoZSBjb21tb24gdXNlLWNhc2VcbiAgICAgIC8vIEBzZWUgaHR0cDovL2pzcGVyZi5jb20vY2FsbC1hcHBseS1zZWd1XG4gICAgICBpZiAoYXJncykge1xuICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZuLmNhbGwobnVsbCk7XG4gICAgICB9XG4gICAgICAvLyBQcmV2ZW50IGlkcyBmcm9tIGxlYWtpbmdcbiAgICAgIGV4cG9ydHMuY2xlYXJJbW1lZGlhdGUoaWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGlkO1xufTtcblxuZXhwb3J0cy5jbGVhckltbWVkaWF0ZSA9IHR5cGVvZiBjbGVhckltbWVkaWF0ZSA9PT0gXCJmdW5jdGlvblwiID8gY2xlYXJJbW1lZGlhdGUgOiBmdW5jdGlvbihpZCkge1xuICBkZWxldGUgaW1tZWRpYXRlSWRzW2lkXTtcbn07XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAod2VicGFjaykvfi9ub2RlLWxpYnMtYnJvd3Nlci9+L3RpbWVycy1icm93c2VyaWZ5L21haW4uanNcbiAqKiBtb2R1bGUgaWQgPSAxMDRcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKTtcbiAgICAgICAgfVxuICAgICAgICBxdWV1ZUluZGV4ID0gLTE7XG4gICAgICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB9XG4gICAgY3VycmVudFF1ZXVlID0gbnVsbDtcbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbn1cblxucHJvY2Vzcy5uZXh0VGljayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBxdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1biwgYXJncykpO1xuICAgIGlmIChxdWV1ZS5sZW5ndGggPT09IDEgJiYgIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxuLy8gdjggbGlrZXMgcHJlZGljdGlibGUgb2JqZWN0c1xuZnVuY3Rpb24gSXRlbShmdW4sIGFycmF5KSB7XG4gICAgdGhpcy5mdW4gPSBmdW47XG4gICAgdGhpcy5hcnJheSA9IGFycmF5O1xufVxuSXRlbS5wcm90b3R5cGUucnVuID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZnVuLmFwcGx5KG51bGwsIHRoaXMuYXJyYXkpO1xufTtcbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xucHJvY2Vzcy52ZXJzaW9uID0gJyc7IC8vIGVtcHR5IHN0cmluZyB0byBhdm9pZCByZWdleHAgaXNzdWVzXG5wcm9jZXNzLnZlcnNpb25zID0ge307XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5wcm9jZXNzLm9uID0gbm9vcDtcbnByb2Nlc3MuYWRkTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5vbmNlID0gbm9vcDtcbnByb2Nlc3Mub2ZmID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBub29wO1xucHJvY2Vzcy5lbWl0ID0gbm9vcDtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuXG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAod2VicGFjaykvfi9ub2RlLWxpYnMtYnJvd3Nlci9+L3RpbWVycy1icm93c2VyaWZ5L34vcHJvY2Vzcy9icm93c2VyLmpzXG4gKiogbW9kdWxlIGlkID0gMTA1XG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iXSwic291cmNlUm9vdCI6IiJ9