diff --git a/openvidu-internet-explorer/LICENSE b/openvidu-internet-explorer/LICENSE deleted file mode 100644 index 8dada3ed..00000000 --- a/openvidu-internet-explorer/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/openvidu-internet-explorer/README.md b/openvidu-internet-explorer/README.md deleted file mode 100644 index 047eb343..00000000 --- a/openvidu-internet-explorer/README.md +++ /dev/null @@ -1,48 +0,0 @@ -[![License badge](https://img.shields.io/badge/license-Apache2-orange.svg)](http://www.apache.org/licenses/LICENSE-2.0) -[![OpenVidu Tests](https://github.com/OpenVidu/openvidu/actions/workflows/openvidu-ce-test.yml/badge.svg)](https://github.com/OpenVidu/openvidu/actions/workflows/openvidu-ce-test.yml) -[![Documentation Status](https://readthedocs.org/projects/openvidu/badge/?version=stable)](https://docs.openvidu.io/en/stable/?badge=stable) -[![Docker badge](https://img.shields.io/docker/pulls/openvidu/openvidu-server-kms.svg)](https://hub.docker.com/r/openvidu/openvidu-server-kms) -[![Support badge](https://img.shields.io/badge/support-sof-yellowgreen.svg)](https://openvidu.discourse.group/) - -[![][OpenViduLogo]](http://openvidu.io) - -openvidu-internet-explorer -=== - -> IE support is a paid feature. Please, contact OpenVidu team through https://openvidu.io/commercial if you are interested - -This is an adaptation of [openvidu-js](https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-js) application with all necessary changes to work fine on IE 11. - - - -OpenVidu Team has been able to bring complete, standards-compliant WebRTC funcionality to Microsoft Internet Explorer desktop browser (v 11). This feature has been released thanks to [Temasys WebRTC Plugin](https://temasys.io/products/plugin/). - -To use this tutorial you should follow the next steps: - -1) Clone the repo -```bash -git clone https://github.com/OpenVidu/openvidu-tutorials.git -``` - -2) You will need an http web server installed in your development computer to execute the tutorial. If you have node.js installed, you can use [http-server](https://github.com/indexzero/http-server) to serve application files. It can be installed with: -```bash -sudo npm install -g http-server -``` -3) Run openvidu-server as it says [here](https://docs.openvidu.io/en/stable/troubleshooting/#3-i-am-using-windows-to-run-the-tutorials-develop-my-app-anything-i-should-know) - -4) Start the tutorial -```bash -http-server openvidu-tutorials/openvidu-internet-explorer/web -``` - -5) Go to `localhost:8080` to test the app once the server is running. The first time you use the docker container, an alert message will suggest you accept the self-signed certificate of openvidu-server when you first try to join a video-call. -If you have problems accepting the certificate you can connect through `127.0.0.1` instead of `localhost`. - -First time you use this application **openvidu-internet-explorer** with Internet Explorer, openvidu-browser will present an alert which will allow you to install the Temasys WebTTC plugin. Once the plugin has been installed, your browser is ready to work with OpenVidu. - -Internet Explorer (IE) is a highly restrictive browser so we have had several stones on the way. One of these stones has been to get access to client's media devices. **IE does not allow to access our webcam more than once**, so you won't be able to test the app between two different IE tabs. And, of course, you cannot access the same camera with two different browsers. - -Another restriction is the ECMAScript version. IE does not fully support a ECMAScript version upper than 5 so this tutorial has been developed with ECMAScript 5. This means that JavaScript code won't have promises and other modern JavaScript features. - - -[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120 diff --git a/openvidu-internet-explorer/web/app.js b/openvidu-internet-explorer/web/app.js deleted file mode 100644 index eead4318..00000000 --- a/openvidu-internet-explorer/web/app.js +++ /dev/null @@ -1,263 +0,0 @@ -var OV; -var session; -var isIE = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0; -var isFirstVideoCreatedByPublisher = true; - - -/* OPENVIDU METHODS */ - -function joinSession() { - - var mySessionId = document.getElementById("sessionId").value; - var myUserName = document.getElementById("userName").value; - - // --- 1) Get an OpenVidu object --- - - OV = new OpenVidu(); - - // --- 2) Init a session --- - - session = OV.initSession(); - - // --- 3) Specify the actions when events take place in the session --- - - // On every new Stream received... - session.on('streamCreated', function (event) { - - // Subscribe to the Stream to receive it. HTML video will be appended to element with 'video-container' id - var subscriber = session.subscribe(event.stream, 'video-container'); - - // When the HTML video has been appended to DOM... - subscriber.on('videoElementCreated', function (event) { - - // Add a new

element for the user's nickname just below its video - appendUserData(subscriber, event.element, subscriber.stream.connection); - }); - }); - - // On every Stream destroyed... - session.on('streamDestroyed', function (event) { - - // Delete the HTML element with the user's nickname. HTML videos are automatically removed from DOM - removeUserData(event.stream.connection); - }); - - - // --- 4) Connect to the session with a valid user token --- - - // Get a token from the OpenVidu deployment - getToken(mySessionId).then(function (token) { - - // First param is the token got from the OpenVidu deployment. Second param can be retrieved by every user on event - // 'streamCreated' (property Stream.connection.data), and will be appended to DOM as the user's nickname - session.connect(token, { clientData: myUserName }) - .then(function () { - - // --- 5) Set page layout for active call --- - - document.getElementById('session-title').innerText = mySessionId; - document.getElementById('join').style.display = 'none'; - document.getElementById('session').style.display = 'block'; - - // --- 6) Get your own camera stream with the desired properties --- - - var publisher = OV.initPublisher('video-container', { - audioSource: undefined, // The source of audio. If undefined default microphone - videoSource: undefined, // The source of video. If undefined default webcam - publishAudio: true, // Whether you want to start publishing with your audio unmuted or not - publishVideo: true, // Whether you want to start publishing with your video enabled or not - resolution: '640x480', // The resolution of your video - frameRate: 30, // The frame rate of your video - insertMode: 'APPEND', // How the video is inserted in the target element 'video-container' - mirror: false // Whether to mirror your local video or not - }); - - // --- 7) Specify the actions when events take place in our publisher --- - - // When our HTML video has been added to DOM... - publisher.on('videoElementCreated', function (event) { - if (isFirstVideoCreatedByPublisher) { - // Calling StreamManger.addVideoElement inside initMainVideo method will - // trigger a new videoElementCreated event in IExplorer. We must ignore it the second - // time to avoid an infinite recursive call to this same event handler - isFirstVideoCreatedByPublisher = false; - initMainVideo(publisher, myUserName); - appendUserData(publisher, event.element, myUserName); - event.element['muted'] = true; - } - }); - - // --- 8) Publish your stream --- - - session.publish(publisher); - - }) - .catch(function (error) { - console.log('There was an error connecting to the session:', error.code, error.message); - }); - }); -} - -function leaveSession() { - - // --- 9) Leave the session by calling 'disconnect' method over the Session object --- - - session.disconnect(); - - // Removing all HTML elements with user's nicknames. - // HTML videos are automatically removed when leaving a Session - removeAllUserData(); - - // Back to 'Join session' page - document.getElementById('join').style.display = 'block'; - document.getElementById('session').style.display = 'none'; -} - - - -/* APPLICATION SPECIFIC METHODS */ - -window.addEventListener('load', function () { - generateParticipantInfo(); -}); - -window.onbeforeunload = function () { - if (session) session.disconnect(); -}; - -function generateParticipantInfo() { - document.getElementById("sessionId").value = "Sessionb"; - document.getElementById("userName").value = "Participant" + Math.floor(Math.random() * 100); -} - -function appendUserData(streamManager, videoElement, connection) { - var userData; - var nodeId; - if (typeof connection === "string") { - userData = connection; - nodeId = connection; - } else { - userData = JSON.parse(connection.data).clientData; - nodeId = connection.connectionId; - } - nodeId = "data-" + nodeId; - if (!document.getElementById(nodeId)) { - // Only if data node does not exist - var dataNode = document.createElement('div'); - dataNode.className = "data-node"; - dataNode.id = nodeId; - dataNode.innerHTML = "

" + userData + "

"; - videoElement.parentNode.insertBefore(dataNode, videoElement.nextSibling); - addClickListener(streamManager, videoElement, userData); - } -} - -function removeUserData(connection) { - var dataNode = document.getElementById("data-" + connection.connectionId); - dataNode.parentNode.removeChild(dataNode); -} - -function removeAllUserData() { - var nicknameElements = document.getElementsByClassName('data-node'); - while (nicknameElements[0]) { - nicknameElements[0].parentNode.removeChild(nicknameElements[0]); - } -} - -function addClickListener(streamManager, videoElement, userData) { - videoElement.addEventListener('mousedown', function () { - var mainVideo; - var differentVideo; - if (isIE) { - mainVideo = $('#main-video object').get(0); - differentVideo = true; - } else { - mainVideo = $('#main-video video').get(0); - differentVideo = mainVideo.srcObject !== videoElement.srcObject - } - if (differentVideo) { - $('#main-video').fadeOut("fast", function () { - $('#main-video p').html(userData); - streamManager.addVideoElement(mainVideo); - $('#main-video').fadeIn("fast"); - }); - } - }); -} - -function initMainVideo(publisher, userData) { - var mainVideo = document.querySelector('#main-video video'); - if (isIE && !mainVideo) { - // If IE and the main video has already been inserted by the plugin, - // search for an object element instead of a video element - mainVideo = document.querySelector('#main-video object'); - } - publisher.addVideoElement(mainVideo); - document.querySelector('#main-video p').innerHTML = userData; -} - - -/** - * -------------------------------------------- - * GETTING A TOKEN FROM YOUR APPLICATION SERVER - * -------------------------------------------- - * The methods below request the creation of a Session and a Token to - * your application server. This keeps your OpenVidu deployment secure. - * - * In this sample code, there is no user control at all. Anybody could - * access your application server endpoints! In a real production - * environment, your application server must identify the user to allow - * access to the endpoints. - * - * Visit https://docs.openvidu.io/en/stable/application-server to learn - * more about the integration of OpenVidu in your application server. - */ - -var OPENVIDU_SERVER_URL = "https://" + location.hostname + ":4443"; -var OPENVIDU_SERVER_SECRET = "MY_SECRET"; - -function getToken(mySessionId) { - return createSession(mySessionId).then(function (sessionId) { return createToken(sessionId); }); -} - -function createSession(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessions - return new Promise(function (resolve, reject) { - $.ajax({ - type: "POST", - url: OPENVIDU_SERVER_URL + "/openvidu/api/sessions", - data: JSON.stringify({ customSessionId: sessionId }), - headers: { - "Authorization": "Basic " + btoa("OPENVIDUAPP:" + OPENVIDU_SERVER_SECRET), - "Content-Type": "application/json" - }, - success: function (response) { resolve(response.id); }, - error: function (error) { - if (error.status === 409) { - resolve(sessionId); - } else { - console.warn('No connection to OpenVidu Server. This may be a certificate error at ' + OPENVIDU_SERVER_URL); - if (window.confirm('No connection to OpenVidu Server. This may be a certificate error at \"' + OPENVIDU_SERVER_URL + '\"\n\nClick OK to navigate and accept it. ' + - 'If no certificate warning is shown, then check that your OpenVidu Server is up and running at "' + OPENVIDU_SERVER_URL + '"')) { - location.assign(OPENVIDU_SERVER_URL + '/accept-certificate'); - } - } - } - }); - }); -} - -function createToken(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessionsltsession_idgtconnection - return new Promise(function (resolve, reject) { - $.ajax({ - type: "POST", - url: OPENVIDU_SERVER_URL + "/openvidu/api/sessions/" + sessionId + "/connection", - data: JSON.stringify({}), - headers: { - "Authorization": "Basic " + btoa("OPENVIDUAPP:" + OPENVIDU_SERVER_SECRET), - "Content-Type": "application/json" - }, - success: function (response) { resolve(response.token); }, - error: function (error) { reject(error); } - }); - }); -} \ No newline at end of file diff --git a/openvidu-internet-explorer/web/index.html b/openvidu-internet-explorer/web/index.html deleted file mode 100644 index d279234c..00000000 --- a/openvidu-internet-explorer/web/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - openvidu-internet-explorer - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-

Join a video session

-
-

- - -

-

- - -

-

- -

-
-
-
- - -
- - - - - - diff --git a/openvidu-internet-explorer/web/openvidu-browser-2.22.0.js b/openvidu-internet-explorer/web/openvidu-browser-2.22.0.js deleted file mode 100644 index 89d6c20b..00000000 --- a/openvidu-internet-explorer/web/openvidu-browser-2.22.0.js +++ /dev/null @@ -1,13589 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) - er = args[0]; - if (er instanceof Error) { - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - // At least give some kind of context to the user - var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); - err.context = er; - throw err; // Unhandled 'error' event - } - - var handler = events[type]; - - if (handler === undefined) - return false; - - if (typeof handler === 'function') { - ReflectApply(handler, this, args); - } else { - var len = handler.length; - var listeners = arrayClone(handler, len); - for (var i = 0; i < len; ++i) - ReflectApply(listeners[i], this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - checkListener(listener); - - events = target._events; - if (events === undefined) { - events = target._events = Object.create(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - // No error code for this since it is a Warning - // eslint-disable-next-line no-restricted-syntax - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' ' + String(type) + ' listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - ProcessEmitWarning(w); - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) - return this.listener.call(this.target); - return this.listener.apply(this.target, arguments); - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - checkListener(listener); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - checkListener(listener); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - checkListener(listener); - - events = this._events; - if (events === undefined) - return this; - - list = events[type]; - if (list === undefined) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else { - spliceOne(list, position); - } - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener !== undefined) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (events === undefined) - return this; - - // not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = Object.keys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = Object.create(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (events === undefined) - return []; - - var evlistener = events[type]; - if (evlistener === undefined) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? - unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events !== undefined) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; -}; - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function spliceOne(list, index) { - for (; index + 1 < list.length; index++) - list[index] = list[index + 1]; - list.pop(); -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function once(emitter, name) { - return new Promise(function (resolve, reject) { - function errorListener(err) { - emitter.removeListener(name, resolver); - reject(err); - } - - function resolver() { - if (typeof emitter.removeListener === 'function') { - emitter.removeListener('error', errorListener); - } - resolve([].slice.call(arguments)); - }; - - eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); - if (name !== 'error') { - addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); - } - }); -} - -function addErrorHandlerIfEventEmitter(emitter, handler, flags) { - if (typeof emitter.on === 'function') { - eventTargetAgnosticAddListener(emitter, 'error', handler, flags); - } -} - -function eventTargetAgnosticAddListener(emitter, name, listener, flags) { - if (typeof emitter.on === 'function') { - if (flags.once) { - emitter.once(name, listener); - } else { - emitter.on(name, listener); - } - } else if (typeof emitter.addEventListener === 'function') { - // EventTarget does not have `error` event semantics like Node - // EventEmitters, we do not listen for `error` events here. - emitter.addEventListener(name, function wrapListener(arg) { - // IE does not have builtin `{ once: true }` support so we - // have to do it manually. - if (flags.once) { - emitter.removeEventListener(name, wrapListener); - } - listener(arg); - }); - } else { - throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); - } -} - -},{}],2:[function(require,module,exports){ -/* jshint node: true */ -'use strict'; - -var normalice = require('normalice'); - -/** - # freeice - - The `freeice` module is a simple way of getting random STUN or TURN server - for your WebRTC application. The list of servers (just STUN at this stage) - were sourced from this [gist](https://gist.github.com/zziuni/3741933). - - ## Example Use - - The following demonstrates how you can use `freeice` with - [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): - - <<< examples/quickconnect.js - - As the `freeice` module generates ice servers in a list compliant with the - WebRTC spec you will be able to use it with raw `RTCPeerConnection` - constructors and other WebRTC libraries. - - ## Hey, don't use my STUN/TURN server! - - If for some reason your free STUN or TURN server ends up in the - list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or - [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) - that is used in this module, you can feel - free to open an issue on this repository and those servers will be removed - within 24 hours (or sooner). This is the quickest and probably the most - polite way to have something removed (and provides us some visibility - if someone opens a pull request requesting that a server is added). - - ## Please add my server! - - If you have a server that you wish to add to the list, that's awesome! I'm - sure I speak on behalf of a whole pile of WebRTC developers who say thanks. - To get it into the list, feel free to either open a pull request or if you - find that process a bit daunting then just create an issue requesting - the addition of the server (make sure you provide all the details, and if - you have a Terms of Service then including that in the PR/issue would be - awesome). - - ## I know of a free server, can I add it? - - Sure, if you do your homework and make sure it is ok to use (I'm currently - in the process of reviewing the terms of those STUN servers included from - the original list). If it's ok to go, then please see the previous entry - for how to add it. - - ## Current List of Servers - - * current as at the time of last `README.md` file generation - - ### STUN - - <<< stun.json - - ### TURN - - <<< turn.json - -**/ - -var freeice = function(opts) { - // if a list of servers has been provided, then use it instead of defaults - var servers = { - stun: (opts || {}).stun || require('./stun.json'), - turn: (opts || {}).turn || require('./turn.json') - }; - - var stunCount = (opts || {}).stunCount || 2; - var turnCount = (opts || {}).turnCount || 0; - var selected; - - function getServers(type, count) { - var out = []; - var input = [].concat(servers[type]); - var idx; - - while (input.length && out.length < count) { - idx = (Math.random() * input.length) | 0; - out = out.concat(input.splice(idx, 1)); - } - - return out.map(function(url) { - //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up - if ((typeof url !== 'string') && (! (url instanceof String))) { - return url; - } else { - return normalice(type + ':' + url); - } - }); - } - - // add stun servers - selected = [].concat(getServers('stun', stunCount)); - - if (turnCount) { - selected = selected.concat(getServers('turn', turnCount)); - } - - return selected; -}; - -module.exports = freeice; -},{"./stun.json":3,"./turn.json":4,"normalice":11}],3:[function(require,module,exports){ -module.exports=[ - "stun.l.google.com:19302", - "stun1.l.google.com:19302", - "stun2.l.google.com:19302", - "stun3.l.google.com:19302", - "stun4.l.google.com:19302", - "stun.ekiga.net", - "stun.ideasip.com", - "stun.schlund.de", - "stun.stunprotocol.org:3478", - "stun.voiparound.com", - "stun.voipbuster.com", - "stun.voipstunt.com", - "stun.voxgratia.org" -] - -},{}],4:[function(require,module,exports){ -module.exports=[] - -},{}],5:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); - - for(var i=4, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; - - return maxVolume; -} - - -var audioContextType; -if (typeof window !== 'undefined') { - audioContextType = window.AudioContext || window.webkitAudioContext; -} -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); - - // make it not break in non-supported browsers - if (!audioContextType) return harker; - - //Config - var options = options || {}, - smoothing = (options.smoothing || 0.1), - interval = (options.interval || 50), - threshold = options.threshold, - play = options.play, - history = options.history || 10, - running = true; - - // Ensure that just a single AudioContext is internally created - audioContext = options.audioContext || audioContext || new audioContextType(); - - var sourceNode, fftBins, analyser; - - analyser = audioContext.createAnalyser(); - analyser.fftSize = 512; - analyser.smoothingTimeConstant = smoothing; - fftBins = new Float32Array(analyser.frequencyBinCount); - - if (stream.jquery) stream = stream[0]; - if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { - //Audio Tag - sourceNode = audioContext.createMediaElementSource(stream); - if (typeof play === 'undefined') play = true; - threshold = threshold || -50; - } else { - //WebRTC Stream - sourceNode = audioContext.createMediaStreamSource(stream); - threshold = threshold || -50; - } - - sourceNode.connect(analyser); - if (play) analyser.connect(audioContext.destination); - - harker.speaking = false; - - harker.suspend = function() { - return audioContext.suspend(); - } - harker.resume = function() { - return audioContext.resume(); - } - Object.defineProperty(harker, 'state', { get: function() { - return audioContext.state; - }}); - audioContext.onstatechange = function() { - harker.emit('state_change', audioContext.state); - } - - harker.setThreshold = function(t) { - threshold = t; - }; - - harker.setInterval = function(i) { - interval = i; - }; - - harker.stop = function() { - running = false; - harker.emit('volume_change', -100, threshold); - if (harker.speaking) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - analyser.disconnect(); - sourceNode.disconnect(); - }; - harker.speakingHistory = []; - for (var i = 0; i < history; i++) { - harker.speakingHistory.push(0); - } - - // Poll the analyser node to determine if speaking - // and emit events if changed - var looper = function() { - setTimeout(function() { - - //check if stop has been called - if(!running) { - return; - } - - var currentVolume = getMaxVolume(analyser, fftBins); - - harker.emit('volume_change', currentVolume, threshold); - - var history = 0; - if (currentVolume > threshold && !harker.speaking) { - // trigger quickly, short history - for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history >= 2) { - harker.speaking = true; - harker.emit('speaking'); - } - } else if (currentVolume < threshold && harker.speaking) { - for (var i = 0; i < harker.speakingHistory.length; i++) { - history += harker.speakingHistory[i]; - } - if (history == 0) { - harker.speaking = false; - harker.emit('stopped_speaking'); - } - } - harker.speakingHistory.shift(); - harker.speakingHistory.push(0 + (currentVolume > threshold)); - - looper(); - }, interval); - }; - looper(); - - return harker; -} - -},{"wildemitter":37}],6:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }) - } - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } - } -} - -},{}],7:[function(require,module,exports){ -/* - * JSNLog 2.30.0 - * Open source under the MIT License. - * Copyright 2012-2017 Mattijs Perdeck All rights reserved. - */ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -function JL(loggerName) { - // If name is empty, return the root logger - if (!loggerName) { - return JL.__; - } - // Implements Array.reduce. JSNLog supports IE8+ and reduce is not supported in that browser. - // Same interface as the standard reduce, except that - if (!Array.prototype.reduce) { - Array.prototype.reduce = function (callback, initialValue) { - var previousValue = initialValue; - for (var i = 0; i < this.length; i++) { - previousValue = callback(previousValue, this[i], i, this); - } - return previousValue; - }; - } - var accumulatedLoggerName = ''; - var logger = ('.' + loggerName).split('.').reduce(function (prev, curr, idx, arr) { - // if loggername is a.b.c, than currentLogger will be set to the loggers - // root (prev: JL, curr: '') - // a (prev: JL.__, curr: 'a') - // a.b (prev: JL.__.__a, curr: 'b') - // a.b.c (prev: JL.__.__a.__a.b, curr: 'c') - // Note that when a new logger name is encountered (such as 'a.b.c'), - // a new logger object is created and added as a property to the parent ('a.b'). - // The root logger is added as a property of the JL object itself. - // It is essential that the name of the property containing the child logger - // contains the full 'path' name of the child logger ('a.b.c') instead of - // just the bit after the last period ('c'). - // This is because the parent inherits properties from its ancestors. - // So if the root has a child logger 'c' (stored in a property 'c' of the root logger), - // then logger 'a.b' has that same property 'c' through inheritance. - // The names of the logger properties start with __, so the root logger - // (which has name ''), has a nice property name '__'. - // accumulatedLoggerName evaluates false ('' is falsy) in first iteration when prev is the root logger. - // accumulatedLoggerName will be the logger name corresponding with the logger in currentLogger. - // Keep in mind that the currentLogger may not be defined yet, so can't get the name from - // the currentLogger object itself. - if (accumulatedLoggerName) { - accumulatedLoggerName += '.' + curr; - } - else { - accumulatedLoggerName = curr; - } - var currentLogger = prev['__' + accumulatedLoggerName]; - // If the currentLogger (or the actual logger being sought) does not yet exist, - // create it now. - if (currentLogger === undefined) { - // Set the prototype of the Logger constructor function to the parent of the logger - // to be created. This way, __proto of the new logger object will point at the parent. - // When logger.level is evaluated and is not present, the JavaScript runtime will - // walk down the prototype chain to find the first ancestor with a level property. - // - // Note that prev at this point refers to the parent logger. - JL.Logger.prototype = prev; - currentLogger = new JL.Logger(accumulatedLoggerName); - prev['__' + accumulatedLoggerName] = currentLogger; - } - return currentLogger; - }, JL.__); - return logger; -} -(function (JL) { - // Initialise requestId to empty string. If you don't do this and the user - // does not set it via setOptions, then the JSNLog-RequestId header will - // have value "undefined", which doesn't look good in a log. - // - // Note that you always want to send a requestId as part of log requests, - // otherwise the server side component doesn't know this is a log request - // and may create a new request id for the log request, causing confusion - // in the log. - JL.requestId = ''; - // Number uniquely identifying every log entry within the request. - JL.entryId = 0; - // Allow property injection of these classes, to enable unit testing - JL._createXMLHttpRequest = function () { return new XMLHttpRequest(); }; - JL._getTime = function () { return (new Date).getTime(); }; - JL._console = console; - // ----- private variables - JL._appenderNames = []; - /** - Copies the value of a property from one object to the other. - This is used to copy property values as part of setOption for loggers and appenders. - - Because loggers inherit property values from their parents, it is important never to - create a property on a logger if the intent is to inherit from the parent. - - Copying rules: - 1) if the from property is undefined (for example, not mentioned in a JSON object), the - to property is not affected at all. - 2) if the from property is null, the to property is deleted (so the logger will inherit from - its parent). - 3) Otherwise, the from property is copied to the to property. - */ - function copyProperty(propertyName, from, to) { - if (from[propertyName] === undefined) { - return; - } - if (from[propertyName] === null) { - delete to[propertyName]; - return; - } - to[propertyName] = from[propertyName]; - } - /** - Returns true if a log should go ahead. - Does not check level. - - @param filters - Filters that determine whether a log can go ahead. - */ - function allow(filters) { - // If enabled is not null or undefined, then if it is false, then return false - // Note that undefined==null (!) - if (!(JL.enabled == null)) { - if (!JL.enabled) { - return false; - } - } - // If the regex contains a bug, that will throw an exception. - // Ignore this, and pass the log item (better too much than too little). - try { - if (filters.userAgentRegex) { - if (!new RegExp(filters.userAgentRegex).test(navigator.userAgent)) { - return false; - } - } - } - catch (e) { } - try { - if (filters.ipRegex && JL.clientIP) { - if (!new RegExp(filters.ipRegex).test(JL.clientIP)) { - return false; - } - } - } - catch (e) { } - return true; - } - /** - Returns true if a log should go ahead, based on the message. - - @param filters - Filters that determine whether a log can go ahead. - - @param message - Message to be logged. - */ - function allowMessage(filters, message) { - // If the regex contains a bug, that will throw an exception. - // Ignore this, and pass the log item (better too much than too little). - try { - if (filters.disallow) { - if (new RegExp(filters.disallow).test(message)) { - return false; - } - } - } - catch (e) { } - return true; - } - // If logObject is a function, the function is evaluated (without parameters) - // and the result returned. - // Otherwise, logObject itself is returned. - function stringifyLogObjectFunction(logObject) { - if (typeof logObject == "function") { - if (logObject instanceof RegExp) { - return logObject.toString(); - } - else { - return logObject(); - } - } - return logObject; - } - var StringifiedLogObject = /** @class */ (function () { - // * msg - - // if the logObject is a scalar (after possible function evaluation), this is set to - // string representing the scalar. Otherwise it is left undefined. - // * meta - - // if the logObject is an object (after possible function evaluation), this is set to - // that object. Otherwise it is left undefined. - // * finalString - - // This is set to the string representation of logObject (after possible function evaluation), - // regardless of whether it is an scalar or an object. An object is stringified to a JSON string. - // Note that you can't call this field "final", because as some point this was a reserved - // JavaScript keyword and using final trips up some minifiers. - function StringifiedLogObject(msg, meta, finalString) { - this.msg = msg; - this.meta = meta; - this.finalString = finalString; - } - return StringifiedLogObject; - }()); - // Takes a logObject, which can be - // * a scalar - // * an object - // * a parameterless function, which returns the scalar or object to log. - // Returns a stringifiedLogObject - function stringifyLogObject(logObject) { - // Note that this works if logObject is null. - // typeof null is object. - // JSON.stringify(null) returns "null". - var actualLogObject = stringifyLogObjectFunction(logObject); - var finalString; - // Note that typeof actualLogObject should not be "function", because that has - // been resolved with stringifyLogObjectFunction. - switch (typeof actualLogObject) { - case "string": - return new StringifiedLogObject(actualLogObject, null, actualLogObject); - case "number": - finalString = actualLogObject.toString(); - return new StringifiedLogObject(finalString, null, finalString); - case "boolean": - finalString = actualLogObject.toString(); - return new StringifiedLogObject(finalString, null, finalString); - case "undefined": - return new StringifiedLogObject("undefined", null, "undefined"); - case "object": - if ((actualLogObject instanceof RegExp) || - (actualLogObject instanceof String) || - (actualLogObject instanceof Number) || - (actualLogObject instanceof Boolean)) { - finalString = actualLogObject.toString(); - return new StringifiedLogObject(finalString, null, finalString); - } - else { - if (typeof JL.serialize === 'function') { - finalString = JL.serialize.call(this, actualLogObject); - } - else { - finalString = JSON.stringify(actualLogObject); - } - // Set the msg field to "" instead of null. Some Winston transports - // assume that the msg field is not null. - return new StringifiedLogObject("", actualLogObject, finalString); - } - default: - return new StringifiedLogObject("unknown", null, "unknown"); - } - } - function setOptions(options) { - copyProperty("enabled", options, this); - copyProperty("maxMessages", options, this); - copyProperty("defaultAjaxUrl", options, this); - copyProperty("clientIP", options, this); - copyProperty("requestId", options, this); - copyProperty("defaultBeforeSend", options, this); - copyProperty("serialize", options, this); - return this; - } - JL.setOptions = setOptions; - function getAllLevel() { return -2147483648; } - JL.getAllLevel = getAllLevel; - function getTraceLevel() { return 1000; } - JL.getTraceLevel = getTraceLevel; - function getDebugLevel() { return 2000; } - JL.getDebugLevel = getDebugLevel; - function getInfoLevel() { return 3000; } - JL.getInfoLevel = getInfoLevel; - function getWarnLevel() { return 4000; } - JL.getWarnLevel = getWarnLevel; - function getErrorLevel() { return 5000; } - JL.getErrorLevel = getErrorLevel; - function getFatalLevel() { return 6000; } - JL.getFatalLevel = getFatalLevel; - function getOffLevel() { return 2147483647; } - JL.getOffLevel = getOffLevel; - function levelToString(level) { - if (level <= 1000) { - return "trace"; - } - if (level <= 2000) { - return "debug"; - } - if (level <= 3000) { - return "info"; - } - if (level <= 4000) { - return "warn"; - } - if (level <= 5000) { - return "error"; - } - return "fatal"; - } - // --------------------- - var Exception = /** @class */ (function () { - // data replaces message. It takes not just strings, but also objects and functions, just like the log function. - // internally, the string representation is stored in the message property (inherited from Error) - // - // inner: inner exception. Can be null or undefined. - function Exception(data, inner) { - this.inner = inner; - this.name = "JL.Exception"; - this.message = stringifyLogObject(data).finalString; - } - return Exception; - }()); - JL.Exception = Exception; - // Derive Exception from Error (a Host object), so browsers - // are more likely to produce a stack trace for it in their console. - // - // Note that instanceof against an object created with this constructor - // will return true in these cases: - // instanceof JL.Exception); - // instanceof Error); - Exception.prototype = new Error(); - // --------------------- - var LogItem = /** @class */ (function () { - // l: level - // m: message - // n: logger name - // t (timeStamp) is number of milliseconds since 1 January 1970 00:00:00 UTC - // u: number uniquely identifying this entry for this request. - // - // Keeping the property names really short, because they will be sent in the - // JSON payload to the server. - function LogItem(l, m, n, t, u) { - this.l = l; - this.m = m; - this.n = n; - this.t = t; - this.u = u; - } - return LogItem; - }()); - JL.LogItem = LogItem; - function newLogItem(levelNbr, message, loggerName) { - JL.entryId++; - return new LogItem(levelNbr, message, loggerName, JL._getTime(), JL.entryId); - } - function clearTimer(timer) { - if (timer.id) { - clearTimeout(timer.id); - timer.id = null; - } - } - function setTimer(timer, timeoutMs, callback) { - var that = this; - if (!timer.id) { - timer.id = setTimeout(function () { - // use call to ensure that the this as used inside sendBatch when it runs is the - // same this at this point. - callback.call(that); - }, timeoutMs); - } - } - var Appender = /** @class */ (function () { - // sendLogItems takes an array of log items. It will be called when - // the appender has items to process (such as, send to the server). - // sendLogItems will call successCallback after the items have been successfully sent. - // - // Note that after sendLogItems returns, the appender may truncate - // the LogItem array, so the function has to copy the content of the array - // in some fashion (eg. serialize) before returning. - function Appender(appenderName, sendLogItems) { - this.appenderName = appenderName; - this.sendLogItems = sendLogItems; - this.level = JL.getTraceLevel(); - // set to super high level, so if user increases level, level is unlikely to get - // above sendWithBufferLevel - this.sendWithBufferLevel = 2147483647; - this.storeInBufferLevel = -2147483648; - this.bufferSize = 0; // buffering switch off by default - this.batchSize = 1; - this.maxBatchSize = 20; - this.batchTimeout = 2147483647; - this.sendTimeout = 5000; - // Holds all log items with levels higher than storeInBufferLevel - // but lower than level. These items may never be sent. - this.buffer = []; - // Holds all items that we do want to send, until we have a full - // batch (as determined by batchSize). - this.batchBuffer = []; - // Holds the id of the timer implementing the batch timeout. - // Can be null. - // This is an object, so it can be passed to a method that updated the timer variable. - this.batchTimeoutTimer = { id: null }; - // Holds the id of the timer implementing the send timeout. - // Can be null. - this.sendTimeoutTimer = { id: null }; - // Number of log items that has been skipped due to batch buffer at max size, - // since appender creation or since creation of the last "skipped" warning log entry. - this.nbrLogItemsSkipped = 0; - // Will be 0 if no log request is outstanding at the moment. - // Otherwise the number of log items in the outstanding request. - this.nbrLogItemsBeingSent = 0; - var emptyNameErrorMessage = "Trying to create an appender without a name or with an empty name"; - // This evaluates to true if appenderName is either null or undefined! - // Do not check here if the name is "", because that would stop you creating the - // default appender. - if (appenderName == undefined) { - throw emptyNameErrorMessage; - } - if (JL._appenderNames.indexOf(appenderName) != -1) { - // If user passed in "", that will now have been picked up as a duplicate - // because default appender also uses "". - if (!appenderName) { - throw emptyNameErrorMessage; - } - throw "Multiple appenders use the same name " + appenderName; - } - JL._appenderNames.push(appenderName); - } - Appender.prototype.addLogItemsToBuffer = function (logItems) { - // If the batch buffer has reached its maximum limit, - // skip the log item and increase the "skipped items" counter. - if (this.batchBuffer.length >= this.maxBatchSize) { - this.nbrLogItemsSkipped += logItems.length; - return; - } - // If maxMessages is not null or undefined, then decrease it by the batch size. - // This can result in a negative maxMessages. - // Note that undefined==null (!) - // - // Note that we may be sending more messages than the maxMessages limit allows, - // if we stored trace messages. Rationale is the buffer for trace messages is limited, - // and if we cut off at exactly maxMessages, we'd also loose the high severity message - // that caused the trace messages to be sent (unless we cater for this specifically, which - // is more complexity). - // - // If there are multiple appenders sending the same message, maxMessage will be decreased - // by each appender for the same message. This is: - // 1) only appenders know whether a message will actually be sent (based on storeInBufferLevel), - // so the loggers couldn't do this update; - // 2) if you have multiple appenders hitting the same server, this may be what you want. - // - // In most cases there is only 1 appender, so this then doesn't matter. - if (!(JL.maxMessages == null)) { - if (JL.maxMessages < 1) { - return; - } - JL.maxMessages -= logItems.length; - } - this.batchBuffer = this.batchBuffer.concat(logItems); - // If this is the first item in the buffer, set the timer - // to ensure it will be sent within the timeout period. - // If it is not the first item, leave the timer alone so to not to - // increase the timeout for the first item. - // - // To determine if this is the first item, look at the timer variable. - // Do not look at the buffer length, because we also put items in the buffer - // via a concat (bypassing this function). - // - // The setTimer method only sets the timer if it is not already running. - var that = this; - setTimer(this.batchTimeoutTimer, this.batchTimeout, function () { - that.sendBatch.call(that); - }); - }; - ; - Appender.prototype.batchBufferHasOverdueMessages = function () { - for (var i = 0; i < this.batchBuffer.length; i++) { - var messageAgeMs = JL._getTime() - this.batchBuffer[i].t; - if (messageAgeMs > this.batchTimeout) { - return true; - } - } - return false; - }; - // Returns true if no more message will ever be added to the batch buffer, - // but the batch buffer has messages now - so if there are not enough to make up a batch, - // and there is no batch timeout, then they will never be sent. This is especially important if - // maxMessages was reached while jsnlog.js was retrying sending messages to the server. - Appender.prototype.batchBufferHasStrandedMessage = function () { - return (!(JL.maxMessages == null)) && (JL.maxMessages < 1) && (this.batchBuffer.length > 0); - }; - Appender.prototype.sendBatchIfComplete = function () { - if ((this.batchBuffer.length >= this.batchSize) || - this.batchBufferHasOverdueMessages() || - this.batchBufferHasStrandedMessage()) { - this.sendBatch(); - } - }; - Appender.prototype.onSendingEnded = function () { - clearTimer(this.sendTimeoutTimer); - this.nbrLogItemsBeingSent = 0; - this.sendBatchIfComplete(); - }; - Appender.prototype.setOptions = function (options) { - copyProperty("level", options, this); - copyProperty("ipRegex", options, this); - copyProperty("userAgentRegex", options, this); - copyProperty("disallow", options, this); - copyProperty("sendWithBufferLevel", options, this); - copyProperty("storeInBufferLevel", options, this); - copyProperty("bufferSize", options, this); - copyProperty("batchSize", options, this); - copyProperty("maxBatchSize", options, this); - copyProperty("batchTimeout", options, this); - copyProperty("sendTimeout", options, this); - if (this.bufferSize < this.buffer.length) { - this.buffer.length = this.bufferSize; - } - if (this.maxBatchSize < this.batchSize) { - throw new JL.Exception({ - "message": "maxBatchSize cannot be smaller than batchSize", - "maxBatchSize": this.maxBatchSize, - "batchSize": this.batchSize - }); - } - return this; - }; - /** - Called by a logger to log a log item. - If in response to this call one or more log items need to be processed - (eg., sent to the server), this method calls this.sendLogItems - with an array with all items to be processed. - - Note that the name and parameters of this function must match those of the log function of - a Winston transport object, so that users can use these transports as appenders. - That is why there are many parameters that are not actually used by this function. - - level - string with the level ("trace", "debug", etc.) Only used by Winston transports. - msg - human readable message. Undefined if the log item is an object. Only used by Winston transports. - meta - log object. Always defined, because at least it contains the logger name. Only used by Winston transports. - callback - function that is called when the log item has been logged. Only used by Winston transports. - levelNbr - level as a number. Not used by Winston transports. - message - log item. If the user logged an object, this is the JSON string. Not used by Winston transports. - loggerName: name of the logger. Not used by Winston transports. - */ - Appender.prototype.log = function (level, msg, meta, callback, levelNbr, message, loggerName) { - var logItem; - if (!allow(this)) { - return; - } - if (!allowMessage(this, message)) { - return; - } - if (levelNbr < this.storeInBufferLevel) { - // Ignore the log item completely - return; - } - logItem = newLogItem(levelNbr, message, loggerName); - if (levelNbr < this.level) { - // Store in the hold buffer. Do not send. - if (this.bufferSize > 0) { - this.buffer.push(logItem); - // If we exceeded max buffer size, remove oldest item - if (this.buffer.length > this.bufferSize) { - this.buffer.shift(); - } - } - return; - } - // Want to send the item - this.addLogItemsToBuffer([logItem]); - if (levelNbr >= this.sendWithBufferLevel) { - // Want to send the contents of the buffer. - // - // Send the buffer AFTER sending the high priority item. - // If you were to send the high priority item after the buffer, - // if we're close to maxMessages or maxBatchSize, - // then the trace messages in the buffer could crowd out the actual high priority item. - if (this.buffer.length) { - this.addLogItemsToBuffer(this.buffer); - this.buffer.length = 0; - } - } - this.sendBatchIfComplete(); - }; - ; - // Processes the batch buffer - // - // Make this public, so it can be called from outside the library, - // when the page is unloaded. - Appender.prototype.sendBatch = function () { - // Do not clear the batch timer if you don't go ahead here because - // a send is already in progress. Otherwise the messages that were stopped from going out - // may get ignored because the batch timer never went off. - if (this.nbrLogItemsBeingSent > 0) { - return; - } - clearTimer(this.batchTimeoutTimer); - if (this.batchBuffer.length == 0) { - return; - } - // Decided at this point to send contents of the buffer - this.nbrLogItemsBeingSent = this.batchBuffer.length; - var that = this; - setTimer(this.sendTimeoutTimer, this.sendTimeout, function () { - that.onSendingEnded.call(that); - }); - this.sendLogItems(this.batchBuffer, function () { - // Log entries have been successfully sent to server - // Remove the first (nbrLogItemsBeingSent) items in the batch buffer, because they are the ones - // that were sent. - that.batchBuffer.splice(0, that.nbrLogItemsBeingSent); - // If items had to be skipped, add a WARN message - if (that.nbrLogItemsSkipped > 0) { - that.batchBuffer.push(newLogItem(getWarnLevel(), "Lost " + that.nbrLogItemsSkipped + " messages. Either connection with the server was down or logging was disabled via the enabled option. Reduce lost messages by increasing the ajaxAppender option maxBatchSize.", that.appenderName)); - that.nbrLogItemsSkipped = 0; - } - that.onSendingEnded.call(that); - }); - }; - return Appender; - }()); - JL.Appender = Appender; - // --------------------- - var AjaxAppender = /** @class */ (function (_super) { - __extends(AjaxAppender, _super); - function AjaxAppender(appenderName) { - return _super.call(this, appenderName, AjaxAppender.prototype.sendLogItemsAjax) || this; - } - AjaxAppender.prototype.setOptions = function (options) { - copyProperty("url", options, this); - copyProperty("beforeSend", options, this); - _super.prototype.setOptions.call(this, options); - return this; - }; - AjaxAppender.prototype.sendLogItemsAjax = function (logItems, successCallback) { - // JSON.stringify is only supported on IE8+ - // Use try-catch in case we get an exception here. - // - // The "r" field is now obsolete. When writing a server side component, - // read the HTTP header "JSNLog-RequestId" - // to get the request id. - // - // The .Net server side component - // now uses the JSNLog-RequestId HTTP Header, because this allows it to - // detect whether the incoming request has a request id. - // If the request id were in the json payload, it would have to read the json - // from the stream, interfering with normal non-logging requests. - // - // To see what characters you can use in the HTTP header, visit: - // http://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions/3561399#3561399 - // - // It needs this ability, so users of NLog can set a requestId variable in NLog - // before the server side component tries to log the client side log message - // through an NLog logger. - // Unlike Log4Net, NLog doesn't allow you to register an object whose ToString() - // is only called when it tries to log something, so the requestId has to be - // determined right at the start of request processing. - try { - // Do not send logs, if JL.enabled is set to false. - // - // Do not call successCallback here. After each timeout, jsnlog will retry sending the message. - // If jsnlog gets re-enabled, it will then log the number of messages logged. - // If it doesn't get re-enabled, amount of cpu cycles wasted is minimal. - if (!allow(this)) { - return; - } - // If a request is in progress, abort it. - // Otherwise, it may call the success callback, which will be very confusing. - // It may also stop the inflight request from resulting in a log at the server. - if (this.xhr && (this.xhr.readyState != 0) && (this.xhr.readyState != 4)) { - this.xhr.abort(); - } - // Because a react-native XMLHttpRequest cannot be reused it needs to be recreated with each request - this.xhr = JL._createXMLHttpRequest(); - // Only determine the url right before you send a log request. - // Do not set the url when constructing the appender. - // - // This is because the server side component sets defaultAjaxUrl - // in a call to setOptions, AFTER the JL object and the default appender - // have been created. - var ajaxUrl = "/jsnlog.logger"; - // This evaluates to true if defaultAjaxUrl is null or undefined - if (!(JL.defaultAjaxUrl == null)) { - ajaxUrl = JL.defaultAjaxUrl; - } - if (this.url) { - ajaxUrl = this.url; - } - this.xhr.open('POST', ajaxUrl); - this.xhr.setRequestHeader('Content-Type', 'application/json'); - this.xhr.setRequestHeader('JSNLog-RequestId', JL.requestId); - var that = this; - this.xhr.onreadystatechange = function () { - // On most browsers, if the request fails (eg. internet is gone), - // it will set xhr.readyState == 4 and xhr.status != 200 (0 if request could not be sent) immediately. - // However, Edge and IE will not change the readyState at all if the internet goes away while waiting - // for a response. - // Some servers will return a 204 (success, no content) when the JSNLog endpoint - // returns the empty response. So check on any code in the 2.. range, not just 200. - if ((that.xhr.readyState == 4) && (that.xhr.status >= 200 && that.xhr.status < 300)) { - successCallback(); - } - }; - var json = { - r: JL.requestId, - lg: logItems - }; - // call beforeSend callback - // first try the callback on the appender - // then the global defaultBeforeSend callback - if (typeof this.beforeSend === 'function') { - this.beforeSend.call(this, this.xhr, json); - } - else if (typeof JL.defaultBeforeSend === 'function') { - JL.defaultBeforeSend.call(this, this.xhr, json); - } - var finalmsg = JSON.stringify(json); - this.xhr.send(finalmsg); - } - catch (e) { } - }; - return AjaxAppender; - }(Appender)); - JL.AjaxAppender = AjaxAppender; - // --------------------- - var ConsoleAppender = /** @class */ (function (_super) { - __extends(ConsoleAppender, _super); - function ConsoleAppender(appenderName) { - return _super.call(this, appenderName, ConsoleAppender.prototype.sendLogItemsConsole) || this; - } - ConsoleAppender.prototype.clog = function (logEntry) { - JL._console.log(logEntry); - }; - ConsoleAppender.prototype.cerror = function (logEntry) { - if (JL._console.error) { - JL._console.error(logEntry); - } - else { - this.clog(logEntry); - } - }; - ConsoleAppender.prototype.cwarn = function (logEntry) { - if (JL._console.warn) { - JL._console.warn(logEntry); - } - else { - this.clog(logEntry); - } - }; - ConsoleAppender.prototype.cinfo = function (logEntry) { - if (JL._console.info) { - JL._console.info(logEntry); - } - else { - this.clog(logEntry); - } - }; - // IE11 has a console.debug function. But its console doesn't have - // the option to show/hide debug messages (the same way Chrome and FF do), - // even though it does have such buttons for Error, Warn, Info. - // - // For now, this means that debug messages can not be hidden on IE. - // Live with this, seeing that it works fine on FF and Chrome, which - // will be much more popular with developers. - ConsoleAppender.prototype.cdebug = function (logEntry) { - if (JL._console.debug) { - JL._console.debug(logEntry); - } - else { - this.cinfo(logEntry); - } - }; - ConsoleAppender.prototype.sendLogItemsConsole = function (logItems, successCallback) { - try { - // Do not send logs, if JL.enabled is set to false - // - // Do not call successCallback here. After each timeout, jsnlog will retry sending the message. - // If jsnlog gets re-enabled, it will then log the number of messages logged. - // If it doesn't get re-enabled, amount of cpu cycles wasted is minimal. - if (!allow(this)) { - return; - } - if (!JL._console) { - return; - } - var i; - for (i = 0; i < logItems.length; ++i) { - var li = logItems[i]; - var msg = li.n + ": " + li.m; - // Only log the timestamp if we're on the server - // (window is undefined). On the browser, the user - // sees the log entry probably immediately, so in that case - // the timestamp is clutter. - if (typeof window === 'undefined') { - msg = new Date(li.t) + " | " + msg; - } - if (li.l <= JL.getDebugLevel()) { - this.cdebug(msg); - } - else if (li.l <= JL.getInfoLevel()) { - this.cinfo(msg); - } - else if (li.l <= JL.getWarnLevel()) { - this.cwarn(msg); - } - else { - this.cerror(msg); - } - } - } - catch (e) { - } - successCallback(); - }; - return ConsoleAppender; - }(Appender)); - JL.ConsoleAppender = ConsoleAppender; - // -------------------- - var Logger = /** @class */ (function () { - function Logger(loggerName) { - this.loggerName = loggerName; - // Create seenRexes, otherwise this logger will use the seenRexes - // of its parent via the prototype chain. - this.seenRegexes = []; - } - Logger.prototype.setOptions = function (options) { - copyProperty("level", options, this); - copyProperty("userAgentRegex", options, this); - copyProperty("disallow", options, this); - copyProperty("ipRegex", options, this); - copyProperty("appenders", options, this); - copyProperty("onceOnly", options, this); - // Reset seenRegexes, in case onceOnly has been changed. - this.seenRegexes = []; - return this; - }; - // Turns an exception into an object that can be sent to the server. - Logger.prototype.buildExceptionObject = function (e) { - var excObject = {}; - if (e.stack) { - excObject.stack = e.stack; - } - else { - excObject.e = e; - } - if (e.message) { - excObject.message = e.message; - } - if (e.name) { - excObject.name = e.name; - } - if (e.data) { - excObject.data = e.data; - } - if (e.inner) { - excObject.inner = this.buildExceptionObject(e.inner); - } - return excObject; - }; - // Logs a log item. - // Parameter e contains an exception (or null or undefined). - // - // Reason that processing exceptions is done at this low level is that - // 1) no need to spend the cpu cycles if the logger is switched off - // 2) fatalException takes both a logObject and an exception, and the logObject - // may be a function that should only be executed if the logger is switched on. - // - // If an exception is passed in, the contents of logObject is attached to the exception - // object in a new property logData. - // The resulting exception object is than worked into a message to the server. - // - // If there is no exception, logObject itself is worked into the message to the server. - Logger.prototype.log = function (level, logObject, e) { - var i = 0; - var compositeMessage; - var excObject; - // If we can't find any appenders, do nothing - if (!this.appenders) { - return this; - } - if (((level >= this.level)) && allow(this)) { - if (e) { - excObject = this.buildExceptionObject(e); - excObject.logData = stringifyLogObjectFunction(logObject); - } - else { - excObject = logObject; - } - compositeMessage = stringifyLogObject(excObject); - if (allowMessage(this, compositeMessage.finalString)) { - // See whether message is a duplicate - if (this.onceOnly) { - i = this.onceOnly.length - 1; - while (i >= 0) { - if (new RegExp(this.onceOnly[i]).test(compositeMessage.finalString)) { - if (this.seenRegexes[i]) { - return this; - } - this.seenRegexes[i] = true; - } - i--; - } - } - // Pass message to all appenders - // Note that these appenders could be Winston transports - // https://github.com/flatiron/winston - compositeMessage.meta = compositeMessage.meta || {}; - // Note that if the user is logging an object, compositeMessage.meta will hold a reference to that object. - // Do not add fields to compositeMessage.meta, otherwise the user's object will get that field out of the blue. - i = this.appenders.length - 1; - while (i >= 0) { - this.appenders[i].log(levelToString(level), compositeMessage.msg, compositeMessage.meta, function () { }, level, compositeMessage.finalString, this.loggerName); - i--; - } - } - } - return this; - }; - Logger.prototype.trace = function (logObject) { return this.log(getTraceLevel(), logObject); }; - Logger.prototype.debug = function (logObject) { return this.log(getDebugLevel(), logObject); }; - Logger.prototype.info = function (logObject) { return this.log(getInfoLevel(), logObject); }; - Logger.prototype.warn = function (logObject) { return this.log(getWarnLevel(), logObject); }; - Logger.prototype.error = function (logObject) { return this.log(getErrorLevel(), logObject); }; - Logger.prototype.fatal = function (logObject) { return this.log(getFatalLevel(), logObject); }; - Logger.prototype.fatalException = function (logObject, e) { return this.log(getFatalLevel(), logObject, e); }; - return Logger; - }()); - JL.Logger = Logger; - function createAjaxAppender(appenderName) { - return new AjaxAppender(appenderName); - } - JL.createAjaxAppender = createAjaxAppender; - function createConsoleAppender(appenderName) { - return new ConsoleAppender(appenderName); - } - JL.createConsoleAppender = createConsoleAppender; - // ----------------------- - // In the browser, the default appender is the AjaxAppender. - // Under nodejs (where there is no "window"), use the ConsoleAppender instead. - // - // Do NOT create an AjaxAppender object if you are not on a browser (that is, window is not defined). - // That would try to create an XmlHttpRequest object, which will crash outside a browser. - var defaultAppender; - if (typeof window !== 'undefined') { - defaultAppender = new AjaxAppender(""); - } - else { - defaultAppender = new ConsoleAppender(""); - } - // Create root logger - // - // Note that this is the parent of all other loggers. - // Logger "x" will be stored at - // JL.__.x - // Logger "x.y" at - // JL.__.x.y - JL.__ = new JL.Logger(""); - JL.__.setOptions({ - level: JL.getDebugLevel(), - appenders: [defaultAppender] - }); -})(JL || (JL = {})); -if (typeof exports !== 'undefined') { - // Allows SystemJs to import jsnlog.js. See - // https://github.com/mperdeck/jsnlog.js/issues/56 - exports.__esModule = true; - exports.JL = JL; -} -// Support AMD module format -var define; -if (typeof define == 'function' && define.amd) { - define('jsnlog', [], function () { - return JL; - }); -} -// If the __jsnlog_configure global function has been -// created, call it now. This allows you to create a global function -// setting logger options etc. inline in the page before jsnlog.js -// has been loaded. -if (typeof __jsnlog_configure == 'function') { - __jsnlog_configure(JL); -} -// Create onerror handler to log uncaught exceptions to the server side log, but only if there -// is no such handler already. -// Must use "typeof window" here, because in NodeJs, window is not defined at all, so cannot refer to window in any way. -if (typeof window !== 'undefined' && !window.onerror) { - window.onerror = function (errorMsg, url, lineNumber, column, errorObj) { - // Send object with all data to server side log, using severity fatal, - // from logger "onerrorLogger" - // - // Use errorMsg.message if available, so Angular 4 template errors will be logged. - // See https://github.com/mperdeck/jsnlog.js/pull/68 - JL("onerrorLogger").fatalException({ - "msg": "Uncaught Exception", - "errorMsg": errorMsg ? (errorMsg.message || errorMsg) : '', - "url": url, - "line number": lineNumber, "column": column - }, errorObj); - // Tell browser to run its own error handler as well - return false; - }; -} -// Deal with unhandled exceptions thrown in promises -if (typeof window !== 'undefined' && !window.onunhandledrejection) { - window.onunhandledrejection = function (event) { - // Send object with all data to server side log, using severity fatal, - // from logger "onerrorLogger". - // Need to check both event.reason.message and event.message, - // because SystemJs wraps exceptions and throws a new object which doesn't have a reason property. - // See https://github.com/systemjs/systemjs/issues/1309 - JL("onerrorLogger").fatalException({ - "msg": "unhandledrejection", - "errorMsg": event.reason ? event.reason.message : event.message || null - }, event.reason); - }; -} - -},{}],8:[function(require,module,exports){ -'use strict'; - -/** - * @param typeMap [Object] Map of MIME type -> Array[extensions] - * @param ... - */ -function Mime() { - this._types = Object.create(null); - this._extensions = Object.create(null); - - for (let i = 0; i < arguments.length; i++) { - this.define(arguments[i]); - } - - this.define = this.define.bind(this); - this.getType = this.getType.bind(this); - this.getExtension = this.getExtension.bind(this); -} - -/** - * Define mimetype -> extension mappings. Each key is a mime-type that maps - * to an array of extensions associated with the type. The first extension is - * used as the default extension for the type. - * - * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); - * - * If a type declares an extension that has already been defined, an error will - * be thrown. To suppress this error and force the extension to be associated - * with the new type, pass `force`=true. Alternatively, you may prefix the - * extension with "*" to map the type to extension, without mapping the - * extension to the type. - * - * e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']}); - * - * - * @param map (Object) type definitions - * @param force (Boolean) if true, force overriding of existing definitions - */ -Mime.prototype.define = function(typeMap, force) { - for (let type in typeMap) { - let extensions = typeMap[type].map(function(t) { - return t.toLowerCase(); - }); - type = type.toLowerCase(); - - for (let i = 0; i < extensions.length; i++) { - const ext = extensions[i]; - - // '*' prefix = not the preferred type for this extension. So fixup the - // extension, and skip it. - if (ext[0] === '*') { - continue; - } - - if (!force && (ext in this._types)) { - throw new Error( - 'Attempt to change mapping for "' + ext + - '" extension from "' + this._types[ext] + '" to "' + type + - '". Pass `force=true` to allow this, otherwise remove "' + ext + - '" from the list of extensions for "' + type + '".' - ); - } - - this._types[ext] = type; - } - - // Use first extension as default - if (force || !this._extensions[type]) { - const ext = extensions[0]; - this._extensions[type] = (ext[0] !== '*') ? ext : ext.substr(1); - } - } -}; - -/** - * Lookup a mime type based on extension - */ -Mime.prototype.getType = function(path) { - path = String(path); - let last = path.replace(/^.*[/\\]/, '').toLowerCase(); - let ext = last.replace(/^.*\./, '').toLowerCase(); - - let hasPath = last.length < path.length; - let hasDot = ext.length < last.length - 1; - - return (hasDot || !hasPath) && this._types[ext] || null; -}; - -/** - * Return file extension associated with a mime type - */ -Mime.prototype.getExtension = function(type) { - type = /^\s*([^;\s]*)/.test(type) && RegExp.$1; - return type && this._extensions[type.toLowerCase()] || null; -}; - -module.exports = Mime; - -},{}],9:[function(require,module,exports){ -'use strict'; - -let Mime = require('./Mime'); -module.exports = new Mime(require('./types/standard')); - -},{"./Mime":8,"./types/standard":10}],10:[function(require,module,exports){ -module.exports = {"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["es","ecma"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/express":["exp"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/trig":["trig"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/step+xml":["stpx"],"model/step+zip":["stpz"],"model/step-xml+zip":["stpxz"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]}; -},{}],11:[function(require,module,exports){ -/** - # normalice - - Normalize an ice server configuration object (or plain old string) into a format - that is usable in all browsers supporting WebRTC. Primarily this module is designed - to help with the transition of the `url` attribute of the configuration object to - the `urls` attribute. - - ## Example Usage - - <<< examples/simple.js - -**/ - -var protocols = [ - 'stun:', - 'turn:' -]; - -module.exports = function(input) { - var url = (input || {}).url || input; - var protocol; - var parts; - var output = {}; - - // if we don't have a string url, then allow the input to passthrough - if (typeof url != 'string' && (! (url instanceof String))) { - return input; - } - - // trim the url string, and convert to an array - url = url.trim(); - - // if the protocol is not known, then passthrough - protocol = protocols[protocols.indexOf(url.slice(0, 5))]; - if (! protocol) { - return input; - } - - // now let's attack the remaining url parts - url = url.slice(5); - parts = url.split('@'); - - output.username = input.username; - output.credential = input.credential; - // if we have an authentication part, then set the credentials - if (parts.length > 1) { - url = parts[1]; - parts = parts[0].split(':'); - - // add the output credential and username - output.username = parts[0]; - output.credential = (input || {}).credential || parts[1] || ''; - } - - output.url = protocol + url; - output.urls = [ output.url ]; - - return output; -}; - -},{}],12:[function(require,module,exports){ -(function (global){(function (){ -/*! - * Platform.js v1.3.6 - * Copyright 2014-2020 Benjamin Tan - * Copyright 2011-2013 John-David Dalton - * Available under MIT license - */ -;(function() { - 'use strict'; - - /** Used to determine if values are of the language type `Object`. */ - var objectTypes = { - 'function': true, - 'object': true - }; - - /** Used as a reference to the global object. */ - var root = (objectTypes[typeof window] && window) || this; - - /** Backup possible global object. */ - var oldRoot = root; - - /** Detect free variable `exports`. */ - var freeExports = objectTypes[typeof exports] && exports; - - /** Detect free variable `module`. */ - var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ - var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { - root = freeGlobal; - } - - /** - * Used as the maximum length of an array-like object. - * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) - * for more details. - */ - var maxSafeInteger = Math.pow(2, 53) - 1; - - /** Regular expression to detect Opera. */ - var reOpera = /\bOpera/; - - /** Possible global object. */ - var thisBinding = this; - - /** Used for native method references. */ - var objectProto = Object.prototype; - - /** Used to check for own properties of an object. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to resolve the internal `[[Class]]` of values. */ - var toString = objectProto.toString; - - /*--------------------------------------------------------------------------*/ - - /** - * Capitalizes a string value. - * - * @private - * @param {string} string The string to capitalize. - * @returns {string} The capitalized string. - */ - function capitalize(string) { - string = String(string); - return string.charAt(0).toUpperCase() + string.slice(1); - } - - /** - * A utility function to clean up the OS name. - * - * @private - * @param {string} os The OS name to clean up. - * @param {string} [pattern] A `RegExp` pattern matching the OS name. - * @param {string} [label] A label for the OS. - */ - function cleanupOS(os, pattern, label) { - // Platform tokens are defined at: - // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx - var data = { - '10.0': '10', - '6.4': '10 Technical Preview', - '6.3': '8.1', - '6.2': '8', - '6.1': 'Server 2008 R2 / 7', - '6.0': 'Server 2008 / Vista', - '5.2': 'Server 2003 / XP 64-bit', - '5.1': 'XP', - '5.01': '2000 SP1', - '5.0': '2000', - '4.0': 'NT', - '4.90': 'ME' - }; - // Detect Windows version from platform tokens. - if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) && - (data = data[/[\d.]+$/.exec(os)])) { - os = 'Windows ' + data; - } - // Correct character case and cleanup string. - os = String(os); - - if (pattern && label) { - os = os.replace(RegExp(pattern, 'i'), label); - } - - os = format( - os.replace(/ ce$/i, ' CE') - .replace(/\bhpw/i, 'web') - .replace(/\bMacintosh\b/, 'Mac OS') - .replace(/_PowerPC\b/i, ' OS') - .replace(/\b(OS X) [^ \d]+/i, '$1') - .replace(/\bMac (OS X)\b/, '$1') - .replace(/\/(\d)/, ' $1') - .replace(/_/g, '.') - .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') - .replace(/\bx86\.64\b/gi, 'x86_64') - .replace(/\b(Windows Phone) OS\b/, '$1') - .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1') - .split(' on ')[0] - ); - - return os; - } - - /** - * An iteration utility for arrays and objects. - * - * @private - * @param {Array|Object} object The object to iterate over. - * @param {Function} callback The function called per iteration. - */ - function each(object, callback) { - var index = -1, - length = object ? object.length : 0; - - if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) { - while (++index < length) { - callback(object[index], index, object); - } - } else { - forOwn(object, callback); - } - } - - /** - * Trim and conditionally capitalize string values. - * - * @private - * @param {string} string The string to format. - * @returns {string} The formatted string. - */ - function format(string) { - string = trim(string); - return /^(?:webOS|i(?:OS|P))/.test(string) - ? string - : capitalize(string); - } - - /** - * Iterates over an object's own properties, executing the `callback` for each. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} callback The function executed per own property. - */ - function forOwn(object, callback) { - for (var key in object) { - if (hasOwnProperty.call(object, key)) { - callback(object[key], key, object); - } - } - } - - /** - * Gets the internal `[[Class]]` of a value. - * - * @private - * @param {*} value The value. - * @returns {string} The `[[Class]]`. - */ - function getClassOf(value) { - return value == null - ? capitalize(value) - : toString.call(value).slice(8, -1); - } - - /** - * Host objects can return type values that are different from their actual - * data type. The objects we are concerned with usually return non-primitive - * types of "object", "function", or "unknown". - * - * @private - * @param {*} object The owner of the property. - * @param {string} property The property to check. - * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`. - */ - function isHostType(object, property) { - var type = object != null ? typeof object[property] : 'number'; - return !/^(?:boolean|number|string|undefined)$/.test(type) && - (type == 'object' ? !!object[property] : true); - } - - /** - * Prepares a string for use in a `RegExp` by making hyphens and spaces optional. - * - * @private - * @param {string} string The string to qualify. - * @returns {string} The qualified string. - */ - function qualify(string) { - return String(string).replace(/([ -])(?!$)/g, '$1?'); - } - - /** - * A bare-bones `Array#reduce` like utility function. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function called per iteration. - * @returns {*} The accumulated result. - */ - function reduce(array, callback) { - var accumulator = null; - each(array, function(value, index) { - accumulator = callback(accumulator, value, index, array); - }); - return accumulator; - } - - /** - * Removes leading and trailing whitespace from a string. - * - * @private - * @param {string} string The string to trim. - * @returns {string} The trimmed string. - */ - function trim(string) { - return String(string).replace(/^ +| +$/g, ''); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a new platform object. - * - * @memberOf platform - * @param {Object|string} [ua=navigator.userAgent] The user agent string or - * context object. - * @returns {Object} A platform object. - */ - function parse(ua) { - - /** The environment context object. */ - var context = root; - - /** Used to flag when a custom context is provided. */ - var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String'; - - // Juggle arguments. - if (isCustomContext) { - context = ua; - ua = null; - } - - /** Browser navigator object. */ - var nav = context.navigator || {}; - - /** Browser user agent string. */ - var userAgent = nav.userAgent || ''; - - ua || (ua = userAgent); - - /** Used to flag when `thisBinding` is the [ModuleScope]. */ - var isModuleScope = isCustomContext || thisBinding == oldRoot; - - /** Used to detect if browser is like Chrome. */ - var likeChrome = isCustomContext - ? !!nav.likeChrome - : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString()); - - /** Internal `[[Class]]` value shortcuts. */ - var objectClass = 'Object', - airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject', - enviroClass = isCustomContext ? objectClass : 'Environment', - javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java), - phantomClass = isCustomContext ? objectClass : 'RuntimeObject'; - - /** Detect Java environments. */ - var java = /\bJava/.test(javaClass) && context.java; - - /** Detect Rhino. */ - var rhino = java && getClassOf(context.environment) == enviroClass; - - /** A character to represent alpha. */ - var alpha = java ? 'a' : '\u03b1'; - - /** A character to represent beta. */ - var beta = java ? 'b' : '\u03b2'; - - /** Browser document object. */ - var doc = context.document || {}; - - /** - * Detect Opera browser (Presto-based). - * http://www.howtocreate.co.uk/operaStuff/operaObject.html - * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini - */ - var opera = context.operamini || context.opera; - - /** Opera `[[Class]]`. */ - var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera)) - ? operaClass - : (opera = null); - - /*------------------------------------------------------------------------*/ - - /** Temporary variable used over the script's lifetime. */ - var data; - - /** The CPU architecture. */ - var arch = ua; - - /** Platform description array. */ - var description = []; - - /** Platform alpha/beta indicator. */ - var prerelease = null; - - /** A flag to indicate that environment features should be used to resolve the platform. */ - var useFeatures = ua == userAgent; - - /** The browser/environment version. */ - var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); - - /** A flag to indicate if the OS ends with "/ Version" */ - var isSpecialCasedOS; - - /* Detectable layout engines (order is important). */ - var layout = getLayout([ - { 'label': 'EdgeHTML', 'pattern': 'Edge' }, - 'Trident', - { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, - 'iCab', - 'Presto', - 'NetFront', - 'Tasman', - 'KHTML', - 'Gecko' - ]); - - /* Detectable browser names (order is important). */ - var name = getName([ - 'Adobe AIR', - 'Arora', - 'Avant Browser', - 'Breach', - 'Camino', - 'Electron', - 'Epiphany', - 'Fennec', - 'Flock', - 'Galeon', - 'GreenBrowser', - 'iCab', - 'Iceweasel', - 'K-Meleon', - 'Konqueror', - 'Lunascape', - 'Maxthon', - { 'label': 'Microsoft Edge', 'pattern': '(?:Edge|Edg|EdgA|EdgiOS)' }, - 'Midori', - 'Nook Browser', - 'PaleMoon', - 'PhantomJS', - 'Raven', - 'Rekonq', - 'RockMelt', - { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' }, - 'SeaMonkey', - { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Sleipnir', - 'SlimBrowser', - { 'label': 'SRWare Iron', 'pattern': 'Iron' }, - 'Sunrise', - 'Swiftfox', - 'Vivaldi', - 'Waterfox', - 'WebPositive', - { 'label': 'Yandex Browser', 'pattern': 'YaBrowser' }, - { 'label': 'UC Browser', 'pattern': 'UCBrowser' }, - 'Opera Mini', - { 'label': 'Opera Mini', 'pattern': 'OPiOS' }, - 'Opera', - { 'label': 'Opera', 'pattern': 'OPR' }, - 'Chromium', - 'Chrome', - { 'label': 'Chrome', 'pattern': '(?:HeadlessChrome)' }, - { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, - { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, - { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' }, - { 'label': 'IE', 'pattern': 'IEMobile' }, - { 'label': 'IE', 'pattern': 'MSIE' }, - 'Safari' - ]); - - /* Detectable products (order is important). */ - var product = getProduct([ - { 'label': 'BlackBerry', 'pattern': 'BB10' }, - 'BlackBerry', - { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, - { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, - { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' }, - { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' }, - { 'label': 'Galaxy S5', 'pattern': 'SM-G900' }, - { 'label': 'Galaxy S6', 'pattern': 'SM-G920' }, - { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' }, - { 'label': 'Galaxy S7', 'pattern': 'SM-G930' }, - { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' }, - 'Google TV', - 'Lumia', - 'iPad', - 'iPod', - 'iPhone', - 'Kindle', - { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, - 'Nexus', - 'Nook', - 'PlayBook', - 'PlayStation Vita', - 'PlayStation', - 'TouchPad', - 'Transformer', - { 'label': 'Wii U', 'pattern': 'WiiU' }, - 'Wii', - 'Xbox One', - { 'label': 'Xbox 360', 'pattern': 'Xbox' }, - 'Xoom' - ]); - - /* Detectable manufacturers. */ - var manufacturer = getManufacturer({ - 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, - 'Alcatel': {}, - 'Archos': {}, - 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, - 'Asus': { 'Transformer': 1 }, - 'Barnes & Noble': { 'Nook': 1 }, - 'BlackBerry': { 'PlayBook': 1 }, - 'Google': { 'Google TV': 1, 'Nexus': 1 }, - 'HP': { 'TouchPad': 1 }, - 'HTC': {}, - 'Huawei': {}, - 'Lenovo': {}, - 'LG': {}, - 'Microsoft': { 'Xbox': 1, 'Xbox One': 1 }, - 'Motorola': { 'Xoom': 1 }, - 'Nintendo': { 'Wii U': 1, 'Wii': 1 }, - 'Nokia': { 'Lumia': 1 }, - 'Oppo': {}, - 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 }, - 'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }, - 'Xiaomi': { 'Mi': 1, 'Redmi': 1 } - }); - - /* Detectable operating systems (order is important). */ - var os = getOS([ - 'Windows Phone', - 'KaiOS', - 'Android', - 'CentOS', - { 'label': 'Chrome OS', 'pattern': 'CrOS' }, - 'Debian', - { 'label': 'DragonFly BSD', 'pattern': 'DragonFly' }, - 'Fedora', - 'FreeBSD', - 'Gentoo', - 'Haiku', - 'Kubuntu', - 'Linux Mint', - 'OpenBSD', - 'Red Hat', - 'SuSE', - 'Ubuntu', - 'Xubuntu', - 'Cygwin', - 'Symbian OS', - 'hpwOS', - 'webOS ', - 'webOS', - 'Tablet OS', - 'Tizen', - 'Linux', - 'Mac OS X', - 'Macintosh', - 'Mac', - 'Windows 98;', - 'Windows ' - ]); - - /*------------------------------------------------------------------------*/ - - /** - * Picks the layout engine from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected layout engine. - */ - function getLayout(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the manufacturer from an array of guesses. - * - * @private - * @param {Array} guesses An object of guesses. - * @returns {null|string} The detected manufacturer. - */ - function getManufacturer(guesses) { - return reduce(guesses, function(result, value, key) { - // Lookup the manufacturer by product or scan the UA for the manufacturer. - return result || ( - value[product] || - value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || - RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua) - ) && key; - }); - } - - /** - * Picks the browser name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected browser name. - */ - function getName(guesses) { - return reduce(guesses, function(result, guess) { - return result || RegExp('\\b' + ( - guess.pattern || qualify(guess) - ) + '\\b', 'i').exec(ua) && (guess.label || guess); - }); - } - - /** - * Picks the OS name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected OS name. - */ - function getOS(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua) - )) { - result = cleanupOS(result, pattern, guess.label || guess); - } - return result; - }); - } - - /** - * Picks the product name from an array of guesses. - * - * @private - * @param {Array} guesses An array of guesses. - * @returns {null|string} The detected product name. - */ - function getProduct(guesses) { - return reduce(guesses, function(result, guess) { - var pattern = guess.pattern || qualify(guess); - if (!result && (result = - RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || - RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) || - RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) - )) { - // Split by forward slash and append product version if needed. - if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) { - result[0] += ' ' + result[1]; - } - // Correct character case and cleanup string. - guess = guess.label || guess; - result = format(result[0] - .replace(RegExp(pattern, 'i'), guess) - .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') - .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2')); - } - return result; - }); - } - - /** - * Resolves the version using an array of UA patterns. - * - * @private - * @param {Array} patterns An array of UA patterns. - * @returns {null|string} The detected version. - */ - function getVersion(patterns) { - return reduce(patterns, function(result, pattern) { - return result || (RegExp(pattern + - '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; - }); - } - - /** - * Returns `platform.description` when the platform object is coerced to a string. - * - * @name toString - * @memberOf platform - * @returns {string} Returns `platform.description` if available, else an empty string. - */ - function toStringPlatform() { - return this.description || ''; - } - - /*------------------------------------------------------------------------*/ - - // Convert layout to an array so we can add extra details. - layout && (layout = [layout]); - - // Detect Android products. - // Browsers on Android devices typically provide their product IDS after "Android;" - // up to "Build" or ") AppleWebKit". - // Example: - // "Mozilla/5.0 (Linux; Android 8.1.0; Moto G (5) Plus) AppleWebKit/537.36 - // (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36" - if (/\bAndroid\b/.test(os) && !product && - (data = /\bAndroid[^;]*;(.*?)(?:Build|\) AppleWebKit)\b/i.exec(ua))) { - product = trim(data[1]) - // Replace any language codes (eg. "en-US"). - .replace(/^[a-z]{2}-[a-z]{2};\s*/i, '') - || null; - } - // Detect product names that contain their manufacturer's name. - if (manufacturer && !product) { - product = getProduct([manufacturer]); - } else if (manufacturer && product) { - product = product - .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.\\s]', 'i'), manufacturer + ' ') - .replace(RegExp('^(' + qualify(manufacturer) + ')[-_.]?(\\w)', 'i'), manufacturer + ' $2'); - } - // Clean up Google TV. - if ((data = /\bGoogle TV\b/.exec(product))) { - product = data[0]; - } - // Detect simulators. - if (/\bSimulator\b/i.test(ua)) { - product = (product ? product + ' ' : '') + 'Simulator'; - } - // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS. - if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) { - description.push('running in Turbo/Uncompressed mode'); - } - // Detect IE Mobile 11. - if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) { - data = parse(ua.replace(/like iPhone OS/, '')); - manufacturer = data.manufacturer; - product = data.product; - } - // Detect iOS. - else if (/^iP/.test(product)) { - name || (name = 'Safari'); - os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) - ? ' ' + data[1].replace(/_/g, '.') - : ''); - } - // Detect Kubuntu. - else if (name == 'Konqueror' && /^Linux\b/i.test(os)) { - os = 'Kubuntu'; - } - // Detect Android browsers. - else if ((manufacturer && manufacturer != 'Google' && - ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) || - (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) { - name = 'Android Browser'; - os = /\bAndroid\b/.test(os) ? os : 'Android'; - } - // Detect Silk desktop/accelerated modes. - else if (name == 'Silk') { - if (!/\bMobi/i.test(ua)) { - os = 'Android'; - description.unshift('desktop mode'); - } - if (/Accelerated *= *true/i.test(ua)) { - description.unshift('accelerated'); - } - } - // Detect UC Browser speed mode. - else if (name == 'UC Browser' && /\bUCWEB\b/.test(ua)) { - description.push('speed mode'); - } - // Detect PaleMoon identifying as Firefox. - else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) { - description.push('identifying as Firefox ' + data[1]); - } - // Detect Firefox OS and products running Firefox. - else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) { - os || (os = 'Firefox OS'); - product || (product = data[1]); - } - // Detect false positives for Firefox/Safari. - else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) { - // Escape the `/` for Firefox 1. - if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { - // Clear name of false positives. - name = null; - } - // Reassign a generic name. - if ((data = product || manufacturer || os) && - (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) { - name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser'; - } - } - // Add Chrome version to description for Electron. - else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) { - description.push('Chromium ' + data); - } - // Detect non-Opera (Presto-based) versions (order is important). - if (!version) { - version = getVersion([ - '(?:Cloud9|CriOS|CrMo|Edge|Edg|EdgA|EdgiOS|FxiOS|HeadlessChrome|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$)|UCBrowser|YaBrowser)', - 'Version', - qualify(name), - '(?:Firefox|Minefield|NetFront)' - ]); - } - // Detect stubborn layout engines. - if ((data = - layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' || - /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') || - /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' || - !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') || - layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront' - )) { - layout = [data]; - } - // Detect Windows Phone 7 desktop mode. - if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { - name += ' Mobile'; - os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x'); - description.unshift('desktop mode'); - } - // Detect Windows Phone 8.x desktop mode. - else if (/\bWPDesktop\b/i.test(ua)) { - name = 'IE Mobile'; - os = 'Windows Phone 8.x'; - description.unshift('desktop mode'); - version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]); - } - // Detect IE 11 identifying as other browsers. - else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) { - if (name) { - description.push('identifying as ' + name + (version ? ' ' + version : '')); - } - name = 'IE'; - version = data[1]; - } - // Leverage environment features. - if (useFeatures) { - // Detect server-side environments. - // Rhino has a global function while others have a global object. - if (isHostType(context, 'global')) { - if (java) { - data = java.lang.System; - arch = data.getProperty('os.arch'); - os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); - } - if (rhino) { - try { - version = context.require('ringo/engine').version.join('.'); - name = 'RingoJS'; - } catch(e) { - if ((data = context.system) && data.global.system == context.system) { - name = 'Narwhal'; - os || (os = data[0].os || null); - } - } - if (!name) { - name = 'Rhino'; - } - } - else if ( - typeof context.process == 'object' && !context.process.browser && - (data = context.process) - ) { - if (typeof data.versions == 'object') { - if (typeof data.versions.electron == 'string') { - description.push('Node ' + data.versions.node); - name = 'Electron'; - version = data.versions.electron; - } else if (typeof data.versions.nw == 'string') { - description.push('Chromium ' + version, 'Node ' + data.versions.node); - name = 'NW.js'; - version = data.versions.nw; - } - } - if (!name) { - name = 'Node.js'; - arch = data.arch; - os = data.platform; - version = /[\d.]+/.exec(data.version); - version = version ? version[0] : null; - } - } - } - // Detect Adobe AIR. - else if (getClassOf((data = context.runtime)) == airRuntimeClass) { - name = 'Adobe AIR'; - os = data.flash.system.Capabilities.os; - } - // Detect PhantomJS. - else if (getClassOf((data = context.phantom)) == phantomClass) { - name = 'PhantomJS'; - version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); - } - // Detect IE compatibility modes. - else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { - // We're in compatibility mode when the Trident version + 4 doesn't - // equal the document mode. - version = [version, doc.documentMode]; - if ((data = +data[1] + 4) != version[1]) { - description.push('IE ' + version[1] + ' mode'); - layout && (layout[1] = ''); - version[1] = data; - } - version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; - } - // Detect IE 11 masking as other browsers. - else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) { - description.push('masking as ' + name + ' ' + version); - name = 'IE'; - version = '11.0'; - layout = ['Trident']; - os = 'Windows'; - } - os = os && format(os); - } - // Detect prerelease phases. - if (version && (data = - /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || - /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || - /\bMinefield\b/i.test(ua) && 'a' - )) { - prerelease = /b/i.test(data) ? 'beta' : 'alpha'; - version = version.replace(RegExp(data + '\\+?$'), '') + - (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); - } - // Detect Firefox Mobile. - if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS|KaiOS)\b/.test(os)) { - name = 'Firefox Mobile'; - } - // Obscure Maxthon's unreliable version. - else if (name == 'Maxthon' && version) { - version = version.replace(/\.[\d.]+/, '.x'); - } - // Detect Xbox 360 and Xbox One. - else if (/\bXbox\b/i.test(product)) { - if (product == 'Xbox 360') { - os = null; - } - if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) { - description.unshift('mobile mode'); - } - } - // Add mobile postfix. - else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) && - (os == 'Windows CE' || /Mobi/i.test(ua))) { - name += ' Mobile'; - } - // Detect IE platform preview. - else if (name == 'IE' && useFeatures) { - try { - if (context.external === null) { - description.unshift('platform preview'); - } - } catch(e) { - description.unshift('embedded'); - } - } - // Detect BlackBerry OS version. - // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp - else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data = - (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || - version - )) { - data = [data, /BB10/.test(ua)]; - os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0]; - version = null; - } - // Detect Opera identifying/masking itself as another browser. - // http://www.opera.com/support/kb/view/843/ - else if (this != forOwn && product != 'Wii' && ( - (useFeatures && opera) || - (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || - (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) || - (name == 'IE' && ( - (os && !/^Win/.test(os) && version > 5.5) || - /\bWindows XP\b/.test(os) && version > 8 || - version == 8 && !/\bTrident\b/.test(ua) - )) - ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) { - // When "identifying", the UA contains both Opera and the other browser's name. - data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); - if (reOpera.test(name)) { - if (/\bIE\b/.test(data) && os == 'Mac OS') { - os = null; - } - data = 'identify' + data; - } - // When "masking", the UA contains only the other browser's name. - else { - data = 'mask' + data; - if (operaClass) { - name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); - } else { - name = 'Opera'; - } - if (/\bIE\b/.test(data)) { - os = null; - } - if (!useFeatures) { - version = null; - } - } - layout = ['Presto']; - description.push(data); - } - // Detect WebKit Nightly and approximate Chrome/Safari versions. - if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - // Correct build number for numeric comparison. - // (e.g. "532.5" becomes "532.05") - data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; - // Nightly builds are postfixed with a "+". - if (name == 'Safari' && data[1].slice(-1) == '+') { - name = 'WebKit Nightly'; - prerelease = 'alpha'; - version = data[1].slice(0, -1); - } - // Clear incorrect browser versions. - else if (version == data[1] || - version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { - version = null; - } - // Use the full Chrome version when available. - data[1] = (/\b(?:Headless)?Chrome\/([\d.]+)/i.exec(ua) || 0)[1]; - // Detect Blink layout engine. - if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') { - layout = ['Blink']; - } - // Detect JavaScriptCore. - // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi - if (!useFeatures || (!likeChrome && !data[1])) { - layout && (layout[1] = 'like Safari'); - data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : data < 602 ? 9 : data < 604 ? 10 : data < 606 ? 11 : data < 608 ? 12 : '12'); - } else { - layout && (layout[1] = 'like Chrome'); - data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28'); - } - // Add the postfix of ".x" or "+" for approximate versions. - layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+')); - // Obscure version for some Safari 1-2 releases. - if (name == 'Safari' && (!version || parseInt(version) > 45)) { - version = data; - } else if (name == 'Chrome' && /\bHeadlessChrome/i.test(ua)) { - description.unshift('headless'); - } - } - // Detect Opera desktop modes. - if (name == 'Opera' && (data = /\bzbov|zvav$/.exec(os))) { - name += ' '; - description.unshift('desktop mode'); - if (data == 'zvav') { - name += 'Mini'; - version = null; - } else { - name += 'Mobile'; - } - os = os.replace(RegExp(' *' + data + '$'), ''); - } - // Detect Chrome desktop mode. - else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) { - description.unshift('desktop mode'); - name = 'Chrome Mobile'; - version = null; - - if (/\bOS X\b/.test(os)) { - manufacturer = 'Apple'; - os = 'iOS 4.3+'; - } else { - os = null; - } - } - // Newer versions of SRWare Iron uses the Chrome tag to indicate its version number. - else if (/\bSRWare Iron\b/.test(name) && !version) { - version = getVersion('Chrome'); - } - // Strip incorrect OS versions. - if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 && - ua.indexOf('/' + data + '-') > -1) { - os = trim(os.replace(data, '')); - } - // Ensure OS does not include the browser name. - if (os && os.indexOf(name) != -1 && !RegExp(name + ' OS').test(os)) { - os = os.replace(RegExp(' *' + qualify(name) + ' *'), ''); - } - // Add layout engine. - if (layout && !/\b(?:Avant|Nook)\b/.test(name) && ( - /Browser|Lunascape|Maxthon/.test(name) || - name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) || - /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|SRWare Iron|Vivaldi|Web)/.test(name) && layout[1])) { - // Don't add layout details to description if they are falsey. - (data = layout[layout.length - 1]) && description.push(data); - } - // Combine contextual information. - if (description.length) { - description = ['(' + description.join('; ') + ')']; - } - // Append manufacturer to description. - if (manufacturer && product && product.indexOf(manufacturer) < 0) { - description.push('on ' + manufacturer); - } - // Append product to description. - if (product) { - description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product); - } - // Parse the OS into an object. - if (os) { - data = / ([\d.+]+)$/.exec(os); - isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/'; - os = { - 'architecture': 32, - 'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os, - 'version': data ? data[1] : null, - 'toString': function() { - var version = this.version; - return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); - } - }; - } - // Add browser/OS architecture. - if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { - if (os) { - os.architecture = 64; - os.family = os.family.replace(RegExp(' *' + data), ''); - } - if ( - name && (/\bWOW64\b/i.test(ua) || - (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua))) - ) { - description.unshift('32-bit'); - } - } - // Chrome 39 and above on OS X is always 64-bit. - else if ( - os && /^OS X/.test(os.family) && - name == 'Chrome' && parseFloat(version) >= 39 - ) { - os.architecture = 64; - } - - ua || (ua = null); - - /*------------------------------------------------------------------------*/ - - /** - * The platform object. - * - * @name platform - * @type Object - */ - var platform = {}; - - /** - * The platform description. - * - * @memberOf platform - * @type string|null - */ - platform.description = ua; - - /** - * The name of the browser's layout engine. - * - * The list of common layout engines include: - * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit" - * - * @memberOf platform - * @type string|null - */ - platform.layout = layout && layout[0]; - - /** - * The name of the product's manufacturer. - * - * The list of manufacturers include: - * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry", - * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo", - * "Nokia", "Samsung" and "Sony" - * - * @memberOf platform - * @type string|null - */ - platform.manufacturer = manufacturer; - - /** - * The name of the browser/environment. - * - * The list of common browser names include: - * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE", - * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk", - * "Opera Mini" and "Opera" - * - * Mobile versions of some browsers have "Mobile" appended to their name: - * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile" - * - * @memberOf platform - * @type string|null - */ - platform.name = name; - - /** - * The alpha/beta release indicator. - * - * @memberOf platform - * @type string|null - */ - platform.prerelease = prerelease; - - /** - * The name of the product hosting the browser. - * - * The list of common products include: - * - * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle", - * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer" - * - * @memberOf platform - * @type string|null - */ - platform.product = product; - - /** - * The browser's user agent string. - * - * @memberOf platform - * @type string|null - */ - platform.ua = ua; - - /** - * The browser/environment version. - * - * @memberOf platform - * @type string|null - */ - platform.version = name && version; - - /** - * The name of the operating system. - * - * @memberOf platform - * @type Object - */ - platform.os = os || { - - /** - * The CPU architecture the OS is built for. - * - * @memberOf platform.os - * @type number|null - */ - 'architecture': null, - - /** - * The family of the OS. - * - * Common values include: - * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista", - * "Windows XP", "OS X", "Linux", "Ubuntu", "Debian", "Fedora", "Red Hat", - * "SuSE", "Android", "iOS" and "Windows Phone" - * - * @memberOf platform.os - * @type string|null - */ - 'family': null, - - /** - * The version of the OS. - * - * @memberOf platform.os - * @type string|null - */ - 'version': null, - - /** - * Returns the OS string. - * - * @memberOf platform.os - * @returns {string} The OS string. - */ - 'toString': function() { return 'null'; } - }; - - platform.parse = parse; - platform.toString = toStringPlatform; - - if (platform.version) { - description.unshift(version); - } - if (platform.name) { - description.unshift(name); - } - if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) { - description.push(product ? '(' + os + ')' : 'on ' + os); - } - if (description.length) { - platform.description = description.join(' '); - } - return platform; - } - - /*--------------------------------------------------------------------------*/ - - // Export platform. - var platform = parse(); - - // Some AMD build optimizers, like r.js, check for condition patterns like the following: - if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { - // Expose platform on the global object to prevent errors when platform is - // loaded by a script tag in the presence of an AMD loader. - // See http://requirejs.org/docs/errors.html#mismatch for more details. - root.platform = platform; - - // Define as an anonymous module so platform can be aliased through path mapping. - define(function() { - return platform; - }); - } - // Check for `exports` after `define` in case a build optimizer adds an `exports` object. - else if (freeExports && freeModule) { - // Export for CommonJS support. - forOwn(platform, function(value, key) { - freeExports[key] = value; - }); - } - else { - // Export to the global object. - root.platform = platform; - } -}.call(this)); - -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],13:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],14:[function(require,module,exports){ -const debug = require('../internal/debug') -const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants') -const { re, t } = require('../internal/re') - -const parseOptions = require('../internal/parse-options') -const { compareIdentifiers } = require('../internal/identifiers') -class SemVer { - constructor (version, options) { - options = parseOptions(options) - - if (version instanceof SemVer) { - if (version.loose === !!options.loose && - version.includePrerelease === !!options.includePrerelease) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError(`Invalid Version: ${version}`) - } - - if (version.length > MAX_LENGTH) { - throw new TypeError( - `version is longer than ${MAX_LENGTH} characters` - ) - } - - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - // this isn't actually relevant for versions, but keep it so that we - // don't run into trouble passing this.options around. - this.includePrerelease = !!options.includePrerelease - - const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) - - if (!m) { - throw new TypeError(`Invalid Version: ${version}`) - } - - this.raw = version - - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map((id) => { - if (/^[0-9]+$/.test(id)) { - const num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - - this.build = m[5] ? m[5].split('.') : [] - this.format() - } - - format () { - this.version = `${this.major}.${this.minor}.${this.patch}` - if (this.prerelease.length) { - this.version += `-${this.prerelease.join('.')}` - } - return this.version - } - - toString () { - return this.version - } - - compare (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - if (typeof other === 'string' && other === this.version) { - return 0 - } - other = new SemVer(other, this.options) - } - - if (other.version === this.version) { - return 0 - } - - return this.compareMain(other) || this.comparePre(other) - } - - compareMain (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return ( - compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) - ) - } - - comparePre (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - let i = 0 - do { - const a = this.prerelease[i] - const b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) - } - - compareBuild (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - let i = 0 - do { - const a = this.build[i] - const b = other.build[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) - } - - // preminor will bump the version up to the next minor release, and immediately - // down to pre-release. premajor and prepatch work the same way. - inc (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if ( - this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0 - ) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - let i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - - default: - throw new Error(`invalid increment argument: ${release}`) - } - this.format() - this.raw = this.version - return this - } -} - -module.exports = SemVer - -},{"../internal/constants":17,"../internal/debug":18,"../internal/identifiers":19,"../internal/parse-options":20,"../internal/re":21}],15:[function(require,module,exports){ -const SemVer = require('../classes/semver') -const major = (a, loose) => new SemVer(a, loose).major -module.exports = major - -},{"../classes/semver":14}],16:[function(require,module,exports){ -const SemVer = require('../classes/semver') -const minor = (a, loose) => new SemVer(a, loose).minor -module.exports = minor - -},{"../classes/semver":14}],17:[function(require,module,exports){ -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -const SEMVER_SPEC_VERSION = '2.0.0' - -const MAX_LENGTH = 256 -const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 - -// Max safe segment length for coercion. -const MAX_SAFE_COMPONENT_LENGTH = 16 - -module.exports = { - SEMVER_SPEC_VERSION, - MAX_LENGTH, - MAX_SAFE_INTEGER, - MAX_SAFE_COMPONENT_LENGTH -} - -},{}],18:[function(require,module,exports){ -(function (process){(function (){ -const debug = ( - typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG) -) ? (...args) => console.error('SEMVER', ...args) - : () => {} - -module.exports = debug - -}).call(this)}).call(this,require('_process')) - -},{"_process":13}],19:[function(require,module,exports){ -const numeric = /^[0-9]+$/ -const compareIdentifiers = (a, b) => { - const anum = numeric.test(a) - const bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) - -module.exports = { - compareIdentifiers, - rcompareIdentifiers -} - -},{}],20:[function(require,module,exports){ -// parse out just the options we care about so we always get a consistent -// obj with keys in a consistent order. -const opts = ['includePrerelease', 'loose', 'rtl'] -const parseOptions = options => - !options ? {} - : typeof options !== 'object' ? { loose: true } - : opts.filter(k => options[k]).reduce((options, k) => { - options[k] = true - return options - }, {}) -module.exports = parseOptions - -},{}],21:[function(require,module,exports){ -const { MAX_SAFE_COMPONENT_LENGTH } = require('./constants') -const debug = require('./debug') -exports = module.exports = {} - -// The actual regexps go on exports.re -const re = exports.re = [] -const src = exports.src = [] -const t = exports.t = {} -let R = 0 - -const createToken = (name, value, isGlobal) => { - const index = R++ - debug(index, value) - t[name] = index - src[index] = value - re[index] = new RegExp(value, isGlobal ? 'g' : undefined) -} - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') -createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+') - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*') - -// ## Main Version -// Three dot-separated numeric identifiers. - -createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})\\.` + - `(${src[t.NUMERICIDENTIFIER]})`) - -createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + - `(${src[t.NUMERICIDENTIFIERLOOSE]})`) - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] -}|${src[t.NONNUMERICIDENTIFIER]})`) - -createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] -}|${src[t.NONNUMERICIDENTIFIER]})`) - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] -}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) - -createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] -}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+') - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] -}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -createToken('FULLPLAIN', `v?${src[t.MAINVERSION] -}${src[t.PRERELEASE]}?${ - src[t.BUILD]}?`) - -createToken('FULL', `^${src[t.FULLPLAIN]}$`) - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] -}${src[t.PRERELEASELOOSE]}?${ - src[t.BUILD]}?`) - -createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) - -createToken('GTLT', '((?:<|>)?=?)') - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) -createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) - -createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + - `(?:${src[t.PRERELEASE]})?${ - src[t.BUILD]}?` + - `)?)?`) - -createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + - `(?:${src[t.PRERELEASELOOSE]})?${ - src[t.BUILD]}?` + - `)?)?`) - -createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) -createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -createToken('COERCE', `${'(^|[^\\d])' + - '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + - `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + - `(?:$|[^\\d])`) -createToken('COERCERTL', src[t.COERCE], true) - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -createToken('LONETILDE', '(?:~>?)') - -createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) -exports.tildeTrimReplace = '$1~' - -createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) -createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -createToken('LONECARET', '(?:\\^)') - -createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) -exports.caretTrimReplace = '$1^' - -createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) -createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) -createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] -}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) -exports.comparatorTrimReplace = '$1$2$3' - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAIN]})` + - `\\s*$`) - -createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + - `\\s+-\\s+` + - `(${src[t.XRANGEPLAINLOOSE]})` + - `\\s*$`) - -// Star ranges basically just allow anything at all. -createToken('STAR', '(<|>)?=?\\s*\\*') -// >=0.0.0 is like a star -createToken('GTE0', '^\\s*>=\\s*0\.0\.0\\s*$') -createToken('GTE0PRE', '^\\s*>=\\s*0\.0\.0-0\\s*$') - -},{"./constants":17,"./debug":18}],22:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -Object.defineProperty(exports, "v1", { - enumerable: true, - get: function () { - return _v.default; - } -}); -Object.defineProperty(exports, "v3", { - enumerable: true, - get: function () { - return _v2.default; - } -}); -Object.defineProperty(exports, "v4", { - enumerable: true, - get: function () { - return _v3.default; - } -}); -Object.defineProperty(exports, "v5", { - enumerable: true, - get: function () { - return _v4.default; - } -}); -Object.defineProperty(exports, "NIL", { - enumerable: true, - get: function () { - return _nil.default; - } -}); -Object.defineProperty(exports, "version", { - enumerable: true, - get: function () { - return _version.default; - } -}); -Object.defineProperty(exports, "validate", { - enumerable: true, - get: function () { - return _validate.default; - } -}); -Object.defineProperty(exports, "stringify", { - enumerable: true, - get: function () { - return _stringify.default; - } -}); -Object.defineProperty(exports, "parse", { - enumerable: true, - get: function () { - return _parse.default; - } -}); - -var _v = _interopRequireDefault(require("./v1.js")); - -var _v2 = _interopRequireDefault(require("./v3.js")); - -var _v3 = _interopRequireDefault(require("./v4.js")); - -var _v4 = _interopRequireDefault(require("./v5.js")); - -var _nil = _interopRequireDefault(require("./nil.js")); - -var _version = _interopRequireDefault(require("./version.js")); - -var _validate = _interopRequireDefault(require("./validate.js")); - -var _stringify = _interopRequireDefault(require("./stringify.js")); - -var _parse = _interopRequireDefault(require("./parse.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -},{"./nil.js":24,"./parse.js":25,"./stringify.js":29,"./v1.js":30,"./v3.js":31,"./v4.js":33,"./v5.js":34,"./validate.js":35,"./version.js":36}],23:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -/* - * Browser-compatible JavaScript MD5 - * - * Modification of JavaScript MD5 - * https://github.com/blueimp/JavaScript-MD5 - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ -function md5(bytes) { - if (typeof bytes === 'string') { - const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape - - bytes = new Uint8Array(msg.length); - - for (let i = 0; i < msg.length; ++i) { - bytes[i] = msg.charCodeAt(i); - } - } - - return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8)); -} -/* - * Convert an array of little-endian words to an array of bytes - */ - - -function md5ToHexEncodedArray(input) { - const output = []; - const length32 = input.length * 32; - const hexTab = '0123456789abcdef'; - - for (let i = 0; i < length32; i += 8) { - const x = input[i >> 5] >>> i % 32 & 0xff; - const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16); - output.push(hex); - } - - return output; -} -/** - * Calculate output length with padding and bit length - */ - - -function getOutputLength(inputLength8) { - return (inputLength8 + 64 >>> 9 << 4) + 14 + 1; -} -/* - * Calculate the MD5 of an array of little-endian words, and a bit length. - */ - - -function wordsToMd5(x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << len % 32; - x[getOutputLength(len) - 1] = len; - let a = 1732584193; - let b = -271733879; - let c = -1732584194; - let d = 271733878; - - for (let i = 0; i < x.length; i += 16) { - const olda = a; - const oldb = b; - const oldc = c; - const oldd = d; - a = md5ff(a, b, c, d, x[i], 7, -680876936); - d = md5ff(d, a, b, c, x[i + 1], 12, -389564586); - c = md5ff(c, d, a, b, x[i + 2], 17, 606105819); - b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330); - a = md5ff(a, b, c, d, x[i + 4], 7, -176418897); - d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426); - c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341); - b = md5ff(b, c, d, a, x[i + 7], 22, -45705983); - a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416); - d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417); - c = md5ff(c, d, a, b, x[i + 10], 17, -42063); - b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162); - a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682); - d = md5ff(d, a, b, c, x[i + 13], 12, -40341101); - c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290); - b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329); - a = md5gg(a, b, c, d, x[i + 1], 5, -165796510); - d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632); - c = md5gg(c, d, a, b, x[i + 11], 14, 643717713); - b = md5gg(b, c, d, a, x[i], 20, -373897302); - a = md5gg(a, b, c, d, x[i + 5], 5, -701558691); - d = md5gg(d, a, b, c, x[i + 10], 9, 38016083); - c = md5gg(c, d, a, b, x[i + 15], 14, -660478335); - b = md5gg(b, c, d, a, x[i + 4], 20, -405537848); - a = md5gg(a, b, c, d, x[i + 9], 5, 568446438); - d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690); - c = md5gg(c, d, a, b, x[i + 3], 14, -187363961); - b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501); - a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467); - d = md5gg(d, a, b, c, x[i + 2], 9, -51403784); - c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473); - b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734); - a = md5hh(a, b, c, d, x[i + 5], 4, -378558); - d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463); - c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562); - b = md5hh(b, c, d, a, x[i + 14], 23, -35309556); - a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060); - d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353); - c = md5hh(c, d, a, b, x[i + 7], 16, -155497632); - b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640); - a = md5hh(a, b, c, d, x[i + 13], 4, 681279174); - d = md5hh(d, a, b, c, x[i], 11, -358537222); - c = md5hh(c, d, a, b, x[i + 3], 16, -722521979); - b = md5hh(b, c, d, a, x[i + 6], 23, 76029189); - a = md5hh(a, b, c, d, x[i + 9], 4, -640364487); - d = md5hh(d, a, b, c, x[i + 12], 11, -421815835); - c = md5hh(c, d, a, b, x[i + 15], 16, 530742520); - b = md5hh(b, c, d, a, x[i + 2], 23, -995338651); - a = md5ii(a, b, c, d, x[i], 6, -198630844); - d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415); - c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905); - b = md5ii(b, c, d, a, x[i + 5], 21, -57434055); - a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571); - d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606); - c = md5ii(c, d, a, b, x[i + 10], 15, -1051523); - b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799); - a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359); - d = md5ii(d, a, b, c, x[i + 15], 10, -30611744); - c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380); - b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649); - a = md5ii(a, b, c, d, x[i + 4], 6, -145523070); - d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379); - c = md5ii(c, d, a, b, x[i + 2], 15, 718787259); - b = md5ii(b, c, d, a, x[i + 9], 21, -343485551); - a = safeAdd(a, olda); - b = safeAdd(b, oldb); - c = safeAdd(c, oldc); - d = safeAdd(d, oldd); - } - - return [a, b, c, d]; -} -/* - * Convert an array bytes to an array of little-endian words - * Characters >255 have their high-byte silently ignored. - */ - - -function bytesToWords(input) { - if (input.length === 0) { - return []; - } - - const length8 = input.length * 8; - const output = new Uint32Array(getOutputLength(length8)); - - for (let i = 0; i < length8; i += 8) { - output[i >> 5] |= (input[i / 8] & 0xff) << i % 32; - } - - return output; -} -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - - -function safeAdd(x, y) { - const lsw = (x & 0xffff) + (y & 0xffff); - const msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return msw << 16 | lsw & 0xffff; -} -/* - * Bitwise rotate a 32-bit number to the left. - */ - - -function bitRotateLeft(num, cnt) { - return num << cnt | num >>> 32 - cnt; -} -/* - * These functions implement the four basic operations the algorithm uses. - */ - - -function md5cmn(q, a, b, x, s, t) { - return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b); -} - -function md5ff(a, b, c, d, x, s, t) { - return md5cmn(b & c | ~b & d, a, b, x, s, t); -} - -function md5gg(a, b, c, d, x, s, t) { - return md5cmn(b & d | c & ~d, a, b, x, s, t); -} - -function md5hh(a, b, c, d, x, s, t) { - return md5cmn(b ^ c ^ d, a, b, x, s, t); -} - -function md5ii(a, b, c, d, x, s, t) { - return md5cmn(c ^ (b | ~d), a, b, x, s, t); -} - -var _default = md5; -exports.default = _default; -},{}],24:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; -var _default = '00000000-0000-0000-0000-000000000000'; -exports.default = _default; -},{}],25:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _validate = _interopRequireDefault(require("./validate.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function parse(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - let v; - const arr = new Uint8Array(16); // Parse ########-....-....-....-............ - - arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; - arr[1] = v >>> 16 & 0xff; - arr[2] = v >>> 8 & 0xff; - arr[3] = v & 0xff; // Parse ........-####-....-....-............ - - arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; - arr[5] = v & 0xff; // Parse ........-....-####-....-............ - - arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; - arr[7] = v & 0xff; // Parse ........-....-....-####-............ - - arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; - arr[9] = v & 0xff; // Parse ........-....-....-....-############ - // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) - - arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; - arr[11] = v / 0x100000000 & 0xff; - arr[12] = v >>> 24 & 0xff; - arr[13] = v >>> 16 & 0xff; - arr[14] = v >>> 8 & 0xff; - arr[15] = v & 0xff; - return arr; -} - -var _default = parse; -exports.default = _default; -},{"./validate.js":35}],26:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; -var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; -exports.default = _default; -},{}],27:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = rng; -// Unique ID creation requires a high quality random # generator. In the browser we therefore -// require the crypto API and do not support built-in fallback to lower quality random number -// generators (like Math.random()). -let getRandomValues; -const rnds8 = new Uint8Array(16); - -function rng() { - // lazy load so that environments that need to polyfill have a chance to do so - if (!getRandomValues) { - // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also, - // find the complete implementation of crypto (msCrypto) on IE11. - getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto); - - if (!getRandomValues) { - throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); - } - } - - return getRandomValues(rnds8); -} -},{}],28:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -// Adapted from Chris Veness' SHA1 code at -// http://www.movable-type.co.uk/scripts/sha1.html -function f(s, x, y, z) { - switch (s) { - case 0: - return x & y ^ ~x & z; - - case 1: - return x ^ y ^ z; - - case 2: - return x & y ^ x & z ^ y & z; - - case 3: - return x ^ y ^ z; - } -} - -function ROTL(x, n) { - return x << n | x >>> 32 - n; -} - -function sha1(bytes) { - const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; - const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; - - if (typeof bytes === 'string') { - const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape - - bytes = []; - - for (let i = 0; i < msg.length; ++i) { - bytes.push(msg.charCodeAt(i)); - } - } else if (!Array.isArray(bytes)) { - // Convert Array-like to Array - bytes = Array.prototype.slice.call(bytes); - } - - bytes.push(0x80); - const l = bytes.length / 4 + 2; - const N = Math.ceil(l / 16); - const M = new Array(N); - - for (let i = 0; i < N; ++i) { - const arr = new Uint32Array(16); - - for (let j = 0; j < 16; ++j) { - arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3]; - } - - M[i] = arr; - } - - M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32); - M[N - 1][14] = Math.floor(M[N - 1][14]); - M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff; - - for (let i = 0; i < N; ++i) { - const W = new Uint32Array(80); - - for (let t = 0; t < 16; ++t) { - W[t] = M[i][t]; - } - - for (let t = 16; t < 80; ++t) { - W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); - } - - let a = H[0]; - let b = H[1]; - let c = H[2]; - let d = H[3]; - let e = H[4]; - - for (let t = 0; t < 80; ++t) { - const s = Math.floor(t / 20); - const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0; - e = d; - d = c; - c = ROTL(b, 30) >>> 0; - b = a; - a = T; - } - - H[0] = H[0] + a >>> 0; - H[1] = H[1] + b >>> 0; - H[2] = H[2] + c >>> 0; - H[3] = H[3] + d >>> 0; - H[4] = H[4] + e >>> 0; - } - - return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff]; -} - -var _default = sha1; -exports.default = _default; -},{}],29:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _validate = _interopRequireDefault(require("./validate.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -const byteToHex = []; - -for (let i = 0; i < 256; ++i) { - byteToHex.push((i + 0x100).toString(16).substr(1)); -} - -function stringify(arr, offset = 0) { - // Note: Be careful editing this code! It's been tuned for performance - // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 - const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one - // of the following: - // - One or more input array values don't map to a hex octet (leading to - // "undefined" in the uuid) - // - Invalid input values for the RFC `version` or `variant` fields - - if (!(0, _validate.default)(uuid)) { - throw TypeError('Stringified UUID is invalid'); - } - - return uuid; -} - -var _default = stringify; -exports.default = _default; -},{"./validate.js":35}],30:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _rng = _interopRequireDefault(require("./rng.js")); - -var _stringify = _interopRequireDefault(require("./stringify.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html -let _nodeId; - -let _clockseq; // Previous uuid creation time - - -let _lastMSecs = 0; -let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details - -function v1(options, buf, offset) { - let i = buf && offset || 0; - const b = buf || new Array(16); - options = options || {}; - let node = options.node || _nodeId; - let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - - if (node == null || clockseq == null) { - const seedBytes = options.random || (options.rng || _rng.default)(); - - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; - } - - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; - } - } // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - - - let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - - let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) - - const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression - - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - - - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } // Per 4.2.1.2 Throw error if too many uuids are requested - - - if (nsecs >= 10000) { - throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - - msecs += 12219292800000; // `time_low` - - const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; // `time_mid` - - const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; // `time_high_and_version` - - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - - b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - - b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` - - b[i++] = clockseq & 0xff; // `node` - - for (let n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } - - return buf || (0, _stringify.default)(b); -} - -var _default = v1; -exports.default = _default; -},{"./rng.js":27,"./stringify.js":29}],31:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _v = _interopRequireDefault(require("./v35.js")); - -var _md = _interopRequireDefault(require("./md5.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v3 = (0, _v.default)('v3', 0x30, _md.default); -var _default = v3; -exports.default = _default; -},{"./md5.js":23,"./v35.js":32}],32:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = _default; -exports.URL = exports.DNS = void 0; - -var _stringify = _interopRequireDefault(require("./stringify.js")); - -var _parse = _interopRequireDefault(require("./parse.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function stringToBytes(str) { - str = unescape(encodeURIComponent(str)); // UTF8 escape - - const bytes = []; - - for (let i = 0; i < str.length; ++i) { - bytes.push(str.charCodeAt(i)); - } - - return bytes; -} - -const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; -exports.DNS = DNS; -const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; -exports.URL = URL; - -function _default(name, version, hashfunc) { - function generateUUID(value, namespace, buf, offset) { - if (typeof value === 'string') { - value = stringToBytes(value); - } - - if (typeof namespace === 'string') { - namespace = (0, _parse.default)(namespace); - } - - if (namespace.length !== 16) { - throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); - } // Compute hash of namespace and value, Per 4.3 - // Future: Use spread syntax when supported on all platforms, e.g. `bytes = - // hashfunc([...namespace, ... value])` - - - let bytes = new Uint8Array(16 + value.length); - bytes.set(namespace); - bytes.set(value, namespace.length); - bytes = hashfunc(bytes); - bytes[6] = bytes[6] & 0x0f | version; - bytes[8] = bytes[8] & 0x3f | 0x80; - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = bytes[i]; - } - - return buf; - } - - return (0, _stringify.default)(bytes); - } // Function#name is not settable on some platforms (#270) - - - try { - generateUUID.name = name; // eslint-disable-next-line no-empty - } catch (err) {} // For CommonJS default export support - - - generateUUID.DNS = DNS; - generateUUID.URL = URL; - return generateUUID; -} -},{"./parse.js":25,"./stringify.js":29}],33:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _rng = _interopRequireDefault(require("./rng.js")); - -var _stringify = _interopRequireDefault(require("./stringify.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function v4(options, buf, offset) { - options = options || {}; - - const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - - - rnds[6] = rnds[6] & 0x0f | 0x40; - rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided - - if (buf) { - offset = offset || 0; - - for (let i = 0; i < 16; ++i) { - buf[offset + i] = rnds[i]; - } - - return buf; - } - - return (0, _stringify.default)(rnds); -} - -var _default = v4; -exports.default = _default; -},{"./rng.js":27,"./stringify.js":29}],34:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _v = _interopRequireDefault(require("./v35.js")); - -var _sha = _interopRequireDefault(require("./sha1.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const v5 = (0, _v.default)('v5', 0x50, _sha.default); -var _default = v5; -exports.default = _default; -},{"./sha1.js":28,"./v35.js":32}],35:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _regex = _interopRequireDefault(require("./regex.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function validate(uuid) { - return typeof uuid === 'string' && _regex.default.test(uuid); -} - -var _default = validate; -exports.default = _default; -},{"./regex.js":26}],36:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = void 0; - -var _validate = _interopRequireDefault(require("./validate.js")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function version(uuid) { - if (!(0, _validate.default)(uuid)) { - throw TypeError('Invalid UUID'); - } - - return parseInt(uuid.substr(14, 1), 16); -} - -var _default = version; -exports.default = _default; -},{"./validate.js":35}],37:[function(require,module,exports){ -/* -WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based -on @visionmedia's Emitter from UI Kit. - -Why? I wanted it standalone. - -I also wanted support for wildcard emitters like this: - -emitter.on('*', function (eventName, other, event, payloads) { - -}); - -emitter.on('somenamespace*', function (eventName, payloads) { - -}); - -Please note that callbacks triggered by wildcard registered events also get -the event name as the first argument. -*/ - -module.exports = WildEmitter; - -function WildEmitter() { } - -WildEmitter.mixin = function (constructor) { - var prototype = constructor.prototype || constructor; - - prototype.isWildEmitter= true; - - // Listen on the given `event` with `fn`. Store a group name if present. - prototype.on = function (event, groupName, fn) { - this.callbacks = this.callbacks || {}; - var hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - func._groupName = group; - (this.callbacks[event] = this.callbacks[event] || []).push(func); - return this; - }; - - // Adds an `event` listener that will be invoked a single - // time then automatically removed. - prototype.once = function (event, groupName, fn) { - var self = this, - hasGroup = (arguments.length === 3), - group = hasGroup ? arguments[1] : undefined, - func = hasGroup ? arguments[2] : arguments[1]; - function on() { - self.off(event, on); - func.apply(this, arguments); - } - this.on(event, group, on); - return this; - }; - - // Unbinds an entire group - prototype.releaseGroup = function (groupName) { - this.callbacks = this.callbacks || {}; - var item, i, len, handlers; - for (item in this.callbacks) { - handlers = this.callbacks[item]; - for (i = 0, len = handlers.length; i < len; i++) { - if (handlers[i]._groupName === groupName) { - //console.log('removing'); - // remove it and shorten the array we're looping through - handlers.splice(i, 1); - i--; - len--; - } - } - } - return this; - }; - - // Remove the given callback for `event` or all - // registered callbacks. - prototype.off = function (event, fn) { - this.callbacks = this.callbacks || {}; - var callbacks = this.callbacks[event], - i; - - if (!callbacks) return this; - - // remove all handlers - if (arguments.length === 1) { - delete this.callbacks[event]; - return this; - } - - // remove specific handler - i = callbacks.indexOf(fn); - if (i !== -1) { - callbacks.splice(i, 1); - if (callbacks.length === 0) { - delete this.callbacks[event]; - } - } - return this; - }; - - /// Emit `event` with the given args. - // also calls any `*` handlers - prototype.emit = function (event) { - this.callbacks = this.callbacks || {}; - var args = [].slice.call(arguments, 1), - callbacks = this.callbacks[event], - specialCallbacks = this.getWildcardCallbacks(event), - i, - len, - item, - listeners; - - if (callbacks) { - listeners = callbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, args); - } - } - - if (specialCallbacks) { - len = specialCallbacks.length; - listeners = specialCallbacks.slice(); - for (i = 0, len = listeners.length; i < len; ++i) { - if (!listeners[i]) { - break; - } - listeners[i].apply(this, [event].concat(args)); - } - } - - return this; - }; - - // Helper for for finding special wildcard event handlers that match the event - prototype.getWildcardCallbacks = function (eventName) { - this.callbacks = this.callbacks || {}; - var item, - split, - result = []; - - for (item in this.callbacks) { - split = item.split('*'); - if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { - result = result.concat(this.callbacks[item]); - } - } - return result; - }; - -}; - -WildEmitter.mixin(WildEmitter); - -},{}],38:[function(require,module,exports){ -/*! - * EventEmitter v5.2.9 - git.io/ee - * Unlicense - http://unlicense.org/ - * Oliver Caldwell - https://oli.me.uk/ - * @preserve - */ - -;(function (exports) { - 'use strict'; - - /** - * Class for managing events. - * Can be extended to provide event functionality in other classes. - * - * @class EventEmitter Manages event registering and emitting. - */ - function EventEmitter() {} - - // Shortcuts to improve speed and size - var proto = EventEmitter.prototype; - var originalGlobalValue = exports.EventEmitter; - - /** - * Finds the index of the listener for the event in its storage array. - * - * @param {Function[]} listeners Array of listeners to search through. - * @param {Function} listener Method to look for. - * @return {Number} Index of the specified listener, -1 if not found - * @api private - */ - function indexOfListener(listeners, listener) { - var i = listeners.length; - while (i--) { - if (listeners[i].listener === listener) { - return i; - } - } - - return -1; - } - - /** - * Alias a method while keeping the context correct, to allow for overwriting of target method. - * - * @param {String} name The name of the target method. - * @return {Function} The aliased method - * @api private - */ - function alias(name) { - return function aliasClosure() { - return this[name].apply(this, arguments); - }; - } - - /** - * Returns the listener array for the specified event. - * Will initialise the event object and listener arrays if required. - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. - * Each property in the object response is an array of listener functions. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Function[]|Object} All listener functions for the event. - */ - proto.getListeners = function getListeners(evt) { - var events = this._getEvents(); - var response; - var key; - - // Return a concatenated array of all matching events if - // the selector is a regular expression. - if (evt instanceof RegExp) { - response = {}; - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - response[key] = events[key]; - } - } - } - else { - response = events[evt] || (events[evt] = []); - } - - return response; - }; - - /** - * Takes a list of listener objects and flattens it into a list of listener functions. - * - * @param {Object[]} listeners Raw listener objects. - * @return {Function[]} Just the listener functions. - */ - proto.flattenListeners = function flattenListeners(listeners) { - var flatListeners = []; - var i; - - for (i = 0; i < listeners.length; i += 1) { - flatListeners.push(listeners[i].listener); - } - - return flatListeners; - }; - - /** - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. - * - * @param {String|RegExp} evt Name of the event to return the listeners from. - * @return {Object} All listener functions for an event in an object. - */ - proto.getListenersAsObject = function getListenersAsObject(evt) { - var listeners = this.getListeners(evt); - var response; - - if (listeners instanceof Array) { - response = {}; - response[evt] = listeners; - } - - return response || listeners; - }; - - function isValidListener (listener) { - if (typeof listener === 'function' || listener instanceof RegExp) { - return true - } else if (listener && typeof listener === 'object') { - return isValidListener(listener.listener) - } else { - return false - } - } - - /** - * Adds a listener function to the specified event. - * The listener will not be added if it is a duplicate. - * If the listener returns true then it will be removed after it is called. - * If you pass a regular expression as the event name then the listener will be added to all events that match it. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListener = function addListener(evt, listener) { - if (!isValidListener(listener)) { - throw new TypeError('listener must be a function'); - } - - var listeners = this.getListenersAsObject(evt); - var listenerIsWrapped = typeof listener === 'object'; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { - listeners[key].push(listenerIsWrapped ? listener : { - listener: listener, - once: false - }); - } - } - - return this; - }; - - /** - * Alias of addListener - */ - proto.on = alias('addListener'); - - /** - * Semi-alias of addListener. It will add a listener that will be - * automatically removed after its first execution. - * - * @param {String|RegExp} evt Name of the event to attach the listener to. - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addOnceListener = function addOnceListener(evt, listener) { - return this.addListener(evt, { - listener: listener, - once: true - }); - }; - - /** - * Alias of addOnceListener. - */ - proto.once = alias('addOnceListener'); - - /** - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. - * You need to tell it what event names should be matched by a regex. - * - * @param {String} evt Name of the event to create. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvent = function defineEvent(evt) { - this.getListeners(evt); - return this; - }; - - /** - * Uses defineEvent to define multiple events. - * - * @param {String[]} evts An array of event names to define. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.defineEvents = function defineEvents(evts) { - for (var i = 0; i < evts.length; i += 1) { - this.defineEvent(evts[i]); - } - return this; - }; - - /** - * Removes a listener function from the specified event. - * When passed a regular expression as the event name, it will remove the listener from all events that match it. - * - * @param {String|RegExp} evt Name of the event to remove the listener from. - * @param {Function} listener Method to remove from the event. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListener = function removeListener(evt, listener) { - var listeners = this.getListenersAsObject(evt); - var index; - var key; - - for (key in listeners) { - if (listeners.hasOwnProperty(key)) { - index = indexOfListener(listeners[key], listener); - - if (index !== -1) { - listeners[key].splice(index, 1); - } - } - } - - return this; - }; - - /** - * Alias of removeListener - */ - proto.off = alias('removeListener'); - - /** - * Adds listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. - * You can also pass it a regular expression to add the array of listeners to all events that match it. - * Yeah, this function does quite a bit. That's probably a bad thing. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.addListeners = function addListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(false, evt, listeners); - }; - - /** - * Removes listeners in bulk using the manipulateListeners method. - * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be removed. - * You can also pass it a regular expression to remove the listeners from all events that match it. - * - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeListeners = function removeListeners(evt, listeners) { - // Pass through to manipulateListeners - return this.manipulateListeners(true, evt, listeners); - }; - - /** - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. - * The first argument will determine if the listeners are removed (true) or added (false). - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. - * You can also pass it an event name and an array of listeners to be added/removed. - * You can also pass it a regular expression to manipulate the listeners of all events that match it. - * - * @param {Boolean} remove True if you want to remove listeners, false if you want to add. - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. - * @param {Function[]} [listeners] An optional array of listener functions to add/remove. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { - var i; - var value; - var single = remove ? this.removeListener : this.addListener; - var multiple = remove ? this.removeListeners : this.addListeners; - - // If evt is an object then pass each of its properties to this method - if (typeof evt === 'object' && !(evt instanceof RegExp)) { - for (i in evt) { - if (evt.hasOwnProperty(i) && (value = evt[i])) { - // Pass the single listener straight through to the singular method - if (typeof value === 'function') { - single.call(this, i, value); - } - else { - // Otherwise pass back to the multiple function - multiple.call(this, i, value); - } - } - } - } - else { - // So evt must be a string - // And listeners must be an array of listeners - // Loop over it and pass each one to the multiple method - i = listeners.length; - while (i--) { - single.call(this, evt, listeners[i]); - } - } - - return this; - }; - - /** - * Removes all listeners from a specified event. - * If you do not specify an event then all listeners will be removed. - * That means every event will be emptied. - * You can also pass a regex to remove all events that match it. - * - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.removeEvent = function removeEvent(evt) { - var type = typeof evt; - var events = this._getEvents(); - var key; - - // Remove different things depending on the state of evt - if (type === 'string') { - // Remove all listeners for the specified event - delete events[evt]; - } - else if (evt instanceof RegExp) { - // Remove all events matching the regex. - for (key in events) { - if (events.hasOwnProperty(key) && evt.test(key)) { - delete events[key]; - } - } - } - else { - // Remove all listeners in all events - delete this._events; - } - - return this; - }; - - /** - * Alias of removeEvent. - * - * Added to mirror the node API. - */ - proto.removeAllListeners = alias('removeEvent'); - - /** - * Emits an event of your choice. - * When emitted, every listener attached to that event will be executed. - * If you pass the optional argument array then those arguments will be passed to every listener upon execution. - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. - * So they will not arrive within the array on the other side, they will be separate. - * You can also pass a regular expression to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {Array} [args] Optional array of arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emitEvent = function emitEvent(evt, args) { - var listenersMap = this.getListenersAsObject(evt); - var listeners; - var listener; - var i; - var key; - var response; - - for (key in listenersMap) { - if (listenersMap.hasOwnProperty(key)) { - listeners = listenersMap[key].slice(0); - - for (i = 0; i < listeners.length; i++) { - // If the listener returns true then it shall be removed from the event - // The function is executed either with a basic call or an apply if there is an args array - listener = listeners[i]; - - if (listener.once === true) { - this.removeListener(evt, listener.listener); - } - - response = listener.listener.apply(this, args || []); - - if (response === this._getOnceReturnValue()) { - this.removeListener(evt, listener.listener); - } - } - } - } - - return this; - }; - - /** - * Alias of emitEvent - */ - proto.trigger = alias('emitEvent'); - - /** - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. - * - * @param {String|RegExp} evt Name of the event to emit and execute listeners for. - * @param {...*} Optional additional arguments to be passed to each listener. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.emit = function emit(evt) { - var args = Array.prototype.slice.call(arguments, 1); - return this.emitEvent(evt, args); - }; - - /** - * Sets the current value to check against when executing listeners. If a - * listeners return value matches the one set here then it will be removed - * after execution. This value defaults to true. - * - * @param {*} value The new value to check for when executing listeners. - * @return {Object} Current instance of EventEmitter for chaining. - */ - proto.setOnceReturnValue = function setOnceReturnValue(value) { - this._onceReturnValue = value; - return this; - }; - - /** - * Fetches the current value to check against when executing listeners. If - * the listeners return value matches this one then it should be removed - * automatically. It will return true by default. - * - * @return {*|Boolean} The current value to check for or the default, true. - * @api private - */ - proto._getOnceReturnValue = function _getOnceReturnValue() { - if (this.hasOwnProperty('_onceReturnValue')) { - return this._onceReturnValue; - } - else { - return true; - } - }; - - /** - * Fetches the events object and creates one if required. - * - * @return {Object} The events storage object. - * @api private - */ - proto._getEvents = function _getEvents() { - return this._events || (this._events = {}); - }; - - /** - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. - * - * @return {Function} Non conflicting EventEmitter class. - */ - EventEmitter.noConflict = function noConflict() { - exports.EventEmitter = originalGlobalValue; - return EventEmitter; - }; - - // Expose the class either via AMD, CommonJS or the global object - if (typeof define === 'function' && define.amd) { - define(function () { - return EventEmitter; - }); - } - else if (typeof module === 'object' && module.exports){ - module.exports = EventEmitter; - } - else { - exports.EventEmitter = EventEmitter; - } -}(typeof window !== 'undefined' ? window : this || {})); - -},{}],39:[function(require,module,exports){ -module.exports={ - "author": "OpenVidu", - "dependencies": { - "freeice": "2.2.2", - "hark": "1.2.3", - "jsnlog": "2.30.0", - "mime": "3.0.0", - "platform": "1.3.6", - "semver": "7.3.5", - "uuid": "8.3.2", - "wolfy87-eventemitter": "5.2.9", - "events": "3.3.0", - "inherits": "2.0.4" - }, - "description": "OpenVidu Browser", - "devDependencies": { - "@types/node": "17.0.8", - "@types/platform": "1.3.4", - "browserify": "17.0.0", - "grunt": "1.4.1", - "grunt-cli": "1.4.3", - "grunt-contrib-copy": "1.0.0", - "grunt-contrib-sass": "2.0.0", - "grunt-contrib-uglify": "5.0.1", - "grunt-contrib-watch": "1.1.0", - "grunt-postcss": "0.9.0", - "grunt-string-replace": "1.3.1", - "grunt-ts": "6.0.0-beta.22", - "terser": "5.10.0", - "tsify": "5.0.4", - "tslint": "6.1.3", - "typedoc": "0.22.10", - "typescript": "4.5.4" - }, - "license": "Apache-2.0", - "main": "lib/index.js", - "name": "openvidu-browser", - "repository": { - "type": "git", - "url": "git://github.com/OpenVidu/openvidu" - }, - "scripts": { - "browserify": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v", - "browserify-prod": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js", - "build": "cd src/OpenVidu && ./../../node_modules/typescript/bin/tsc && cd ../.. && ./node_modules/typescript/bin/tsc --declaration src/index.ts --outDir ./lib --sourceMap --target es5 --lib dom,es5,es2015.promise,scripthost && rm -rf ./ts4.4 && mkdir -p ./ts4.4/lib && cp -r ./lib ./ts4.4 && find ./ts4.4/lib -type f ! -iname '*.d.ts' -delete && ./config/replace_for_ts44.sh", - "docs": "./generate-docs.sh" - }, - "types": "lib/index.d.ts", - "typesVersions": { - "<4.4": { - "*": [ - "ts4.4/*" - ] - } - }, - "version": "2.22.0" -} -},{}],40:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var OpenVidu_1 = require("./OpenVidu/OpenVidu"); -var jsnlog_1 = require("jsnlog"); -if (window) { - window['OpenVidu'] = OpenVidu_1.OpenVidu; -} -jsnlog_1.JL.setOptions({ enabled: false }); - -},{"./OpenVidu/OpenVidu":45,"jsnlog":7}],41:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Connection = void 0; -var Stream_1 = require("./Stream"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var Connection = (function () { - function Connection(session, connectionOptions) { - this.session = session; - this.disposed = false; - var msg = "'Connection' created "; - if (!!connectionOptions.role) { - this.localOptions = connectionOptions; - this.connectionId = this.localOptions.id; - this.creationTime = this.localOptions.createdAt; - this.data = this.localOptions.metadata; - this.rpcSessionId = this.localOptions.sessionId; - this.role = this.localOptions.role; - this.record = this.localOptions.record; - msg += '(local)'; - } - else { - this.remoteOptions = connectionOptions; - this.connectionId = this.remoteOptions.id; - this.creationTime = this.remoteOptions.createdAt; - if (this.remoteOptions.metadata) { - this.data = this.remoteOptions.metadata; - } - if (this.remoteOptions.streams) { - this.initRemoteStreams(this.remoteOptions.streams); - } - msg += "(remote) with 'connectionId' [" + this.remoteOptions.id + ']'; - } - logger.info(msg); - } - Connection.prototype.sendIceCandidate = function (candidate) { - var _this = this; - logger.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' + - this.connectionId, candidate); - this.session.openvidu.sendRequest('onIceCandidate', { - endpointName: this.connectionId, - candidate: candidate.candidate, - sdpMid: candidate.sdpMid, - sdpMLineIndex: candidate.sdpMLineIndex - }, function (error, response) { - if (error) { - logger.error('Error sending ICE candidate: ' + JSON.stringify(error)); - _this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, ExceptionEvent_1.ExceptionEventName.ICE_CANDIDATE_ERROR, _this.session, "There was an unexpected error on the server-side processing an ICE candidate generated and sent by the client-side", error)]); - } - }); - }; - Connection.prototype.initRemoteStreams = function (options) { - var _this = this; - options.forEach(function (opts) { - var streamOptions = { - id: opts.id, - createdAt: opts.createdAt, - connection: _this, - hasAudio: opts.hasAudio, - hasVideo: opts.hasVideo, - audioActive: opts.audioActive, - videoActive: opts.videoActive, - typeOfVideo: opts.typeOfVideo, - frameRate: opts.frameRate, - videoDimensions: !!opts.videoDimensions ? JSON.parse(opts.videoDimensions) : undefined, - filter: !!opts.filter ? opts.filter : undefined - }; - var stream = new Stream_1.Stream(_this.session, streamOptions); - _this.addStream(stream); - }); - logger.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); - }; - Connection.prototype.addStream = function (stream) { - stream.connection = this; - this.stream = stream; - }; - Connection.prototype.removeStream = function (streamId) { - delete this.stream; - }; - Connection.prototype.dispose = function () { - if (!!this.stream) { - delete this.stream; - } - this.disposed = true; - }; - return Connection; -}()); -exports.Connection = Connection; - -},{"../OpenViduInternal/Events/ExceptionEvent":58,"../OpenViduInternal/Logger/OpenViduLogger":79,"./Stream":48}],42:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.EventDispatcher = void 0; -var EventEmitter = require("wolfy87-eventemitter"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var EventDispatcher = (function () { - function EventDispatcher() { - this.userHandlerArrowHandler = new WeakMap(); - this.ee = new EventEmitter(); - } - EventDispatcher.prototype.onAux = function (type, message, handler) { - var arrowHandler = function (event) { - if (event) { - logger.info(message, event); - } - else { - logger.info(message); - } - handler(event); - }; - this.userHandlerArrowHandler.set(handler, arrowHandler); - this.ee.on(type, arrowHandler); - return this; - }; - EventDispatcher.prototype.onceAux = function (type, message, handler) { - var _this = this; - var arrowHandler = function (event) { - if (event) { - logger.info(message, event); - } - else { - logger.info(message); - } - handler(event); - _this.userHandlerArrowHandler.delete(handler); - }; - this.userHandlerArrowHandler.set(handler, arrowHandler); - this.ee.once(type, arrowHandler); - return this; - }; - EventDispatcher.prototype.offAux = function (type, handler) { - if (!handler) { - this.ee.removeAllListeners(type); - } - else { - var arrowHandler = this.userHandlerArrowHandler.get(handler); - if (!!arrowHandler) { - this.ee.off(type, arrowHandler); - } - this.userHandlerArrowHandler.delete(handler); - } - return this; - }; - return EventDispatcher; -}()); -exports.EventDispatcher = EventDispatcher; - -},{"../OpenViduInternal/Logger/OpenViduLogger":79,"wolfy87-eventemitter":38}],43:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Filter = void 0; -var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var Filter = (function () { - function Filter(type, options) { - this.handlers = new Map(); - this.type = type; - this.options = options; - } - Filter.prototype.execMethod = function (method, params) { - var _this = this; - return new Promise(function (resolve, reject) { - var _a; - logger.info('Executing filter method to stream ' + _this.stream.streamId); - var finalParams; - var successExecMethod = function (triggerEvent) { - logger.info('Filter method successfully executed on Stream ' + _this.stream.streamId); - var oldValue = Object.assign({}, _this.stream.filter); - _this.stream.filter.lastExecMethod = { method: method, params: finalParams }; - if (triggerEvent) { - _this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.stream.session, _this.stream, 'filter', _this.stream.filter, oldValue, 'execFilterMethod')]); - _this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.stream.streamManager, _this.stream, 'filter', _this.stream.filter, oldValue, 'execFilterMethod')]); - } - return resolve(); - }; - if (_this.type.startsWith('VB:')) { - if (typeof params === 'string') { - try { - params = JSON.parse(params); - } - catch (error) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Wrong params syntax: ' + error)); - } - } - finalParams = params; - if (method === 'update') { - if (!((_a = _this.stream.virtualBackgroundSinkElements) === null || _a === void 0 ? void 0 : _a.VB)) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'There is no Virtual Background filter applied')); - } - else { - _this.stream.virtualBackgroundSinkElements.VB.updateValues(params) - .then(function () { return successExecMethod(false); }) - .catch(function (error) { - if (error.name === OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR) { - return reject(new OpenViduError_1.OpenViduError(error.name, error.message)); - } - else { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Error updating values on Virtual Background filter: ' + error)); - } - }); - } - } - else { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, "Unknown Virtual Background method \"".concat(method, "\""))); - } - } - else { - var stringParams = void 0; - if (typeof params !== 'string') { - try { - stringParams = JSON.stringify(params); - } - catch (error) { - var errorMsg = "'params' property must be a JSON formatted object"; - logger.error(errorMsg); - return reject(errorMsg); - } - } - else { - stringParams = params; - } - finalParams = stringParams; - _this.stream.session.openvidu.sendRequest('execFilterMethod', { streamId: _this.stream.streamId, method: method, params: stringParams }, function (error, response) { - if (error) { - logger.error('Error executing filter method for Stream ' + _this.stream.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to execute a filter method")); - } - else { - return reject(error); - } - } - else { - return successExecMethod(true); - } - }); - } - }); - }; - Filter.prototype.addEventListener = function (eventType, handler) { - var _this = this; - return new Promise(function (resolve, reject) { - logger.info('Adding filter event listener to event ' + eventType + ' to stream ' + _this.stream.streamId); - _this.stream.session.openvidu.sendRequest('addFilterEventListener', { streamId: _this.stream.streamId, eventType: eventType }, function (error, response) { - if (error) { - logger.error('Error adding filter event listener to event ' + eventType + 'for Stream ' + _this.stream.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener")); - } - else { - return reject(error); - } - } - else { - _this.handlers.set(eventType, handler); - logger.info('Filter event listener to event ' + eventType + ' successfully applied on Stream ' + _this.stream.streamId); - return resolve(); - } - }); - }); - }; - Filter.prototype.removeEventListener = function (eventType) { - var _this = this; - return new Promise(function (resolve, reject) { - logger.info('Removing filter event listener to event ' + eventType + ' to stream ' + _this.stream.streamId); - _this.stream.session.openvidu.sendRequest('removeFilterEventListener', { streamId: _this.stream.streamId, eventType: eventType }, function (error, response) { - if (error) { - logger.error('Error removing filter event listener to event ' + eventType + 'for Stream ' + _this.stream.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to add a filter event listener")); - } - else { - return reject(error); - } - } - else { - _this.handlers.delete(eventType); - logger.info('Filter event listener to event ' + eventType + ' successfully removed on Stream ' + _this.stream.streamId); - return resolve(); - } - }); - }); - }; - return Filter; -}()); -exports.Filter = Filter; - -},{"../OpenViduInternal/Enums/OpenViduError":52,"../OpenViduInternal/Events/StreamPropertyChangedEvent":67,"../OpenViduInternal/Logger/OpenViduLogger":79}],44:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.LocalRecorder = void 0; -var LocalRecorderState_1 = require("../OpenViduInternal/Enums/LocalRecorderState"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var Mime = require("mime/lite"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var LocalRecorder = (function () { - function LocalRecorder(stream) { - this.stream = stream; - this.chunks = []; - platform = Platform_1.PlatformUtils.getInstance(); - this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection'; - this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord'; - this.state = LocalRecorderState_1.LocalRecorderState.READY; - } - LocalRecorder.prototype.record = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (typeof options === 'string' || options instanceof String) { - return reject("When calling LocalRecorder.record(options) parameter 'options' cannot be a string. Must be an object like { mimeType: \"".concat(options, "\" }")); - } - if (typeof MediaRecorder === 'undefined') { - logger.error('MediaRecorder not supported on your device. See compatibility in https://caniuse.com/#search=MediaRecorder'); - throw (Error('MediaRecorder not supported on your device. See compatibility in https://caniuse.com/#search=MediaRecorder')); - } - if (_this.state !== LocalRecorderState_1.LocalRecorderState.READY) { - throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before')); - } - logger.log("Starting local recording of stream '" + _this.stream.streamId + "' of connection '" + _this.connectionId + "'"); - if (!options) { - options = { mimeType: 'video/webm' }; - } - else if (!options.mimeType) { - options.mimeType = 'video/webm'; - } - _this.mediaRecorder = new MediaRecorder(_this.stream.getMediaStream(), options); - _this.mediaRecorder.start(); - } - catch (err) { - return reject(err); - } - _this.mediaRecorder.ondataavailable = function (e) { - if (e.data.size > 0) { - _this.chunks.push(e.data); - } - }; - _this.mediaRecorder.onerror = function (e) { - logger.error('MediaRecorder error: ', e); - }; - _this.mediaRecorder.onstart = function () { - logger.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - }; - _this.mediaRecorder.onpause = function () { - logger.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ')'); - }; - _this.mediaRecorder.onresume = function () { - logger.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ')'); - }; - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - return resolve(); - }); - }; - LocalRecorder.prototype.stop = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state === LocalRecorderState_1.LocalRecorderState.READY || _this.state === LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before')); - } - _this.mediaRecorder.onstop = function () { - _this.onStopDefault(); - return resolve(); - }; - _this.mediaRecorder.stop(); - } - catch (e) { - return reject(e); - } - }); - }; - LocalRecorder.prototype.pause = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.RECORDING) { - return reject(Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before')); - } - _this.mediaRecorder.pause(); - _this.state = LocalRecorderState_1.LocalRecorderState.PAUSED; - return resolve(); - } - catch (error) { - return reject(error); - } - }); - }; - LocalRecorder.prototype.resume = function () { - var _this = this; - return new Promise(function (resolve, reject) { - try { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.PAUSED) { - throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.pause()\' before')); - } - _this.mediaRecorder.resume(); - _this.state = LocalRecorderState_1.LocalRecorderState.RECORDING; - return resolve(); - } - catch (error) { - return reject(error); - } - }); - }; - LocalRecorder.prototype.preview = function (parentElement) { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - this.videoPreview = document.createElement('video'); - this.videoPreview.id = this.id; - this.videoPreview.autoplay = true; - if (platform.isSafariBrowser()) { - this.videoPreview.setAttribute('playsinline', 'true'); - } - if (typeof parentElement === 'string') { - var parentElementDom = document.getElementById(parentElement); - if (parentElementDom) { - this.videoPreview = parentElementDom.appendChild(this.videoPreview); - } - } - else { - this.videoPreview = parentElement.appendChild(this.videoPreview); - } - this.videoPreview.src = this.videoPreviewSrc; - return this.videoPreview; - }; - LocalRecorder.prototype.clean = function () { - var _this = this; - var f = function () { - delete _this.blob; - _this.chunks = []; - _this.state = LocalRecorderState_1.LocalRecorderState.READY; - }; - if (this.state === LocalRecorderState_1.LocalRecorderState.RECORDING || this.state === LocalRecorderState_1.LocalRecorderState.PAUSED) { - this.stop().then(function () { return f(); }).catch(function () { return f(); }); - } - else { - f(); - } - }; - LocalRecorder.prototype.download = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var a = document.createElement('a'); - a.style.display = 'none'; - document.body.appendChild(a); - var url = window.URL.createObjectURL(this.blob); - a.href = url; - a.download = this.id + '.' + Mime.getExtension(this.blob.type); - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - } - }; - LocalRecorder.prototype.getBlob = function () { - if (this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); - } - else { - return this.blob; - } - }; - LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - return reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_1 = new XMLHttpRequest(); - http_1.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_1.setRequestHeader(key, headers[key]); - } - } - http_1.onreadystatechange = function () { - if (http_1.readyState === 4) { - if (http_1.status.toString().charAt(0) === '2') { - return resolve(http_1.responseText); - } - else { - return reject(http_1.status); - } - } - }; - http_1.send(_this.blob); - } - }); - }; - LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.state !== LocalRecorderState_1.LocalRecorderState.FINISHED) { - return reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before')); - } - else { - var http_2 = new XMLHttpRequest(); - http_2.open('POST', endpoint, true); - if (typeof headers === 'object') { - for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) { - var key = _a[_i]; - http_2.setRequestHeader(key, headers[key]); - } - } - var sendable = new FormData(); - sendable.append('file', _this.blob, _this.id + '.' + Mime.getExtension(_this.blob.type)); - http_2.onreadystatechange = function () { - if (http_2.readyState === 4) { - if (http_2.status.toString().charAt(0) === '2') { - return resolve(http_2.responseText); - } - else { - return reject(http_2.status); - } - } - }; - http_2.send(sendable); - } - }); - }; - LocalRecorder.prototype.onStopDefault = function () { - logger.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ')'); - this.blob = new Blob(this.chunks, { type: this.mediaRecorder.mimeType }); - this.chunks = []; - this.videoPreviewSrc = window.URL.createObjectURL(this.blob); - this.state = LocalRecorderState_1.LocalRecorderState.FINISHED; - }; - return LocalRecorder; -}()); -exports.LocalRecorder = LocalRecorder; - -},{"../OpenViduInternal/Enums/LocalRecorderState":51,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Utils/Platform":83,"mime/lite":9}],45:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.OpenVidu = void 0; -var LocalRecorder_1 = require("./LocalRecorder"); -var Publisher_1 = require("./Publisher"); -var Session_1 = require("./Session"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); -var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); -var OpenViduLoggerConfiguration_1 = require("../OpenViduInternal/Logger/OpenViduLoggerConfiguration"); -var EventEmitter = require("wolfy87-eventemitter"); -var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); -var packageJson = require('../../package.json'); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var OpenVidu = (function () { - function OpenVidu() { - var _this = this; - this.masterNodeHasCrashed = false; - this.publishers = []; - this.secret = ''; - this.recorder = false; - this.life = -1; - this.advancedConfiguration = {}; - this.webrtcStatsInterval = -1; - this.sendBrowserLogs = OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.disabled; - this.isAtLeastPro = false; - this.isEnterprise = false; - this.ee = new EventEmitter(); - platform = Platform_1.PlatformUtils.getInstance(); - this.libraryVersion = packageJson.version; - logger.info("OpenVidu initialized"); - logger.info('Platform detected: ' + platform.getDescription()); - logger.info('openvidu-browser version: ' + this.libraryVersion); - if (platform.isMobileDevice() || platform.isReactNative()) { - this.onOrientationChanged(function () { - _this.publishers.forEach(function (publisher) { - if (publisher.stream.isLocalStreamPublished && !!publisher.stream && !!publisher.stream.hasVideo) { - _this.sendNewVideoDimensionsIfRequired(publisher, 'deviceRotated', 75, 10); - } - }); - }); - } - } - OpenVidu.prototype.initSession = function () { - this.session = new Session_1.Session(this); - return this.session; - }; - OpenVidu.prototype.initPublisher = function (targetElement, param2, param3) { - var properties; - if (!!param2 && (typeof param2 !== 'function')) { - properties = param2; - properties = { - audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, - frameRate: (typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), - insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, - publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, - publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, - resolution: (typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), - videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined, - videoSimulcast: properties.videoSimulcast, - filter: properties.filter - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - mirror: true, - publishAudio: true, - publishVideo: true, - resolution: '640x480' - }; - } - var publisher = new Publisher_1.Publisher(targetElement, properties, this); - var completionHandler; - if (!!param2 && (typeof param2 === 'function')) { - completionHandler = param2; - } - else if (!!param3) { - completionHandler = param3; - } - publisher.initialize() - .then(function () { - if (completionHandler !== undefined) { - completionHandler(undefined); - } - publisher.emitEvent('accessAllowed', []); - }).catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - publisher.emitEvent('accessDenied', [error]); - }); - this.publishers.push(publisher); - return publisher; - }; - OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - var publisher; - var callback = function (error) { - if (!!error) { - return reject(error); - } - else { - return resolve(publisher); - } - }; - if (!!properties) { - publisher = _this.initPublisher(targetElement, properties, callback); - } - else { - publisher = _this.initPublisher(targetElement, callback); - } - }); - }; - OpenVidu.prototype.initLocalRecorder = function (stream) { - return new LocalRecorder_1.LocalRecorder(stream); - }; - OpenVidu.prototype.checkSystemRequirements = function () { - if (platform.isIPhoneOrIPad()) { - if (platform.isIOSWithSafari() || platform.isIonicIos() || - platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()) { - return 1; - } - return 0; - } - if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || - platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isOperaBrowser() || - platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() || - platform.isSafariBrowser() || platform.isAndroidBrowser() || platform.isElectron() || platform.isSamsungBrowser()) { - return 1; - } - return 0; - }; - OpenVidu.prototype.checkScreenSharingCapabilities = function () { - return platform.canScreenShare(); - }; - OpenVidu.prototype.getDevices = function () { - return new Promise(function (resolve, reject) { - navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { - var _a; - var devices = []; - if (platform.isIonicAndroid() && typeof cordova != "undefined" && ((_a = cordova === null || cordova === void 0 ? void 0 : cordova.plugins) === null || _a === void 0 ? void 0 : _a.EnumerateDevicesPlugin)) { - cordova.plugins.EnumerateDevicesPlugin.getEnumerateDevices().then(function (pluginDevices) { - var pluginAudioDevices = []; - var videoDevices = []; - var audioDevices = []; - pluginAudioDevices = pluginDevices.filter(function (device) { return device.kind === 'audioinput'; }); - videoDevices = deviceInfos.filter(function (device) { return device.kind === 'videoinput'; }); - audioDevices = deviceInfos.filter(function (device) { return device.kind === 'audioinput'; }); - videoDevices.forEach(function (deviceInfo, index) { - if (!deviceInfo.label) { - var label = ""; - if (index === 0) { - label = "Front Camera"; - } - else if (index === 1) { - label = "Back Camera"; - } - else { - label = "Unknown Camera"; - } - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: label - }); - } - else { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - audioDevices.forEach(function (deviceInfo, index) { - if (!deviceInfo.label) { - var label = ""; - switch (index) { - case 0: - label = 'Default'; - break; - case 1: - var defaultMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Built'); })[0]; - label = defaultMatch ? defaultMatch.label : 'Built-in Microphone'; - break; - case 2: - var wiredMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Wired'); })[0]; - if (wiredMatch) { - label = wiredMatch.label; - } - else { - label = 'Headset earpiece'; - } - break; - case 3: - var wirelessMatch = pluginAudioDevices.filter(function (d) { return d.label.includes('Bluetooth'); })[0]; - label = wirelessMatch ? wirelessMatch.label : 'Wireless'; - break; - default: - label = "Unknown Microphone"; - break; - } - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: label - }); - } - else { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - return resolve(devices); - }); - } - else { - deviceInfos.forEach(function (deviceInfo) { - if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { - devices.push({ - kind: deviceInfo.kind, - deviceId: deviceInfo.deviceId, - label: deviceInfo.label - }); - } - }); - return resolve(devices); - } - }).catch(function (error) { - logger.error('Error getting devices', error); - return reject(error); - }); - }); - }; - OpenVidu.prototype.getUserMedia = function (options) { - var _this = this; - return new Promise(function (resolve, reject) { - var askForAudioStreamOnly = function (previousMediaStream, constraints) { - var definedAudioConstraint = ((constraints.audio === undefined) ? true : constraints.audio); - var constraintsAux = { audio: definedAudioConstraint, video: false }; - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - previousMediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - return resolve(previousMediaStream); - }) - .catch(function (error) { - previousMediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - previousMediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - return reject(_this.generateAudioDeviceError(error, constraintsAux)); - }); - }; - _this.generateMediaConstraints(options).then(function (myConstraints) { - var _a, _b; - if (!!myConstraints.videoTrack && !!myConstraints.audioTrack || - !!myConstraints.audioTrack && ((_a = myConstraints.constraints) === null || _a === void 0 ? void 0 : _a.video) === false || - !!myConstraints.videoTrack && ((_b = myConstraints.constraints) === null || _b === void 0 ? void 0 : _b.audio) === false) { - return resolve(_this.addAlreadyProvidedTracks(myConstraints, new MediaStream())); - } - else { - if (!!myConstraints.videoTrack) { - delete myConstraints.constraints.video; - } - if (!!myConstraints.audioTrack) { - delete myConstraints.constraints.audio; - } - var mustAskForAudioTrackLater_1 = false; - if (typeof options.videoSource === 'string') { - if (options.videoSource === 'screen' || - options.videoSource === 'window' || - (platform.isElectron() && options.videoSource.startsWith('screen:'))) { - mustAskForAudioTrackLater_1 = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false); - if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { - navigator.mediaDevices['getDisplayMedia']({ video: true }) - .then(function (mediaStream) { - _this.addAlreadyProvidedTracks(myConstraints, mediaStream); - if (mustAskForAudioTrackLater_1) { - askForAudioStreamOnly(mediaStream, myConstraints.constraints); - return; - } - else { - return resolve(mediaStream); - } - }) - .catch(function (error) { - var errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - var errorMessage = error.toString(); - return reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - return; - } - else { - } - } - else { - } - } - var constraintsAux = mustAskForAudioTrackLater_1 ? { video: myConstraints.constraints.video } : myConstraints.constraints; - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.addAlreadyProvidedTracks(myConstraints, mediaStream); - if (mustAskForAudioTrackLater_1) { - askForAudioStreamOnly(mediaStream, myConstraints.constraints); - return; - } - else { - return resolve(mediaStream); - } - }) - .catch(function (error) { - var errorName; - var errorMessage = error.toString(); - if (!(options.videoSource === 'screen')) { - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; - } - return reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - } - }).catch(function (error) { return reject(error); }); - }); - }; - OpenVidu.prototype.enableProdMode = function () { - logger.enableProdMode(); - }; - OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { - this.advancedConfiguration = configuration; - }; - OpenVidu.prototype.onOrientationChanged = function (handler) { - window.addEventListener('orientationchange', handler); - }; - OpenVidu.prototype.sendNewVideoDimensionsIfRequired = function (publisher, reason, WAIT_INTERVAL, MAX_ATTEMPTS) { - var _this = this; - var attempts = 0; - var oldWidth = publisher.stream.videoDimensions.width; - var oldHeight = publisher.stream.videoDimensions.height; - var repeatUntilChangeOrMaxAttempts = setInterval(function () { - attempts++; - if (attempts > MAX_ATTEMPTS) { - clearTimeout(repeatUntilChangeOrMaxAttempts); - } - publisher.getVideoDimensions().then(function (newDimensions) { - if (newDimensions.width !== oldWidth || newDimensions.height !== oldHeight) { - clearTimeout(repeatUntilChangeOrMaxAttempts); - _this.sendVideoDimensionsChangedEvent(publisher, reason, oldWidth, oldHeight, newDimensions.width, newDimensions.height); - } - }); - }, WAIT_INTERVAL); - }; - OpenVidu.prototype.sendVideoDimensionsChangedEvent = function (publisher, reason, oldWidth, oldHeight, newWidth, newHeight) { - var _this = this; - publisher.stream.videoDimensions = { - width: newWidth || 0, - height: newHeight || 0 - }; - this.sendRequest('streamPropertyChanged', { - streamId: publisher.stream.streamId, - property: 'videoDimensions', - newValue: JSON.stringify(publisher.stream.videoDimensions), - reason: reason - }, function (error, response) { - if (error) { - logger.error("Error sending 'streamPropertyChanged' event", error); - } - else { - _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, reason)]); - publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, reason)]); - _this.session.sendVideoData(publisher); - } - }); - }; - ; - OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { - var _this = this; - return new Promise(function (resolve, reject) { - var myConstraints = { - audioTrack: undefined, - videoTrack: undefined, - constraints: { - audio: undefined, - video: undefined - } - }; - var audioSource = publisherProperties.audioSource; - var videoSource = publisherProperties.videoSource; - if (audioSource === null || audioSource === false) { - myConstraints.constraints.audio = false; - } - if (videoSource === null || videoSource === false) { - myConstraints.constraints.video = false; - } - if (myConstraints.constraints.audio === false && myConstraints.constraints.video === false) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time")); - } - if (typeof MediaStreamTrack !== 'undefined' && audioSource instanceof MediaStreamTrack) { - myConstraints.audioTrack = audioSource; - } - if (typeof MediaStreamTrack !== 'undefined' && videoSource instanceof MediaStreamTrack) { - myConstraints.videoTrack = videoSource; - } - if (audioSource === undefined) { - myConstraints.constraints.audio = true; - } - if (videoSource === undefined) { - myConstraints.constraints.video = { - width: { - ideal: 640 - }, - height: { - ideal: 480 - } - }; - } - if (videoSource !== null && videoSource !== false) { - if (!!publisherProperties.resolution) { - var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); - var idealWidth = Number(widthAndHeight[0]); - var idealHeight = Number(widthAndHeight[1]); - myConstraints.constraints.video = { - width: { - ideal: idealWidth - }, - height: { - ideal: idealHeight - } - }; - } - if (!!publisherProperties.frameRate) { - myConstraints.constraints.video.frameRate = { ideal: publisherProperties.frameRate }; - } - } - _this.configureDeviceIdOrScreensharing(myConstraints, publisherProperties, resolve, reject); - return resolve(myConstraints); - }); - }; - OpenVidu.prototype.startWs = function (onConnectSucces) { - var config = { - heartbeat: 5000, - ws: { - uri: this.wsUri + '?sessionId=' + this.session.sessionId, - onconnected: onConnectSucces, - ondisconnect: this.disconnectCallback.bind(this), - onreconnecting: this.reconnectingCallback.bind(this), - onreconnected: this.reconnectedCallback.bind(this), - ismasternodecrashed: this.isMasterNodeCrashed.bind(this) - }, - rpc: { - requestTimeout: 10000, - heartbeatRequestTimeout: 5000, - participantJoined: this.session.onParticipantJoined.bind(this.session), - participantPublished: this.session.onParticipantPublished.bind(this.session), - participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), - participantLeft: this.session.onParticipantLeft.bind(this.session), - participantEvicted: this.session.onParticipantEvicted.bind(this.session), - recordingStarted: this.session.onRecordingStarted.bind(this.session), - recordingStopped: this.session.onRecordingStopped.bind(this.session), - sendMessage: this.session.onNewMessage.bind(this.session), - streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session), - connectionPropertyChanged: this.session.onConnectionPropertyChanged.bind(this.session), - networkQualityLevelChanged: this.session.onNetworkQualityLevelChangedChanged.bind(this.session), - filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session), - iceCandidate: this.session.recvIceCandidate.bind(this.session), - mediaError: this.session.onMediaError.bind(this.session), - masterNodeCrashedNotification: this.onMasterNodeCrashedNotification.bind(this), - forciblyReconnectSubscriber: this.session.onForciblyReconnectSubscriber.bind(this.session) - } - }; - this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); - }; - OpenVidu.prototype.onMasterNodeCrashedNotification = function (response) { - console.error('Master Node has crashed'); - this.masterNodeHasCrashed = true; - this.session.onLostConnection("nodeCrashed"); - this.jsonRpcClient.close(4103, "Master Node has crashed"); - }; - OpenVidu.prototype.getWsReadyState = function () { - return this.jsonRpcClient.getReadyState(); - }; - OpenVidu.prototype.closeWs = function () { - this.jsonRpcClient.close(4102, "Connection closed by client"); - }; - OpenVidu.prototype.sendRequest = function (method, params, callback) { - if (params && params instanceof Function) { - callback = params; - params = {}; - } - logger.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); - }; - OpenVidu.prototype.getWsUri = function () { - return this.wsUri; - }; - OpenVidu.prototype.getSecret = function () { - return this.secret; - }; - OpenVidu.prototype.getRecorder = function () { - return this.recorder; - }; - OpenVidu.prototype.generateAudioDeviceError = function (error, constraints) { - if (error.name === 'Error') { - error.name = error.constructor.name; - } - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - return new OpenViduError_1.OpenViduError(errorName, errorMessage); - case 'notallowederror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - return new OpenViduError_1.OpenViduError(errorName, errorMessage); - case 'overconstrainederror': - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - return new OpenViduError_1.OpenViduError(errorName, errorMessage); - case 'notreadableerror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ALREADY_IN_USE; - errorMessage = error.toString(); - return (new OpenViduError_1.OpenViduError(errorName, errorMessage)); - default: - return new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_GENERIC_ERROR, error.toString()); - } - }; - OpenVidu.prototype.addAlreadyProvidedTracks = function (myConstraints, mediaStream, stream) { - if (!!myConstraints.videoTrack) { - mediaStream.addTrack(myConstraints.videoTrack); - if (!!stream) { - if (!!myConstraints.constraints.video) { - stream.lastVideoTrackConstraints = myConstraints.constraints.video; - } - else { - stream.lastVideoTrackConstraints = myConstraints.videoTrack.getConstraints(); - } - } - } - if (!!myConstraints.audioTrack) { - mediaStream.addTrack(myConstraints.audioTrack); - } - return mediaStream; - }; - OpenVidu.prototype.configureDeviceIdOrScreensharing = function (myConstraints, publisherProperties, resolve, reject) { - var _this = this; - var audioSource = publisherProperties.audioSource; - var videoSource = publisherProperties.videoSource; - if (typeof audioSource === 'string') { - myConstraints.constraints.audio = { deviceId: { exact: audioSource } }; - } - if (typeof videoSource === 'string') { - if (!this.isScreenShare(videoSource)) { - this.setVideoSource(myConstraints, videoSource); - } - else { - if (!this.checkScreenSharingCapabilities()) { - var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0), Edge (>= 80) or Electron. Detected client: ' + platform.getName() + ' ' + platform.getVersion()); - logger.error(error); - return reject(error); - } - else { - if (platform.isElectron()) { - var prefix = "screen:"; - var videoSourceString = videoSource; - var electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length); - myConstraints.constraints.video = { - mandatory: { - chromeMediaSource: 'desktop', - chromeMediaSourceId: electronScreenId - } - }; - return resolve(myConstraints); - } - else { - if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) && !navigator.mediaDevices['getDisplayMedia']) { - screenSharing.getScreenConstraints(function (error, screenConstraints) { - if (!!error || !!screenConstraints.mandatory && screenConstraints.mandatory.chromeMediaSource === 'screen') { - if (error === 'permission-denied' || error === 'PermissionDeniedError') { - var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - logger.error(error_1); - return reject(error_1); - } - else { - var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); - screenSharing.getChromeExtensionStatus(extensionId, function (status) { - if (status === 'installed-disabled') { - var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - logger.error(error_2); - return reject(error_2); - } - if (status === 'not-installed') { - var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); - logger.error(error_3); - return reject(error_3); - } - }); - return; - } - } - else { - myConstraints.constraints.video = screenConstraints; - return resolve(myConstraints); - } - }); - return; - } - else { - if (navigator.mediaDevices['getDisplayMedia']) { - return resolve(myConstraints); - } - else { - var firefoxString = (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? publisherProperties.videoSource : undefined; - screenSharingAuto.getScreenId(firefoxString, function (error, sourceId, screenConstraints) { - if (!!error) { - if (error === 'not-installed') { - var extensionUrl = !!_this.advancedConfiguration.screenShareChromeExtension ? _this.advancedConfiguration.screenShareChromeExtension : - 'https://chrome.google.com/webstore/detail/openvidu-screensharing/lfcgfepafnobdloecchnfaclibenjold'; - var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, extensionUrl); - logger.error(err); - return reject(err); - } - else if (error === 'installed-disabled') { - var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); - logger.error(err); - return reject(err); - } - else if (error === 'permission-denied') { - var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); - logger.error(err); - return reject(err); - } - else { - var err = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, 'Unknown error when accessing screen share'); - logger.error(err); - logger.error(error); - return reject(err); - } - } - else { - myConstraints.constraints.video = screenConstraints.video; - return resolve(myConstraints); - } - }); - return; - } - } - } - } - } - } - }; - OpenVidu.prototype.setVideoSource = function (myConstraints, videoSource) { - if (!myConstraints.constraints.video) { - myConstraints.constraints.video = {}; - } - myConstraints.constraints.video['deviceId'] = { exact: videoSource }; - }; - OpenVidu.prototype.disconnectCallback = function () { - logger.warn('Websocket connection lost'); - if (this.isRoomAvailable()) { - this.session.onLostConnection('networkDisconnect'); - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.reconnectingCallback = function () { - logger.warn('Websocket connection lost (reconnecting)'); - if (!this.isRoomAvailable()) { - alert('Connection error. Please reload page.'); - } - else { - this.session.emitEvent('reconnecting', []); - } - }; - OpenVidu.prototype.reconnectWebsocketThroughRpcConnectMethod = function (rpcSessionId) { - var _this = this; - this.sendRequest('connect', { sessionId: rpcSessionId, reconnect: true }, function (error, response) { - if (!!error) { - if (_this.isMasterNodeCrashed()) { - logger.warn('Master Node has crashed!'); - } - else { - logger.error(error); - var notifyLostConnection_1 = function (reason, errorMsg) { - logger.warn(errorMsg); - _this.session.onLostConnection(reason); - _this.jsonRpcClient.close(4101, "Reconnection fault: " + errorMsg); - }; - var rpcSessionStatus = function () { - if (_this.life === -1) { - notifyLostConnection_1('networkDisconnect', 'WS successfully reconnected but the user was already evicted due to timeout'); - } - else { - _this.sendRequest('sessionStatus', { sessionId: _this.session.sessionId }, function (error, response) { - if (error != null) { - console.error('Error checking session status', error); - } - else { - if (_this.life === response.life) { - notifyLostConnection_1('networkDisconnect', 'WS successfully reconnected but the user was already evicted due to timeout'); - } - else { - notifyLostConnection_1('nodeCrashed', 'WS successfully reconnected to OpenVidu Server but your Master Node crashed'); - } - } - }); - } - }; - if (error.code === 40007 && error.message === 'reconnection error') { - console.error('Invalid RPC sessionId. Client network disconnection or Master Node crash'); - rpcSessionStatus(); - } - else { - rpcSessionStatus(); - } - } - } - else { - _this.jsonRpcClient.resetPing(); - _this.session.onRecoveredConnection(); - } - }); - }; - OpenVidu.prototype.reconnectedCallback = function () { - logger.warn('Websocket reconnected'); - if (this.isRoomAvailable()) { - if (!!this.session.connection) { - this.reconnectWebsocketThroughRpcConnectMethod(this.session.connection.rpcSessionId); - } - else { - logger.warn('There was no previous connection when running reconnection callback'); - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this.session, 'networkDisconnect'); - this.session.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehavior(); - } - } - else { - alert('Connection error. Please reload page.'); - } - }; - OpenVidu.prototype.isMasterNodeCrashed = function () { - return this.masterNodeHasCrashed; - }; - OpenVidu.prototype.isRoomAvailable = function () { - if (this.session !== undefined && this.session instanceof Session_1.Session) { - return true; - } - else { - logger.warn('Session instance not found'); - return false; - } - }; - OpenVidu.prototype.isScreenShare = function (videoSource) { - return videoSource === 'screen' || - videoSource === 'window' || - (platform.isElectron() && videoSource.startsWith('screen:')); - }; - return OpenVidu; -}()); -exports.OpenVidu = OpenVidu; - -},{"../../package.json":39,"../OpenViduInternal/Enums/OpenViduError":52,"../OpenViduInternal/Enums/VideoInsertMode":54,"../OpenViduInternal/Events/SessionDisconnectedEvent":63,"../OpenViduInternal/Events/StreamPropertyChangedEvent":67,"../OpenViduInternal/KurentoUtils/kurento-jsonrpc":74,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Logger/OpenViduLoggerConfiguration":80,"../OpenViduInternal/ScreenSharing/Screen-Capturing":82,"../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto":81,"../OpenViduInternal/Utils/Platform":83,"./LocalRecorder":44,"./Publisher":46,"./Session":47,"wolfy87-eventemitter":38}],46:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Publisher = void 0; -var Session_1 = require("./Session"); -var Stream_1 = require("./Stream"); -var StreamManager_1 = require("./StreamManager"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var TypeOfVideo_1 = require("../OpenViduInternal/Enums/TypeOfVideo"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var Publisher = (function (_super) { - __extends(Publisher, _super); - function Publisher(targEl, properties, openvidu) { - var _this = _super.call(this, new Stream_1.Stream((!!openvidu.session) ? openvidu.session : new Session_1.Session(openvidu), { publisherProperties: properties, mediaConstraints: {} }), targEl) || this; - _this.accessAllowed = false; - _this.isSubscribedToRemote = false; - _this.accessDenied = false; - platform = Platform_1.PlatformUtils.getInstance(); - _this.properties = properties; - _this.openvidu = openvidu; - _this.stream.ee.on('local-stream-destroyed', function (reason) { - _this.stream.isLocalStreamPublished = false; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', _this.stream, reason); - _this.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehavior(); - }); - return _this; - } - Publisher.prototype.publishAudio = function (enabled) { - var _this = this; - if (this.stream.audioActive !== enabled) { - var affectedMediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); - affectedMediaStream.getAudioTracks().forEach(function (track) { - track.enabled = enabled; - }); - if (!!this.session && !!this.stream.streamId) { - this.session.openvidu.sendRequest('streamPropertyChanged', { - streamId: this.stream.streamId, - property: 'audioActive', - newValue: enabled, - reason: 'publishAudio' - }, function (error, response) { - if (error) { - logger.error("Error sending 'streamPropertyChanged' event", error); - } - else { - _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'audioActive', enabled, !enabled, 'publishAudio')]); - _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'audioActive', enabled, !enabled, 'publishAudio')]); - _this.session.sendVideoData(_this.stream.streamManager); - } - }); - } - this.stream.audioActive = enabled; - logger.info("'Publisher' has " + (enabled ? 'published' : 'unpublished') + ' its audio stream'); - } - }; - Publisher.prototype.publishVideo = function (enabled, resource) { - var _this = this; - return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { - var affectedMediaStream_1, mustRestartMediaStream_1, oldVideoTrack, replaceVideoTrack, mediaStream, error_1; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!(this.stream.videoActive !== enabled)) return [3, 9]; - affectedMediaStream_1 = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); - mustRestartMediaStream_1 = false; - affectedMediaStream_1.getVideoTracks().forEach(function (track) { - track.enabled = enabled; - if (!enabled && resource === true) { - track.stop(); - } - else if (enabled && track.readyState === 'ended') { - mustRestartMediaStream_1 = true; - } - }); - if (!(!enabled && resource === true && !!this.stream.filter && this.stream.filter.type.startsWith('VB:'))) return [3, 2]; - this.stream.lastVBFilter = this.stream.filter; - return [4, this.stream.removeFilterAux(true)]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - if (!mustRestartMediaStream_1) return [3, 8]; - oldVideoTrack = affectedMediaStream_1.getVideoTracks()[0]; - affectedMediaStream_1.removeTrack(oldVideoTrack); - replaceVideoTrack = function (tr) { return __awaiter(_this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - affectedMediaStream_1.addTrack(tr); - if (!this.stream.isLocalStreamPublished) return [3, 2]; - return [4, this.replaceTrackInRtcRtpSender(tr)]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - if (!!this.stream.lastVBFilter) { - setTimeout(function () { return __awaiter(_this, void 0, void 0, function () { - var options, lastExecMethod; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - options = this.stream.lastVBFilter.options; - lastExecMethod = this.stream.lastVBFilter.lastExecMethod; - if (!!lastExecMethod && lastExecMethod.method === 'update') { - options = Object.assign({}, options, lastExecMethod.params); - } - return [4, this.stream.applyFilter(this.stream.lastVBFilter.type, options)]; - case 1: - _a.sent(); - delete this.stream.lastVBFilter; - return [2]; - } - }); - }); }, 1); - } - return [2]; - } - }); - }); }; - if (!(!!resource && resource instanceof MediaStreamTrack)) return [3, 4]; - return [4, replaceVideoTrack(resource)]; - case 3: - _a.sent(); - return [3, 8]; - case 4: - _a.trys.push([4, 7, , 8]); - return [4, navigator.mediaDevices.getUserMedia({ audio: false, video: this.stream.lastVideoTrackConstraints })]; - case 5: - mediaStream = _a.sent(); - return [4, replaceVideoTrack(mediaStream.getVideoTracks()[0])]; - case 6: - _a.sent(); - return [3, 8]; - case 7: - error_1 = _a.sent(); - return [2, reject(error_1)]; - case 8: - if (!!this.session && !!this.stream.streamId) { - this.session.openvidu.sendRequest('streamPropertyChanged', { - streamId: this.stream.streamId, - property: 'videoActive', - newValue: enabled, - reason: 'publishVideo' - }, function (error, response) { - if (error) { - logger.error("Error sending 'streamPropertyChanged' event", error); - } - else { - _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this.stream, 'videoActive', enabled, !enabled, 'publishVideo')]); - _this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, _this.stream, 'videoActive', enabled, !enabled, 'publishVideo')]); - _this.session.sendVideoData(_this.stream.streamManager); - } - }); - } - this.stream.videoActive = enabled; - logger.info("'Publisher' has " + (enabled ? 'published' : 'unpublished') + ' its video stream'); - return [2, resolve()]; - case 9: return [2]; - } - }); - }); }); - }; - Publisher.prototype.subscribeToRemote = function (value) { - value = (value !== undefined) ? value : true; - this.isSubscribedToRemote = value; - this.stream.subscribeToMyRemote(value); - }; - Publisher.prototype.on = function (type, handler) { - var _this = this; - _super.prototype.on.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.on('stream-created-by-publisher', function () { - _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.emitEvent('accessAllowed', []); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.emitEvent('accessDenied', []); - } - } - return this; - }; - Publisher.prototype.once = function (type, handler) { - var _this = this; - _super.prototype.once.call(this, type, handler); - if (type === 'streamCreated') { - if (!!this.stream && this.stream.isLocalStreamPublished) { - this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, this, 'streamCreated', this.stream, '')]); - } - else { - this.stream.ee.once('stream-created-by-publisher', function () { - _this.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', _this.stream, '')]); - }); - } - } - if (type === 'accessAllowed') { - if (this.accessAllowed) { - this.emitEvent('accessAllowed', []); - } - } - if (type === 'accessDenied') { - if (this.accessDenied) { - this.emitEvent('accessDenied', []); - } - } - return this; - }; - Publisher.prototype.off = function (type, handler) { - _super.prototype.off.call(this, type, handler); - return this; - }; - Publisher.prototype.replaceTrack = function (track) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2, this.replaceTrackAux(track, true)]; - }); - }); - }; - Publisher.prototype.initialize = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var constraints = {}; - var constraintsAux = {}; - var timeForDialogEvent = 2000; - var startTime; - var errorCallback = function (openViduError) { - _this.accessDenied = true; - _this.accessAllowed = false; - logger.error("Publisher initialization failed. ".concat(openViduError.name, ": ").concat(openViduError.message)); - return reject(openViduError); - }; - var successCallback = function (mediaStream) { - var _a, _b; - _this.accessAllowed = true; - _this.accessDenied = false; - if (typeof MediaStreamTrack !== 'undefined' && _this.properties.audioSource instanceof MediaStreamTrack) { - mediaStream.removeTrack(mediaStream.getAudioTracks()[0]); - mediaStream.addTrack(_this.properties.audioSource); - } - if (typeof MediaStreamTrack !== 'undefined' && _this.properties.videoSource instanceof MediaStreamTrack) { - mediaStream.removeTrack(mediaStream.getVideoTracks()[0]); - mediaStream.addTrack(_this.properties.videoSource); - } - if (!!mediaStream.getAudioTracks()[0]) { - var enabled = (_this.stream.audioActive !== undefined && _this.stream.audioActive !== null) ? _this.stream.audioActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; - mediaStream.getAudioTracks()[0].enabled = enabled; - } - if (!!mediaStream.getVideoTracks()[0]) { - var enabled = (_this.stream.videoActive !== undefined && _this.stream.videoActive !== null) ? _this.stream.videoActive : !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; - mediaStream.getVideoTracks()[0].enabled = enabled; - } - for (var _i = 0, _c = mediaStream.getAudioTracks(); _i < _c.length; _i++) { - var track = _c[_i]; - if (!((_a = track.contentHint) === null || _a === void 0 ? void 0 : _a.length)) { - track.contentHint = ''; - logger.info("Audio track Content Hint set: '".concat(track.contentHint, "'")); - } - } - for (var _d = 0, _e = mediaStream.getVideoTracks(); _d < _e.length; _d++) { - var track = _e[_d]; - if (!((_b = track.contentHint) === null || _b === void 0 ? void 0 : _b.length)) { - switch (_this.stream.typeOfVideo) { - case TypeOfVideo_1.TypeOfVideo.SCREEN: - track.contentHint = "detail"; - break; - case TypeOfVideo_1.TypeOfVideo.CUSTOM: - logger.warn("CUSTOM type video track was provided without Content Hint!"); - track.contentHint = "motion"; - break; - case TypeOfVideo_1.TypeOfVideo.CAMERA: - case TypeOfVideo_1.TypeOfVideo.IPCAM: - default: - track.contentHint = "motion"; - break; - } - logger.info("Video track Content Hint set: '".concat(track.contentHint, "'")); - } - } - _this.initializeVideoReference(mediaStream); - if (!_this.stream.displayMyRemote()) { - _this.stream.updateMediaStreamInVideos(); - } - delete _this.firstVideoElement; - if (_this.stream.isSendVideo()) { - _this.getVideoDimensions().then(function (dimensions) { - _this.stream.videoDimensions = { - width: dimensions.width, - height: dimensions.height - }; - if (_this.stream.isSendScreen()) { - _this.screenShareResizeInterval = setInterval(function () { - var settings = mediaStream.getVideoTracks()[0].getSettings(); - var newWidth = settings.width; - var newHeight = settings.height; - var widthChanged = newWidth != null && newWidth !== _this.stream.videoDimensions.width; - var heightChanged = newHeight != null && newHeight !== _this.stream.videoDimensions.height; - if (_this.stream.isLocalStreamPublished && (widthChanged || heightChanged)) { - _this.openvidu.sendVideoDimensionsChangedEvent(_this, 'screenResized', _this.stream.videoDimensions.width, _this.stream.videoDimensions.height, newWidth || 0, newHeight || 0); - } - }, 650); - } - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - }); - } - else { - _this.stream.isLocalStreamReadyToPublish = true; - _this.stream.ee.emitEvent('stream-ready-to-publish', []); - } - return resolve(); - }; - var getMediaSuccess = function (mediaStream, definedAudioConstraint) { - _this.clearPermissionDialogTimer(startTime, timeForDialogEvent); - if (_this.stream.isSendScreen() && _this.stream.isSendAudio()) { - constraintsAux.audio = definedAudioConstraint; - constraintsAux.video = false; - startTime = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (audioOnlyStream) { - _this.clearPermissionDialogTimer(startTime, timeForDialogEvent); - mediaStream.addTrack(audioOnlyStream.getAudioTracks()[0]); - successCallback(mediaStream); - }) - .catch(function (error) { - _this.clearPermissionDialogTimer(startTime, timeForDialogEvent); - mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorCallback(_this.openvidu.generateAudioDeviceError(error, constraints)); - return; - }); - } - else { - successCallback(mediaStream); - } - }; - var getMediaError = function (error) { - logger.error("getMediaError: ".concat(error.toString())); - _this.clearPermissionDialogTimer(startTime, timeForDialogEvent); - if (error.name === 'Error') { - error.name = error.constructor.name; - } - var errorName, errorMessage; - switch (error.name.toLowerCase()) { - case 'notfounderror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'notallowederror': - errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.DEVICE_ACCESS_DENIED; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - case 'overconstrainederror': - navigator.mediaDevices.getUserMedia({ - audio: false, - video: constraints.video - }) - .then(function (mediaStream) { - mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; - errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }).catch(function (e) { - if (error.constraint.toLowerCase() === 'deviceid') { - errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; - errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; - } - else { - errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; - errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; - } - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - }); - break; - case 'aborterror': - case 'notreadableerror': - errorName = OpenViduError_1.OpenViduErrorName.DEVICE_ALREADY_IN_USE; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - default: - errorName = OpenViduError_1.OpenViduErrorName.GENERIC_ERROR; - errorMessage = error.toString(); - errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); - break; - } - }; - _this.openvidu.generateMediaConstraints(_this.properties) - .then(function (myConstraints) { - var _a, _b; - if (!!myConstraints.videoTrack && !!myConstraints.audioTrack || - !!myConstraints.audioTrack && ((_a = myConstraints.constraints) === null || _a === void 0 ? void 0 : _a.video) === false || - !!myConstraints.videoTrack && ((_b = myConstraints.constraints) === null || _b === void 0 ? void 0 : _b.audio) === false) { - successCallback(_this.openvidu.addAlreadyProvidedTracks(myConstraints, new MediaStream(), _this.stream)); - return; - } - constraints = myConstraints.constraints; - var outboundStreamOptions = { - mediaConstraints: constraints, - publisherProperties: _this.properties - }; - _this.stream.setOutboundStreamOptions(outboundStreamOptions); - var definedAudioConstraint = ((constraints.audio === undefined) ? true : constraints.audio); - constraintsAux.audio = _this.stream.isSendScreen() ? false : definedAudioConstraint; - constraintsAux.video = constraints.video; - startTime = Date.now(); - _this.setPermissionDialogTimer(timeForDialogEvent); - if (_this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { - navigator.mediaDevices['getDisplayMedia']({ video: true }) - .then(function (mediaStream) { - _this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream); - getMediaSuccess(mediaStream, definedAudioConstraint); - }) - .catch(function (error) { - getMediaError(error); - }); - } - else { - _this.stream.lastVideoTrackConstraints = constraintsAux.video; - navigator.mediaDevices.getUserMedia(constraintsAux) - .then(function (mediaStream) { - _this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream, _this.stream); - getMediaSuccess(mediaStream, definedAudioConstraint); - }) - .catch(function (error) { - getMediaError(error); - }); - } - }) - .catch(function (error) { - errorCallback(error); - }); - }); - }; - Publisher.prototype.replaceTrackAux = function (track, updateLastConstraints) { - return __awaiter(this, void 0, void 0, function () { - var trackOriginalEnabledValue, error_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - trackOriginalEnabledValue = track.enabled; - if (track.kind === 'video') { - track.enabled = this.stream.videoActive; - } - else if (track.kind === 'audio') { - track.enabled = this.stream.audioActive; - } - _a.label = 1; - case 1: - _a.trys.push([1, 7, , 8]); - if (!this.stream.isLocalStreamPublished) return [3, 4]; - return [4, this.replaceTrackInMediaStream(track, updateLastConstraints)]; - case 2: - _a.sent(); - return [4, this.replaceTrackInRtcRtpSender(track)]; - case 3: return [2, _a.sent()]; - case 4: return [4, this.replaceTrackInMediaStream(track, updateLastConstraints)]; - case 5: return [2, _a.sent()]; - case 6: return [3, 8]; - case 7: - error_2 = _a.sent(); - track.enabled = trackOriginalEnabledValue; - throw error_2; - case 8: return [2]; - } - }); - }); - }; - Publisher.prototype.getVideoDimensions = function () { - var _this = this; - return new Promise(function (resolve, reject) { - var requiresDomInsertion = platform.isIonicIos() || platform.isIOSWithSafari(); - var loadedmetadataListener; - var resolveDimensions = function () { - var width; - var height; - if (typeof _this.stream.getMediaStream().getVideoTracks()[0].getSettings === 'function') { - var settings = _this.stream.getMediaStream().getVideoTracks()[0].getSettings(); - width = settings.width || _this.videoReference.videoWidth; - height = settings.height || _this.videoReference.videoHeight; - } - else { - logger.warn('MediaStreamTrack does not have getSettings method on ' + platform.getDescription()); - width = _this.videoReference.videoWidth; - height = _this.videoReference.videoHeight; - } - if (loadedmetadataListener != null) { - _this.videoReference.removeEventListener('loadedmetadata', loadedmetadataListener); - } - if (requiresDomInsertion) { - document.body.removeChild(_this.videoReference); - } - return resolve({ width: width, height: height }); - }; - if (_this.videoReference.readyState >= 1) { - resolveDimensions(); - } - else { - loadedmetadataListener = function () { - if (!_this.videoReference.videoWidth) { - var interval_1 = setInterval(function () { - if (!!_this.videoReference.videoWidth) { - clearInterval(interval_1); - resolveDimensions(); - } - }, 40); - } - else { - resolveDimensions(); - } - }; - _this.videoReference.addEventListener('loadedmetadata', loadedmetadataListener); - if (requiresDomInsertion) { - document.body.appendChild(_this.videoReference); - } - } - }); - }; - Publisher.prototype.reestablishStreamPlayingEvent = function () { - if (this.ee.getListeners('streamPlaying').length > 0) { - this.addPlayEventToFirstVideo(); - } - }; - Publisher.prototype.initializeVideoReference = function (mediaStream) { - this.videoReference = document.createElement('video'); - this.videoReference.setAttribute('muted', 'true'); - this.videoReference.style.display = 'none'; - if (platform.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) { - this.videoReference.setAttribute('playsinline', 'true'); - } - this.stream.setMediaStream(mediaStream); - if (!!this.firstVideoElement) { - this.createVideoElement(this.firstVideoElement.targetElement, this.properties.insertMode); - } - this.videoReference.srcObject = mediaStream; - }; - Publisher.prototype.replaceTrackInMediaStream = function (track, updateLastConstraints) { - return __awaiter(this, void 0, void 0, function () { - var mediaStream, removedTrack; - return __generator(this, function (_a) { - mediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); - if (track.kind === 'video') { - removedTrack = mediaStream.getVideoTracks()[0]; - if (updateLastConstraints) { - this.stream.lastVideoTrackConstraints = track.getConstraints(); - } - } - else { - removedTrack = mediaStream.getAudioTracks()[0]; - } - mediaStream.removeTrack(removedTrack); - removedTrack.stop(); - mediaStream.addTrack(track); - if (track.kind === 'video' && this.stream.isLocalStreamPublished && updateLastConstraints) { - this.openvidu.sendNewVideoDimensionsIfRequired(this, 'trackReplaced', 50, 30); - this.session.sendVideoData(this.stream.streamManager, 5, true, 5); - } - return [2]; - }); - }); - }; - Publisher.prototype.setPermissionDialogTimer = function (waitTime) { - var _this = this; - this.permissionDialogTimeout = setTimeout(function () { - _this.emitEvent('accessDialogOpened', []); - }, waitTime); - }; - Publisher.prototype.clearPermissionDialogTimer = function (startTime, waitTime) { - clearTimeout(this.permissionDialogTimeout); - if ((Date.now() - startTime) > waitTime) { - this.emitEvent('accessDialogClosed', []); - } - }; - Publisher.prototype.replaceTrackInRtcRtpSender = function (track) { - return __awaiter(this, void 0, void 0, function () { - var senders, sender; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - senders = this.stream.getRTCPeerConnection().getSenders(); - if (track.kind === 'video') { - sender = senders.find(function (s) { return !!s.track && s.track.kind === 'video'; }); - if (!sender) { - throw new Error('There\'s no replaceable track for that kind of MediaStreamTrack in this Publisher object'); - } - } - else if (track.kind === 'audio') { - sender = senders.find(function (s) { return !!s.track && s.track.kind === 'audio'; }); - if (!sender) { - throw new Error('There\'s no replaceable track for that kind of MediaStreamTrack in this Publisher object'); - } - } - else { - throw new Error('Unknown track kind ' + track.kind); - } - return [4, sender.replaceTrack(track)]; - case 1: - _a.sent(); - return [2]; - } - }); - }); - }; - return Publisher; -}(StreamManager_1.StreamManager)); -exports.Publisher = Publisher; - -},{"../OpenViduInternal/Enums/OpenViduError":52,"../OpenViduInternal/Enums/TypeOfVideo":53,"../OpenViduInternal/Events/StreamEvent":65,"../OpenViduInternal/Events/StreamPropertyChangedEvent":67,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Utils/Platform":83,"./Session":47,"./Stream":48,"./StreamManager":49}],47:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Session = void 0; -var Connection_1 = require("./Connection"); -var Filter_1 = require("./Filter"); -var Subscriber_1 = require("./Subscriber"); -var EventDispatcher_1 = require("./EventDispatcher"); -var ConnectionEvent_1 = require("../OpenViduInternal/Events/ConnectionEvent"); -var FilterEvent_1 = require("../OpenViduInternal/Events/FilterEvent"); -var RecordingEvent_1 = require("../OpenViduInternal/Events/RecordingEvent"); -var SessionDisconnectedEvent_1 = require("../OpenViduInternal/Events/SessionDisconnectedEvent"); -var SignalEvent_1 = require("../OpenViduInternal/Events/SignalEvent"); -var StreamEvent_1 = require("../OpenViduInternal/Events/StreamEvent"); -var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent"); -var ConnectionPropertyChangedEvent_1 = require("../OpenViduInternal/Events/ConnectionPropertyChangedEvent"); -var NetworkQualityLevelChangedEvent_1 = require("../OpenViduInternal/Events/NetworkQualityLevelChangedEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var semverMajor = require("semver/functions/major"); -var semverMinor = require("semver/functions/minor"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var Session = (function (_super) { - __extends(Session, _super); - function Session(openvidu) { - var _this = _super.call(this) || this; - _this.streamManagers = []; - _this.remoteStreamsCreated = new Map(); - _this.remoteConnections = new Map(); - platform = Platform_1.PlatformUtils.getInstance(); - _this.openvidu = openvidu; - return _this; - } - Session.prototype.connect = function (token, metadata) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.processToken(token); - if (_this.openvidu.checkSystemRequirements()) { - _this.options = { - sessionId: _this.sessionId, - participantId: token, - metadata: !!metadata ? _this.stringClientMetadata(metadata) : '' - }; - _this.connectAux(token) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - } - else { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu')); - } - }); - }; - Session.prototype.disconnect = function () { - this.leave(false, 'disconnect'); - }; - Session.prototype.subscribe = function (stream, targetElement, param3, param4) { - var properties = {}; - if (!!param3 && typeof param3 !== 'function') { - properties = { - insertMode: (typeof param3.insertMode !== 'undefined') ? ((typeof param3.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[param3.insertMode] : properties.insertMode) : VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, - subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true - }; - } - else { - properties = { - insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, - subscribeToAudio: true, - subscribeToVideo: true - }; - } - var completionHandler = undefined; - if (!!param3 && (typeof param3 === 'function')) { - completionHandler = param3; - } - else if (!!param4) { - completionHandler = param4; - } - if (!this.sessionConnected()) { - if (completionHandler !== undefined) { - completionHandler(this.notConnectedError()); - } - throw this.notConnectedError(); - } - logger.info('Subscribing to ' + stream.connection.connectionId); - stream.subscribe() - .then(function () { - logger.info('Subscribed correctly to ' + stream.connection.connectionId); - if (completionHandler !== undefined) { - completionHandler(undefined); - } - }) - .catch(function (error) { - if (completionHandler !== undefined) { - completionHandler(error); - } - }); - var subscriber = new Subscriber_1.Subscriber(stream, targetElement, properties); - if (!!subscriber.targetElement) { - stream.streamManager.createVideoElement(subscriber.targetElement, properties.insertMode); - } - return subscriber; - }; - Session.prototype.subscribeAsync = function (stream, targetElement, properties) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - var subscriber; - var callback = function (error) { - if (!!error) { - return reject(error); - } - else { - return resolve(subscriber); - } - }; - if (!!properties) { - subscriber = _this.subscribe(stream, targetElement, properties, callback); - } - else { - subscriber = _this.subscribe(stream, targetElement, callback); - } - }); - }; - Session.prototype.unsubscribe = function (subscriber) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - else { - var connectionId_1 = subscriber.stream.connection.connectionId; - logger.info('Unsubscribing from ' + connectionId_1); - _this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { - if (error) { - logger.error('Error unsubscribing from ' + connectionId_1); - return reject(error); - } - else { - logger.info('Unsubscribed correctly from ' + connectionId_1); - subscriber.stream.streamManager.removeAllVideos(); - subscriber.stream.disposeWebRtcPeer(); - subscriber.stream.disposeMediaStream(); - return resolve(); - } - }); - } - }); - }; - Session.prototype.publish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - publisher.session = _this; - publisher.stream.session = _this; - if (!publisher.stream.publishedOnce) { - _this.connection.addStream(publisher.stream); - publisher.stream.publish() - .then(function () { - _this.sendVideoData(publisher, 8, true, 5); - return resolve(); - }) - .catch(function (error) { return reject(error); }); - } - else { - publisher.initialize() - .then(function () { - _this.connection.addStream(publisher.stream); - publisher.reestablishStreamPlayingEvent(); - publisher.stream.publish() - .then(function () { - _this.sendVideoData(publisher, 8, true, 5); - return resolve(); - }) - .catch(function (error) { return reject(error); }); - }).catch(function (error) { return reject(error); }); - } - }); - }; - Session.prototype.unpublish = function (publisher) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - throw _this.notConnectedError(); - } - var stream = publisher.stream; - if (!stream.connection) { - return reject(new Error('The associated Connection object of this Publisher is null')); - } - else if (stream.connection !== _this.connection) { - return reject(new Error('The associated Connection object of this Publisher is not your local Connection.' + - "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method")); - } - else { - logger.info('Unpublishing local media (' + stream.connection.connectionId + ')'); - _this.openvidu.sendRequest('unpublishVideo', function (error, response) { - if (error) { - return reject(error); - } - else { - logger.info('Media unpublished correctly'); - stream.disposeWebRtcPeer(); - if (stream.connection.stream == stream) { - delete stream.connection.stream; - } - var streamEvent = new StreamEvent_1.StreamEvent(true, publisher, 'streamDestroyed', publisher.stream, 'unpublish'); - publisher.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehavior(); - return resolve(); - } - }); - } - }); - }; - Session.prototype.forceDisconnect = function (connection) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - logger.info('Forcing disconnect for connection ' + connection.connectionId); - _this.openvidu.sendRequest('forceDisconnect', { connectionId: connection.connectionId }, function (error, response) { - if (error) { - logger.error('Error forcing disconnect for Connection ' + connection.connectionId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force a disconnection")); - } - else { - return reject(error); - } - } - else { - logger.info('Forcing disconnect correctly for Connection ' + connection.connectionId); - return resolve(); - } - }); - }); - }; - Session.prototype.forceUnpublish = function (stream) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - logger.info('Forcing unpublish for stream ' + stream.streamId); - _this.openvidu.sendRequest('forceUnpublish', { streamId: stream.streamId }, function (error, response) { - if (error) { - logger.error('Error forcing unpublish for Stream ' + stream.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to force an unpublishing")); - } - else { - return reject(error); - } - } - else { - logger.info('Forcing unpublish correctly for Stream ' + stream.streamId); - return resolve(); - } - }); - }); - }; - Session.prototype.signal = function (signal) { - var _this = this; - return new Promise(function (resolve, reject) { - if (!_this.sessionConnected()) { - return reject(_this.notConnectedError()); - } - var signalMessage = {}; - if (signal.to && signal.to.length > 0) { - var connectionIds_1 = []; - signal.to.forEach(function (connection) { - if (!!connection.connectionId) { - connectionIds_1.push(connection.connectionId); - } - }); - signalMessage['to'] = connectionIds_1; - } - else { - signalMessage['to'] = []; - } - signalMessage['data'] = signal.data ? signal.data : ''; - var typeAux = signal.type ? signal.type : 'signal'; - if (!!typeAux) { - if (typeAux.substring(0, 7) !== 'signal:') { - typeAux = 'signal:' + typeAux; - } - } - signalMessage['type'] = typeAux; - _this.openvidu.sendRequest('sendMessage', { - message: JSON.stringify(signalMessage) - }, function (error, response) { - if (!!error) { - return reject(error); - } - else { - return resolve(); - } - }); - }); - }; - Session.prototype.on = function (type, handler) { - var _a, _b, _c, _d; - _super.prototype.onAux.call(this, type, "Event '" + type + "' triggered by 'Session'", handler); - if (type === 'publisherStartSpeaking') { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) { - remoteConnection.stream.enableHarkSpeakingEvent(); - } - }); - if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.hasAudio)) { - this.connection.stream.enableHarkSpeakingEvent(); - } - } - if (type === 'publisherStopSpeaking') { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) { - remoteConnection.stream.enableHarkStoppedSpeakingEvent(); - } - }); - if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.hasAudio)) { - this.connection.stream.enableHarkStoppedSpeakingEvent(); - } - } - return this; - }; - Session.prototype.once = function (type, handler) { - var _a, _b, _c, _d; - _super.prototype.onceAux.call(this, type, "Event '" + type + "' triggered once by 'Session'", handler); - if (type === 'publisherStartSpeaking') { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) { - remoteConnection.stream.enableOnceHarkSpeakingEvent(); - } - }); - if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.hasAudio)) { - this.connection.stream.enableOnceHarkSpeakingEvent(); - } - } - if (type === 'publisherStopSpeaking') { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.hasAudio)) { - remoteConnection.stream.enableOnceHarkStoppedSpeakingEvent(); - } - }); - if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.hasAudio)) { - this.connection.stream.enableOnceHarkStoppedSpeakingEvent(); - } - } - return this; - }; - Session.prototype.off = function (type, handler) { - var _this = this; - var _a, _b, _c, _d; - _super.prototype.offAux.call(this, type, handler); - if (type === 'publisherStartSpeaking') { - if (!this.anySpeechEventListenerEnabled('publisherStartSpeaking', false)) { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.streamManager)) { - if (!_this.anySpeechEventListenerEnabled('publisherStartSpeaking', false, remoteConnection.stream.streamManager)) { - remoteConnection.stream.disableHarkSpeakingEvent(false); - } - } - }); - if (!!((_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.stream) === null || _b === void 0 ? void 0 : _b.streamManager)) { - if (!this.anySpeechEventListenerEnabled('publisherStartSpeaking', false, this.connection.stream.streamManager)) { - this.connection.stream.disableHarkSpeakingEvent(false); - } - } - } - } - if (type === 'publisherStopSpeaking') { - if (!this.anySpeechEventListenerEnabled('publisherStopSpeaking', false)) { - this.remoteConnections.forEach(function (remoteConnection) { - var _a; - if (!!((_a = remoteConnection.stream) === null || _a === void 0 ? void 0 : _a.streamManager)) { - if (!_this.anySpeechEventListenerEnabled('publisherStopSpeaking', false, remoteConnection.stream.streamManager)) { - remoteConnection.stream.disableHarkStoppedSpeakingEvent(false); - } - } - }); - if (!!((_d = (_c = this.connection) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.streamManager)) { - if (!this.anySpeechEventListenerEnabled('publisherStopSpeaking', false, this.connection.stream.streamManager)) { - this.connection.stream.disableHarkStoppedSpeakingEvent(false); - } - } - } - } - return this; - }; - Session.prototype.onParticipantJoined = function (event) { - var _this = this; - this.getConnection(event.id, '') - .then(function (connection) { - logger.warn('Connection ' + connection.connectionId + ' already exists in connections list'); - }) - .catch(function (openViduError) { - var connection = new Connection_1.Connection(_this, event); - _this.remoteConnections.set(event.id, connection); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - }; - Session.prototype.onParticipantLeft = function (event) { - var _this = this; - this.getRemoteConnection(event.connectionId, 'onParticipantLeft').then(function (connection) { - if (!!connection.stream) { - var stream = connection.stream; - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', stream, event.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehavior(); - _this.remoteStreamsCreated.delete(stream.streamId); - } - _this.remoteConnections.delete(connection.connectionId); - _this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionDestroyed', connection, event.reason)]); - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - }; - Session.prototype.onParticipantPublished = function (event) { - var _this = this; - var afterConnectionFound = function (connection) { - _this.remoteConnections.set(connection.connectionId, connection); - if (!_this.remoteStreamsCreated.get(connection.stream.streamId)) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', connection.stream, '')]); - } - _this.remoteStreamsCreated.set(connection.stream.streamId, true); - }; - var connection; - this.getRemoteConnection(event.id, 'onParticipantPublished') - .then(function (con) { - connection = con; - event.metadata = con.data; - connection.remoteOptions = event; - connection.initRemoteStreams(event.streams); - afterConnectionFound(connection); - }) - .catch(function (openViduError) { - connection = new Connection_1.Connection(_this, event); - afterConnectionFound(connection); - }); - }; - Session.prototype.onParticipantUnpublished = function (event) { - var _this = this; - if (event.connectionId === this.connection.connectionId) { - this.stopPublisherStream(event.reason); - } - else { - this.getRemoteConnection(event.connectionId, 'onParticipantUnpublished') - .then(function (connection) { - var streamEvent = new StreamEvent_1.StreamEvent(true, _this, 'streamDestroyed', connection.stream, event.reason); - _this.ee.emitEvent('streamDestroyed', [streamEvent]); - streamEvent.callDefaultBehavior(); - var streamId = connection.stream.streamId; - _this.remoteStreamsCreated.delete(streamId); - connection.removeStream(streamId); - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - } - }; - Session.prototype.onParticipantEvicted = function (event) { - if (event.connectionId === this.connection.connectionId) { - if (!!this.sessionId && !this.connection.disposed) { - this.leave(true, event.reason); - } - } - }; - Session.prototype.onNewMessage = function (event) { - var _this = this; - logger.info('New signal: ' + JSON.stringify(event)); - var strippedType = !!event.type ? event.type.replace(/^(signal:)/, '') : undefined; - if (!!event.from) { - this.getConnection(event.from, "Connection '" + event.from + "' unknown when 'onNewMessage'. Existing remote connections: " - + JSON.stringify(this.remoteConnections.keys()) + '. Existing local connection: ' + this.connection.connectionId) - .then(function (connection) { - _this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(_this, strippedType, event.data, connection)]); - if (!!event.type && event.type !== 'signal') { - _this.ee.emitEvent(event.type, [new SignalEvent_1.SignalEvent(_this, strippedType, event.data, connection)]); - } - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - } - else { - this.ee.emitEvent('signal', [new SignalEvent_1.SignalEvent(this, strippedType, event.data, undefined)]); - if (!!event.type && event.type !== 'signal') { - this.ee.emitEvent(event.type, [new SignalEvent_1.SignalEvent(this, strippedType, event.data, undefined)]); - } - } - }; - Session.prototype.onStreamPropertyChanged = function (event) { - var _this = this; - var callback = function (connection) { - if (!!connection.stream && connection.stream.streamId === event.streamId) { - var stream = connection.stream; - var oldValue = void 0; - switch (event.property) { - case 'audioActive': - oldValue = stream.audioActive; - event.newValue = event.newValue === 'true'; - stream.audioActive = event.newValue; - break; - case 'videoActive': - oldValue = stream.videoActive; - event.newValue = event.newValue === 'true'; - stream.videoActive = event.newValue; - break; - case 'videoDimensions': - oldValue = stream.videoDimensions; - event.newValue = JSON.parse(JSON.parse(event.newValue)); - stream.videoDimensions = event.newValue; - break; - case 'filter': - oldValue = stream.filter; - event.newValue = (Object.keys(event.newValue).length > 0) ? event.newValue : undefined; - if (event.newValue !== undefined) { - stream.filter = new Filter_1.Filter(event.newValue.type, event.newValue.options); - stream.filter.stream = stream; - if (event.newValue.lastExecMethod) { - stream.filter.lastExecMethod = event.newValue.lastExecMethod; - } - } - else { - delete stream.filter; - } - event.newValue = stream.filter; - break; - } - _this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this, stream, event.property, event.newValue, oldValue, event.reason)]); - if (!!stream.streamManager) { - stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(stream.streamManager, stream, event.property, event.newValue, oldValue, event.reason)]); - } - } - else { - logger.error("No stream with streamId '" + event.streamId + "' found for connection '" + event.connectionId + "' on 'streamPropertyChanged' event"); - } - }; - if (event.connectionId === this.connection.connectionId) { - callback(this.connection); - } - else { - this.getRemoteConnection(event.connectionId, 'onStreamPropertyChanged') - .then(function (connection) { - callback(connection); - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - } - }; - Session.prototype.onConnectionPropertyChanged = function (event) { - var oldValue; - switch (event.property) { - case 'role': - oldValue = this.connection.role.slice(); - this.connection.role = event.newValue; - this.connection.localOptions.role = event.newValue; - break; - case 'record': - oldValue = this.connection.record; - event.newValue = event.newValue === 'true'; - this.connection.record = event.newValue; - this.connection.localOptions.record = event.newValue; - break; - } - this.ee.emitEvent('connectionPropertyChanged', [new ConnectionPropertyChangedEvent_1.ConnectionPropertyChangedEvent(this, this.connection, event.property, event.newValue, oldValue)]); - }; - Session.prototype.onNetworkQualityLevelChangedChanged = function (event) { - var _this = this; - if (event.connectionId === this.connection.connectionId) { - this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent_1.NetworkQualityLevelChangedEvent(this, event.newValue, event.oldValue, this.connection)]); - } - else { - this.getConnection(event.connectionId, 'Connection not found for connectionId ' + event.connectionId) - .then(function (connection) { - _this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent_1.NetworkQualityLevelChangedEvent(_this, event.newValue, event.oldValue, connection)]); - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - } - }; - Session.prototype.recvIceCandidate = function (event) { - var candidateInit = { - candidate: event.candidate, - sdpMLineIndex: event.sdpMLineIndex, - sdpMid: event.sdpMid, - }; - var iceCandidate = new RTCIceCandidate(candidateInit); - this.getConnection(event.senderConnectionId, 'Connection not found for connectionId ' + event.senderConnectionId + ' owning endpoint ' + event.endpointName + '. Ice candidate will be ignored: ' + iceCandidate) - .then(function (connection) { - var stream = connection.stream; - stream.getWebRtcPeer().addIceCandidate(iceCandidate).catch(function (error) { - logger.error('Error adding candidate for ' + stream.streamId - + ' stream of endpoint ' + event.endpointName + ': ' + error); - }); - }) - .catch(function (openViduError) { - logger.error(openViduError); - }); - }; - Session.prototype.onSessionClosed = function (msg) { - logger.info('Session closed: ' + JSON.stringify(msg)); - var s = msg.sessionId; - if (s !== undefined) { - this.ee.emitEvent('session-closed', [{ - session: s - }]); - } - else { - logger.warn('Session undefined on session closed', msg); - } - }; - Session.prototype.onLostConnection = function (reason) { - logger.warn('Lost connection in Session ' + this.sessionId); - if (!!this.sessionId && !!this.connection && !this.connection.disposed) { - this.leave(true, reason); - } - }; - Session.prototype.onRecoveredConnection = function () { - logger.info('Recovered connection in Session ' + this.sessionId); - this.reconnectBrokenStreams(); - this.ee.emitEvent('reconnected', []); - }; - Session.prototype.onMediaError = function (event) { - logger.error('Media error: ' + JSON.stringify(event)); - var err = event.error; - if (err) { - this.ee.emitEvent('error-media', [{ - error: err - }]); - } - else { - logger.warn('Received undefined media error:', event); - } - }; - Session.prototype.onRecordingStarted = function (event) { - this.ee.emitEvent('recordingStarted', [new RecordingEvent_1.RecordingEvent(this, 'recordingStarted', event.id, event.name)]); - }; - Session.prototype.onRecordingStopped = function (event) { - this.ee.emitEvent('recordingStopped', [new RecordingEvent_1.RecordingEvent(this, 'recordingStopped', event.id, event.name, event.reason)]); - }; - Session.prototype.onFilterEventDispatched = function (event) { - var _this = this; - var connectionId = event.connectionId; - this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId) - .then(function (connection) { - logger.info("Filter event of type \"".concat(event.eventType, "\" dispatched")); - var stream = connection.stream; - if (!stream || !stream.filter) { - return logger.error("Filter event of type \"".concat(event.eventType, "\" dispatched for stream ").concat(stream.streamId, " but there is no ").concat(!stream ? 'stream' : 'filter', " defined")); - } - var eventHandler = stream.filter.handlers.get(event.eventType); - if (!eventHandler || typeof eventHandler !== 'function') { - var actualHandlers = Array.from(stream.filter.handlers.keys()); - return logger.error("Filter event of type \"".concat(event.eventType, "\" not handled or not a function! Active filter events: ").concat(actualHandlers.join(','))); - } - else { - eventHandler.call(_this, new FilterEvent_1.FilterEvent(stream.filter, event.eventType, event.data)); - } - }); - }; - Session.prototype.onForciblyReconnectSubscriber = function (event) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.getRemoteConnection(event.connectionId, 'onForciblyReconnectSubscriber') - .then(function (connection) { - if (!!connection.stream && connection.stream.streamId === event.streamId) { - var stream_1 = connection.stream; - if (stream_1.setupReconnectionEventEmitter(resolve, reject)) { - if (stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] != null) { - stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] = event; - return reject('Ongoing forced subscriber reconnection'); - } - else { - stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent'] = event; - var callback_1 = function () { - var eventAux = stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent']; - delete stream_1.reconnectionEventEmitter['onForciblyReconnectSubscriberLastEvent']; - _this.onForciblyReconnectSubscriber(eventAux); - }; - stream_1.reconnectionEventEmitter.once('success', function () { - callback_1(); - }); - stream_1.reconnectionEventEmitter.once('error', function () { - callback_1(); - }); - } - return; - } - stream_1.completeWebRtcPeerReceive(true, true, event.sdpOffer) - .then(function () { return stream_1.finalResolveForSubscription(true, resolve); }) - .catch(function (error) { return stream_1.finalRejectForSubscription(true, "Error while forcibly reconnecting remote stream ".concat(event.streamId, ": ").concat(error.toString()), reject); }); - } - else { - var errMsg = "No stream with streamId '" + event.streamId + "' found for connection '" + event.connectionId + "' on 'streamPropertyChanged' event"; - logger.error(errMsg); - return reject(errMsg); - } - }) - .catch(function (openViduError) { - logger.error(openViduError); - return reject(openViduError); - }); - }); - }; - Session.prototype.reconnectBrokenStreams = function () { - logger.info('Re-establishing media connections...'); - var someReconnection = false; - if (!!this.connection.stream && this.connection.stream.streamIceConnectionStateBroken()) { - logger.warn('Re-establishing Publisher ' + this.connection.stream.streamId); - this.connection.stream.initWebRtcPeerSend(true); - someReconnection = true; - } - this.remoteConnections.forEach(function (remoteConnection) { - if (!!remoteConnection.stream && remoteConnection.stream.streamIceConnectionStateBroken()) { - logger.warn('Re-establishing Subscriber ' + remoteConnection.stream.streamId); - remoteConnection.stream.initWebRtcPeerReceive(true); - someReconnection = true; - } - }); - if (!someReconnection) { - logger.info('There were no media streams in need of a reconnection'); - } - }; - Session.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - Session.prototype.leave = function (forced, reason) { - var _this = this; - forced = !!forced; - logger.info('Leaving Session (forced=' + forced + ')'); - this.stopVideoDataIntervals(); - if (!!this.connection) { - if (!this.connection.disposed && !forced) { - this.openvidu.sendRequest('leaveRoom', function (error, response) { - if (error) { - logger.error("leaveRoom error: ".concat(JSON.stringify(error))); - } - _this.openvidu.closeWs(); - }); - } - else { - this.openvidu.closeWs(); - } - this.stopPublisherStream(reason); - if (!this.connection.disposed) { - var sessionDisconnectEvent = new SessionDisconnectedEvent_1.SessionDisconnectedEvent(this, reason); - this.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]); - sessionDisconnectEvent.callDefaultBehavior(); - } - } - else { - logger.warn('You were not connected to the session ' + this.sessionId); - } - logger.flush(); - }; - Session.prototype.initializeParams = function (token) { - var joinParams = { - token: (!!token) ? token : '', - session: this.sessionId, - platform: !!platform.getDescription() ? platform.getDescription() : 'unknown', - sdkVersion: this.openvidu.libraryVersion, - metadata: !!this.options.metadata ? this.options.metadata : '', - secret: this.openvidu.getSecret(), - recorder: this.openvidu.getRecorder() - }; - return joinParams; - }; - Session.prototype.sendVideoData = function (streamManager, intervalSeconds, doInterval, maxLoops) { - var _this = this; - var _a, _b; - if (intervalSeconds === void 0) { intervalSeconds = 1; } - if (doInterval === void 0) { doInterval = false; } - if (maxLoops === void 0) { maxLoops = 1; } - if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || - platform.isOperaMobileBrowser() || platform.isEdgeBrowser() || platform.isEdgeMobileBrowser() || platform.isElectron() || - (platform.isSafariBrowser() && !platform.isIonicIos()) || platform.isAndroidBrowser() || - platform.isSamsungBrowser() || platform.isIonicAndroid() || platform.isIOSWithSafari()) { - var obtainAndSendVideo_1 = function () { return __awaiter(_this, void 0, void 0, function () { - var pc, statsMap, arr_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - pc = streamManager.stream.getRTCPeerConnection(); - if (!(pc.connectionState === 'connected')) return [3, 2]; - return [4, pc.getStats()]; - case 1: - statsMap = _a.sent(); - arr_1 = []; - statsMap.forEach(function (stats) { - if (("frameWidth" in stats) && ("frameHeight" in stats) && (arr_1.length === 0)) { - arr_1.push(stats); - } - }); - if (arr_1.length > 0) { - this.openvidu.sendRequest('videoData', { - height: arr_1[0].frameHeight, - width: arr_1[0].frameWidth, - videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false, - audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false - }, function (error, response) { - if (error) { - logger.error("Error sending 'videoData' event", error); - } - }); - } - _a.label = 2; - case 2: return [2]; - } - }); - }); }; - if (doInterval) { - var loops_1 = 1; - this.videoDataInterval = setInterval(function () { - if (loops_1 < maxLoops) { - loops_1++; - obtainAndSendVideo_1(); - } - else { - clearInterval(_this.videoDataInterval); - } - }, intervalSeconds * 1000); - } - else { - this.videoDataTimeout = setTimeout(obtainAndSendVideo_1, intervalSeconds * 1000); - } - } - else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isIonicIos() || platform.isReactNative()) { - this.openvidu.sendRequest('videoData', { - height: ((_a = streamManager.stream.videoDimensions) === null || _a === void 0 ? void 0 : _a.height) || 0, - width: ((_b = streamManager.stream.videoDimensions) === null || _b === void 0 ? void 0 : _b.width) || 0, - videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false, - audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false - }, function (error, response) { - if (error) { - logger.error("Error sending 'videoData' event", error); - } - }); - } - else { - logger.error('Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu for Network Quality'); - } - }; - Session.prototype.sessionConnected = function () { - return this.connection != null; - }; - Session.prototype.notConnectedError = function () { - return new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_NOT_CONNECTED, "There is no connection to the session. Method 'Session.connect' must be successfully completed first"); - }; - Session.prototype.anySpeechEventListenerEnabled = function (event, onlyOnce, streamManager) { - var handlersInSession = this.ee.getListeners(event); - if (onlyOnce) { - handlersInSession = handlersInSession.filter(function (h) { return h.once; }); - } - var listenersInSession = handlersInSession.length; - if (listenersInSession > 0) - return true; - var listenersInStreamManager = 0; - if (!!streamManager) { - var handlersInStreamManager = streamManager.ee.getListeners(event); - if (onlyOnce) { - handlersInStreamManager = handlersInStreamManager.filter(function (h) { return h.once; }); - } - listenersInStreamManager = handlersInStreamManager.length; - } - return listenersInStreamManager > 0; - }; - Session.prototype.getTokenParams = function (token) { - var match = token.match(/^(wss?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/); - if (!!match) { - var url = { - protocol: match[1], - host: match[2], - hostname: match[3], - port: match[4], - pathname: match[5], - search: match[6], - hash: match[7] - }; - var params = token.split('?'); - var queryParams = decodeURI(params[1]) - .split('&') - .map(function (param) { return param.split('='); }) - .reduce(function (values, _a) { - var key = _a[0], value = _a[1]; - values[key] = value; - return values; - }, {}); - return { - sessionId: queryParams['sessionId'], - secret: queryParams['secret'], - recorder: queryParams['recorder'], - webrtcStatsInterval: queryParams['webrtcStatsInterval'], - sendBrowserLogs: queryParams['sendBrowserLogs'], - edition: queryParams['edition'], - wsUri: 'wss://' + url.host + '/openvidu', - httpUri: 'https://' + url.host - }; - } - else { - throw new Error("Token not valid: \"".concat(token, "\"")); - } - }; - Session.prototype.connectAux = function (token) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.openvidu.startWs(function (error) { - if (!!error) { - return reject(error); - } - else { - var joinParams = _this.initializeParams(token); - _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { - if (!!error) { - return reject(error); - } - else { - _this.processJoinRoomResponse(response, token); - _this.connection = new Connection_1.Connection(_this, response); - var events_1 = { - connections: new Array(), - streams: new Array() - }; - var existingParticipants = response.value; - existingParticipants.forEach(function (remoteConnectionOptions) { - var connection = new Connection_1.Connection(_this, remoteConnectionOptions); - _this.remoteConnections.set(connection.connectionId, connection); - events_1.connections.push(connection); - if (!!connection.stream) { - _this.remoteStreamsCreated.set(connection.stream.streamId, true); - events_1.streams.push(connection.stream); - } - }); - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', _this.connection, '')]); - events_1.connections.forEach(function (connection) { - _this.ee.emitEvent('connectionCreated', [new ConnectionEvent_1.ConnectionEvent(false, _this, 'connectionCreated', connection, '')]); - }); - events_1.streams.forEach(function (stream) { - _this.ee.emitEvent('streamCreated', [new StreamEvent_1.StreamEvent(false, _this, 'streamCreated', stream, '')]); - }); - return resolve(); - } - }); - } - }); - }); - }; - Session.prototype.stopPublisherStream = function (reason) { - if (!!this.connection.stream) { - this.connection.stream.disposeWebRtcPeer(); - if (this.connection.stream.isLocalStreamPublished) { - this.connection.stream.ee.emitEvent('local-stream-destroyed', [reason]); - } - } - }; - Session.prototype.stopVideoDataIntervals = function () { - clearInterval(this.videoDataInterval); - clearTimeout(this.videoDataTimeout); - }; - Session.prototype.stringClientMetadata = function (metadata) { - if (typeof metadata !== 'string') { - return JSON.stringify(metadata); - } - else { - return metadata; - } - }; - Session.prototype.getConnection = function (connectionId, errorMessage) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections.get(connectionId); - if (!!connection) { - return resolve(connection); - } - else { - if (_this.connection.connectionId === connectionId) { - return resolve(_this.connection); - } - else { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - } - }); - }; - Session.prototype.getRemoteConnection = function (connectionId, operation) { - var _this = this; - return new Promise(function (resolve, reject) { - var connection = _this.remoteConnections.get(connectionId); - if (!!connection) { - return resolve(connection); - } - else { - var errorMessage = 'Remote connection ' + connectionId + " unknown when '" + operation + "'. " + - 'Existing remote connections: ' + JSON.stringify(_this.remoteConnections.keys()); - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); - } - }); - }; - Session.prototype.processToken = function (token) { - var tokenParams = this.getTokenParams(token); - this.sessionId = tokenParams.sessionId; - if (!!tokenParams.secret) { - this.openvidu.secret = tokenParams.secret; - } - if (!!tokenParams.recorder) { - this.openvidu.recorder = true; - } - if (!!tokenParams.webrtcStatsInterval) { - this.openvidu.webrtcStatsInterval = tokenParams.webrtcStatsInterval; - } - if (!!tokenParams.sendBrowserLogs) { - this.openvidu.sendBrowserLogs = tokenParams.sendBrowserLogs; - } - this.openvidu.isAtLeastPro = tokenParams.edition === 'pro' || tokenParams.edition === 'enterprise'; - this.openvidu.isEnterprise = tokenParams.edition === 'enterprise'; - this.openvidu.wsUri = tokenParams.wsUri; - this.openvidu.httpUri = tokenParams.httpUri; - }; - Session.prototype.processJoinRoomResponse = function (opts, token) { - this.sessionId = opts.session; - if (opts.customIceServers != null && opts.customIceServers.length > 0) { - this.openvidu.iceServers = []; - for (var _i = 0, _a = opts.customIceServers; _i < _a.length; _i++) { - var iceServer = _a[_i]; - var rtcIceServer = { - urls: [iceServer.url] - }; - logger.log("STUN/TURN server IP: " + iceServer.url); - if (iceServer.username != null && iceServer.credential != null) { - rtcIceServer.username = iceServer.username; - rtcIceServer.credential = iceServer.credential; - logger.log('TURN credentials [' + iceServer.username + ':' + iceServer.credential + ']'); - } - this.openvidu.iceServers.push(rtcIceServer); - } - } - else if (opts.coturnIp != null && opts.coturnPort != null && opts.turnUsername != null && opts.turnCredential != null) { - var turnUrl1 = 'turn:' + opts.coturnIp + ':' + opts.coturnPort; - this.openvidu.iceServers = [ - { urls: [turnUrl1], username: opts.turnUsername, credential: opts.turnCredential } - ]; - logger.log("STUN/TURN server IP: " + opts.coturnIp); - logger.log('TURN temp credentials [' + opts.turnUsername + ':' + opts.turnCredential + ']'); - } - this.openvidu.role = opts.role; - this.openvidu.finalUserId = opts.finalUserId; - this.openvidu.mediaServer = opts.mediaServer; - this.openvidu.videoSimulcast = opts.videoSimulcast; - this.capabilities = { - subscribe: true, - publish: this.openvidu.role !== 'SUBSCRIBER', - forceUnpublish: this.openvidu.role === 'MODERATOR', - forceDisconnect: this.openvidu.role === 'MODERATOR' - }; - logger.info("openvidu-server version: " + opts.version); - if (opts.life != null) { - this.openvidu.life = opts.life; - } - var minorDifference = semverMinor(opts.version) - semverMinor(this.openvidu.libraryVersion); - if ((semverMajor(opts.version) !== semverMajor(this.openvidu.libraryVersion)) || !(minorDifference == 0 || minorDifference == 1)) { - logger.error("openvidu-browser (".concat(this.openvidu.libraryVersion, ") and openvidu-server (").concat(opts.version, ") versions are incompatible. ") - + 'Errors are likely to occur. openvidu-browser SDK is only compatible with the same version or the immediately following minor version of an OpenVidu deployment'); - } - else if (minorDifference == 1) { - logger.warn("openvidu-browser version ".concat(this.openvidu.libraryVersion, " does not match openvidu-server version ").concat(opts.version, ". ") - + "These versions are still compatible with each other, but openvidu-browser version must be updated as soon as possible to ".concat(semverMajor(opts.version), ".").concat(semverMinor(opts.version), ".x. ") - + "This client using openvidu-browser ".concat(this.openvidu.libraryVersion, " will become incompatible with the next release of openvidu-server")); - } - OpenViduLogger_1.OpenViduLogger.configureJSNLog(this.openvidu, token); - this.token = token; - }; - return Session; -}(EventDispatcher_1.EventDispatcher)); -exports.Session = Session; - -},{"../OpenViduInternal/Enums/OpenViduError":52,"../OpenViduInternal/Enums/VideoInsertMode":54,"../OpenViduInternal/Events/ConnectionEvent":55,"../OpenViduInternal/Events/ConnectionPropertyChangedEvent":56,"../OpenViduInternal/Events/FilterEvent":59,"../OpenViduInternal/Events/NetworkQualityLevelChangedEvent":60,"../OpenViduInternal/Events/RecordingEvent":62,"../OpenViduInternal/Events/SessionDisconnectedEvent":63,"../OpenViduInternal/Events/SignalEvent":64,"../OpenViduInternal/Events/StreamEvent":65,"../OpenViduInternal/Events/StreamPropertyChangedEvent":67,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Utils/Platform":83,"./Connection":41,"./EventDispatcher":42,"./Filter":43,"./Subscriber":50,"semver/functions/major":15,"semver/functions/minor":16}],48:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Stream = void 0; -var Filter_1 = require("./Filter"); -var Subscriber_1 = require("./Subscriber"); -var WebRtcPeer_1 = require("../OpenViduInternal/WebRtcPeer/WebRtcPeer"); -var WebRtcStats_1 = require("../OpenViduInternal/WebRtcStats/WebRtcStats"); -var ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent"); -var PublisherSpeakingEvent_1 = require("../OpenViduInternal/Events/PublisherSpeakingEvent"); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var StreamPropertyChangedEvent_1 = require("../OpenViduInternal/Events/StreamPropertyChangedEvent"); -var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); -var TypeOfVideo_1 = require("../OpenViduInternal/Enums/TypeOfVideo"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var uuid_1 = require("uuid"); -var hark = require("hark"); -var EventEmitter = require("wolfy87-eventemitter"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var Stream = (function () { - function Stream(session, options) { - var _this = this; - this.isSubscribeToRemote = false; - this.isLocalStreamReadyToPublish = false; - this.isLocalStreamPublished = false; - this.publishedOnce = false; - this.harkSpeakingEnabled = false; - this.harkSpeakingEnabledOnce = false; - this.harkStoppedSpeakingEnabled = false; - this.harkStoppedSpeakingEnabledOnce = false; - this.harkVolumeChangeEnabled = false; - this.harkVolumeChangeEnabledOnce = false; - this.ee = new EventEmitter(); - platform = Platform_1.PlatformUtils.getInstance(); - this.session = session; - if (options.hasOwnProperty('id')) { - this.inboundStreamOpts = options; - this.streamId = this.inboundStreamOpts.id; - this.creationTime = this.inboundStreamOpts.createdAt; - this.hasAudio = this.inboundStreamOpts.hasAudio; - this.hasVideo = this.inboundStreamOpts.hasVideo; - if (this.hasAudio) { - this.audioActive = this.inboundStreamOpts.audioActive; - } - if (this.hasVideo) { - this.videoActive = this.inboundStreamOpts.videoActive; - this.typeOfVideo = (!this.inboundStreamOpts.typeOfVideo) ? undefined : this.inboundStreamOpts.typeOfVideo; - this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; - this.videoDimensions = this.inboundStreamOpts.videoDimensions; - } - if (!!this.inboundStreamOpts.filter && (Object.keys(this.inboundStreamOpts.filter).length > 0)) { - if (!!this.inboundStreamOpts.filter.lastExecMethod && Object.keys(this.inboundStreamOpts.filter.lastExecMethod).length === 0) { - delete this.inboundStreamOpts.filter.lastExecMethod; - } - this.filter = this.inboundStreamOpts.filter; - } - } - else { - this.outboundStreamOpts = options; - this.hasAudio = this.isSendAudio(); - this.hasVideo = this.isSendVideo(); - if (this.hasAudio) { - this.audioActive = !!this.outboundStreamOpts.publisherProperties.publishAudio; - } - if (this.hasVideo) { - this.videoActive = !!this.outboundStreamOpts.publisherProperties.publishVideo; - this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; - if (typeof MediaStreamTrack !== 'undefined' && this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) { - this.typeOfVideo = TypeOfVideo_1.TypeOfVideo.CUSTOM; - } - else { - this.typeOfVideo = this.isSendScreen() ? TypeOfVideo_1.TypeOfVideo.SCREEN : TypeOfVideo_1.TypeOfVideo.CAMERA; - } - } - if (!!this.outboundStreamOpts.publisherProperties.filter) { - this.filter = this.outboundStreamOpts.publisherProperties.filter; - } - } - this.ee.on('mediastream-updated', function () { - var _a; - _this.streamManager.updateMediaStream(_this.mediaStream); - logger.debug('Video srcObject [' + ((_a = _this.mediaStream) === null || _a === void 0 ? void 0 : _a.id) + '] updated in stream [' + _this.streamId + ']'); - }); - } - Stream.prototype.reconnect = function () { - return this.reconnectStream('API'); - }; - Stream.prototype.applyFilter = function (type, options) { - var _this = this; - return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { - var resolveApplyFilter, openviduToken_1, tokenParams_1, afterScriptLoaded_1, script, optionsString; - var _this = this; - return __generator(this, function (_a) { - if (!!this.filter) { - return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, 'There is already a filter applied to Stream ' + this.streamId))]; - } - resolveApplyFilter = function (error, triggerEvent) { - if (error) { - logger.error('Error applying filter for Stream ' + _this.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to apply a filter")); - } - else { - return reject(error); - } - } - else { - logger.info('Filter successfully applied on Stream ' + _this.streamId); - var oldValue = _this.filter; - _this.filter = new Filter_1.Filter(type, options); - _this.filter.stream = _this; - if (triggerEvent) { - _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this, 'filter', _this.filter, oldValue, 'applyFilter')]); - _this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.streamManager, _this, 'filter', _this.filter, oldValue, 'applyFilter')]); - } - return resolve(_this.filter); - } - }; - if (type.startsWith('VB:')) { - if (!this.hasVideo) { - return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'The Virtual Background filter requires a video track to be applied'))]; - } - if (!this.mediaStream || this.streamManager.videos.length === 0) { - return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'The StreamManager requires some video element to be attached to it in order to apply a Virtual Background filter'))]; - } - if (!!this.session.token) { - openviduToken_1 = this.session.token; - } - else { - openviduToken_1 = options['token']; - } - if (!openviduToken_1) { - return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'Virtual Background requires the client to be connected to a Session or to have a "token" property available in "options" parameter with a valid OpenVidu token'))]; - } - tokenParams_1 = this.session.getTokenParams(openviduToken_1); - if (tokenParams_1.edition !== 'pro' && tokenParams_1.edition !== 'enterprise') { - return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, 'OpenVidu Virtual Background API is available from OpenVidu Pro edition onwards'))]; - } - openviduToken_1 = encodeURIComponent(btoa(openviduToken_1)); - logger.info('Applying Virtual Background to stream ' + this.streamId); - afterScriptLoaded_1 = function () { return __awaiter(_this, void 0, void 0, function () { - var id, mediaStreamClone, videoClone, VB, filteredVideo, _a, error_1; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - _b.trys.push([0, 8, , 9]); - id = this.streamId + '_' + (0, uuid_1.v4)(); - mediaStreamClone = this.mediaStream.clone(); - videoClone = this.streamManager.videos[0].video.cloneNode(false); - videoClone.id = VirtualBackground.VirtualBackground.SOURCE_VIDEO_PREFIX + id; - videoClone.srcObject = mediaStreamClone; - videoClone.muted = true; - this.virtualBackgroundSourceElements = { videoClone: videoClone, mediaStreamClone: mediaStreamClone }; - VirtualBackground.VirtualBackground.hideHtmlElement(videoClone, false); - VirtualBackground.VirtualBackground.appendHtmlElementToHiddenContainer(videoClone, id); - return [4, videoClone.play()]; - case 1: - _b.sent(); - VB = new VirtualBackground.VirtualBackground({ - id: id, - openviduServerUrl: new URL(tokenParams_1.httpUri), - openviduToken: openviduToken_1, - inputVideo: videoClone, - inputResolution: '160x96', - outputFramerate: 24 - }); - filteredVideo = void 0; - _a = type; - switch (_a) { - case 'VB:blur': return [3, 2]; - case 'VB:image': return [3, 4]; - } - return [3, 6]; - case 2: return [4, VB.backgroundBlur(options)]; - case 3: - filteredVideo = _b.sent(); - return [3, 7]; - case 4: return [4, VB.backgroundImage(options)]; - case 5: - filteredVideo = _b.sent(); - return [3, 7]; - case 6: throw new Error('Unknown Virtual Background filter: ' + type); - case 7: - this.virtualBackgroundSinkElements = { VB: VB, video: filteredVideo }; - videoClone.style.display = 'none'; - if (this.streamManager.remote) { - this.streamManager.replaceTrackInMediaStream(this.virtualBackgroundSinkElements.video.srcObject.getVideoTracks()[0], false); - } - else { - this.streamManager.replaceTrackAux(this.virtualBackgroundSinkElements.video.srcObject.getVideoTracks()[0], false); - } - resolveApplyFilter(undefined, false); - return [3, 9]; - case 8: - error_1 = _b.sent(); - if (error_1.name === OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR) { - resolveApplyFilter(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.VIRTUAL_BACKGROUND_ERROR, error_1.message), false); - } - else { - resolveApplyFilter(error_1, false); - } - return [3, 9]; - case 9: return [2]; - } - }); - }); }; - if (typeof VirtualBackground === "undefined") { - script = document.createElement("script"); - script.type = "text/javascript"; - script.src = tokenParams_1.httpUri + '/openvidu/virtual-background/openvidu-virtual-background.js?token=' + openviduToken_1; - script.onload = function () { return __awaiter(_this, void 0, void 0, function () { - var error_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4, afterScriptLoaded_1()]; - case 1: - _a.sent(); - resolve(new Filter_1.Filter(type, options)); - return [3, 3]; - case 2: - error_2 = _a.sent(); - reject(error_2); - return [3, 3]; - case 3: return [2]; - } - }); - }); }; - document.body.appendChild(script); - } - else { - afterScriptLoaded_1() - .then(function () { return resolve(new Filter_1.Filter(type, options)); }) - .catch(function (error) { return reject(error); }); - } - } - else { - if (!this.session.sessionConnected()) { - return [2, reject(this.session.notConnectedError())]; - } - logger.info('Applying server filter to stream ' + this.streamId); - options = options != null ? options : {}; - optionsString = options; - if (typeof optionsString !== 'string') { - optionsString = JSON.stringify(optionsString); - } - this.session.openvidu.sendRequest('applyFilter', { streamId: this.streamId, type: type, options: optionsString }, function (error, response) { - resolveApplyFilter(error, true); - }); - } - return [2]; - }); - }); }); - }; - Stream.prototype.removeFilter = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4, this.removeFilterAux(false)]; - case 1: return [2, _a.sent()]; - } - }); - }); - }; - Stream.prototype.getRTCPeerConnection = function () { - return this.webRtcPeer.pc; - }; - Stream.prototype.getMediaStream = function () { - return this.mediaStream; - }; - Stream.prototype.removeFilterAux = function (isDisposing) { - var _this = this; - return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { - var resolveRemoveFilter, mediaStreamClone, error_3; - var _this = this; - var _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - resolveRemoveFilter = function (error, triggerEvent) { - if (error) { - delete _this.filter; - logger.error('Error removing filter for Stream ' + _this.streamId, error); - if (error.code === 401) { - return reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to remove a filter")); - } - else { - return reject(error); - } - } - else { - logger.info('Filter successfully removed from Stream ' + _this.streamId); - var oldValue = _this.filter; - delete _this.filter; - if (triggerEvent) { - _this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.session, _this, 'filter', _this.filter, oldValue, 'applyFilter')]); - _this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent_1.StreamPropertyChangedEvent(_this.streamManager, _this, 'filter', _this.filter, oldValue, 'applyFilter')]); - } - return resolve(); - } - }; - if (!!!this.filter) return [3, 12]; - if (!((_a = this.filter) === null || _a === void 0 ? void 0 : _a.type.startsWith('VB:'))) return [3, 10]; - _b.label = 1; - case 1: - _b.trys.push([1, 8, , 9]); - mediaStreamClone = this.virtualBackgroundSourceElements.mediaStreamClone; - if (!!isDisposing) return [3, 6]; - if (!this.streamManager.remote) return [3, 3]; - return [4, this.streamManager.replaceTrackInMediaStream(mediaStreamClone.getVideoTracks()[0], false)]; - case 2: - _b.sent(); - return [3, 5]; - case 3: return [4, this.streamManager.replaceTrackAux(mediaStreamClone.getVideoTracks()[0], false)]; - case 4: - _b.sent(); - _b.label = 5; - case 5: return [3, 7]; - case 6: - mediaStreamClone.getTracks().forEach(function (track) { return track.stop(); }); - _b.label = 7; - case 7: - this.virtualBackgroundSinkElements.VB.cleanUp(); - delete this.virtualBackgroundSinkElements; - delete this.virtualBackgroundSourceElements; - return [2, resolveRemoveFilter(undefined, false)]; - case 8: - error_3 = _b.sent(); - return [2, resolveRemoveFilter(error_3, false)]; - case 9: return [3, 11]; - case 10: - if (!this.session.sessionConnected()) { - return [2, reject(this.session.notConnectedError())]; - } - logger.info('Removing filter of stream ' + this.streamId); - this.session.openvidu.sendRequest('removeFilter', { streamId: this.streamId }, function (error, response) { - return resolveRemoveFilter(error, true); - }); - _b.label = 11; - case 11: return [3, 13]; - case 12: return [2, reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, "Stream " + this.streamId + " has no filter applied"))]; - case 13: return [2]; - } - }); - }); }); - }; - Stream.prototype.setMediaStream = function (mediaStream) { - this.mediaStream = mediaStream; - }; - Stream.prototype.updateMediaStreamInVideos = function () { - this.ee.emitEvent('mediastream-updated', []); - }; - Stream.prototype.getWebRtcPeer = function () { - return this.webRtcPeer; - }; - Stream.prototype.subscribeToMyRemote = function (value) { - this.isSubscribeToRemote = value; - }; - Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { - this.outboundStreamOpts = outboundStreamOpts; - }; - Stream.prototype.subscribe = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.initWebRtcPeerReceive(false) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - }); - }; - Stream.prototype.publish = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocalStreamReadyToPublish) { - _this.initWebRtcPeerSend(false) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - } - else { - _this.ee.once('stream-ready-to-publish', function () { - _this.publish() - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - }); - } - }); - }; - Stream.prototype.disposeWebRtcPeer = function () { - var webrtcId; - if (!!this.webRtcPeer) { - this.webRtcPeer.dispose(); - webrtcId = this.webRtcPeer.getId(); - } - this.stopWebRtcStats(); - logger.info((!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + "RTCPeerConnection with id [" + webrtcId + "] from 'Stream' with id [" + this.streamId + '] is now closed'); - }; - Stream.prototype.disposeMediaStream = function () { - return __awaiter(this, void 0, void 0, function () { - var error_4; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!(!!this.filter && this.filter.type.startsWith('VB:'))) return [3, 4]; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4, this.removeFilterAux(true)]; - case 2: - _a.sent(); - console.debug("Success removing Virtual Background filter for stream ".concat(this.streamId)); - return [3, 4]; - case 3: - error_4 = _a.sent(); - console.error("Error removing Virtual Background filter for stream ".concat(this.streamId), error_4); - return [3, 4]; - case 4: - if (this.mediaStream) { - this.mediaStream.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.mediaStream.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.mediaStream; - } - if (this.localMediaStreamWhenSubscribedToRemote) { - this.localMediaStreamWhenSubscribedToRemote.getAudioTracks().forEach(function (track) { - track.stop(); - }); - this.localMediaStreamWhenSubscribedToRemote.getVideoTracks().forEach(function (track) { - track.stop(); - }); - delete this.localMediaStreamWhenSubscribedToRemote; - } - if (!!this.speechEvent) { - if (!!this.speechEvent.stop) { - this.speechEvent.stop(); - } - delete this.speechEvent; - } - logger.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "MediaStream from 'Stream' with id [" + this.streamId + '] is now disposed'); - return [2]; - } - }); - }); - }; - Stream.prototype.displayMyRemote = function () { - return this.isSubscribeToRemote; - }; - Stream.prototype.isSendAudio = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.audioSource !== null && - this.outboundStreamOpts.publisherProperties.audioSource !== false); - }; - Stream.prototype.isSendVideo = function () { - return (!!this.outboundStreamOpts && - this.outboundStreamOpts.publisherProperties.videoSource !== null && - this.outboundStreamOpts.publisherProperties.videoSource !== false); - }; - Stream.prototype.isSendScreen = function () { - var screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen'; - if (platform.isElectron()) { - screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' && - this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:'); - } - return !!this.outboundStreamOpts && screen; - }; - Stream.prototype.enableHarkSpeakingEvent = function () { - var _this = this; - this.setHarkListenerIfNotExists(); - if (!this.harkSpeakingEnabled && !!this.speechEvent) { - this.harkSpeakingEnabled = true; - this.speechEvent.on('speaking', function () { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.streamManager.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.harkSpeakingEnabledOnce = false; - }); - } - }; - Stream.prototype.enableOnceHarkSpeakingEvent = function () { - var _this = this; - this.setHarkListenerIfNotExists(); - if (!this.harkSpeakingEnabledOnce && !!this.speechEvent) { - this.harkSpeakingEnabledOnce = true; - this.speechEvent.once('speaking', function () { - if (_this.harkSpeakingEnabledOnce) { - _this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - _this.streamManager.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStartSpeaking', _this.connection, _this.streamId)]); - } - _this.disableHarkSpeakingEvent(true); - }); - } - }; - Stream.prototype.disableHarkSpeakingEvent = function (disabledByOnce) { - if (!!this.speechEvent) { - this.harkSpeakingEnabledOnce = false; - if (disabledByOnce) { - if (this.harkSpeakingEnabled) { - return; - } - } - else { - this.harkSpeakingEnabled = false; - } - if (this.harkVolumeChangeEnabled || - this.harkVolumeChangeEnabledOnce || - this.harkStoppedSpeakingEnabled || - this.harkStoppedSpeakingEnabledOnce) { - this.speechEvent.off('speaking'); - } - else { - this.speechEvent.stop(); - delete this.speechEvent; - } - } - }; - Stream.prototype.enableHarkStoppedSpeakingEvent = function () { - var _this = this; - this.setHarkListenerIfNotExists(); - if (!this.harkStoppedSpeakingEnabled && !!this.speechEvent) { - this.harkStoppedSpeakingEnabled = true; - this.speechEvent.on('stopped_speaking', function () { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.streamManager.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.harkStoppedSpeakingEnabledOnce = false; - }); - } - }; - Stream.prototype.enableOnceHarkStoppedSpeakingEvent = function () { - var _this = this; - this.setHarkListenerIfNotExists(); - if (!this.harkStoppedSpeakingEnabledOnce && !!this.speechEvent) { - this.harkStoppedSpeakingEnabledOnce = true; - this.speechEvent.once('stopped_speaking', function () { - if (_this.harkStoppedSpeakingEnabledOnce) { - _this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.session, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - _this.streamManager.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent_1.PublisherSpeakingEvent(_this.streamManager, 'publisherStopSpeaking', _this.connection, _this.streamId)]); - } - _this.disableHarkStoppedSpeakingEvent(true); - }); - } - }; - Stream.prototype.disableHarkStoppedSpeakingEvent = function (disabledByOnce) { - if (!!this.speechEvent) { - this.harkStoppedSpeakingEnabledOnce = false; - if (disabledByOnce) { - if (this.harkStoppedSpeakingEnabled) { - return; - } - } - else { - this.harkStoppedSpeakingEnabled = false; - } - if (this.harkVolumeChangeEnabled || - this.harkVolumeChangeEnabledOnce || - this.harkSpeakingEnabled || - this.harkSpeakingEnabledOnce) { - this.speechEvent.off('stopped_speaking'); - } - else { - this.speechEvent.stop(); - delete this.speechEvent; - } - } - }; - Stream.prototype.enableHarkVolumeChangeEvent = function (force) { - var _this = this; - if (this.setHarkListenerIfNotExists()) { - if (!this.harkVolumeChangeEnabled || force) { - this.harkVolumeChangeEnabled = true; - this.speechEvent.on('volume_change', function (harkEvent) { - var oldValue = _this.speechEvent.oldVolumeValue; - var value = { newValue: harkEvent, oldValue: oldValue }; - _this.speechEvent.oldVolumeValue = harkEvent; - _this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent_1.StreamManagerEvent(_this.streamManager, 'streamAudioVolumeChange', value)]); - }); - } - } - else { - this.harkVolumeChangeEnabled = true; - } - }; - Stream.prototype.enableOnceHarkVolumeChangeEvent = function (force) { - var _this = this; - if (this.setHarkListenerIfNotExists()) { - if (!this.harkVolumeChangeEnabledOnce || force) { - this.harkVolumeChangeEnabledOnce = true; - this.speechEvent.once('volume_change', function (harkEvent) { - var oldValue = _this.speechEvent.oldVolumeValue; - var value = { newValue: harkEvent, oldValue: oldValue }; - _this.speechEvent.oldVolumeValue = harkEvent; - _this.disableHarkVolumeChangeEvent(true); - _this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent_1.StreamManagerEvent(_this.streamManager, 'streamAudioVolumeChange', value)]); - }); - } - } - else { - this.harkVolumeChangeEnabledOnce = true; - } - }; - Stream.prototype.disableHarkVolumeChangeEvent = function (disabledByOnce) { - if (!!this.speechEvent) { - this.harkVolumeChangeEnabledOnce = false; - if (disabledByOnce) { - if (this.harkVolumeChangeEnabled) { - return; - } - } - else { - this.harkVolumeChangeEnabled = false; - } - if (this.harkSpeakingEnabled || - this.harkSpeakingEnabledOnce || - this.harkStoppedSpeakingEnabled || - this.harkStoppedSpeakingEnabledOnce) { - this.speechEvent.off('volume_change'); - } - else { - this.speechEvent.stop(); - delete this.speechEvent; - } - } - }; - Stream.prototype.isLocal = function () { - return (!this.inboundStreamOpts && !!this.outboundStreamOpts); - }; - Stream.prototype.getSelectedIceCandidate = function () { - var _this = this; - return new Promise(function (resolve, reject) { - _this.webRtcStats.getSelectedIceCandidateInfo() - .then(function (report) { return resolve(report); }) - .catch(function (error) { return reject(error); }); - }); - }; - Stream.prototype.getRemoteIceCandidateList = function () { - return this.webRtcPeer.remoteCandidatesQueue; - }; - Stream.prototype.getLocalIceCandidateList = function () { - return this.webRtcPeer.localCandidatesQueue; - }; - Stream.prototype.streamIceConnectionStateBroken = function () { - if (!this.getWebRtcPeer() || !this.getRTCPeerConnection()) { - return false; - } - if (this.isLocal() && !!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) { - logger.warn("OpenVidu Browser advanced configuration option \"forceMediaReconnectionAfterNetworkDrop\" is enabled. Stream ".concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") will force a reconnection")); - return true; - } - var iceConnectionState = this.getRTCPeerConnection().iceConnectionState; - return iceConnectionState !== 'connected' && iceConnectionState !== 'completed'; - }; - Stream.prototype.setHarkListenerIfNotExists = function () { - if (!!this.mediaStream) { - if (!this.speechEvent) { - var harkOptions = !!this.harkOptions ? this.harkOptions : (this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}); - harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 100; - harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50; - this.speechEvent = hark(this.mediaStream, harkOptions); - } - return true; - } - return false; - }; - Stream.prototype.setupReconnectionEventEmitter = function (resolve, reject) { - if (this.reconnectionEventEmitter == undefined) { - this.reconnectionEventEmitter = new EventEmitter(); - return false; - } - else { - console.warn("Trying to reconnect stream ".concat(this.streamId, " (").concat(this.isLocal() ? 'Publisher' : 'Subscriber', ") but an ongoing reconnection process is active. Waiting for response...")); - this.reconnectionEventEmitter.once('success', function () { return resolve(); }); - this.reconnectionEventEmitter.once('error', function (error) { return reject(error); }); - return true; - } - }; - Stream.prototype.initWebRtcPeerSend = function (reconnect) { - var _this = this; - return new Promise(function (resolve, reject) { - var _a; - if (reconnect) { - if (_this.setupReconnectionEventEmitter(resolve, reject)) { - return; - } - } - else { - _this.initHarkEvents(); - } - var finalResolve = function () { - var _a; - if (reconnect) { - (_a = _this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('success'); - delete _this.reconnectionEventEmitter; - } - return resolve(); - }; - var finalReject = function (error) { - var _a; - if (reconnect) { - (_a = _this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('error', [error]); - delete _this.reconnectionEventEmitter; - } - return reject(error); - }; - var successOfferCallback = function (sdpOfferParam) { - logger.debug('Sending SDP offer to publish as ' - + _this.streamId, sdpOfferParam); - var method = reconnect ? 'reconnectStream' : 'publishVideo'; - var params; - if (reconnect) { - params = { - stream: _this.streamId, - sdpString: sdpOfferParam - }; - } - else { - var typeOfVideo = void 0; - if (_this.isSendVideo()) { - typeOfVideo = (typeof MediaStreamTrack !== 'undefined' && _this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) ? TypeOfVideo_1.TypeOfVideo.CUSTOM : (_this.isSendScreen() ? TypeOfVideo_1.TypeOfVideo.SCREEN : TypeOfVideo_1.TypeOfVideo.CAMERA); - } - params = { - doLoopback: _this.displayMyRemote() || false, - hasAudio: _this.isSendAudio(), - hasVideo: _this.isSendVideo(), - audioActive: _this.audioActive, - videoActive: _this.videoActive, - typeOfVideo: typeOfVideo, - frameRate: !!_this.frameRate ? _this.frameRate : -1, - videoDimensions: JSON.stringify(_this.videoDimensions), - filter: _this.outboundStreamOpts.publisherProperties.filter, - sdpOffer: sdpOfferParam - }; - } - _this.session.openvidu.sendRequest(method, params, function (error, response) { - if (error) { - if (error.code === 401) { - finalReject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.OPENVIDU_PERMISSION_DENIED, "You don't have permissions to publish")); - } - else { - finalReject('Error on publishVideo: ' + JSON.stringify(error)); - } - } - else { - _this.webRtcPeer.processRemoteAnswer(response.sdpAnswer) - .then(function () { - _this.streamId = response.id; - _this.creationTime = response.createdAt; - _this.isLocalStreamPublished = true; - _this.publishedOnce = true; - if (_this.displayMyRemote()) { - _this.localMediaStreamWhenSubscribedToRemote = _this.mediaStream; - _this.remotePeerSuccessfullyEstablished(reconnect); - } - if (reconnect) { - _this.ee.emitEvent('stream-reconnected-by-publisher', []); - } - else { - _this.ee.emitEvent('stream-created-by-publisher', []); - } - _this.initWebRtcStats(); - logger.info("'Publisher' (" + _this.streamId + ") successfully " + (reconnect ? "reconnected" : "published") + " to session"); - finalResolve(); - }) - .catch(function (error) { - finalReject(error); - }); - } - }); - }; - var config = { - mediaConstraints: { - audio: _this.hasAudio, - video: _this.hasVideo, - }, - simulcast: (_a = _this.outboundStreamOpts.publisherProperties.videoSimulcast) !== null && _a !== void 0 ? _a : _this.session.openvidu.videoSimulcast, - onIceCandidate: _this.connection.sendIceCandidate.bind(_this.connection), - onIceConnectionStateException: function (exceptionName, message, data) { _this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, exceptionName, _this, message, data)]); }, - iceServers: _this.getIceServersConf(), - mediaStream: _this.mediaStream, - mediaServer: _this.session.openvidu.mediaServer, - typeOfVideo: _this.typeOfVideo ? TypeOfVideo_1.TypeOfVideo[_this.typeOfVideo] : undefined, - }; - if (_this.session.openvidu.mediaServer !== 'mediasoup') { - config.simulcast = false; - } - if (reconnect) { - _this.disposeWebRtcPeer(); - } - if (_this.displayMyRemote()) { - _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendrecv(config); - } - else { - _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerSendonly(config); - } - _this.webRtcPeer.addIceConnectionStateChangeListener('publisher of ' + _this.connection.connectionId); - _this.webRtcPeer.createOffer().then(function (sdpOffer) { - _this.webRtcPeer.processLocalOffer(sdpOffer) - .then(function () { - successOfferCallback(sdpOffer.sdp); - }).catch(function (error) { - finalReject(new Error('(publish) SDP process local offer error: ' + JSON.stringify(error))); - }); - }).catch(function (error) { - finalReject(new Error('(publish) SDP create offer error: ' + JSON.stringify(error))); - }); - }); - }; - Stream.prototype.finalResolveForSubscription = function (reconnect, resolve) { - var _a; - logger.info("'Subscriber' (" + this.streamId + ") successfully " + (reconnect ? "reconnected" : "subscribed")); - this.remotePeerSuccessfullyEstablished(reconnect); - this.initWebRtcStats(); - if (reconnect) { - (_a = this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('success'); - delete this.reconnectionEventEmitter; - } - return resolve(); - }; - Stream.prototype.finalRejectForSubscription = function (reconnect, error, reject) { - var _a; - logger.error("Error for 'Subscriber' (" + this.streamId + ") while trying to " + (reconnect ? "reconnect" : "subscribe") + ": " + error.toString()); - if (reconnect) { - (_a = this.reconnectionEventEmitter) === null || _a === void 0 ? void 0 : _a.emitEvent('error', [error]); - delete this.reconnectionEventEmitter; - } - return reject(error); - }; - Stream.prototype.initWebRtcPeerReceive = function (reconnect) { - var _this = this; - return new Promise(function (resolve, reject) { - if (reconnect) { - if (_this.setupReconnectionEventEmitter(resolve, reject)) { - return; - } - } - if (_this.session.openvidu.mediaServer === 'mediasoup') { - _this.initWebRtcPeerReceiveFromServer(reconnect) - .then(function () { return _this.finalResolveForSubscription(reconnect, resolve); }) - .catch(function (error) { return _this.finalRejectForSubscription(reconnect, error, reject); }); - } - else { - _this.initWebRtcPeerReceiveFromClient(reconnect) - .then(function () { return _this.finalResolveForSubscription(reconnect, resolve); }) - .catch(function (error) { return _this.finalRejectForSubscription(reconnect, error, reject); }); - } - }); - }; - Stream.prototype.initWebRtcPeerReceiveFromClient = function (reconnect) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.completeWebRtcPeerReceive(reconnect, false) - .then(function (response) { - _this.webRtcPeer.processRemoteAnswer(response.sdpAnswer) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - }) - .catch(function (error) { return reject(error); }); - }); - }; - Stream.prototype.initWebRtcPeerReceiveFromServer = function (reconnect) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.session.openvidu.sendRequest('prepareReceiveVideoFrom', { sender: _this.streamId, reconnect: reconnect }, function (error, response) { - if (error) { - return reject(new Error('Error on prepareReceiveVideoFrom: ' + JSON.stringify(error))); - } - else { - _this.completeWebRtcPeerReceive(reconnect, false, response.sdpOffer) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - } - }); - }); - }; - Stream.prototype.completeWebRtcPeerReceive = function (reconnect, forciblyReconnect, sdpOfferByServer) { - var _this = this; - return new Promise(function (resolve, reject) { - logger.debug("'Session.subscribe(Stream)' called"); - var sendSdpToServer = function (sdpString) { - logger.debug("Sending local SDP ".concat((!!sdpOfferByServer ? 'answer' : 'offer'), " to subscribe to ").concat(_this.streamId), sdpString); - var method = reconnect ? 'reconnectStream' : 'receiveVideoFrom'; - var params = {}; - params[reconnect ? 'stream' : 'sender'] = _this.streamId; - if (!!sdpOfferByServer) { - params[reconnect ? 'sdpString' : 'sdpAnswer'] = sdpString; - } - else { - params['sdpOffer'] = sdpString; - } - if (reconnect) { - params['forciblyReconnect'] = forciblyReconnect; - } - _this.session.openvidu.sendRequest(method, params, function (error, response) { - if (error) { - return reject(new Error('Error on ' + method + ' : ' + JSON.stringify(error))); - } - else { - return resolve(response); - } - }); - }; - var config = { - mediaConstraints: { - audio: _this.hasAudio, - video: _this.hasVideo, - }, - simulcast: false, - onIceCandidate: _this.connection.sendIceCandidate.bind(_this.connection), - onIceConnectionStateException: function (exceptionName, message, data) { _this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.session, exceptionName, _this, message, data)]); }, - iceServers: _this.getIceServersConf(), - mediaServer: _this.session.openvidu.mediaServer, - typeOfVideo: _this.typeOfVideo ? TypeOfVideo_1.TypeOfVideo[_this.typeOfVideo] : undefined, - }; - if (reconnect) { - _this.disposeWebRtcPeer(); - } - _this.webRtcPeer = new WebRtcPeer_1.WebRtcPeerRecvonly(config); - _this.webRtcPeer.addIceConnectionStateChangeListener(_this.streamId); - if (!!sdpOfferByServer) { - _this.webRtcPeer.processRemoteOffer(sdpOfferByServer).then(function () { - _this.webRtcPeer.createAnswer().then(function (sdpAnswer) { - _this.webRtcPeer.processLocalAnswer(sdpAnswer).then(function () { - sendSdpToServer(sdpAnswer.sdp); - }).catch(function (error) { - return reject(new Error('(subscribe) SDP process local answer error: ' + JSON.stringify(error))); - }); - }).catch(function (error) { - return reject(new Error('(subscribe) SDP create answer error: ' + JSON.stringify(error))); - }); - }).catch(function (error) { - return reject(new Error('(subscribe) SDP process remote offer error: ' + JSON.stringify(error))); - }); - } - else { - _this.webRtcPeer.createOffer().then(function (sdpOffer) { - _this.webRtcPeer.processLocalOffer(sdpOffer).then(function () { - sendSdpToServer(sdpOffer.sdp); - }).catch(function (error) { - return reject(new Error('(subscribe) SDP process local offer error: ' + JSON.stringify(error))); - }); - }).catch(function (error) { - return reject(new Error('(subscribe) SDP create offer error: ' + JSON.stringify(error))); - }); - } - }); - }; - Stream.prototype.remotePeerSuccessfullyEstablished = function (reconnect) { - if (reconnect && this.mediaStream != null) { - this.disposeMediaStream(); - } - this.mediaStream = new MediaStream(); - var receiver; - for (var _i = 0, _a = this.webRtcPeer.pc.getReceivers(); _i < _a.length; _i++) { - receiver = _a[_i]; - if (!!receiver.track) { - this.mediaStream.addTrack(receiver.track); - } - } - logger.debug('Peer remote stream', this.mediaStream); - if (!!this.mediaStream) { - if (this.streamManager instanceof Subscriber_1.Subscriber) { - if (!!this.mediaStream.getAudioTracks()[0]) { - var enabled = reconnect ? this.audioActive : !!(this.streamManager.properties.subscribeToAudio); - this.mediaStream.getAudioTracks()[0].enabled = enabled; - } - if (!!this.mediaStream.getVideoTracks()[0]) { - var enabled = reconnect ? this.videoActive : !!(this.streamManager.properties.subscribeToVideo); - this.mediaStream.getVideoTracks()[0].enabled = enabled; - } - } - this.updateMediaStreamInVideos(); - this.initHarkEvents(); - } - }; - Stream.prototype.initHarkEvents = function () { - if (!!this.mediaStream.getAudioTracks()[0]) { - if (this.session.anySpeechEventListenerEnabled('publisherStartSpeaking', true, this.streamManager)) { - this.enableOnceHarkSpeakingEvent(); - } - if (this.session.anySpeechEventListenerEnabled('publisherStartSpeaking', false, this.streamManager)) { - this.enableHarkSpeakingEvent(); - } - if (this.session.anySpeechEventListenerEnabled('publisherStopSpeaking', true, this.streamManager)) { - this.enableOnceHarkStoppedSpeakingEvent(); - } - if (this.session.anySpeechEventListenerEnabled('publisherStopSpeaking', false, this.streamManager)) { - this.enableHarkStoppedSpeakingEvent(); - } - if (this.harkVolumeChangeEnabledOnce) { - this.enableOnceHarkVolumeChangeEvent(true); - } - if (this.harkVolumeChangeEnabled) { - this.enableHarkVolumeChangeEvent(true); - } - } - }; - Stream.prototype.onIceConnectionStateExceptionHandler = function (exceptionName, message, data) { - switch (exceptionName) { - case ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED: - this.onIceConnectionFailed(); - break; - case ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED: - this.onIceConnectionDisconnected(); - break; - } - this.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(this.session, exceptionName, this, message, data)]); - }; - Stream.prototype.onIceConnectionFailed = function () { - logger.log("[ICE_CONNECTION_FAILED] Handling ICE_CONNECTION_FAILED event. Reconnecting stream ".concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ")")); - this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED); - }; - Stream.prototype.onIceConnectionDisconnected = function () { - var _this = this; - logger.log("[ICE_CONNECTION_DISCONNECTED] Handling ICE_CONNECTION_DISCONNECTED event. Waiting for ICE to be restored and reconnect stream ".concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") if not possible")); - var timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000; - this.awaitWebRtcPeerConnectionState(timeout).then(function (state) { - switch (state) { - case 'failed': - logger.warn("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ".concat(_this.streamId, " (").concat((_this.isLocal() ? 'Publisher' : 'Subscriber'), ") is now failed after ICE_CONNECTION_DISCONNECTED")); - break; - case 'connected': - case 'completed': - logger.log("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ".concat(_this.streamId, " (").concat((_this.isLocal() ? 'Publisher' : 'Subscriber'), ") automatically restored after ICE_CONNECTION_DISCONNECTED. Current ICE connection state: ").concat(state)); - break; - case 'closed': - case 'checking': - case 'new': - case 'disconnected': - logger.warn("[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ".concat(_this.streamId, " (").concat((_this.isLocal() ? 'Publisher' : 'Subscriber'), ") couldn't be restored after ICE_CONNECTION_DISCONNECTED event. Current ICE connection state after ").concat(timeout, " ms: ").concat(state)); - _this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED); - break; - } - }); - }; - Stream.prototype.reconnectStreamAndLogResultingIceConnectionState = function (event) { - return __awaiter(this, void 0, void 0, function () { - var finalIceStateAfterReconnection, error_5; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4, this.reconnectStreamAndReturnIceConnectionState(event)]; - case 1: - finalIceStateAfterReconnection = _a.sent(); - switch (finalIceStateAfterReconnection) { - case 'connected': - case 'completed': - logger.log("[".concat(event, "] Stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") successfully reconnected after ").concat(event, ". Current ICE connection state: ").concat(finalIceStateAfterReconnection)); - break; - default: - logger.error("[".concat(event, "] Stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") failed to reconnect after ").concat(event, ". Current ICE connection state: ").concat(finalIceStateAfterReconnection)); - break; - } - return [3, 3]; - case 2: - error_5 = _a.sent(); - logger.error("[".concat(event, "] Error reconnecting stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") after ").concat(event, ": ").concat(error_5)); - return [3, 3]; - case 3: return [2]; - } - }); - }); - }; - Stream.prototype.reconnectStreamAndReturnIceConnectionState = function (event) { - return __awaiter(this, void 0, void 0, function () { - var timeout, error_6; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - logger.log("[".concat(event, "] Reconnecting stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") after event ").concat(event)); - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4, this.reconnectStream(event)]; - case 2: - _a.sent(); - timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000; - return [2, this.awaitWebRtcPeerConnectionState(timeout)]; - case 3: - error_6 = _a.sent(); - logger.warn("[".concat(event, "] Error reconnecting stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), "). Reason: ").concat(error_6)); - return [2, this.awaitWebRtcPeerConnectionState(1)]; - case 4: return [2]; - } - }); - }); - }; - Stream.prototype.reconnectStream = function (event) { - return __awaiter(this, void 0, void 0, function () { - var isWsConnected, errorMsg; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4, this.isWebsocketConnected(event, 3000)]; - case 1: - isWsConnected = _a.sent(); - if (isWsConnected) { - logger.log("[".concat(event, "] Trying to reconnect stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") and the websocket is opened")); - if (this.isLocal()) { - return [2, this.initWebRtcPeerSend(true)]; - } - else { - return [2, this.initWebRtcPeerReceive(true)]; - } - } - else { - errorMsg = "[".concat(event, "] Trying to reconnect stream ").concat(this.streamId, " (").concat((this.isLocal() ? 'Publisher' : 'Subscriber'), ") but the websocket wasn't opened"); - logger.error(errorMsg); - throw Error(errorMsg); - } - return [2]; - } - }); - }); - }; - Stream.prototype.isWebsocketConnected = function (event, msResponseTimeout) { - var _this = this; - return new Promise(function (resolve, reject) { - var wsReadyState = _this.session.openvidu.getWsReadyState(); - if (wsReadyState === 1) { - var responseTimeout_1 = setTimeout(function () { - console.warn("[".concat(event, "] Websocket timeout of ").concat(msResponseTimeout, "ms")); - return resolve(false); - }, msResponseTimeout); - _this.session.openvidu.sendRequest('echo', {}, function (error, response) { - clearTimeout(responseTimeout_1); - if (!!error) { - console.warn("[".concat(event, "] Websocket 'echo' returned error: ").concat(error)); - return resolve(false); - } - else { - return resolve(true); - } - }); - } - else { - console.warn("[".concat(event, "] Websocket readyState is ").concat(wsReadyState)); - return resolve(false); - } - }); - }; - Stream.prototype.awaitWebRtcPeerConnectionState = function (timeout) { - return __awaiter(this, void 0, void 0, function () { - var state, interval, intervals, i; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - state = this.getRTCPeerConnection().iceConnectionState; - interval = 150; - intervals = Math.ceil(timeout / interval); - i = 0; - _a.label = 1; - case 1: - if (!(i < intervals)) return [3, 4]; - state = this.getRTCPeerConnection().iceConnectionState; - if (state === 'connected' || state === 'completed') { - return [3, 4]; - } - return [4, new Promise(function (resolve) { return setTimeout(resolve, interval); })]; - case 2: - _a.sent(); - _a.label = 3; - case 3: - i++; - return [3, 1]; - case 4: return [2, state]; - } - }); - }); - }; - Stream.prototype.initWebRtcStats = function () { - this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); - this.webRtcStats.initWebRtcStats(); - }; - Stream.prototype.stopWebRtcStats = function () { - if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { - this.webRtcStats.stopWebRtcStats(); - } - }; - Stream.prototype.getIceServersConf = function () { - var returnValue; - if (!!this.session.openvidu.advancedConfiguration.iceServers) { - returnValue = this.session.openvidu.advancedConfiguration.iceServers === 'freeice' ? - undefined : - this.session.openvidu.advancedConfiguration.iceServers; - } - else if (this.session.openvidu.iceServers) { - returnValue = this.session.openvidu.iceServers; - } - else { - returnValue = undefined; - } - return returnValue; - }; - Stream.prototype.gatherStatsForPeer = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if (_this.isLocal()) { - _this.getRTCPeerConnection().getSenders().forEach(function (sender) { return sender.getStats() - .then(function (response) { - response.forEach(function (report) { - if (_this.isReportWanted(report)) { - var finalReport = {}; - finalReport['type'] = report.type; - finalReport['timestamp'] = report.timestamp; - finalReport['id'] = report.id; - if (report.type === 'outbound-rtp') { - finalReport['ssrc'] = report.ssrc; - finalReport['firCount'] = report.firCount; - finalReport['pliCount'] = report.pliCount; - finalReport['nackCount'] = report.nackCount; - finalReport['qpSum'] = report.qpSum; - if (!!report.kind) { - finalReport['mediaType'] = report.kind; - } - else if (!!report.mediaType) { - finalReport['mediaType'] = report.mediaType; - } - else { - finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio'; - } - if (finalReport['mediaType'] === 'video') { - finalReport['framesEncoded'] = report.framesEncoded; - } - finalReport['packetsSent'] = report.packetsSent; - finalReport['bytesSent'] = report.bytesSent; - } - if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) { - finalReport['availableOutgoingBitrate'] = report.availableOutgoingBitrate; - finalReport['rtt'] = report.currentRoundTripTime; - finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived; - } - if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') { - } - logger.log(finalReport); - } - }); - }); }); - } - else { - _this.getRTCPeerConnection().getReceivers().forEach(function (receiver) { return receiver.getStats() - .then(function (response) { - response.forEach(function (report) { - if (_this.isReportWanted(report)) { - var finalReport = {}; - finalReport['type'] = report.type; - finalReport['timestamp'] = report.timestamp; - finalReport['id'] = report.id; - if (report.type === 'inbound-rtp') { - finalReport['ssrc'] = report.ssrc; - finalReport['firCount'] = report.firCount; - finalReport['pliCount'] = report.pliCount; - finalReport['nackCount'] = report.nackCount; - finalReport['qpSum'] = report.qpSum; - if (!!report.kind) { - finalReport['mediaType'] = report.kind; - } - else if (!!report.mediaType) { - finalReport['mediaType'] = report.mediaType; - } - else { - finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio'; - } - if (finalReport['mediaType'] === 'video') { - finalReport['framesDecoded'] = report.framesDecoded; - } - finalReport['packetsReceived'] = report.packetsReceived; - finalReport['packetsLost'] = report.packetsLost; - finalReport['jitter'] = report.jitter; - finalReport['bytesReceived'] = report.bytesReceived; - } - if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) { - finalReport['availableIncomingBitrate'] = report.availableIncomingBitrate; - finalReport['rtt'] = report.currentRoundTripTime; - finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived; - } - if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') { - } - logger.log(finalReport); - } - }); - }); }); - } - }); - }; - Stream.prototype.isReportWanted = function (report) { - return report.type === 'inbound-rtp' && !this.isLocal() || - report.type === 'outbound-rtp' && this.isLocal() || - (report.type === 'candidate-pair' && report.nominated && report.bytesSent > 0); - }; - return Stream; -}()); -exports.Stream = Stream; - -},{"../OpenViduInternal/Enums/OpenViduError":52,"../OpenViduInternal/Enums/TypeOfVideo":53,"../OpenViduInternal/Events/ExceptionEvent":58,"../OpenViduInternal/Events/PublisherSpeakingEvent":61,"../OpenViduInternal/Events/StreamManagerEvent":66,"../OpenViduInternal/Events/StreamPropertyChangedEvent":67,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Utils/Platform":83,"../OpenViduInternal/WebRtcPeer/WebRtcPeer":84,"../OpenViduInternal/WebRtcStats/WebRtcStats":85,"./Filter":43,"./Subscriber":50,"hark":5,"uuid":22,"wolfy87-eventemitter":38}],49:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.StreamManager = void 0; -var EventDispatcher_1 = require("./EventDispatcher"); -var StreamManagerEvent_1 = require("../OpenViduInternal/Events/StreamManagerEvent"); -var VideoElementEvent_1 = require("../OpenViduInternal/Events/VideoElementEvent"); -var ExceptionEvent_1 = require("../OpenViduInternal/Events/ExceptionEvent"); -var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var Platform_1 = require("../OpenViduInternal/Utils/Platform"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var StreamManager = (function (_super) { - __extends(StreamManager, _super); - function StreamManager(stream, targetElement) { - var _this = _super.call(this) || this; - _this.videos = []; - _this.lazyLaunchVideoElementCreatedEvent = false; - platform = Platform_1.PlatformUtils.getInstance(); - _this.stream = stream; - _this.stream.streamManager = _this; - _this.remote = !_this.stream.isLocal(); - if (!!targetElement) { - var targEl = void 0; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - if (!!targEl) { - _this.firstVideoElement = { - targetElement: targEl, - video: document.createElement('video'), - id: '', - canplayListenerAdded: false - }; - if (platform.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) { - _this.firstVideoElement.video.setAttribute('playsinline', 'true'); - } - _this.targetElement = targEl; - _this.element = targEl; - } - } - _this.canPlayListener = function () { - _this.deactivateStreamPlayingEventExceptionTimeout(); - _this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(_this, 'streamPlaying', undefined)]); - }; - return _this; - } - StreamManager.prototype.on = function (type, handler) { - _super.prototype.onAux.call(this, type, "Event '" + type + "' triggered by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = false; - } - } - if (type === 'streamPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this, 'streamPlaying', undefined)]); - } - } - if (this.stream.hasAudio) { - if (type === 'publisherStartSpeaking') { - this.stream.enableHarkSpeakingEvent(); - } - if (type === 'publisherStopSpeaking') { - this.stream.enableHarkStoppedSpeakingEvent(); - } - if (type === 'streamAudioVolumeChange') { - this.stream.enableHarkVolumeChangeEvent(false); - } - } - return this; - }; - StreamManager.prototype.once = function (type, handler) { - _super.prototype.onceAux.call(this, type, "Event '" + type + "' triggered once by '" + (this.remote ? 'Subscriber' : 'Publisher') + "'", handler); - if (type === 'videoElementCreated') { - if (!!this.stream && this.lazyLaunchVideoElementCreatedEvent) { - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(this.videos[0].video, this, 'videoElementCreated')]); - } - } - if (type === 'streamPlaying') { - if (this.videos[0] && this.videos[0].video && - this.videos[0].video.currentTime > 0 && - this.videos[0].video.paused === false && - this.videos[0].video.ended === false && - this.videos[0].video.readyState === 4) { - this.ee.emitEvent('streamPlaying', [new StreamManagerEvent_1.StreamManagerEvent(this, 'streamPlaying', undefined)]); - } - } - if (this.stream.hasAudio) { - if (type === 'publisherStartSpeaking') { - this.stream.enableOnceHarkSpeakingEvent(); - } - if (type === 'publisherStopSpeaking') { - this.stream.enableOnceHarkStoppedSpeakingEvent(); - } - if (type === 'streamAudioVolumeChange') { - this.stream.enableOnceHarkVolumeChangeEvent(false); - } - } - return this; - }; - StreamManager.prototype.off = function (type, handler) { - _super.prototype.offAux.call(this, type, handler); - if (type === 'publisherStartSpeaking') { - var remainingStartSpeakingEventListeners = this.ee.getListeners(type).length + this.stream.session.ee.getListeners(type).length; - if (remainingStartSpeakingEventListeners === 0) { - this.stream.disableHarkSpeakingEvent(false); - } - } - if (type === 'publisherStopSpeaking') { - var remainingStopSpeakingEventListeners = this.ee.getListeners(type).length + this.stream.session.ee.getListeners(type).length; - if (remainingStopSpeakingEventListeners === 0) { - this.stream.disableHarkStoppedSpeakingEvent(false); - } - } - if (type === 'streamAudioVolumeChange') { - var remainingVolumeEventListeners = this.ee.getListeners(type).length; - if (remainingVolumeEventListeners === 0) { - this.stream.disableHarkVolumeChangeEvent(false); - } - } - return this; - }; - StreamManager.prototype.addVideoElement = function (video) { - this.initializeVideoProperties(video); - if (!this.remote && this.stream.displayMyRemote()) { - if (video.srcObject !== this.stream.getMediaStream()) { - video.srcObject = this.stream.getMediaStream(); - } - } - for (var _i = 0, _a = this.videos; _i < _a.length; _i++) { - var v = _a[_i]; - if (v.video === video) { - return 0; - } - } - var returnNumber = 1; - for (var _b = 0, _c = this.stream.session.streamManagers; _b < _c.length; _b++) { - var streamManager = _c[_b]; - if (streamManager.disassociateVideo(video)) { - returnNumber = -1; - break; - } - } - this.stream.session.streamManagers.forEach(function (streamManager) { - streamManager.disassociateVideo(video); - }); - this.pushNewStreamManagerVideo({ - video: video, - id: video.id, - canplayListenerAdded: false - }); - logger.info('New video element associated to ', this); - return returnNumber; - }; - StreamManager.prototype.createVideoElement = function (targetElement, insertMode) { - var targEl; - if (typeof targetElement === 'string') { - targEl = document.getElementById(targetElement); - if (!targEl) { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - } - else if (targetElement instanceof HTMLElement) { - targEl = targetElement; - } - else { - throw new Error("The provided 'targetElement' couldn't be resolved to any HTML element: " + targetElement); - } - var video = this.createVideo(); - this.initializeVideoProperties(video); - var insMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; - switch (insMode) { - case VideoInsertMode_1.VideoInsertMode.AFTER: - targEl.parentNode.insertBefore(video, targEl.nextSibling); - break; - case VideoInsertMode_1.VideoInsertMode.APPEND: - targEl.appendChild(video); - break; - case VideoInsertMode_1.VideoInsertMode.BEFORE: - targEl.parentNode.insertBefore(video, targEl); - break; - case VideoInsertMode_1.VideoInsertMode.PREPEND: - targEl.insertBefore(video, targEl.childNodes[0]); - break; - case VideoInsertMode_1.VideoInsertMode.REPLACE: - targEl.parentNode.replaceChild(video, targEl); - break; - default: - insMode = VideoInsertMode_1.VideoInsertMode.APPEND; - targEl.appendChild(video); - break; - } - var v = { - targetElement: targEl, - video: video, - insertMode: insMode, - id: video.id, - canplayListenerAdded: false - }; - this.pushNewStreamManagerVideo(v); - this.ee.emitEvent('videoElementCreated', [new VideoElementEvent_1.VideoElementEvent(v.video, this, 'videoElementCreated')]); - this.lazyLaunchVideoElementCreatedEvent = !!this.firstVideoElement; - return video; - }; - StreamManager.prototype.updatePublisherSpeakingEventsOptions = function (publisherSpeakingEventsOptions) { - var currentHarkOptions = !!this.stream.harkOptions ? this.stream.harkOptions : (this.stream.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {}); - var newInterval = (typeof publisherSpeakingEventsOptions.interval === 'number') ? - publisherSpeakingEventsOptions.interval : ((typeof currentHarkOptions.interval === 'number') ? currentHarkOptions.interval : 100); - var newThreshold = (typeof publisherSpeakingEventsOptions.threshold === 'number') ? - publisherSpeakingEventsOptions.threshold : ((typeof currentHarkOptions.threshold === 'number') ? currentHarkOptions.threshold : -50); - this.stream.harkOptions = { - interval: newInterval, - threshold: newThreshold - }; - if (!!this.stream.speechEvent) { - this.stream.speechEvent.setInterval(newInterval); - this.stream.speechEvent.setThreshold(newThreshold); - } - }; - StreamManager.prototype.initializeVideoProperties = function (video) { - if (!(!this.remote && this.stream.displayMyRemote())) { - if (video.srcObject !== this.stream.getMediaStream()) { - video.srcObject = this.stream.getMediaStream(); - } - } - video.autoplay = true; - video.controls = false; - if (platform.isSafariBrowser() || (platform.isIPhoneOrIPad() && (platform.isChromeMobileBrowser() || platform.isEdgeMobileBrowser() || platform.isOperaMobileBrowser() || platform.isFirefoxMobileBrowser()))) { - video.setAttribute('playsinline', 'true'); - } - if (!video.id) { - video.id = (this.remote ? 'remote-' : 'local-') + 'video-' + this.stream.streamId; - if (!this.id && !!this.targetElement) { - this.id = video.id; - } - } - if (this.remote && this.isMirroredVideo(video)) { - this.removeMirrorVideo(video); - } - else if (!this.remote && !this.stream.displayMyRemote()) { - video.muted = true; - if (this.isMirroredVideo(video) && !this.stream.outboundStreamOpts.publisherProperties.mirror) { - this.removeMirrorVideo(video); - } - else if (this.stream.outboundStreamOpts.publisherProperties.mirror && !this.stream.isSendScreen()) { - this.mirrorVideo(video); - } - } - }; - StreamManager.prototype.removeAllVideos = function () { - var _this = this; - for (var i = this.stream.session.streamManagers.length - 1; i >= 0; --i) { - if (this.stream.session.streamManagers[i] === this) { - this.stream.session.streamManagers.splice(i, 1); - } - } - this.videos.forEach(function (streamManagerVideo) { - if (!!streamManagerVideo.video && !!streamManagerVideo.video.removeEventListener) { - streamManagerVideo.video.removeEventListener('canplay', _this.canPlayListener); - } - streamManagerVideo.canplayListenerAdded = false; - if (!!streamManagerVideo.targetElement) { - streamManagerVideo.video.parentNode.removeChild(streamManagerVideo.video); - _this.ee.emitEvent('videoElementDestroyed', [new VideoElementEvent_1.VideoElementEvent(streamManagerVideo.video, _this, 'videoElementDestroyed')]); - } - _this.removeSrcObject(streamManagerVideo); - _this.videos.filter(function (v) { return !v.targetElement; }); - }); - }; - StreamManager.prototype.disassociateVideo = function (video) { - var disassociated = false; - for (var i = 0; i < this.videos.length; i++) { - if (this.videos[i].video === video) { - this.videos[i].video.removeEventListener('canplay', this.canPlayListener); - this.videos.splice(i, 1); - disassociated = true; - logger.info('Video element disassociated from ', this); - break; - } - } - return disassociated; - }; - StreamManager.prototype.addPlayEventToFirstVideo = function () { - if ((!!this.videos[0]) && (!!this.videos[0].video) && (!this.videos[0].canplayListenerAdded)) { - this.activateStreamPlayingEventExceptionTimeout(); - this.videos[0].video.addEventListener('canplay', this.canPlayListener); - this.videos[0].canplayListenerAdded = true; - } - }; - StreamManager.prototype.updateMediaStream = function (mediaStream) { - this.videos.forEach(function (streamManagerVideo) { - streamManagerVideo.video.srcObject = mediaStream; - if (platform.isIonicIos()) { - var vParent = streamManagerVideo.video.parentElement; - var newVideo = streamManagerVideo.video; - vParent.replaceChild(newVideo, streamManagerVideo.video); - streamManagerVideo.video = newVideo; - } - }); - }; - StreamManager.prototype.emitEvent = function (type, eventArray) { - this.ee.emitEvent(type, eventArray); - }; - StreamManager.prototype.createVideo = function () { - return document.createElement('video'); - }; - StreamManager.prototype.removeSrcObject = function (streamManagerVideo) { - streamManagerVideo.video.srcObject = null; - this.deactivateStreamPlayingEventExceptionTimeout(); - }; - StreamManager.prototype.pushNewStreamManagerVideo = function (streamManagerVideo) { - this.videos.push(streamManagerVideo); - this.addPlayEventToFirstVideo(); - if (this.stream.session.streamManagers.indexOf(this) === -1) { - this.stream.session.streamManagers.push(this); - } - }; - StreamManager.prototype.mirrorVideo = function (video) { - if (!platform.isIonicIos()) { - video.style.transform = 'rotateY(180deg)'; - video.style.webkitTransform = 'rotateY(180deg)'; - } - }; - StreamManager.prototype.removeMirrorVideo = function (video) { - video.style.transform = 'unset'; - video.style.webkitTransform = 'unset'; - }; - StreamManager.prototype.isMirroredVideo = function (video) { - return video.style.transform === 'rotateY(180deg)' || video.style.webkitTransform === 'rotateY(180deg)'; - }; - StreamManager.prototype.activateStreamPlayingEventExceptionTimeout = function () { - var _this = this; - if (!this.remote) { - return; - } - if (this.streamPlayingEventExceptionTimeout != null) { - return; - } - var msTimeout = this.stream.session.openvidu.advancedConfiguration.noStreamPlayingEventExceptionTimeout || 4000; - this.streamPlayingEventExceptionTimeout = setTimeout(function () { - var msg = 'StreamManager of Stream ' + _this.stream.streamId + ' (' + (_this.remote ? 'Subscriber' : 'Publisher') + ') did not trigger "streamPlaying" event in ' + msTimeout + ' ms'; - logger.warn(msg); - _this.stream.session.emitEvent('exception', [new ExceptionEvent_1.ExceptionEvent(_this.stream.session, ExceptionEvent_1.ExceptionEventName.NO_STREAM_PLAYING_EVENT, _this, msg)]); - delete _this.streamPlayingEventExceptionTimeout; - }, msTimeout); - }; - StreamManager.prototype.deactivateStreamPlayingEventExceptionTimeout = function () { - clearTimeout(this.streamPlayingEventExceptionTimeout); - delete this.streamPlayingEventExceptionTimeout; - }; - return StreamManager; -}(EventDispatcher_1.EventDispatcher)); -exports.StreamManager = StreamManager; - -},{"../OpenViduInternal/Enums/VideoInsertMode":54,"../OpenViduInternal/Events/ExceptionEvent":58,"../OpenViduInternal/Events/StreamManagerEvent":66,"../OpenViduInternal/Events/VideoElementEvent":68,"../OpenViduInternal/Logger/OpenViduLogger":79,"../OpenViduInternal/Utils/Platform":83,"./EventDispatcher":42}],50:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Subscriber = void 0; -var StreamManager_1 = require("./StreamManager"); -var OpenViduLogger_1 = require("../OpenViduInternal/Logger/OpenViduLogger"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var Subscriber = (function (_super) { - __extends(Subscriber, _super); - function Subscriber(stream, targEl, properties) { - var _this = _super.call(this, stream, targEl) || this; - _this.element = _this.targetElement; - _this.stream = stream; - _this.properties = properties; - return _this; - } - Subscriber.prototype.subscribeToAudio = function (value) { - this.stream.getMediaStream().getAudioTracks().forEach(function (track) { - track.enabled = value; - }); - this.stream.audioActive = value; - logger.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its audio stream'); - return this; - }; - Subscriber.prototype.subscribeToVideo = function (value) { - this.stream.getMediaStream().getVideoTracks().forEach(function (track) { - track.enabled = value; - }); - this.stream.videoActive = value; - logger.info("'Subscriber' has " + (value ? 'subscribed to' : 'unsubscribed from') + ' its video stream'); - return this; - }; - Subscriber.prototype.replaceTrackInMediaStream = function (track, updateLastConstraints) { - return __awaiter(this, void 0, void 0, function () { - var mediaStream, removedTrack; - return __generator(this, function (_a) { - mediaStream = this.stream.getMediaStream(); - if (track.kind === 'video') { - removedTrack = mediaStream.getVideoTracks()[0]; - if (updateLastConstraints) { - this.stream.lastVideoTrackConstraints = track.getConstraints(); - } - } - else { - removedTrack = mediaStream.getAudioTracks()[0]; - } - mediaStream.removeTrack(removedTrack); - removedTrack.stop(); - mediaStream.addTrack(track); - return [2]; - }); - }); - }; - return Subscriber; -}(StreamManager_1.StreamManager)); -exports.Subscriber = Subscriber; - -},{"../OpenViduInternal/Logger/OpenViduLogger":79,"./StreamManager":49}],51:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.LocalRecorderState = void 0; -var LocalRecorderState; -(function (LocalRecorderState) { - LocalRecorderState["READY"] = "READY"; - LocalRecorderState["RECORDING"] = "RECORDING"; - LocalRecorderState["PAUSED"] = "PAUSED"; - LocalRecorderState["FINISHED"] = "FINISHED"; -})(LocalRecorderState = exports.LocalRecorderState || (exports.LocalRecorderState = {})); - -},{}],52:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.OpenViduError = exports.OpenViduErrorName = void 0; -var OpenViduErrorName; -(function (OpenViduErrorName) { - OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED"; - OpenViduErrorName["DEVICE_ACCESS_DENIED"] = "DEVICE_ACCESS_DENIED"; - OpenViduErrorName["DEVICE_ALREADY_IN_USE"] = "DEVICE_ALREADY_IN_USE"; - OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED"; - OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; - OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; - OpenViduErrorName["SCREEN_EXTENSION_DISABLED"] = "SCREEN_EXTENSION_DISABLED"; - OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; - OpenViduErrorName["INPUT_AUDIO_DEVICE_GENERIC_ERROR"] = "INPUT_AUDIO_DEVICE_GENERIC_ERROR"; - OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; - OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; - OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; - OpenViduErrorName["OPENVIDU_NOT_CONNECTED"] = "OPENVIDU_NOT_CONNECTED"; - OpenViduErrorName["VIRTUAL_BACKGROUND_ERROR"] = "VIRTUAL_BACKGROUND_ERROR"; - OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; -})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); -var OpenViduError = (function () { - function OpenViduError(name, message) { - this.name = name; - this.message = message; - } - return OpenViduError; -}()); -exports.OpenViduError = OpenViduError; - -},{}],53:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.TypeOfVideo = void 0; -var TypeOfVideo; -(function (TypeOfVideo) { - TypeOfVideo["CAMERA"] = "CAMERA"; - TypeOfVideo["SCREEN"] = "SCREEN"; - TypeOfVideo["CUSTOM"] = "CUSTOM"; - TypeOfVideo["IPCAM"] = "IPCAM"; -})(TypeOfVideo = exports.TypeOfVideo || (exports.TypeOfVideo = {})); - -},{}],54:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.VideoInsertMode = void 0; -var VideoInsertMode; -(function (VideoInsertMode) { - VideoInsertMode["AFTER"] = "AFTER"; - VideoInsertMode["APPEND"] = "APPEND"; - VideoInsertMode["BEFORE"] = "BEFORE"; - VideoInsertMode["PREPEND"] = "PREPEND"; - VideoInsertMode["REPLACE"] = "REPLACE"; -})(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); - -},{}],55:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ConnectionEvent = void 0; -var Event_1 = require("./Event"); -var ConnectionEvent = (function (_super) { - __extends(ConnectionEvent, _super); - function ConnectionEvent(cancelable, target, type, connection, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.connection = connection; - _this.reason = reason; - return _this; - } - ConnectionEvent.prototype.callDefaultBehavior = function () { }; - return ConnectionEvent; -}(Event_1.Event)); -exports.ConnectionEvent = ConnectionEvent; - -},{"./Event":57}],56:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ConnectionPropertyChangedEvent = void 0; -var Event_1 = require("./Event"); -var ConnectionPropertyChangedEvent = (function (_super) { - __extends(ConnectionPropertyChangedEvent, _super); - function ConnectionPropertyChangedEvent(target, connection, changedProperty, newValue, oldValue) { - var _this = _super.call(this, false, target, 'connectionPropertyChanged') || this; - _this.connection = connection; - _this.changedProperty = changedProperty; - _this.newValue = newValue; - _this.oldValue = oldValue; - return _this; - } - ConnectionPropertyChangedEvent.prototype.callDefaultBehavior = function () { }; - return ConnectionPropertyChangedEvent; -}(Event_1.Event)); -exports.ConnectionPropertyChangedEvent = ConnectionPropertyChangedEvent; - -},{"./Event":57}],57:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Event = void 0; -var Event = (function () { - function Event(cancelable, target, type) { - this.hasBeenPrevented = false; - this.cancelable = cancelable; - this.target = target; - this.type = type; - } - Event.prototype.isDefaultPrevented = function () { - return this.hasBeenPrevented; - }; - Event.prototype.preventDefault = function () { - this.callDefaultBehavior = function () { }; - this.hasBeenPrevented = true; - }; - return Event; -}()); -exports.Event = Event; - -},{}],58:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ExceptionEvent = exports.ExceptionEventName = void 0; -var Event_1 = require("./Event"); -var ExceptionEventName; -(function (ExceptionEventName) { - ExceptionEventName["ICE_CANDIDATE_ERROR"] = "ICE_CANDIDATE_ERROR"; - ExceptionEventName["ICE_CONNECTION_FAILED"] = "ICE_CONNECTION_FAILED"; - ExceptionEventName["ICE_CONNECTION_DISCONNECTED"] = "ICE_CONNECTION_DISCONNECTED"; - ExceptionEventName["NO_STREAM_PLAYING_EVENT"] = "NO_STREAM_PLAYING_EVENT"; -})(ExceptionEventName = exports.ExceptionEventName || (exports.ExceptionEventName = {})); -var ExceptionEvent = (function (_super) { - __extends(ExceptionEvent, _super); - function ExceptionEvent(session, name, origin, message, data) { - var _this = _super.call(this, false, session, 'exception') || this; - _this.name = name; - _this.origin = origin; - _this.message = message; - _this.data = data; - return _this; - } - ExceptionEvent.prototype.callDefaultBehavior = function () { }; - return ExceptionEvent; -}(Event_1.Event)); -exports.ExceptionEvent = ExceptionEvent; - -},{"./Event":57}],59:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FilterEvent = void 0; -var Event_1 = require("./Event"); -var FilterEvent = (function (_super) { - __extends(FilterEvent, _super); - function FilterEvent(target, eventType, data) { - var _this = _super.call(this, false, target, eventType) || this; - _this.data = data; - return _this; - } - FilterEvent.prototype.callDefaultBehavior = function () { }; - return FilterEvent; -}(Event_1.Event)); -exports.FilterEvent = FilterEvent; - -},{"./Event":57}],60:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.NetworkQualityLevelChangedEvent = void 0; -var Event_1 = require("./Event"); -var NetworkQualityLevelChangedEvent = (function (_super) { - __extends(NetworkQualityLevelChangedEvent, _super); - function NetworkQualityLevelChangedEvent(target, newValue, oldValue, connection) { - var _this = _super.call(this, false, target, 'networkQualityLevelChanged') || this; - _this.newValue = newValue; - _this.oldValue = oldValue; - _this.connection = connection; - return _this; - } - NetworkQualityLevelChangedEvent.prototype.callDefaultBehavior = function () { }; - return NetworkQualityLevelChangedEvent; -}(Event_1.Event)); -exports.NetworkQualityLevelChangedEvent = NetworkQualityLevelChangedEvent; - -},{"./Event":57}],61:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PublisherSpeakingEvent = void 0; -var Event_1 = require("./Event"); -var PublisherSpeakingEvent = (function (_super) { - __extends(PublisherSpeakingEvent, _super); - function PublisherSpeakingEvent(target, type, connection, streamId) { - var _this = _super.call(this, false, target, type) || this; - _this.type = type; - _this.connection = connection; - _this.streamId = streamId; - return _this; - } - PublisherSpeakingEvent.prototype.callDefaultBehavior = function () { }; - return PublisherSpeakingEvent; -}(Event_1.Event)); -exports.PublisherSpeakingEvent = PublisherSpeakingEvent; - -},{"./Event":57}],62:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.RecordingEvent = void 0; -var Event_1 = require("./Event"); -var RecordingEvent = (function (_super) { - __extends(RecordingEvent, _super); - function RecordingEvent(target, type, id, name, reason) { - var _this = _super.call(this, false, target, type) || this; - _this.id = id; - if (name !== id) { - _this.name = name; - } - _this.reason = reason; - return _this; - } - RecordingEvent.prototype.callDefaultBehavior = function () { }; - return RecordingEvent; -}(Event_1.Event)); -exports.RecordingEvent = RecordingEvent; - -},{"./Event":57}],63:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.SessionDisconnectedEvent = void 0; -var Event_1 = require("./Event"); -var OpenViduLogger_1 = require("../Logger/OpenViduLogger"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var SessionDisconnectedEvent = (function (_super) { - __extends(SessionDisconnectedEvent, _super); - function SessionDisconnectedEvent(target, reason) { - var _this = _super.call(this, true, target, 'sessionDisconnected') || this; - _this.reason = reason; - return _this; - } - SessionDisconnectedEvent.prototype.callDefaultBehavior = function () { - logger.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'"); - var session = this.target; - session.remoteConnections.forEach(function (remoteConnection) { - var _a, _b, _c, _d, _e, _f, _g, _h; - var connectionId = remoteConnection.connectionId; - if (!!((_a = session.remoteConnections.get(connectionId)) === null || _a === void 0 ? void 0 : _a.stream)) { - (_b = session.remoteConnections.get(connectionId)) === null || _b === void 0 ? void 0 : _b.stream.disposeWebRtcPeer(); - (_c = session.remoteConnections.get(connectionId)) === null || _c === void 0 ? void 0 : _c.stream.disposeMediaStream(); - if ((_d = session.remoteConnections.get(connectionId)) === null || _d === void 0 ? void 0 : _d.stream.streamManager) { - (_e = session.remoteConnections.get(connectionId)) === null || _e === void 0 ? void 0 : _e.stream.streamManager.removeAllVideos(); - } - var streamId = (_g = (_f = session.remoteConnections.get(connectionId)) === null || _f === void 0 ? void 0 : _f.stream) === null || _g === void 0 ? void 0 : _g.streamId; - if (!!streamId) { - session.remoteStreamsCreated.delete(streamId); - } - (_h = session.remoteConnections.get(connectionId)) === null || _h === void 0 ? void 0 : _h.dispose(); - } - session.remoteConnections.delete(connectionId); - }); - }; - return SessionDisconnectedEvent; -}(Event_1.Event)); -exports.SessionDisconnectedEvent = SessionDisconnectedEvent; - -},{"../Logger/OpenViduLogger":79,"./Event":57}],64:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.SignalEvent = void 0; -var Event_1 = require("./Event"); -var SignalEvent = (function (_super) { - __extends(SignalEvent, _super); - function SignalEvent(target, type, data, from) { - var _this = _super.call(this, false, target, 'signal') || this; - if (!!type) { - _this.type = 'signal:' + type; - } - _this.data = data; - _this.from = from; - return _this; - } - SignalEvent.prototype.callDefaultBehavior = function () { }; - return SignalEvent; -}(Event_1.Event)); -exports.SignalEvent = SignalEvent; - -},{"./Event":57}],65:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.StreamEvent = void 0; -var Event_1 = require("./Event"); -var Publisher_1 = require("../../OpenVidu/Publisher"); -var Session_1 = require("../../OpenVidu/Session"); -var OpenViduLogger_1 = require("../Logger/OpenViduLogger"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var StreamEvent = (function (_super) { - __extends(StreamEvent, _super); - function StreamEvent(cancelable, target, type, stream, reason) { - var _this = _super.call(this, cancelable, target, type) || this; - _this.stream = stream; - _this.reason = reason; - return _this; - } - StreamEvent.prototype.callDefaultBehavior = function () { - if (this.type === 'streamDestroyed') { - if (this.target instanceof Session_1.Session) { - logger.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Session'"); - this.stream.disposeWebRtcPeer(); - } - else if (this.target instanceof Publisher_1.Publisher) { - logger.info("Calling default behavior upon '" + this.type + "' event dispatched by 'Publisher'"); - clearInterval(this.target.screenShareResizeInterval); - this.stream.isLocalStreamReadyToPublish = false; - var openviduPublishers = this.target.openvidu.publishers; - for (var i = 0; i < openviduPublishers.length; i++) { - if (openviduPublishers[i] === this.target) { - openviduPublishers.splice(i, 1); - break; - } - } - } - this.stream.disposeMediaStream(); - if (this.stream.streamManager) - this.stream.streamManager.removeAllVideos(); - this.stream.session.remoteStreamsCreated.delete(this.stream.streamId); - var remoteConnection = this.stream.session.remoteConnections.get(this.stream.connection.connectionId); - if (!!remoteConnection && !!remoteConnection.remoteOptions) { - var streamOptionsServer = remoteConnection.remoteOptions.streams; - for (var i = streamOptionsServer.length - 1; i >= 0; --i) { - if (streamOptionsServer[i].id === this.stream.streamId) { - streamOptionsServer.splice(i, 1); - } - } - } - } - }; - return StreamEvent; -}(Event_1.Event)); -exports.StreamEvent = StreamEvent; - -},{"../../OpenVidu/Publisher":46,"../../OpenVidu/Session":47,"../Logger/OpenViduLogger":79,"./Event":57}],66:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.StreamManagerEvent = void 0; -var Event_1 = require("./Event"); -var StreamManagerEvent = (function (_super) { - __extends(StreamManagerEvent, _super); - function StreamManagerEvent(target, type, value) { - var _this = _super.call(this, false, target, type) || this; - _this.value = value; - return _this; - } - StreamManagerEvent.prototype.callDefaultBehavior = function () { }; - return StreamManagerEvent; -}(Event_1.Event)); -exports.StreamManagerEvent = StreamManagerEvent; - -},{"./Event":57}],67:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.StreamPropertyChangedEvent = void 0; -var Event_1 = require("./Event"); -var StreamPropertyChangedEvent = (function (_super) { - __extends(StreamPropertyChangedEvent, _super); - function StreamPropertyChangedEvent(target, stream, changedProperty, newValue, oldValue, reason) { - var _this = _super.call(this, false, target, 'streamPropertyChanged') || this; - _this.stream = stream; - _this.changedProperty = changedProperty; - _this.newValue = newValue; - _this.oldValue = oldValue; - _this.reason = reason; - return _this; - } - StreamPropertyChangedEvent.prototype.callDefaultBehavior = function () { }; - return StreamPropertyChangedEvent; -}(Event_1.Event)); -exports.StreamPropertyChangedEvent = StreamPropertyChangedEvent; - -},{"./Event":57}],68:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -exports.VideoElementEvent = void 0; -var Event_1 = require("./Event"); -var VideoElementEvent = (function (_super) { - __extends(VideoElementEvent, _super); - function VideoElementEvent(element, target, type) { - var _this = _super.call(this, false, target, type) || this; - _this.element = element; - return _this; - } - VideoElementEvent.prototype.callDefaultBehavior = function () { }; - return VideoElementEvent; -}(Event_1.Event)); -exports.VideoElementEvent = VideoElementEvent; - -},{"./Event":57}],69:[function(require,module,exports){ -function Mapper() { - var sources = {}; - this.forEach = function (callback) { - for (var key in sources) { - var source = sources[key]; - for (var key2 in source) - callback(source[key2]); - } - ; - }; - this.get = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return undefined; - return ids[id]; - }; - this.remove = function (id, source) { - var ids = sources[source]; - if (ids == undefined) - return; - delete ids[id]; - for (var i in ids) { - return false; - } - delete sources[source]; - }; - this.set = function (value, id, source) { - if (value == undefined) - return this.remove(id, source); - var ids = sources[source]; - if (ids == undefined) - sources[source] = ids = {}; - ids[id] = value; - }; -} -; -Mapper.prototype.pop = function (id, source) { - var value = this.get(id, source); - if (value == undefined) - return undefined; - this.remove(id, source); - return value; -}; -module.exports = Mapper; - -},{}],70:[function(require,module,exports){ -var JsonRpcClient = require('./jsonrpcclient'); -exports.JsonRpcClient = JsonRpcClient; - -},{"./jsonrpcclient":71}],71:[function(require,module,exports){ -var RpcBuilder = require('../'); -var WebSocketWithReconnection = require('./transports/webSocketWithReconnection'); -var OpenViduLogger = require('../../../Logger/OpenViduLogger').OpenViduLogger; -Date.now = Date.now || function () { - return +new Date; -}; -var PING_INTERVAL = 5000; -var RECONNECTING = 'RECONNECTING'; -var CONNECTED = 'CONNECTED'; -var DISCONNECTED = 'DISCONNECTED'; -var Logger = OpenViduLogger.getInstance(); -function JsonRpcClient(configuration) { - var self = this; - var wsConfig = configuration.ws; - var notReconnectIfNumLessThan = -1; - var pingNextNum = 0; - var enabledPings = true; - var pingPongStarted = false; - var pingInterval; - var status = DISCONNECTED; - var onreconnecting = wsConfig.onreconnecting; - var onreconnected = wsConfig.onreconnected; - var onconnected = wsConfig.onconnected; - var onerror = wsConfig.onerror; - configuration.rpc.pull = function (params, request) { - request.reply(null, "push"); - }; - wsConfig.onreconnecting = function () { - Logger.debug("--------- ONRECONNECTING -----------"); - if (status === RECONNECTING) { - Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it"); - return; - } - stopPing(); - status = RECONNECTING; - if (onreconnecting) { - onreconnecting(); - } - }; - wsConfig.onreconnected = function () { - Logger.debug("--------- ONRECONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - updateNotReconnectIfLessThan(); - if (onreconnected) { - onreconnected(); - } - }; - wsConfig.onconnected = function () { - Logger.debug("--------- ONCONNECTED -----------"); - if (status === CONNECTED) { - Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it"); - return; - } - status = CONNECTED; - enabledPings = true; - usePing(); - if (onconnected) { - onconnected(); - } - }; - wsConfig.onerror = function (error) { - Logger.debug("--------- ONERROR -----------"); - status = DISCONNECTED; - stopPing(); - if (onerror) { - onerror(error); - } - }; - var ws = new WebSocketWithReconnection(wsConfig); - Logger.debug('Connecting websocket to URI: ' + wsConfig.uri); - var rpcBuilderOptions = { - request_timeout: configuration.rpc.requestTimeout, - ping_request_timeout: configuration.rpc.heartbeatRequestTimeout - }; - var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) { - Logger.debug('Received request: ' + JSON.stringify(request)); - try { - var func = configuration.rpc[request.method]; - if (func === undefined) { - Logger.error("Method " + request.method + " not registered in client"); - } - else { - func(request.params, request); - } - } - catch (err) { - Logger.error('Exception processing request: ' + JSON.stringify(request)); - Logger.error(err); - } - }); - this.send = function (method, params, callback) { - var requestTime = Date.now(); - rpc.encode(method, params, function (error, result) { - if (error) { - try { - Logger.error("ERROR:" + error.message + " in Request: method:" + - method + " params:" + JSON.stringify(params) + " request:" + - error.request); - if (error.data) { - Logger.error("ERROR DATA:" + JSON.stringify(error.data)); - } - } - catch (e) { } - error.requestTime = requestTime; - } - if (callback) { - if (result != undefined && result.value !== 'pong') { - Logger.debug('Response: ' + JSON.stringify(result)); - } - callback(error, result); - } - }); - }; - function updateNotReconnectIfLessThan() { - Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' + - notReconnectIfNumLessThan + ')'); - notReconnectIfNumLessThan = pingNextNum; - } - function sendPing() { - if (enabledPings) { - var params = null; - if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) { - params = { - interval: configuration.heartbeat || PING_INTERVAL - }; - } - pingNextNum++; - self.send('ping', params, (function (pingNum) { - return function (error, result) { - if (error) { - Logger.debug("Error in ping request #" + pingNum + " (" + - error.message + ")"); - if (pingNum > notReconnectIfNumLessThan) { - enabledPings = false; - updateNotReconnectIfLessThan(); - Logger.debug("Server did not respond to ping message #" + - pingNum + ". Reconnecting... "); - ws.reconnectWs(); - } - } - }; - })(pingNextNum)); - } - else { - Logger.debug("Trying to send ping, but ping is not enabled"); - } - } - function usePing() { - if (!pingPongStarted) { - Logger.debug("Starting ping (if configured)"); - pingPongStarted = true; - if (configuration.heartbeat != undefined) { - pingInterval = setInterval(sendPing, configuration.heartbeat); - sendPing(); - } - } - } - function stopPing() { - clearInterval(pingInterval); - pingPongStarted = false; - enabledPings = false; - pingNextNum = -1; - rpc.cancel(); - } - this.close = function (code, reason) { - Logger.debug("Closing with code: " + code + " because: " + reason); - if (pingInterval != undefined) { - Logger.debug("Clearing ping interval"); - clearInterval(pingInterval); - } - pingPongStarted = false; - enabledPings = false; - ws.close(code, reason); - }; - this.reconnect = function () { - ws.reconnectWs(); - }; - this.resetPing = function () { - enabledPings = true; - pingNextNum = 0; - usePing(); - }; - this.getReadyState = function () { - return ws.getReadyState(); - }; -} -module.exports = JsonRpcClient; - -},{"../":74,"../../../Logger/OpenViduLogger":79,"./transports/webSocketWithReconnection":73}],72:[function(require,module,exports){ -var WebSocketWithReconnection = require('./webSocketWithReconnection'); -exports.WebSocketWithReconnection = WebSocketWithReconnection; - -},{"./webSocketWithReconnection":73}],73:[function(require,module,exports){ -"use strict"; -var OpenViduLogger = require('../../../../Logger/OpenViduLogger').OpenViduLogger; -var Logger = OpenViduLogger.getInstance(); -var MAX_RETRIES = 2000; -var RETRY_TIME_MS = 3000; -var CONNECTING = 0; -var OPEN = 1; -var CLOSING = 2; -var CLOSED = 3; -function WebSocketWithReconnection(config) { - var closing = false; - var registerMessageHandler; - var wsUri = config.uri; - var reconnecting = false; - var ws = new WebSocket(wsUri); - ws.onopen = function () { - Logger.debug("WebSocket connected to " + wsUri); - if (config.onconnected) { - config.onconnected(); - } - }; - ws.onerror = function (error) { - Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error); - if (config.onerror) { - config.onerror(error); - } - }; - var reconnectionOnClose = function () { - if (ws.readyState === CLOSED) { - if (closing) { - Logger.debug("Connection closed by user"); - } - else { - if (config.ismasternodecrashed()) { - Logger.error("Master Node has crashed. Stopping reconnection process"); - } - else { - Logger.debug("Connection closed unexpectedly. Reconnecting..."); - reconnect(MAX_RETRIES, 1); - } - } - } - else { - Logger.debug("Close callback from previous websocket. Ignoring it"); - } - }; - ws.onclose = reconnectionOnClose; - function reconnect(maxRetries, numRetries) { - Logger.debug("reconnect (attempt #" + numRetries + ", max=" + maxRetries + ")"); - if (numRetries === 1) { - if (reconnecting) { - Logger.warn("Trying to reconnect when already reconnecting... Ignoring this reconnection."); - return; - } - else { - reconnecting = true; - } - if (config.onreconnecting) { - config.onreconnecting(); - } - } - reconnectAux(maxRetries, numRetries); - } - function addReconnectionQueryParamsIfMissing(uriString) { - var searchParams = new URLSearchParams((new URL(uriString)).search); - if (!searchParams.has("reconnect")) { - uriString = (Array.from(searchParams).length > 0) ? (uriString + '&reconnect=true') : (uriString + '?reconnect=true'); - } - return uriString; - } - function reconnectAux(maxRetries, numRetries) { - Logger.debug("Reconnection attempt #" + numRetries); - ws.close(4104, 'Connection closed for reconnection'); - wsUri = addReconnectionQueryParamsIfMissing(wsUri); - ws = new WebSocket(wsUri); - ws.onopen = function () { - Logger.debug("Reconnected to " + wsUri + " after " + numRetries + " attempts..."); - reconnecting = false; - registerMessageHandler(); - if (config.onreconnected()) { - config.onreconnected(); - } - ws.onclose = reconnectionOnClose; - }; - ws.onerror = function (error) { - Logger.warn("Reconnection error: ", error); - if (numRetries === maxRetries) { - if (config.ondisconnect) { - config.ondisconnect(); - } - } - else { - setTimeout(function () { - reconnect(maxRetries, numRetries + 1); - }, RETRY_TIME_MS); - } - }; - } - this.close = function (code, reason) { - closing = true; - ws.close(code, reason); - }; - this.reconnectWs = function () { - Logger.debug("reconnectWs"); - reconnect(MAX_RETRIES, 1); - }; - this.send = function (message) { - ws.send(message); - }; - this.addEventListener = function (type, callback) { - registerMessageHandler = function () { - ws.addEventListener(type, callback); - }; - registerMessageHandler(); - }; - this.getReadyState = function () { - return ws.readyState; - }; -} -module.exports = WebSocketWithReconnection; - -},{"../../../../Logger/OpenViduLogger":79}],74:[function(require,module,exports){ -var defineProperty_IE8 = false; -if (Object.defineProperty) { - try { - Object.defineProperty({}, "x", {}); - } - catch (e) { - defineProperty_IE8 = true; - } -} -if (!Function.prototype.bind) { - Function.prototype.bind = function (oThis) { - if (typeof this !== 'function') { - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis ? - this : - oThis, aArgs.concat(Array.prototype.slice.call(arguments))); - }; - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - return fBound; - }; -} -var EventEmitter = require('events').EventEmitter; -var inherits = require('inherits'); -var packers = require('./packers'); -var Mapper = require('./Mapper'); -var BASE_TIMEOUT = 5000; -function unifyResponseMethods(responseMethods) { - if (!responseMethods) - return {}; - for (var key in responseMethods) { - var value = responseMethods[key]; - if (typeof value == 'string') - responseMethods[key] = { - response: value - }; - } - ; - return responseMethods; -} -; -function unifyTransport(transport) { - if (!transport) - return; - if (transport instanceof Function) - return { - send: transport - }; - if (transport.send instanceof Function) - return transport; - if (transport.postMessage instanceof Function) { - transport.send = transport.postMessage; - return transport; - } - if (transport.write instanceof Function) { - transport.send = transport.write; - return transport; - } - if (transport.onmessage !== undefined) - return; - if (transport.pause instanceof Function) - return; - throw new SyntaxError("Transport is not a function nor a valid object"); -} -; -function RpcNotification(method, params) { - if (defineProperty_IE8) { - this.method = method; - this.params = params; - } - else { - Object.defineProperty(this, 'method', { - value: method, - enumerable: true - }); - Object.defineProperty(this, 'params', { - value: params, - enumerable: true - }); - } -} -; -function RpcBuilder(packer, options, transport, onRequest) { - var self = this; - if (!packer) - throw new SyntaxError('Packer is not defined'); - if (!packer.pack || !packer.unpack) - throw new SyntaxError('Packer is invalid'); - var responseMethods = unifyResponseMethods(packer.responseMethods); - if (options instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = options; - transport = undefined; - options = undefined; - } - ; - if (options && options.send instanceof Function) { - if (transport && !(transport instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - onRequest = transport; - transport = options; - options = undefined; - } - ; - if (transport instanceof Function) { - if (onRequest != undefined) - throw new SyntaxError("There can't be parameters after onRequest"); - onRequest = transport; - transport = undefined; - } - ; - if (transport && transport.send instanceof Function) - if (onRequest && !(onRequest instanceof Function)) - throw new SyntaxError("Only a function can be after transport"); - options = options || {}; - EventEmitter.call(this); - if (onRequest) - this.on('request', onRequest); - if (defineProperty_IE8) - this.peerID = options.peerID; - else - Object.defineProperty(this, 'peerID', { - value: options.peerID - }); - var max_retries = options.max_retries || 0; - function transportMessage(event) { - self.decode(event.data || event); - } - ; - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - if (transport) { - if (transport.removeEventListener) - transport.removeEventListener('message', transportMessage); - else if (transport.removeListener) - transport.removeListener('data', transportMessage); - } - ; - if (value) { - if (value.addEventListener) - value.addEventListener('message', transportMessage); - else if (value.addListener) - value.addListener('data', transportMessage); - } - ; - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - this.setTransport(transport); - var request_timeout = options.request_timeout || BASE_TIMEOUT; - var ping_request_timeout = options.ping_request_timeout || request_timeout; - var response_timeout = options.response_timeout || BASE_TIMEOUT; - var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT; - var requestID = 0; - var requests = new Mapper(); - var responses = new Mapper(); - var processedResponses = new Mapper(); - var message2Key = {}; - function storeResponse(message, id, dest) { - var response = { - message: message, - timeout: setTimeout(function () { - responses.remove(id, dest); - }, response_timeout) - }; - responses.set(response, id, dest); - } - ; - function storeProcessedResponse(ack, from) { - var timeout = setTimeout(function () { - processedResponses.remove(ack, from); - }, duplicates_timeout); - processedResponses.set(timeout, ack, from); - } - ; - function RpcRequest(method, params, id, from, transport) { - RpcNotification.call(this, method, params); - this.getTransport = function () { - return transport; - }; - this.setTransport = function (value) { - transport = unifyTransport(value); - }; - if (!defineProperty_IE8) - Object.defineProperty(this, 'transport', { - get: this.getTransport.bind(this), - set: this.setTransport.bind(this) - }); - var response = responses.get(id, from); - if (!(transport || self.getTransport())) { - if (defineProperty_IE8) - this.duplicated = Boolean(response); - else - Object.defineProperty(this, 'duplicated', { - value: Boolean(response) - }); - } - var responseMethod = responseMethods[method]; - this.pack = packer.pack.bind(packer, this, id); - this.reply = function (error, result, transport) { - if (error instanceof Function || error && error.send instanceof Function) { - if (result != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = error; - result = null; - error = undefined; - } - else if (result instanceof Function || - result && result.send instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - transport = result; - result = null; - } - ; - transport = unifyTransport(transport); - if (response) - clearTimeout(response.timeout); - if (from != undefined) { - if (error) - error.dest = from; - if (result) - result.dest = from; - } - ; - var message; - if (error || result != undefined) { - if (self.peerID != undefined) { - if (error) - error.from = self.peerID; - else - result.from = self.peerID; - } - if (responseMethod) { - if (responseMethod.error == undefined && error) - message = { - error: error - }; - else { - var method = error ? - responseMethod.error : - responseMethod.response; - message = { - method: method, - params: error || result - }; - } - } - else - message = { - error: error, - result: result - }; - message = packer.pack(message, id); - } - else if (response) - message = response.message; - else - message = packer.pack({ - result: null - }, id); - storeResponse(message, id, from); - transport = transport || this.getTransport() || self.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - } - ; - inherits(RpcRequest, RpcNotification); - function cancel(message) { - var key = message2Key[message]; - if (!key) - return; - delete message2Key[message]; - var request = requests.pop(key.id, key.dest); - if (!request) - return; - clearTimeout(request.timeout); - storeProcessedResponse(key.id, key.dest); - } - ; - this.cancel = function (message) { - if (message) - return cancel(message); - for (var message in message2Key) - cancel(message); - }; - this.close = function () { - var transport = this.getTransport(); - if (transport && transport.close) - transport.close(4003, "Cancel request"); - this.cancel(); - processedResponses.forEach(clearTimeout); - responses.forEach(function (response) { - clearTimeout(response.timeout); - }); - }; - this.encode = function (method, params, dest, transport, callback) { - if (params instanceof Function) { - if (dest != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = params; - transport = undefined; - dest = undefined; - params = undefined; - } - else if (dest instanceof Function) { - if (transport != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = dest; - transport = undefined; - dest = undefined; - } - else if (transport instanceof Function) { - if (callback != undefined) - throw new SyntaxError("There can't be parameters after callback"); - callback = transport; - transport = undefined; - } - ; - if (self.peerID != undefined) { - params = params || {}; - params.from = self.peerID; - } - ; - if (dest != undefined) { - params = params || {}; - params.dest = dest; - } - ; - var message = { - method: method, - params: params - }; - if (callback) { - var id = requestID++; - var retried = 0; - message = packer.pack(message, id); - function dispatchCallback(error, result) { - self.cancel(message); - callback(error, result); - } - ; - var request = { - message: message, - callback: dispatchCallback, - responseMethods: responseMethods[method] || {} - }; - var encode_transport = unifyTransport(transport); - function sendRequest(transport) { - var rt = (method === 'ping' ? ping_request_timeout : request_timeout); - request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++)); - message2Key[message] = { - id: id, - dest: dest - }; - requests.set(request, id, dest); - transport = transport || encode_transport || self.getTransport(); - if (transport) - return transport.send(message); - return message; - } - ; - function retry(transport) { - transport = unifyTransport(transport); - console.warn(retried + ' retry for request message:', message); - var timeout = processedResponses.pop(id, dest); - clearTimeout(timeout); - return sendRequest(transport); - } - ; - function timeout() { - if (retried < max_retries) - return retry(transport); - var error = new Error('Request has timed out'); - error.request = message; - error.retry = retry; - dispatchCallback(error); - } - ; - return sendRequest(transport); - } - ; - message = packer.pack(message); - transport = transport || this.getTransport(); - if (transport) - return transport.send(message); - return message; - }; - this.decode = function (message, transport) { - if (!message) - throw new TypeError("Message is not defined"); - try { - message = packer.unpack(message); - } - catch (e) { - return console.debug(e, message); - } - ; - var id = message.id; - var ack = message.ack; - var method = message.method; - var params = message.params || {}; - var from = params.from; - var dest = params.dest; - if (self.peerID != undefined && from == self.peerID) - return; - if (id == undefined && ack == undefined) { - var notification = new RpcNotification(method, params); - if (self.emit('request', notification)) - return; - return notification; - } - ; - function processRequest() { - transport = unifyTransport(transport) || self.getTransport(); - if (transport) { - var response = responses.get(id, from); - if (response) - return transport.send(response.message); - } - ; - var idAck = (id != undefined) ? id : ack; - var request = new RpcRequest(method, params, idAck, from, transport); - if (self.emit('request', request)) - return; - return request; - } - ; - function processResponse(request, error, result) { - request.callback(error, result); - } - ; - function duplicatedResponse(timeout) { - console.warn("Response already processed", message); - clearTimeout(timeout); - storeProcessedResponse(ack, from); - } - ; - if (method) { - if (dest == undefined || dest == self.peerID) { - var request = requests.get(ack, from); - if (request) { - var responseMethods = request.responseMethods; - if (method == responseMethods.error) - return processResponse(request, params); - if (method == responseMethods.response) - return processResponse(request, null, params); - return processRequest(); - } - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - } - return processRequest(); - } - ; - var error = message.error; - var result = message.result; - if (error && error.dest && error.dest != self.peerID) - return; - if (result && result.dest && result.dest != self.peerID) - return; - var request = requests.get(ack, from); - if (!request) { - var processed = processedResponses.get(ack, from); - if (processed) - return duplicatedResponse(processed); - return console.warn("No callback was defined for this message", message); - } - ; - processResponse(request, error, result); - }; -} -; -inherits(RpcBuilder, EventEmitter); -RpcBuilder.RpcNotification = RpcNotification; -module.exports = RpcBuilder; -var clients = require('./clients'); -var transports = require('./clients/transports'); -RpcBuilder.clients = clients; -RpcBuilder.clients.transports = transports; -RpcBuilder.packers = packers; - -},{"./Mapper":69,"./clients":70,"./clients/transports":72,"./packers":77,"events":1,"inherits":6}],75:[function(require,module,exports){ -function pack(message, id) { - var result = { - jsonrpc: "2.0" - }; - if (message.method) { - result.method = message.method; - if (message.params) - result.params = message.params; - if (id != undefined) - result.id = id; - } - else if (id != undefined) { - if (message.error) { - if (message.result !== undefined) - throw new TypeError("Both result and error are defined"); - result.error = message.error; - } - else if (message.result !== undefined) - result.result = message.result; - else - throw new TypeError("No result or error is defined"); - result.id = id; - } - ; - return JSON.stringify(result); -} -; -function unpack(message) { - var result = message; - if (typeof message === 'string' || message instanceof String) { - result = JSON.parse(message); - } - var version = result.jsonrpc; - if (version !== '2.0') - throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); - if (result.method == undefined) { - if (result.id == undefined) - throw new TypeError("Invalid message: " + message); - var result_defined = result.result !== undefined; - var error_defined = result.error !== undefined; - if (result_defined && error_defined) - throw new TypeError("Both result and error are defined: " + message); - if (!result_defined && !error_defined) - throw new TypeError("No result or error is defined: " + message); - result.ack = result.id; - delete result.id; - } - return result; -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],76:[function(require,module,exports){ -function pack(message) { - throw new TypeError("Not yet implemented"); -} -; -function unpack(message) { - throw new TypeError("Not yet implemented"); -} -; -exports.pack = pack; -exports.unpack = unpack; - -},{}],77:[function(require,module,exports){ -var JsonRPC = require('./JsonRPC'); -var XmlRPC = require('./XmlRPC'); -exports.JsonRPC = JsonRPC; -exports.XmlRPC = XmlRPC; - -},{"./JsonRPC":75,"./XmlRPC":76}],78:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ConsoleLogger = void 0; -var ConsoleLogger = (function () { - function ConsoleLogger(console) { - this.logger = console; - this.log = window.console.log, - this.info = window.console.info, - this.debug = window.console.debug, - this.warn = window.console.warn, - this.error = window.console.error; - } - return ConsoleLogger; -}()); -exports.ConsoleLogger = ConsoleLogger; - -},{}],79:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.OpenViduLogger = void 0; -var jsnlog_1 = require("jsnlog"); -var ConsoleLogger_1 = require("./ConsoleLogger"); -var OpenViduLoggerConfiguration_1 = require("./OpenViduLoggerConfiguration"); -var OpenViduLogger = (function () { - function OpenViduLogger() { - this.JSNLOG_URL = "/openvidu/elk/openvidu-browser-logs"; - this.MAX_JSNLOG_BATCH_LOG_MESSAGES = 100; - this.MAX_MSECONDS_BATCH_MESSAGES = 5000; - this.MAX_LENGTH_STRING_JSON = 1000; - this.defaultConsoleLogger = new ConsoleLogger_1.ConsoleLogger(window.console); - this.isProdMode = false; - this.isJSNLogSetup = false; - } - OpenViduLogger.configureJSNLog = function (openVidu, token) { - var _this = this; - try { - if ((window['LOG_JSNLOG_RESULTS']) || - (this.instance && openVidu.isAtLeastPro - && this.instance.isOpenViduBrowserLogsDebugActive(openVidu) - && this.instance.canConfigureJSNLog(openVidu, this.instance))) { - if (openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug_app) { - this.instance.replaceWindowConsole(); - } - this.instance.isJSNLogSetup = false; - this.instance.info("Configuring JSNLogs."); - var finalUserId_1 = openVidu.finalUserId; - var sessionId_1 = openVidu.session.sessionId; - var beforeSendCallback = function (xhr) { - var parentReadyStateFunction = xhr.onreadystatechange; - xhr.onreadystatechange = function () { - if (_this.isInvalidResponse(xhr)) { - Object.defineProperty(xhr, "readyState", { value: 4 }); - Object.defineProperty(xhr, "status", { value: 200 }); - _this.instance.disableLogger(); - } - parentReadyStateFunction(); - }; - xhr.setRequestHeader('Authorization', "Basic " + btoa("".concat(finalUserId_1, "%/%").concat(sessionId_1) + ":" + token)); - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.setRequestHeader('OV-Final-User-Id', finalUserId_1); - xhr.setRequestHeader('OV-Session-Id', sessionId_1); - xhr.setRequestHeader('OV-Token', token); - }; - this.instance.currentAppender = jsnlog_1.JL.createAjaxAppender("appender-".concat(finalUserId_1, "-").concat(sessionId_1)); - this.instance.currentAppender.setOptions({ - beforeSend: beforeSendCallback, - maxBatchSize: 1000, - batchSize: this.instance.MAX_JSNLOG_BATCH_LOG_MESSAGES, - batchTimeout: this.instance.MAX_MSECONDS_BATCH_MESSAGES - }); - var logSerializer = function (obj) { - var getCircularReplacer = function () { - var seen = new WeakSet(); - return function (key, value) { - if (typeof value === "object" && value != null) { - if (seen.has(value) || (HTMLElement && value instanceof HTMLElement)) { - return; - } - seen.add(value); - } - return value; - }; - }; - var stringifyJson = JSON.stringify(obj, getCircularReplacer()); - if (stringifyJson.length > _this.instance.MAX_LENGTH_STRING_JSON) { - stringifyJson = "".concat(stringifyJson.substring(0, _this.instance.MAX_LENGTH_STRING_JSON), "..."); - } - if (window['LOG_JSNLOG_RESULTS']) { - console.log(stringifyJson); - } - return stringifyJson; - }; - jsnlog_1.JL.setOptions({ - defaultAjaxUrl: openVidu.httpUri + this.instance.JSNLOG_URL, - serialize: logSerializer, - enabled: true - }); - (0, jsnlog_1.JL)().setOptions({ - appenders: [this.instance.currentAppender] - }); - this.instance.isJSNLogSetup = true; - this.instance.loggingSessionId = sessionId_1; - this.instance.info("JSNLog configured."); - } - } - catch (e) { - console.error("Error configuring JSNLog: "); - console.error(e); - this.instance.disableLogger(); - } - }; - OpenViduLogger.getInstance = function () { - if (!OpenViduLogger.instance) { - OpenViduLogger.instance = new OpenViduLogger(); - } - return OpenViduLogger.instance; - }; - OpenViduLogger.isInvalidResponse = function (xhr) { - return xhr.status == 401 || xhr.status == 403 || xhr.status == 404 || xhr.status == 0; - }; - OpenViduLogger.prototype.canConfigureJSNLog = function (openVidu, logger) { - return openVidu.session.sessionId != logger.loggingSessionId; - }; - OpenViduLogger.prototype.isOpenViduBrowserLogsDebugActive = function (openVidu) { - return openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug || - openVidu.sendBrowserLogs === OpenViduLoggerConfiguration_1.OpenViduLoggerConfiguration.debug_app; - }; - OpenViduLogger.prototype.getConsoleWithJSNLog = function () { - return function (openViduLogger) { - return { - log: function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - openViduLogger.defaultConsoleLogger.log.apply(openViduLogger.defaultConsoleLogger.logger, arguments); - if (openViduLogger.isJSNLogSetup) { - (0, jsnlog_1.JL)().info(arguments); - } - }, - info: function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - openViduLogger.defaultConsoleLogger.info.apply(openViduLogger.defaultConsoleLogger.logger, arguments); - if (openViduLogger.isJSNLogSetup) { - (0, jsnlog_1.JL)().info(arguments); - } - }, - debug: function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - openViduLogger.defaultConsoleLogger.debug.apply(openViduLogger.defaultConsoleLogger.logger, arguments); - }, - warn: function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - openViduLogger.defaultConsoleLogger.warn.apply(openViduLogger.defaultConsoleLogger.logger, arguments); - if (openViduLogger.isJSNLogSetup) { - (0, jsnlog_1.JL)().warn(arguments); - } - }, - error: function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - openViduLogger.defaultConsoleLogger.error.apply(openViduLogger.defaultConsoleLogger.logger, arguments); - if (openViduLogger.isJSNLogSetup) { - (0, jsnlog_1.JL)().error(arguments); - } - } - }; - }(this); - }; - OpenViduLogger.prototype.replaceWindowConsole = function () { - window.console = this.defaultConsoleLogger.logger; - window.console.log = this.getConsoleWithJSNLog().log; - window.console.info = this.getConsoleWithJSNLog().info; - window.console.debug = this.getConsoleWithJSNLog().debug; - window.console.warn = this.getConsoleWithJSNLog().warn; - window.console.error = this.getConsoleWithJSNLog().error; - }; - OpenViduLogger.prototype.disableLogger = function () { - jsnlog_1.JL.setOptions({ enabled: false }); - this.isJSNLogSetup = false; - this.loggingSessionId = undefined; - this.currentAppender = undefined; - window.console = this.defaultConsoleLogger.logger; - window.console.log = this.defaultConsoleLogger.log; - window.console.info = this.defaultConsoleLogger.info; - window.console.debug = this.defaultConsoleLogger.debug; - window.console.warn = this.defaultConsoleLogger.warn; - window.console.error = this.defaultConsoleLogger.error; - }; - OpenViduLogger.prototype.log = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - if (!this.isProdMode) { - this.defaultConsoleLogger.log.apply(this.defaultConsoleLogger.logger, arguments); - } - if (this.isJSNLogSetup) { - (0, jsnlog_1.JL)().info(arguments); - } - }; - OpenViduLogger.prototype.debug = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - if (!this.isProdMode) { - this.defaultConsoleLogger.debug.apply(this.defaultConsoleLogger.logger, arguments); - } - }; - OpenViduLogger.prototype.info = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - if (!this.isProdMode) { - this.defaultConsoleLogger.info.apply(this.defaultConsoleLogger.logger, arguments); - } - if (this.isJSNLogSetup) { - (0, jsnlog_1.JL)().info(arguments); - } - }; - OpenViduLogger.prototype.warn = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - this.defaultConsoleLogger.warn.apply(this.defaultConsoleLogger.logger, arguments); - if (this.isJSNLogSetup) { - (0, jsnlog_1.JL)().warn(arguments); - } - }; - OpenViduLogger.prototype.error = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - this.defaultConsoleLogger.error.apply(this.defaultConsoleLogger.logger, arguments); - if (this.isJSNLogSetup) { - (0, jsnlog_1.JL)().error(arguments); - } - }; - OpenViduLogger.prototype.flush = function () { - if (this.isJSNLogSetup && this.currentAppender != null) { - this.currentAppender.sendBatch(); - } - }; - OpenViduLogger.prototype.enableProdMode = function () { - this.isProdMode = true; - }; - return OpenViduLogger; -}()); -exports.OpenViduLogger = OpenViduLogger; - -},{"./ConsoleLogger":78,"./OpenViduLoggerConfiguration":80,"jsnlog":7}],80:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.OpenViduLoggerConfiguration = void 0; -var OpenViduLoggerConfiguration; -(function (OpenViduLoggerConfiguration) { - OpenViduLoggerConfiguration["disabled"] = "disabled"; - OpenViduLoggerConfiguration["debug"] = "debug"; - OpenViduLoggerConfiguration["debug_app"] = "debug_app"; -})(OpenViduLoggerConfiguration = exports.OpenViduLoggerConfiguration || (exports.OpenViduLoggerConfiguration = {})); - -},{}],81:[function(require,module,exports){ -window.getScreenId = function (firefoxString, callback, custom_parameter) { - if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { - callback({ - video: true - }); - return; - } - if (!!navigator.mozGetUserMedia) { - callback(null, 'firefox', { - video: { - mozMediaSource: firefoxString, - mediaSource: firefoxString - } - }); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - callback('permission-denied'); - } - else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); - } - window.removeEventListener('message', onIFrameCallback); - } - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); - window.removeEventListener('message', onIFrameCallback); - } - } - if (!custom_parameter) { - setTimeout(postGetSourceIdMessage, 100); - } - else { - setTimeout(function () { - postGetSourceIdMessage(custom_parameter); - }, 100); - } -}; -function getScreenConstraints(error, sourceId, canRequestAudioTrack) { - var screen_constraints = { - audio: false, - video: { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, - maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 - }, - optional: [] - } - }; - if (!!canRequestAudioTrack) { - screen_constraints.audio = { - mandatory: { - chromeMediaSource: error ? 'screen' : 'desktop', - }, - optional: [] - }; - } - if (sourceId) { - screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; - if (screen_constraints.audio && screen_constraints.audio.mandatory) { - screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; - } - } - return screen_constraints; -} -function postGetSourceIdMessage(custom_parameter) { - if (!iframe) { - loadIFrame(function () { - postGetSourceIdMessage(custom_parameter); - }); - return; - } - if (!iframe.isLoaded) { - setTimeout(function () { - postGetSourceIdMessage(custom_parameter); - }, 100); - return; - } - if (!custom_parameter) { - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); - } - else if (!!custom_parameter.forEach) { - iframe.contentWindow.postMessage({ - captureCustomSourceId: custom_parameter - }, '*'); - } - else { - iframe.contentWindow.postMessage({ - captureSourceIdWithAudio: true - }, '*'); - } -} -var iframe; -window.getScreenConstraints = function (callback) { - loadIFrame(function () { - getScreenId(function (error, sourceId, screen_constraints) { - if (!screen_constraints) { - screen_constraints = { - video: true - }; - } - callback(error, screen_constraints.video); - }); - }); -}; -function loadIFrame(loadCallback) { - if (iframe) { - loadCallback(); - return; - } - iframe = document.createElement('iframe'); - iframe.onload = function () { - iframe.isLoaded = true; - loadCallback(); - }; - iframe.src = 'https://openvidu.github.io/openvidu-screen-sharing-chrome-extension/'; - iframe.style.display = 'none'; - (document.body || document.documentElement).appendChild(iframe); -} -window.getChromeExtensionStatus = function (callback) { - if (!!navigator.mozGetUserMedia) { - callback('installed-enabled'); - return; - } - window.addEventListener('message', onIFrameCallback); - function onIFrameCallback(event) { - if (!event.data) - return; - if (event.data.chromeExtensionStatus) { - callback(event.data.chromeExtensionStatus); - window.removeEventListener('message', onIFrameCallback); - } - } - setTimeout(postGetChromeExtensionStatusMessage, 100); -}; -function postGetChromeExtensionStatusMessage() { - if (!iframe) { - loadIFrame(postGetChromeExtensionStatusMessage); - return; - } - if (!iframe.isLoaded) { - setTimeout(postGetChromeExtensionStatusMessage, 100); - return; - } - iframe.contentWindow.postMessage({ - getChromeExtensionStatus: true - }, '*'); -} -exports.getScreenId = window.getScreenId; - -},{}],82:[function(require,module,exports){ -var chromeMediaSource = 'screen'; -var sourceId; -var screenCallback; -if (typeof window !== 'undefined' && typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined') { - var isFirefox = typeof window.InstallTrigger !== 'undefined'; - var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; - var isChrome = !!window.chrome && !isOpera; - window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - onMessageCallback(event.data); - }); -} -function onMessageCallback(data) { - if (data == 'PermissionDeniedError') { - if (screenCallback) - return screenCallback('PermissionDeniedError'); - else - throw new Error('PermissionDeniedError'); - } - if (data == 'rtcmulticonnection-extension-loaded') { - chromeMediaSource = 'desktop'; - } - if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); - } -} -function isChromeExtensionAvailable(callback) { - if (!callback) - return; - if (chromeMediaSource == 'desktop') - return callback(true); - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback(false); - } - else - callback(true); - }, 2000); -} -function getSourceId(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('get-sourceId', '*'); -} -function getCustomSourceId(arr, callback) { - if (!arr || !arr.forEach) - throw '"arr" parameter is mandatory and it must be an array.'; - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage({ - 'get-custom-sourceId': arr - }, '*'); -} -function getSourceIdWithAudio(callback) { - if (!callback) - throw '"callback" parameter is mandatory.'; - if (sourceId) - return callback(sourceId); - screenCallback = callback; - window.postMessage('audio-plus-tab', '*'); -} -function getChromeExtensionStatus(extensionid, callback) { - if (isFirefox) - return callback('not-chrome'); - if (arguments.length != 2) { - callback = extensionid; - extensionid = 'lfcgfepafnobdloecchnfaclibenjold'; - } - var image = document.createElement('img'); - image.src = 'chrome-extension://' + extensionid + '/icon.png'; - image.onload = function () { - chromeMediaSource = 'screen'; - window.postMessage('are-you-there', '*'); - setTimeout(function () { - if (chromeMediaSource == 'screen') { - callback('installed-disabled'); - } - else - callback('installed-enabled'); - }, 2000); - }; - image.onerror = function () { - callback('not-installed'); - }; -} -function getScreenConstraintsWithAudio(callback) { - getScreenConstraints(callback, true); -} -function getScreenConstraints(callback, captureSourceIdWithAudio) { - sourceId = ''; - var firefoxScreenConstraints = { - mozMediaSource: 'window', - mediaSource: 'window' - }; - if (isFirefox) - return callback(null, firefoxScreenConstraints); - var screen_constraints = { - mandatory: { - chromeMediaSource: chromeMediaSource, - maxWidth: screen.width > 1920 ? screen.width : 1920, - maxHeight: screen.height > 1080 ? screen.height : 1080 - }, - optional: [] - }; - if (chromeMediaSource == 'desktop' && !sourceId) { - if (captureSourceIdWithAudio) { - getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - if (canRequestAudioTrack) { - screen_constraints.canRequestAudioTrack = true; - } - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - } - else { - getSourceId(function (sourceId) { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); - } - return; - } - if (chromeMediaSource == 'desktop') { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - } - callback(null, screen_constraints); -} -exports.getScreenConstraints = getScreenConstraints; -exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; -exports.isChromeExtensionAvailable = isChromeExtensionAvailable; -exports.getChromeExtensionStatus = getChromeExtensionStatus; -exports.getSourceId = getSourceId; - -},{}],83:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PlatformUtils = void 0; -var platform = require("platform"); -var PlatformUtils = (function () { - function PlatformUtils() { - } - PlatformUtils.getInstance = function () { - if (!this.instance) { - this.instance = new PlatformUtils(); - } - return PlatformUtils.instance; - }; - PlatformUtils.prototype.isChromeBrowser = function () { - return platform.name === "Chrome"; - }; - PlatformUtils.prototype.isSafariBrowser = function () { - return platform.name === "Safari"; - }; - PlatformUtils.prototype.isChromeMobileBrowser = function () { - return platform.name === "Chrome Mobile"; - }; - PlatformUtils.prototype.isFirefoxBrowser = function () { - return platform.name === "Firefox"; - }; - PlatformUtils.prototype.isFirefoxMobileBrowser = function () { - return platform.name === "Firefox Mobile" || platform.name === "Firefox for iOS"; - }; - PlatformUtils.prototype.isOperaBrowser = function () { - return platform.name === "Opera"; - }; - PlatformUtils.prototype.isOperaMobileBrowser = function () { - return platform.name === "Opera Mobile"; - }; - PlatformUtils.prototype.isEdgeBrowser = function () { - var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1; - return platform.name === "Microsoft Edge" && version >= 80; - }; - PlatformUtils.prototype.isEdgeMobileBrowser = function () { - var _a, _b; - var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1; - return platform.name === "Microsoft Edge" && (((_a = platform.os) === null || _a === void 0 ? void 0 : _a.family) === 'Android' || ((_b = platform.os) === null || _b === void 0 ? void 0 : _b.family) === 'iOS') && version > 45; - }; - PlatformUtils.prototype.isAndroidBrowser = function () { - return platform.name === "Android Browser"; - }; - PlatformUtils.prototype.isElectron = function () { - return platform.name === "Electron"; - }; - PlatformUtils.prototype.isSamsungBrowser = function () { - return (platform.name === "Samsung Internet Mobile" || - platform.name === "Samsung Internet"); - }; - PlatformUtils.prototype.isIPhoneOrIPad = function () { - var userAgent = !!platform.ua ? platform.ua : navigator.userAgent; - var isTouchable = "ontouchend" in document; - var isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable; - var isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) && - /\b(\w*Mobile\w*)\b/.test(userAgent) && - isTouchable; - return isIPad || isIPhone; - }; - PlatformUtils.prototype.isIOSWithSafari = function () { - var userAgent = !!platform.ua ? platform.ua : navigator.userAgent; - return this.isIPhoneOrIPad() && (/\b(\w*Apple\w*)\b/.test(navigator.vendor) && - /\b(\w*Safari\w*)\b/.test(userAgent) && - !/\b(\w*CriOS\w*)\b/.test(userAgent) && - !/\b(\w*FxiOS\w*)\b/.test(userAgent)); - }; - PlatformUtils.prototype.isIonicIos = function () { - return this.isIPhoneOrIPad() && platform.ua.indexOf("Safari") === -1; - }; - PlatformUtils.prototype.isIonicAndroid = function () { - return (platform.os.family === "Android" && platform.name == "Android Browser"); - }; - PlatformUtils.prototype.isMobileDevice = function () { - return platform.os.family === "iOS" || platform.os.family === "Android"; - }; - PlatformUtils.prototype.isReactNative = function () { - return false; - }; - PlatformUtils.prototype.isChromium = function () { - return this.isChromeBrowser() || this.isChromeMobileBrowser() || - this.isOperaBrowser() || this.isOperaMobileBrowser() || - this.isEdgeBrowser() || this.isEdgeMobileBrowser() || - this.isSamsungBrowser() || - this.isIonicAndroid() || this.isIonicIos() || - this.isElectron(); - }; - PlatformUtils.prototype.canScreenShare = function () { - var version = (platform === null || platform === void 0 ? void 0 : platform.version) ? parseFloat(platform.version) : -1; - if (this.isMobileDevice()) { - return false; - } - return (this.isChromeBrowser() || - this.isFirefoxBrowser() || - this.isOperaBrowser() || - this.isElectron() || - this.isEdgeBrowser() || - (this.isSafariBrowser() && version >= 13)); - }; - PlatformUtils.prototype.getName = function () { - return platform.name || ""; - }; - PlatformUtils.prototype.getVersion = function () { - return platform.version || ""; - }; - PlatformUtils.prototype.getFamily = function () { - return platform.os.family || ""; - }; - PlatformUtils.prototype.getDescription = function () { - return platform.description || ""; - }; - return PlatformUtils; -}()); -exports.PlatformUtils = PlatformUtils; - -},{"platform":12}],84:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.WebRtcPeerSendrecv = exports.WebRtcPeerSendonly = exports.WebRtcPeerRecvonly = exports.WebRtcPeer = void 0; -var freeice = require("freeice"); -var uuid_1 = require("uuid"); -var ExceptionEvent_1 = require("../Events/ExceptionEvent"); -var OpenViduLogger_1 = require("../Logger/OpenViduLogger"); -var Platform_1 = require("../Utils/Platform"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -var WebRtcPeer = (function () { - function WebRtcPeer(configuration) { - var _this = this; - this.remoteCandidatesQueue = []; - this.localCandidatesQueue = []; - this.iceCandidateList = []; - this.candidategatheringdone = false; - platform = Platform_1.PlatformUtils.getInstance(); - this.configuration = __assign(__assign({}, configuration), { iceServers: !!configuration.iceServers && - configuration.iceServers.length > 0 - ? configuration.iceServers - : freeice(), mediaStream: configuration.mediaStream !== undefined - ? configuration.mediaStream - : null, mode: !!configuration.mode ? configuration.mode : "sendrecv", id: !!configuration.id ? configuration.id : this.generateUniqueId() }); - logger.debug("[WebRtcPeer] configuration:\n".concat(JSON.stringify(this.configuration, null, 2))); - this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); - this.pc.addEventListener("icecandidate", function (event) { - if (event.candidate !== null) { - var candidateInit = event.candidate; - var iceCandidate = new RTCIceCandidate(candidateInit); - _this.configuration.onIceCandidate(iceCandidate); - if (iceCandidate.candidate !== '') { - _this.localCandidatesQueue.push(iceCandidate); - } - } - }); - this.pc.addEventListener('signalingstatechange', function () { - if (_this.pc.signalingState === 'stable') { - while (_this.iceCandidateList.length > 0) { - var candidate = _this.iceCandidateList.shift(); - _this.pc.addIceCandidate(candidate); - } - } - }); - } - WebRtcPeer.prototype.getId = function () { - return this.configuration.id; - }; - WebRtcPeer.prototype.dispose = function () { - logger.debug('Disposing WebRtcPeer'); - if (this.pc) { - if (this.pc.signalingState === 'closed') { - return; - } - this.pc.close(); - this.remoteCandidatesQueue = []; - this.localCandidatesQueue = []; - } - }; - WebRtcPeer.prototype.createOfferLegacy = function () { - if (!!this.configuration.mediaStream) { - this.deprecatedPeerConnectionTrackApi(); - } - var hasAudio = this.configuration.mediaConstraints.audio; - var hasVideo = this.configuration.mediaConstraints.video; - var options = { - offerToReceiveAudio: this.configuration.mode !== "sendonly" && hasAudio, - offerToReceiveVideo: this.configuration.mode !== "sendonly" && hasVideo, - }; - logger.debug("[createOfferLegacy] RTCPeerConnection.createOffer() options:", JSON.stringify(options)); - return this.pc.createOffer(options); - }; - WebRtcPeer.prototype.createOffer = function () { - var _a, _b, _c, _d, _e, _f, _g, _h; - return __awaiter(this, void 0, void 0, function () { - var _i, _j, track, tcInit, trackSettings, trackConsts, trackWidth, trackHeight, trackPixels, maxLayers, l, layerDiv, encoding, tc, sendParams, needSetParams, error_1, message, _k, _l, kind, sdpOffer, error_2, message; - return __generator(this, function (_m) { - switch (_m.label) { - case 0: - if (!("addTransceiver" in this.pc)) { - logger.warn("[createOffer] Method RTCPeerConnection.addTransceiver() is NOT available; using LEGACY offerToReceive{Audio,Video}"); - return [2, this.createOfferLegacy()]; - } - else { - logger.debug("[createOffer] Method RTCPeerConnection.addTransceiver() is available; using it"); - } - if (!(this.configuration.mode !== "recvonly")) return [3, 7]; - if (!this.configuration.mediaStream) { - throw new Error("[WebRtcPeer.createOffer] Direction is '".concat(this.configuration.mode, "', but no stream was configured to be sent")); - } - _i = 0, _j = this.configuration.mediaStream.getTracks(); - _m.label = 1; - case 1: - if (!(_i < _j.length)) return [3, 6]; - track = _j[_i]; - tcInit = { - direction: this.configuration.mode, - streams: [this.configuration.mediaStream], - }; - if (track.kind === "video" && this.configuration.simulcast) { - trackSettings = track.getSettings(); - trackConsts = track.getConstraints(); - trackWidth = (_c = (_b = (_a = trackSettings.width) !== null && _a !== void 0 ? _a : trackConsts.width.ideal) !== null && _b !== void 0 ? _b : trackConsts.width) !== null && _c !== void 0 ? _c : 0; - trackHeight = (_f = (_e = (_d = trackSettings.height) !== null && _d !== void 0 ? _d : trackConsts.height.ideal) !== null && _e !== void 0 ? _e : trackConsts.height) !== null && _f !== void 0 ? _f : 0; - logger.info("[createOffer] Video track dimensions: ".concat(trackWidth, "x").concat(trackHeight)); - trackPixels = trackWidth * trackHeight; - maxLayers = 0; - if (trackPixels >= 960 * 540) { - maxLayers = 3; - } - else if (trackPixels >= 480 * 270) { - maxLayers = 2; - } - else { - maxLayers = 1; - } - tcInit.sendEncodings = []; - for (l = 0; l < maxLayers; l++) { - layerDiv = Math.pow(2, (maxLayers - l - 1)); - encoding = { - rid: "rdiv" + layerDiv.toString(), - scalabilityMode: "L1T1", - }; - if (["detail", "text"].includes(track.contentHint)) { - encoding.scaleResolutionDownBy = 1.0; - encoding.maxFramerate = Math.floor(30 / layerDiv); - } - else { - encoding.scaleResolutionDownBy = layerDiv; - } - tcInit.sendEncodings.push(encoding); - } - } - tc = this.pc.addTransceiver(track, tcInit); - if (!(track.kind === "video")) return [3, 5]; - sendParams = tc.sender.getParameters(); - needSetParams = false; - if (!((_g = sendParams.degradationPreference) === null || _g === void 0 ? void 0 : _g.length)) { - if (["detail", "text"].includes(track.contentHint)) { - sendParams.degradationPreference = "maintain-resolution"; - } - else { - sendParams.degradationPreference = "balanced"; - } - logger.info("[createOffer] Video sender Degradation Preference set: ".concat(sendParams.degradationPreference)); - needSetParams = true; - } - if (this.configuration.simulcast) { - if (((_h = sendParams.encodings) === null || _h === void 0 ? void 0 : _h.length) !== tcInit.sendEncodings.length) { - sendParams.encodings = tcInit.sendEncodings; - needSetParams = true; - } - } - if (!needSetParams) return [3, 5]; - logger.debug("[createOffer] Setting new RTCRtpSendParameters to video sender"); - _m.label = 2; - case 2: - _m.trys.push([2, 4, , 5]); - return [4, tc.sender.setParameters(sendParams)]; - case 3: - _m.sent(); - return [3, 5]; - case 4: - error_1 = _m.sent(); - message = "[WebRtcPeer.createOffer] Cannot set RTCRtpSendParameters to video sender"; - if (error_1 instanceof Error) { - message += ": ".concat(error_1.message); - } - throw new Error(message); - case 5: - _i++; - return [3, 1]; - case 6: return [3, 8]; - case 7: - for (_k = 0, _l = ["audio", "video"]; _k < _l.length; _k++) { - kind = _l[_k]; - if (!this.configuration.mediaConstraints[kind]) { - continue; - } - this.configuration.mediaStream = new MediaStream(); - this.pc.addTransceiver(kind, { - direction: this.configuration.mode, - streams: [this.configuration.mediaStream], - }); - } - _m.label = 8; - case 8: - _m.trys.push([8, 10, , 11]); - return [4, this.pc.createOffer()]; - case 9: - sdpOffer = _m.sent(); - return [3, 11]; - case 10: - error_2 = _m.sent(); - message = "[WebRtcPeer.createOffer] Browser failed creating an SDP Offer"; - if (error_2 instanceof Error) { - message += ": ".concat(error_2.message); - } - throw new Error(message); - case 11: return [2, sdpOffer]; - } - }); - }); - }; - WebRtcPeer.prototype.deprecatedPeerConnectionTrackApi = function () { - for (var _i = 0, _a = this.configuration.mediaStream.getTracks(); _i < _a.length; _i++) { - var track = _a[_i]; - this.pc.addTrack(track, this.configuration.mediaStream); - } - }; - WebRtcPeer.prototype.createAnswer = function () { - var _this = this; - return new Promise(function (resolve, reject) { - if ("getTransceivers" in _this.pc) { - logger.debug("[createAnswer] Method RTCPeerConnection.getTransceivers() is available; using it"); - var _loop_1 = function (kind) { - if (!_this.configuration.mediaConstraints[kind]) { - return "continue"; - } - var tc = _this.pc - .getTransceivers() - .find(function (tc) { return tc.receiver.track.kind === kind; }); - if (tc) { - tc.direction = _this.configuration.mode; - } - else { - return { value: reject(new Error("".concat(kind, " requested, but no transceiver was created from remote description"))) }; - } - }; - for (var _i = 0, _a = ["audio", "video"]; _i < _a.length; _i++) { - var kind = _a[_i]; - var state_1 = _loop_1(kind); - if (typeof state_1 === "object") - return state_1.value; - } - _this.pc - .createAnswer() - .then(function (sdpAnswer) { return resolve(sdpAnswer); }) - .catch(function (error) { return reject(error); }); - } - else { - var offerAudio = void 0, offerVideo = true; - if (!!_this.configuration.mediaConstraints) { - offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? - _this.configuration.mediaConstraints.audio : true; - offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? - _this.configuration.mediaConstraints.video : true; - var constraints = { - offerToReceiveAudio: offerAudio, - offerToReceiveVideo: offerVideo - }; - _this.pc.createAnswer(constraints) - .then(function (sdpAnswer) { return resolve(sdpAnswer); }) - .catch(function (error) { return reject(error); }); - } - } - }); - }; - WebRtcPeer.prototype.processLocalOffer = function (offer) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.pc.setLocalDescription(offer) - .then(function () { - var localDescription = _this.pc.localDescription; - if (!!localDescription) { - logger.debug('Local description set', localDescription.sdp); - return resolve(); - } - else { - return reject('Local description is not defined'); - } - }) - .catch(function (error) { return reject(error); }); - }); - }; - WebRtcPeer.prototype.processRemoteOffer = function (sdpOffer) { - var _this = this; - return new Promise(function (resolve, reject) { - var offer = { - type: 'offer', - sdp: sdpOffer - }; - logger.debug('SDP offer received, setting remote description', offer); - if (_this.pc.signalingState === 'closed') { - return reject('RTCPeerConnection is closed when trying to set remote description'); - } - _this.setRemoteDescription(offer) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - }); - }; - WebRtcPeer.prototype.processLocalAnswer = function (answer) { - var _this = this; - return new Promise(function (resolve, reject) { - logger.debug('SDP answer created, setting local description'); - if (_this.pc.signalingState === 'closed') { - return reject('RTCPeerConnection is closed when trying to set local description'); - } - _this.pc.setLocalDescription(answer) - .then(function () { return resolve(); }) - .catch(function (error) { return reject(error); }); - }); - }; - WebRtcPeer.prototype.processRemoteAnswer = function (sdpAnswer) { - var _this = this; - return new Promise(function (resolve, reject) { - var answer = { - type: 'answer', - sdp: sdpAnswer - }; - logger.debug('SDP answer received, setting remote description'); - if (_this.pc.signalingState === 'closed') { - return reject('RTCPeerConnection is closed when trying to set remote description'); - } - _this.setRemoteDescription(answer) - .then(function () { - resolve(); - }) - .catch(function (error) { return reject(error); }); - }); - }; - WebRtcPeer.prototype.setRemoteDescription = function (sdp) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2, this.pc.setRemoteDescription(sdp)]; - }); - }); - }; - WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { - var _this = this; - return new Promise(function (resolve, reject) { - logger.debug('Remote ICE candidate received', iceCandidate); - _this.remoteCandidatesQueue.push(iceCandidate); - switch (_this.pc.signalingState) { - case 'closed': - reject(new Error('PeerConnection object is closed')); - break; - case 'stable': - if (!!_this.pc.remoteDescription) { - _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); }).catch(function (error) { return reject(error); }); - } - else { - _this.iceCandidateList.push(iceCandidate); - resolve(); - } - break; - default: - _this.iceCandidateList.push(iceCandidate); - resolve(); - } - }); - }; - WebRtcPeer.prototype.addIceConnectionStateChangeListener = function (otherId) { - var _this = this; - this.pc.addEventListener('iceconnectionstatechange', function () { - var iceConnectionState = _this.pc.iceConnectionState; - switch (iceConnectionState) { - case 'disconnected': - var msg1 = 'IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "disconnected". Possible network disconnection'; - logger.warn(msg1); - _this.configuration.onIceConnectionStateException(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_DISCONNECTED, msg1); - break; - case 'failed': - var msg2 = 'IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') to "failed"'; - logger.error(msg2); - _this.configuration.onIceConnectionStateException(ExceptionEvent_1.ExceptionEventName.ICE_CONNECTION_FAILED, msg2); - break; - case 'closed': - logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "closed"'); - break; - case 'new': - logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "new"'); - break; - case 'checking': - logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "checking"'); - break; - case 'connected': - logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "connected"'); - break; - case 'completed': - logger.log('IceConnectionState of RTCPeerConnection ' + _this.configuration.id + ' (' + otherId + ') change to "completed"'); - break; - } - }); - }; - WebRtcPeer.prototype.generateUniqueId = function () { - return (0, uuid_1.v4)(); - }; - return WebRtcPeer; -}()); -exports.WebRtcPeer = WebRtcPeer; -var WebRtcPeerRecvonly = (function (_super) { - __extends(WebRtcPeerRecvonly, _super); - function WebRtcPeerRecvonly(configuration) { - var _this = this; - configuration.mode = 'recvonly'; - _this = _super.call(this, configuration) || this; - return _this; - } - return WebRtcPeerRecvonly; -}(WebRtcPeer)); -exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; -var WebRtcPeerSendonly = (function (_super) { - __extends(WebRtcPeerSendonly, _super); - function WebRtcPeerSendonly(configuration) { - var _this = this; - configuration.mode = 'sendonly'; - _this = _super.call(this, configuration) || this; - return _this; - } - return WebRtcPeerSendonly; -}(WebRtcPeer)); -exports.WebRtcPeerSendonly = WebRtcPeerSendonly; -var WebRtcPeerSendrecv = (function (_super) { - __extends(WebRtcPeerSendrecv, _super); - function WebRtcPeerSendrecv(configuration) { - var _this = this; - configuration.mode = 'sendrecv'; - _this = _super.call(this, configuration) || this; - return _this; - } - return WebRtcPeerSendrecv; -}(WebRtcPeer)); -exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; - -},{"../Events/ExceptionEvent":58,"../Logger/OpenViduLogger":79,"../Utils/Platform":83,"freeice":2,"uuid":22}],85:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.WebRtcStats = void 0; -var OpenViduLogger_1 = require("../Logger/OpenViduLogger"); -var Platform_1 = require("../Utils/Platform"); -var logger = OpenViduLogger_1.OpenViduLogger.getInstance(); -var platform; -; -var WebRtcStats = (function () { - function WebRtcStats(stream) { - this.stream = stream; - this.STATS_ITEM_NAME = 'webrtc-stats-config'; - this.webRtcStatsEnabled = false; - this.statsInterval = 1; - platform = Platform_1.PlatformUtils.getInstance(); - } - WebRtcStats.prototype.isEnabled = function () { - return this.webRtcStatsEnabled; - }; - WebRtcStats.prototype.initWebRtcStats = function () { - var _this = this; - var webrtcObj = localStorage.getItem(this.STATS_ITEM_NAME); - if (!!webrtcObj) { - this.webRtcStatsEnabled = true; - var webrtcStatsConfig = JSON.parse(webrtcObj); - logger.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - logger.warn('localStorage item: ' + JSON.stringify(webrtcStatsConfig)); - this.POST_URL = webrtcStatsConfig.httpEndpoint; - this.statsInterval = webrtcStatsConfig.interval; - this.webRtcStatsIntervalId = setInterval(function () { return __awaiter(_this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4, this.sendStatsToHttpEndpoint()]; - case 1: - _a.sent(); - return [2]; - } - }); - }); }, this.statsInterval * 1000); - } - else { - logger.debug('WebRtc stats not enabled'); - } - }; - WebRtcStats.prototype.getSelectedIceCandidateInfo = function () { - var _this = this; - return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { - var statsReport, transportStat, candidatePairs, localCandidates, remoteCandidates, selectedCandidatePair, selectedCandidatePairId, length_1, iterator, i, candidatePair, localCandidateId, remoteCandidateId, finalLocalCandidate, candList, cand, _i, cand_1, c, finalRemoteCandidate, candList, cand, _a, cand_2, c; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: return [4, this.stream.getRTCPeerConnection().getStats()]; - case 1: - statsReport = _b.sent(); - candidatePairs = new Map(); - localCandidates = new Map(); - remoteCandidates = new Map(); - statsReport.forEach(function (stat) { - if (stat.type === 'transport' && (platform.isChromium() || platform.isSafariBrowser() || platform.isReactNative())) { - transportStat = stat; - } - switch (stat.type) { - case 'candidate-pair': - candidatePairs.set(stat.id, stat); - break; - case 'local-candidate': - localCandidates.set(stat.id, stat); - break; - case 'remote-candidate': - remoteCandidates.set(stat.id, stat); - break; - } - }); - if (transportStat != null) { - selectedCandidatePairId = transportStat.selectedCandidatePairId; - selectedCandidatePair = candidatePairs.get(selectedCandidatePairId); - } - else { - length_1 = candidatePairs.size; - iterator = candidatePairs.values(); - for (i = 0; i < length_1; i++) { - candidatePair = iterator.next().value; - if (candidatePair['selected']) { - selectedCandidatePair = candidatePair; - break; - } - } - } - localCandidateId = selectedCandidatePair.localCandidateId; - remoteCandidateId = selectedCandidatePair.remoteCandidateId; - finalLocalCandidate = localCandidates.get(localCandidateId); - if (!!finalLocalCandidate) { - candList = this.stream.getLocalIceCandidateList(); - cand = candList.filter(function (c) { - return (!!c.candidate && - (c.candidate.indexOf(finalLocalCandidate.ip) >= 0 || c.candidate.indexOf(finalLocalCandidate.address) >= 0) && - c.candidate.indexOf(finalLocalCandidate.port) >= 0); - }); - finalLocalCandidate.raw = []; - for (_i = 0, cand_1 = cand; _i < cand_1.length; _i++) { - c = cand_1[_i]; - finalLocalCandidate.raw.push(c.candidate); - } - } - else { - finalLocalCandidate = 'ERROR: No active local ICE candidate. Probably ICE-TCP is being used'; - } - finalRemoteCandidate = remoteCandidates.get(remoteCandidateId); - if (!!finalRemoteCandidate) { - candList = this.stream.getRemoteIceCandidateList(); - cand = candList.filter(function (c) { - return (!!c.candidate && - (c.candidate.indexOf(finalRemoteCandidate.ip) >= 0 || c.candidate.indexOf(finalRemoteCandidate.address) >= 0) && - c.candidate.indexOf(finalRemoteCandidate.port) >= 0); - }); - finalRemoteCandidate.raw = []; - for (_a = 0, cand_2 = cand; _a < cand_2.length; _a++) { - c = cand_2[_a]; - finalRemoteCandidate.raw.push(c.candidate); - } - } - else { - finalRemoteCandidate = 'ERROR: No active remote ICE candidate. Probably ICE-TCP is being used'; - } - return [2, resolve({ - localCandidate: finalLocalCandidate, - remoteCandidate: finalRemoteCandidate - })]; - } - }); - }); }); - }; - WebRtcStats.prototype.stopWebRtcStats = function () { - if (this.webRtcStatsEnabled) { - clearInterval(this.webRtcStatsIntervalId); - logger.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); - } - }; - WebRtcStats.prototype.sendStats = function (url, response) { - return __awaiter(this, void 0, void 0, function () { - var configuration, error_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - configuration = { - headers: { - 'Content-type': 'application/json' - }, - body: JSON.stringify(response), - method: 'POST', - }; - return [4, fetch(url, configuration)]; - case 1: - _a.sent(); - return [3, 3]; - case 2: - error_1 = _a.sent(); - logger.error("sendStats error: ".concat(JSON.stringify(error_1))); - return [3, 3]; - case 3: return [2]; - } - }); - }); - }; - WebRtcStats.prototype.sendStatsToHttpEndpoint = function () { - return __awaiter(this, void 0, void 0, function () { - var webrtcStats, response, error_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 3, , 4]); - return [4, this.getCommonStats()]; - case 1: - webrtcStats = _a.sent(); - response = this.generateJSONStatsResponse(webrtcStats); - return [4, this.sendStats(this.POST_URL, response)]; - case 2: - _a.sent(); - return [3, 4]; - case 3: - error_2 = _a.sent(); - logger.log(error_2); - return [3, 4]; - case 4: return [2]; - } - }); - }); - }; - WebRtcStats.prototype.getCommonStats = function () { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - return [2, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { - var statsReport, response_1, videoTrackStats_1, candidatePairStats_1, error_3; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4, this.stream.getRTCPeerConnection().getStats()]; - case 1: - statsReport = _a.sent(); - response_1 = this.getWebRtcStatsResponseOutline(); - videoTrackStats_1 = ['framesReceived', 'framesDropped', 'framesSent', 'frameHeight', 'frameWidth']; - candidatePairStats_1 = ['availableOutgoingBitrate', 'currentRoundTripTime']; - statsReport.forEach(function (stat) { - var mediaType = stat.mediaType != null ? stat.mediaType : stat.kind; - var addStat = function (direction, key) { - if (stat[key] != null && response_1[direction] != null) { - if (!mediaType && (videoTrackStats_1.indexOf(key) > -1)) { - mediaType = 'video'; - } - if (direction != null && mediaType != null && key != null && response_1[direction][mediaType] != null) { - response_1[direction][mediaType][key] = Number(stat[key]); - } - else if (direction != null && key != null && candidatePairStats_1.includes(key)) { - response_1[direction][key] = Number(stat[key]); - } - } - }; - switch (stat.type) { - case "outbound-rtp": - addStat('outbound', 'bytesSent'); - addStat('outbound', 'packetsSent'); - addStat('outbound', 'framesEncoded'); - addStat('outbound', 'nackCount'); - addStat('outbound', 'firCount'); - addStat('outbound', 'pliCount'); - addStat('outbound', 'qpSum'); - break; - case "inbound-rtp": - addStat('inbound', 'bytesReceived'); - addStat('inbound', 'packetsReceived'); - addStat('inbound', 'packetsLost'); - addStat('inbound', 'jitter'); - addStat('inbound', 'framesDecoded'); - addStat('inbound', 'nackCount'); - addStat('inbound', 'firCount'); - addStat('inbound', 'pliCount'); - break; - case 'track': - addStat('inbound', 'jitterBufferDelay'); - addStat('inbound', 'framesReceived'); - addStat('outbound', 'framesDropped'); - addStat('outbound', 'framesSent'); - addStat(_this.stream.isLocal() ? 'outbound' : 'inbound', 'frameHeight'); - addStat(_this.stream.isLocal() ? 'outbound' : 'inbound', 'frameWidth'); - break; - case 'candidate-pair': - addStat('candidatepair', 'currentRoundTripTime'); - addStat('candidatepair', 'availableOutgoingBitrate'); - break; - } - }); - if (!(response_1 === null || response_1 === void 0 ? void 0 : response_1.candidatepair) || Object.keys(response_1.candidatepair).length === 0) { - delete response_1.candidatepair; - } - return [2, resolve(response_1)]; - case 2: - error_3 = _a.sent(); - logger.error('Error getting common stats: ', error_3); - return [2, reject(error_3)]; - case 3: return [2]; - } - }); - }); })]; - }); - }); - }; - WebRtcStats.prototype.generateJSONStatsResponse = function (stats) { - return { - '@timestamp': new Date().toISOString(), - participant_id: this.stream.connection.data, - session_id: this.stream.session.sessionId, - platform: platform.getName(), - platform_description: platform.getDescription(), - stream: 'webRTC', - webrtc_stats: stats - }; - }; - WebRtcStats.prototype.getWebRtcStatsResponseOutline = function () { - if (this.stream.isLocal()) { - return { - outbound: { - audio: {}, - video: {} - }, - candidatepair: {} - }; - } - else { - return { - inbound: { - audio: {}, - video: {} - } - }; - } - }; - return WebRtcStats; -}()); -exports.WebRtcStats = WebRtcStats; - -},{"../Logger/OpenViduLogger":79,"../Utils/Platform":83}]},{},[40]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mcmVlaWNlL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2Uvc3R1bi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2ZyZWVpY2UvdHVybi5qc29uIiwiLi4vbm9kZV9tb2R1bGVzL2hhcmsvaGFyay5qcyIsIi4uL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2pzbmxvZy9qc25sb2cuanMiLCIuLi9ub2RlX21vZHVsZXMvbWltZS9NaW1lLmpzIiwiLi4vbm9kZV9tb2R1bGVzL21pbWUvbGl0ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9taW1lL3R5cGVzL3N0YW5kYXJkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL25vcm1hbGljZS9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9wbGF0Zm9ybS9wbGF0Zm9ybS5qcyIsIi4uL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvc2VtdmVyL2NsYXNzZXMvc2VtdmVyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NlbXZlci9mdW5jdGlvbnMvbWFqb3IuanMiLCIuLi9ub2RlX21vZHVsZXMvc2VtdmVyL2Z1bmN0aW9ucy9taW5vci5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZW12ZXIvaW50ZXJuYWwvY29uc3RhbnRzLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3NlbXZlci9pbnRlcm5hbC9kZWJ1Zy5qcyIsIi4uL25vZGVfbW9kdWxlcy9zZW12ZXIvaW50ZXJuYWwvaWRlbnRpZmllcnMuanMiLCIuLi9ub2RlX21vZHVsZXMvc2VtdmVyL2ludGVybmFsL3BhcnNlLW9wdGlvbnMuanMiLCIuLi9ub2RlX21vZHVsZXMvc2VtdmVyL2ludGVybmFsL3JlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvbWQ1LWJyb3dzZXIuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L25pbC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvcGFyc2UuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3JlZ2V4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9ybmctYnJvd3Nlci5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3Qvc2hhMS1icm93c2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC9zdHJpbmdpZnkuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3YxLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92My5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvdjM1LmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92NC5qcyIsIi4uL25vZGVfbW9kdWxlcy91dWlkL2Rpc3QvdjUuanMiLCIuLi9ub2RlX21vZHVsZXMvdXVpZC9kaXN0L3ZhbGlkYXRlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3V1aWQvZGlzdC92ZXJzaW9uLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3dpbGRlbWl0dGVyL3dpbGRlbWl0dGVyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3dvbGZ5ODctZXZlbnRlbWl0dGVyL0V2ZW50RW1pdHRlci5qcyIsIi4uL3BhY2thZ2UuanNvbiIsIk1haW4udHMiLCJPcGVuVmlkdS9Db25uZWN0aW9uLnRzIiwiT3BlblZpZHUvRXZlbnREaXNwYXRjaGVyLnRzIiwiT3BlblZpZHUvRmlsdGVyLnRzIiwiT3BlblZpZHUvTG9jYWxSZWNvcmRlci50cyIsIk9wZW5WaWR1L09wZW5WaWR1LnRzIiwiT3BlblZpZHUvUHVibGlzaGVyLnRzIiwiT3BlblZpZHUvU2Vzc2lvbi50cyIsIk9wZW5WaWR1L1N0cmVhbS50cyIsIk9wZW5WaWR1L1N0cmVhbU1hbmFnZXIudHMiLCJPcGVuVmlkdS9TdWJzY3JpYmVyLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUudHMiLCJPcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3IudHMiLCJPcGVuVmlkdUludGVybmFsL0VudW1zL1R5cGVPZlZpZGVvLnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9Db25uZWN0aW9uUHJvcGVydHlDaGFuZ2VkRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V4Y2VwdGlvbkV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRmlsdGVyRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9OZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvUHVibGlzaGVyU3BlYWtpbmdFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1JlY29yZGluZ0V2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2lnbmFsRXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudC50cyIsIk9wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50LnRzIiwiT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQudHMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvTWFwcGVyLmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvaW5kZXguanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvY2xpZW50cy9qc29ucnBjY2xpZW50LmpzIiwiT3BlblZpZHVJbnRlcm5hbC9LdXJlbnRvVXRpbHMva3VyZW50by1qc29ucnBjL2NsaWVudHMvdHJhbnNwb3J0cy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9jbGllbnRzL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbi5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvS3VyZW50b1V0aWxzL2t1cmVudG8tanNvbnJwYy9wYWNrZXJzL0pzb25SUEMuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9YbWxSUEMuanMiLCJPcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMvcGFja2Vycy9pbmRleC5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL0NvbnNvbGVMb2dnZXIudHMiLCJPcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbi50cyIsIk9wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8uanMiLCJPcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZy5qcyIsIk9wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0udHMiLCJPcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlci50cyIsIk9wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDamZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzV1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9SQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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RTtvQkFDTixLQUFLLEVBQUUsRUFBRTtvQkFDVCxLQUFLLEVBQUUsRUFBRTtpQkFDWjtnQkFDRCxhQUFhLEVBQUUsRUFBRTthQUNwQixDQUFDO1NBQ0w7YUFBTTtZQUNILE9BQU87Z0JBQ0gsT0FBTyxFQUFFO29CQUNMLEtBQUssRUFBRSxFQUFFO29CQUNULEtBQUssRUFBRSxFQUFFO2lCQUNaO2FBQ0osQ0FBQztTQUNMO0lBQ0wsQ0FBQztJQUVMLGtCQUFDO0FBQUQsQ0F4V0EsQUF3V0MsSUFBQTtBQXhXWSxrQ0FBVyIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSID0gdHlwZW9mIFJlZmxlY3QgPT09ICdvYmplY3QnID8gUmVmbGVjdCA6IG51bGxcbnZhciBSZWZsZWN0QXBwbHkgPSBSICYmIHR5cGVvZiBSLmFwcGx5ID09PSAnZnVuY3Rpb24nXG4gID8gUi5hcHBseVxuICA6IGZ1bmN0aW9uIFJlZmxlY3RBcHBseSh0YXJnZXQsIHJlY2VpdmVyLCBhcmdzKSB7XG4gICAgcmV0dXJuIEZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseS5jYWxsKHRhcmdldCwgcmVjZWl2ZXIsIGFyZ3MpO1xuICB9XG5cbnZhciBSZWZsZWN0T3duS2V5c1xuaWYgKFIgJiYgdHlwZW9mIFIub3duS2V5cyA9PT0gJ2Z1bmN0aW9uJykge1xuICBSZWZsZWN0T3duS2V5cyA9IFIub3duS2V5c1xufSBlbHNlIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7XG4gIFJlZmxlY3RPd25LZXlzID0gZnVuY3Rpb24gUmVmbGVjdE93bktleXModGFyZ2V0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRhcmdldClcbiAgICAgIC5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyh0YXJnZXQpKTtcbiAgfTtcbn0gZWxzZSB7XG4gIFJlZmxlY3RPd25LZXlzID0gZnVuY3Rpb24gUmVmbGVjdE93bktleXModGFyZ2V0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRhcmdldCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIFByb2Nlc3NFbWl0V2FybmluZyh3YXJuaW5nKSB7XG4gIGlmIChjb25zb2xlICYmIGNvbnNvbGUud2FybikgY29uc29sZS53YXJuKHdhcm5pbmcpO1xufVxuXG52YXIgTnVtYmVySXNOYU4gPSBOdW1iZXIuaXNOYU4gfHwgZnVuY3Rpb24gTnVtYmVySXNOYU4odmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9PSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xuICBFdmVudEVtaXR0ZXIuaW5pdC5jYWxsKHRoaXMpO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5tb2R1bGUuZXhwb3J0cy5vbmNlID0gb25jZTtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHNDb3VudCA9IDA7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbmZ1bmN0aW9uIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpIHtcbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIEZ1bmN0aW9uLiBSZWNlaXZlZCB0eXBlICcgKyB0eXBlb2YgbGlzdGVuZXIpO1xuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uKGFyZykge1xuICAgIGlmICh0eXBlb2YgYXJnICE9PSAnbnVtYmVyJyB8fCBhcmcgPCAwIHx8IE51bWJlcklzTmFOKGFyZykpIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgb2YgXCJkZWZhdWx0TWF4TGlzdGVuZXJzXCIgaXMgb3V0IG9mIHJhbmdlLiBJdCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIG51bWJlci4gUmVjZWl2ZWQgJyArIGFyZyArICcuJyk7XG4gICAgfVxuICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gIH1cbn0pO1xuXG5FdmVudEVtaXR0ZXIuaW5pdCA9IGZ1bmN0aW9uKCkge1xuXG4gIGlmICh0aGlzLl9ldmVudHMgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5fZXZlbnRzID09PSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykuX2V2ZW50cykge1xuICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICB9XG5cbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn07XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIHNldE1heExpc3RlbmVycyhuKSB7XG4gIGlmICh0eXBlb2YgbiAhPT0gJ251bWJlcicgfHwgbiA8IDAgfHwgTnVtYmVySXNOYU4obikpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIG9mIFwiblwiIGlzIG91dCBvZiByYW5nZS4gSXQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBudW1iZXIuIFJlY2VpdmVkICcgKyBuICsgJy4nKTtcbiAgfVxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIF9nZXRNYXhMaXN0ZW5lcnModGhhdCkge1xuICBpZiAodGhhdC5fbWF4TGlzdGVuZXJzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICByZXR1cm4gdGhhdC5fbWF4TGlzdGVuZXJzO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmdldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uIGdldE1heExpc3RlbmVycygpIHtcbiAgcmV0dXJuIF9nZXRNYXhMaXN0ZW5lcnModGhpcyk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KHR5cGUpIHtcbiAgdmFyIGFyZ3MgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyZ3MucHVzaChhcmd1bWVudHNbaV0pO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICBpZiAoZXZlbnRzICE9PSB1bmRlZmluZWQpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PT0gdW5kZWZpbmVkKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICB2YXIgZXI7XG4gICAgaWYgKGFyZ3MubGVuZ3RoID4gMClcbiAgICAgIGVyID0gYXJnc1swXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgLy8gTm90ZTogVGhlIGNvbW1lbnRzIG9uIHRoZSBgdGhyb3dgIGxpbmVzIGFyZSBpbnRlbnRpb25hbCwgdGhleSBzaG93XG4gICAgICAvLyB1cCBpbiBOb2RlJ3Mgb3V0cHV0IGlmIHRoaXMgcmVzdWx0cyBpbiBhbiB1bmhhbmRsZWQgZXhjZXB0aW9uLlxuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfVxuICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmhhbmRsZWQgZXJyb3IuJyArIChlciA/ICcgKCcgKyBlci5tZXNzYWdlICsgJyknIDogJycpKTtcbiAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgIHRocm93IGVycjsgLy8gVW5oYW5kbGVkICdlcnJvcicgZXZlbnRcbiAgfVxuXG4gIHZhciBoYW5kbGVyID0gZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChoYW5kbGVyID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIFJlZmxlY3RBcHBseShoYW5kbGVyLCB0aGlzLCBhcmdzKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgUmVmbGVjdEFwcGx5KGxpc3RlbmVyc1tpXSwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcik7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmIChldmVudHMgPT09IHVuZGVmaW5lZCkge1xuICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICB0YXJnZXQuX2V2ZW50c0NvdW50ID0gMDtcbiAgfSBlbHNlIHtcbiAgICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAgIC8vIGFkZGluZyBpdCB0byB0aGUgbGlzdGVuZXJzLCBmaXJzdCBlbWl0IFwibmV3TGlzdGVuZXJcIi5cbiAgICBpZiAoZXZlbnRzLm5ld0xpc3RlbmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRhcmdldC5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoZXhpc3RpbmcgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gICAgKyt0YXJnZXQuX2V2ZW50c0NvdW50O1xuICB9IGVsc2Uge1xuICAgIGlmICh0eXBlb2YgZXhpc3RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPVxuICAgICAgICBwcmVwZW5kID8gW2xpc3RlbmVyLCBleGlzdGluZ10gOiBbZXhpc3RpbmcsIGxpc3RlbmVyXTtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICB9IGVsc2UgaWYgKHByZXBlbmQpIHtcbiAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleGlzdGluZy5wdXNoKGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICAgIG0gPSBfZ2V0TWF4TGlzdGVuZXJzKHRhcmdldCk7XG4gICAgaWYgKG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0gJiYgIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgIC8vIE5vIGVycm9yIGNvZGUgZm9yIHRoaXMgc2luY2UgaXQgaXMgYSBXYXJuaW5nXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1zeW50YXhcbiAgICAgIHZhciB3ID0gbmV3IEVycm9yKCdQb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQuICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnICcgKyBTdHJpbmcodHlwZSkgKyAnIGxpc3RlbmVycyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0Jyk7XG4gICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgIHcuZW1pdHRlciA9IHRhcmdldDtcbiAgICAgIHcudHlwZSA9IHR5cGU7XG4gICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgUHJvY2Vzc0VtaXRXYXJuaW5nKHcpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgdHJ1ZSk7XG4gICAgfTtcblxuZnVuY3Rpb24gb25jZVdyYXBwZXIoKSB7XG4gIGlmICghdGhpcy5maXJlZCkge1xuICAgIHRoaXMudGFyZ2V0LnJlbW92ZUxpc3RlbmVyKHRoaXMudHlwZSwgdGhpcy53cmFwRm4pO1xuICAgIHRoaXMuZmlyZWQgPSB0cnVlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCk7XG4gICAgcmV0dXJuIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy50YXJnZXQsIGFyZ3VtZW50cyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX29uY2VXcmFwKHRhcmdldCwgdHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIHN0YXRlID0geyBmaXJlZDogZmFsc2UsIHdyYXBGbjogdW5kZWZpbmVkLCB0YXJnZXQ6IHRhcmdldCwgdHlwZTogdHlwZSwgbGlzdGVuZXI6IGxpc3RlbmVyIH07XG4gIHZhciB3cmFwcGVkID0gb25jZVdyYXBwZXIuYmluZChzdGF0ZSk7XG4gIHdyYXBwZWQubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgc3RhdGUud3JhcEZuID0gd3JhcHBlZDtcbiAgcmV0dXJuIHdyYXBwZWQ7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIG9uY2UodHlwZSwgbGlzdGVuZXIpIHtcbiAgY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcik7XG4gIHRoaXMub24odHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5wcmVwZW5kT25jZUxpc3RlbmVyID1cbiAgICBmdW5jdGlvbiBwcmVwZW5kT25jZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKTtcbiAgICAgIHRoaXMucHJlcGVuZExpc3RlbmVyKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuLy8gRW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmIGFuZCBvbmx5IGlmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdCwgZXZlbnRzLCBwb3NpdGlvbiwgaSwgb3JpZ2luYWxMaXN0ZW5lcjtcblxuICAgICAgY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcik7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmIChldmVudHMgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGxpc3QgPSBldmVudHNbdHlwZV07XG4gICAgICBpZiAobGlzdCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8IGxpc3QubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBzcGxpY2VPbmUobGlzdCwgcG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKVxuICAgICAgICAgIGV2ZW50c1t0eXBlXSA9IGxpc3RbMF07XG5cbiAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lciAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vZmYgPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUFsbExpc3RlbmVycyA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpIHtcbiAgICAgIHZhciBsaXN0ZW5lcnMsIGV2ZW50cywgaTtcblxuICAgICAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICAgICAgaWYgKGV2ZW50cyA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnRzW3R5cGVdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1t0eXBlXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICBsaXN0ZW5lcnMgPSBldmVudHNbdHlwZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbGlzdGVuZXJzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cyA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBbXTtcblxuICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcbiAgaWYgKGV2bGlzdGVuZXIgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gW107XG5cbiAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKVxuICAgIHJldHVybiB1bndyYXAgPyBbZXZsaXN0ZW5lci5saXN0ZW5lciB8fCBldmxpc3RlbmVyXSA6IFtldmxpc3RlbmVyXTtcblxuICByZXR1cm4gdW53cmFwID9cbiAgICB1bndyYXBMaXN0ZW5lcnMoZXZsaXN0ZW5lcikgOiBhcnJheUNsb25lKGV2bGlzdGVuZXIsIGV2bGlzdGVuZXIubGVuZ3RoKTtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiBsaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCB0cnVlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmF3TGlzdGVuZXJzID0gZnVuY3Rpb24gcmF3TGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5saXN0ZW5lckNvdW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbGlzdGVuZXJDb3VudC5jYWxsKGVtaXR0ZXIsIHR5cGUpO1xuICB9XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQgPSBsaXN0ZW5lckNvdW50O1xuZnVuY3Rpb24gbGlzdGVuZXJDb3VudCh0eXBlKSB7XG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG5cbiAgaWYgKGV2ZW50cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDA7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZXZlbnROYW1lcyA9IGZ1bmN0aW9uIGV2ZW50TmFtZXMoKSB7XG4gIHJldHVybiB0aGlzLl9ldmVudHNDb3VudCA+IDAgPyBSZWZsZWN0T3duS2V5cyh0aGlzLl9ldmVudHMpIDogW107XG59O1xuXG5mdW5jdGlvbiBhcnJheUNsb25lKGFyciwgbikge1xuICB2YXIgY29weSA9IG5ldyBBcnJheShuKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpXG4gICAgY29weVtpXSA9IGFycltpXTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKDsgaW5kZXggKyAxIDwgbGlzdC5sZW5ndGg7IGluZGV4KyspXG4gICAgbGlzdFtpbmRleF0gPSBsaXN0W2luZGV4ICsgMV07XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIHVud3JhcExpc3RlbmVycyhhcnIpIHtcbiAgdmFyIHJldCA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXQubGVuZ3RoOyArK2kpIHtcbiAgICByZXRbaV0gPSBhcnJbaV0ubGlzdGVuZXIgfHwgYXJyW2ldO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIG9uY2UoZW1pdHRlciwgbmFtZSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGZ1bmN0aW9uIGVycm9yTGlzdGVuZXIoZXJyKSB7XG4gICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKG5hbWUsIHJlc29sdmVyKTtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlc29sdmVyKCkge1xuICAgICAgaWYgKHR5cGVvZiBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgZXJyb3JMaXN0ZW5lcik7XG4gICAgICB9XG4gICAgICByZXNvbHZlKFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKSk7XG4gICAgfTtcblxuICAgIGV2ZW50VGFyZ2V0QWdub3N0aWNBZGRMaXN0ZW5lcihlbWl0dGVyLCBuYW1lLCByZXNvbHZlciwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIGlmIChuYW1lICE9PSAnZXJyb3InKSB7XG4gICAgICBhZGRFcnJvckhhbmRsZXJJZkV2ZW50RW1pdHRlcihlbWl0dGVyLCBlcnJvckxpc3RlbmVyLCB7IG9uY2U6IHRydWUgfSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gYWRkRXJyb3JIYW5kbGVySWZFdmVudEVtaXR0ZXIoZW1pdHRlciwgaGFuZGxlciwgZmxhZ3MpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLm9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZXZlbnRUYXJnZXRBZ25vc3RpY0FkZExpc3RlbmVyKGVtaXR0ZXIsICdlcnJvcicsIGhhbmRsZXIsIGZsYWdzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBldmVudFRhcmdldEFnbm9zdGljQWRkTGlzdGVuZXIoZW1pdHRlciwgbmFtZSwgbGlzdGVuZXIsIGZsYWdzKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5vbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGlmIChmbGFncy5vbmNlKSB7XG4gICAgICBlbWl0dGVyLm9uY2UobmFtZSwgbGlzdGVuZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbWl0dGVyLm9uKG5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIGVtaXR0ZXIuYWRkRXZlbnRMaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIEV2ZW50VGFyZ2V0IGRvZXMgbm90IGhhdmUgYGVycm9yYCBldmVudCBzZW1hbnRpY3MgbGlrZSBOb2RlXG4gICAgLy8gRXZlbnRFbWl0dGVycywgd2UgZG8gbm90IGxpc3RlbiBmb3IgYGVycm9yYCBldmVudHMgaGVyZS5cbiAgICBlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgZnVuY3Rpb24gd3JhcExpc3RlbmVyKGFyZykge1xuICAgICAgLy8gSUUgZG9lcyBub3QgaGF2ZSBidWlsdGluIGB7IG9uY2U6IHRydWUgfWAgc3VwcG9ydCBzbyB3ZVxuICAgICAgLy8gaGF2ZSB0byBkbyBpdCBtYW51YWxseS5cbiAgICAgIGlmIChmbGFncy5vbmNlKSB7XG4gICAgICAgIGVtaXR0ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihuYW1lLCB3cmFwTGlzdGVuZXIpO1xuICAgICAgfVxuICAgICAgbGlzdGVuZXIoYXJnKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJlbWl0dGVyXCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIEV2ZW50RW1pdHRlci4gUmVjZWl2ZWQgdHlwZSAnICsgdHlwZW9mIGVtaXR0ZXIpO1xuICB9XG59XG4iLCIvKiBqc2hpbnQgbm9kZTogdHJ1ZSAqL1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9ybWFsaWNlID0gcmVxdWlyZSgnbm9ybWFsaWNlJyk7XG5cbi8qKlxuICAjIGZyZWVpY2VcblxuICBUaGUgYGZyZWVpY2VgIG1vZHVsZSBpcyBhIHNpbXBsZSB3YXkgb2YgZ2V0dGluZyByYW5kb20gU1RVTiBvciBUVVJOIHNlcnZlclxuICBmb3IgeW91ciBXZWJSVEMgYXBwbGljYXRpb24uICBUaGUgbGlzdCBvZiBzZXJ2ZXJzIChqdXN0IFNUVU4gYXQgdGhpcyBzdGFnZSlcbiAgd2VyZSBzb3VyY2VkIGZyb20gdGhpcyBbZ2lzdF0oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20venppdW5pLzM3NDE5MzMpLlxuXG4gICMjIEV4YW1wbGUgVXNlXG5cbiAgVGhlIGZvbGxvd2luZyBkZW1vbnN0cmF0ZXMgaG93IHlvdSBjYW4gdXNlIGBmcmVlaWNlYCB3aXRoXG4gIFtydGMtcXVpY2tjb25uZWN0XShodHRwczovL2dpdGh1Yi5jb20vcnRjLWlvL3J0Yy1xdWlja2Nvbm5lY3QpOlxuXG4gIDw8PCBleGFtcGxlcy9xdWlja2Nvbm5lY3QuanNcblxuICBBcyB0aGUgYGZyZWVpY2VgIG1vZHVsZSBnZW5lcmF0ZXMgaWNlIHNlcnZlcnMgaW4gYSBsaXN0IGNvbXBsaWFudCB3aXRoIHRoZVxuICBXZWJSVEMgc3BlYyB5b3Ugd2lsbCBiZSBhYmxlIHRvIHVzZSBpdCB3aXRoIHJhdyBgUlRDUGVlckNvbm5lY3Rpb25gXG4gIGNvbnN0cnVjdG9ycyBhbmQgb3RoZXIgV2ViUlRDIGxpYnJhcmllcy5cblxuICAjIyBIZXksIGRvbid0IHVzZSBteSBTVFVOL1RVUk4gc2VydmVyIVxuXG4gIElmIGZvciBzb21lIHJlYXNvbiB5b3VyIGZyZWUgU1RVTiBvciBUVVJOIHNlcnZlciBlbmRzIHVwIGluIHRoZVxuICBsaXN0IG9mIHNlcnZlcnMgKFtzdHVuXShodHRwczovL2dpdGh1Yi5jb20vRGFtb25PZWhsbWFuL2ZyZWVpY2UvYmxvYi9tYXN0ZXIvc3R1bi5qc29uKSBvclxuICBbdHVybl0oaHR0cHM6Ly9naXRodWIuY29tL0RhbW9uT2VobG1hbi9mcmVlaWNlL2Jsb2IvbWFzdGVyL3R1cm4uanNvbikpXG4gIHRoYXQgaXMgdXNlZCBpbiB0aGlzIG1vZHVsZSwgeW91IGNhbiBmZWVsXG4gIGZyZWUgdG8gb3BlbiBhbiBpc3N1ZSBvbiB0aGlzIHJlcG9zaXRvcnkgYW5kIHRob3NlIHNlcnZlcnMgd2lsbCBiZSByZW1vdmVkXG4gIHdpdGhpbiAyNCBob3VycyAob3Igc29vbmVyKS4gIFRoaXMgaXMgdGhlIHF1aWNrZXN0IGFuZCBwcm9iYWJseSB0aGUgbW9zdFxuICBwb2xpdGUgd2F5IHRvIGhhdmUgc29tZXRoaW5nIHJlbW92ZWQgKGFuZCBwcm92aWRlcyB1cyBzb21lIHZpc2liaWxpdHlcbiAgaWYgc29tZW9uZSBvcGVucyBhIHB1bGwgcmVxdWVzdCByZXF1ZXN0aW5nIHRoYXQgYSBzZXJ2ZXIgaXMgYWRkZWQpLlxuXG4gICMjIFBsZWFzZSBhZGQgbXkgc2VydmVyIVxuXG4gIElmIHlvdSBoYXZlIGEgc2VydmVyIHRoYXQgeW91IHdpc2ggdG8gYWRkIHRvIHRoZSBsaXN0LCB0aGF0J3MgYXdlc29tZSEgSSdtXG4gIHN1cmUgSSBzcGVhayBvbiBiZWhhbGYgb2YgYSB3aG9sZSBwaWxlIG9mIFdlYlJUQyBkZXZlbG9wZXJzIHdobyBzYXkgdGhhbmtzLlxuICBUbyBnZXQgaXQgaW50byB0aGUgbGlzdCwgZmVlbCBmcmVlIHRvIGVpdGhlciBvcGVuIGEgcHVsbCByZXF1ZXN0IG9yIGlmIHlvdVxuICBmaW5kIHRoYXQgcHJvY2VzcyBhIGJpdCBkYXVudGluZyB0aGVuIGp1c3QgY3JlYXRlIGFuIGlzc3VlIHJlcXVlc3RpbmdcbiAgdGhlIGFkZGl0aW9uIG9mIHRoZSBzZXJ2ZXIgKG1ha2Ugc3VyZSB5b3UgcHJvdmlkZSBhbGwgdGhlIGRldGFpbHMsIGFuZCBpZlxuICB5b3UgaGF2ZSBhIFRlcm1zIG9mIFNlcnZpY2UgdGhlbiBpbmNsdWRpbmcgdGhhdCBpbiB0aGUgUFIvaXNzdWUgd291bGQgYmVcbiAgYXdlc29tZSkuXG5cbiAgIyMgSSBrbm93IG9mIGEgZnJlZSBzZXJ2ZXIsIGNhbiBJIGFkZCBpdD9cblxuICBTdXJlLCBpZiB5b3UgZG8geW91ciBob21ld29yayBhbmQgbWFrZSBzdXJlIGl0IGlzIG9rIHRvIHVzZSAoSSdtIGN1cnJlbnRseVxuICBpbiB0aGUgcHJvY2VzcyBvZiByZXZpZXdpbmcgdGhlIHRlcm1zIG9mIHRob3NlIFNUVU4gc2VydmVycyBpbmNsdWRlZCBmcm9tXG4gIHRoZSBvcmlnaW5hbCBsaXN0KS4gIElmIGl0J3Mgb2sgdG8gZ28sIHRoZW4gcGxlYXNlIHNlZSB0aGUgcHJldmlvdXMgZW50cnlcbiAgZm9yIGhvdyB0byBhZGQgaXQuXG5cbiAgIyMgQ3VycmVudCBMaXN0IG9mIFNlcnZlcnNcblxuICAqIGN1cnJlbnQgYXMgYXQgdGhlIHRpbWUgb2YgbGFzdCBgUkVBRE1FLm1kYCBmaWxlIGdlbmVyYXRpb25cblxuICAjIyMgU1RVTlxuXG4gIDw8PCBzdHVuLmpzb25cblxuICAjIyMgVFVSTlxuXG4gIDw8PCB0dXJuLmpzb25cblxuKiovXG5cbnZhciBmcmVlaWNlID0gZnVuY3Rpb24ob3B0cykge1xuICAvLyBpZiBhIGxpc3Qgb2Ygc2VydmVycyBoYXMgYmVlbiBwcm92aWRlZCwgdGhlbiB1c2UgaXQgaW5zdGVhZCBvZiBkZWZhdWx0c1xuICB2YXIgc2VydmVycyA9IHtcbiAgICBzdHVuOiAob3B0cyB8fCB7fSkuc3R1biB8fCByZXF1aXJlKCcuL3N0dW4uanNvbicpLFxuICAgIHR1cm46IChvcHRzIHx8IHt9KS50dXJuIHx8IHJlcXVpcmUoJy4vdHVybi5qc29uJylcbiAgfTtcblxuICB2YXIgc3R1bkNvdW50ID0gKG9wdHMgfHwge30pLnN0dW5Db3VudCB8fCAyO1xuICB2YXIgdHVybkNvdW50ID0gKG9wdHMgfHwge30pLnR1cm5Db3VudCB8fCAwO1xuICB2YXIgc2VsZWN0ZWQ7XG5cbiAgZnVuY3Rpb24gZ2V0U2VydmVycyh0eXBlLCBjb3VudCkge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaW5wdXQgPSBbXS5jb25jYXQoc2VydmVyc1t0eXBlXSk7XG4gICAgdmFyIGlkeDtcblxuICAgIHdoaWxlIChpbnB1dC5sZW5ndGggJiYgb3V0Lmxlbmd0aCA8IGNvdW50KSB7XG4gICAgICBpZHggPSAoTWF0aC5yYW5kb20oKSAqIGlucHV0Lmxlbmd0aCkgfCAwO1xuICAgICAgb3V0ID0gb3V0LmNvbmNhdChpbnB1dC5zcGxpY2UoaWR4LCAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5tYXAoZnVuY3Rpb24odXJsKSB7XG4gICAgICAgIC8vSWYgaXQncyBhIG5vdCBhIHN0cmluZywgZG9uJ3QgdHJ5IHRvIFwibm9ybWFsaWNlXCIgaXQgb3RoZXJ3aXNlIHVzaW5nIHR5cGU6dXJsIHdpbGwgc2NyZXcgaXQgdXBcbiAgICAgICAgaWYgKCh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGljZSh0eXBlICsgJzonICsgdXJsKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gYWRkIHN0dW4gc2VydmVyc1xuICBzZWxlY3RlZCA9IFtdLmNvbmNhdChnZXRTZXJ2ZXJzKCdzdHVuJywgc3R1bkNvdW50KSk7XG5cbiAgaWYgKHR1cm5Db3VudCkge1xuICAgIHNlbGVjdGVkID0gc2VsZWN0ZWQuY29uY2F0KGdldFNlcnZlcnMoJ3R1cm4nLCB0dXJuQ291bnQpKTtcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnJlZWljZTsiLCJtb2R1bGUuZXhwb3J0cz1bXG4gIFwic3R1bi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMS5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMi5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuMy5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuNC5sLmdvb2dsZS5jb206MTkzMDJcIixcbiAgXCJzdHVuLmVraWdhLm5ldFwiLFxuICBcInN0dW4uaWRlYXNpcC5jb21cIixcbiAgXCJzdHVuLnNjaGx1bmQuZGVcIixcbiAgXCJzdHVuLnN0dW5wcm90b2NvbC5vcmc6MzQ3OFwiLFxuICBcInN0dW4udm9pcGFyb3VuZC5jb21cIixcbiAgXCJzdHVuLnZvaXBidXN0ZXIuY29tXCIsXG4gIFwic3R1bi52b2lwc3R1bnQuY29tXCIsXG4gIFwic3R1bi52b3hncmF0aWEub3JnXCJcbl1cbiIsIm1vZHVsZS5leHBvcnRzPVtdXG4iLCJ2YXIgV2lsZEVtaXR0ZXIgPSByZXF1aXJlKCd3aWxkZW1pdHRlcicpO1xuXG5mdW5jdGlvbiBnZXRNYXhWb2x1bWUgKGFuYWx5c2VyLCBmZnRCaW5zKSB7XG4gIHZhciBtYXhWb2x1bWUgPSAtSW5maW5pdHk7XG4gIGFuYWx5c2VyLmdldEZsb2F0RnJlcXVlbmN5RGF0YShmZnRCaW5zKTtcblxuICBmb3IodmFyIGk9NCwgaWk9ZmZ0Qmlucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgaWYgKGZmdEJpbnNbaV0gPiBtYXhWb2x1bWUgJiYgZmZ0Qmluc1tpXSA8IDApIHtcbiAgICAgIG1heFZvbHVtZSA9IGZmdEJpbnNbaV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBtYXhWb2x1bWU7XG59XG5cblxudmFyIGF1ZGlvQ29udGV4dFR5cGU7XG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgYXVkaW9Db250ZXh0VHlwZSA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbn1cbi8vIHVzZSBhIHNpbmdsZSBhdWRpbyBjb250ZXh0IGR1ZSB0byBoYXJkd2FyZSBsaW1pdHNcbnZhciBhdWRpb0NvbnRleHQgPSBudWxsO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihzdHJlYW0sIG9wdGlvbnMpIHtcbiAgdmFyIGhhcmtlciA9IG5ldyBXaWxkRW1pdHRlcigpO1xuXG4gIC8vIG1ha2UgaXQgbm90IGJyZWFrIGluIG5vbi1zdXBwb3J0ZWQgYnJvd3NlcnNcbiAgaWYgKCFhdWRpb0NvbnRleHRUeXBlKSByZXR1cm4gaGFya2VyO1xuXG4gIC8vQ29uZmlnXG4gIHZhciBvcHRpb25zID0gb3B0aW9ucyB8fCB7fSxcbiAgICAgIHNtb290aGluZyA9IChvcHRpb25zLnNtb290aGluZyB8fCAwLjEpLFxuICAgICAgaW50ZXJ2YWwgPSAob3B0aW9ucy5pbnRlcnZhbCB8fCA1MCksXG4gICAgICB0aHJlc2hvbGQgPSBvcHRpb25zLnRocmVzaG9sZCxcbiAgICAgIHBsYXkgPSBvcHRpb25zLnBsYXksXG4gICAgICBoaXN0b3J5ID0gb3B0aW9ucy5oaXN0b3J5IHx8IDEwLFxuICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgLy8gRW5zdXJlIHRoYXQganVzdCBhIHNpbmdsZSBBdWRpb0NvbnRleHQgaXMgaW50ZXJuYWxseSBjcmVhdGVkXG4gIGF1ZGlvQ29udGV4dCA9IG9wdGlvbnMuYXVkaW9Db250ZXh0IHx8IGF1ZGlvQ29udGV4dCB8fCBuZXcgYXVkaW9Db250ZXh0VHlwZSgpO1xuXG4gIHZhciBzb3VyY2VOb2RlLCBmZnRCaW5zLCBhbmFseXNlcjtcblxuICBhbmFseXNlciA9IGF1ZGlvQ29udGV4dC5jcmVhdGVBbmFseXNlcigpO1xuICBhbmFseXNlci5mZnRTaXplID0gNTEyO1xuICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBzbW9vdGhpbmc7XG4gIGZmdEJpbnMgPSBuZXcgRmxvYXQzMkFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcblxuICBpZiAoc3RyZWFtLmpxdWVyeSkgc3RyZWFtID0gc3RyZWFtWzBdO1xuICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgSFRNTEF1ZGlvRWxlbWVudCB8fCBzdHJlYW0gaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB7XG4gICAgLy9BdWRpbyBUYWdcbiAgICBzb3VyY2VOb2RlID0gYXVkaW9Db250ZXh0LmNyZWF0ZU1lZGlhRWxlbWVudFNvdXJjZShzdHJlYW0pO1xuICAgIGlmICh0eXBlb2YgcGxheSA9PT0gJ3VuZGVmaW5lZCcpIHBsYXkgPSB0cnVlO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH0gZWxzZSB7XG4gICAgLy9XZWJSVEMgU3RyZWFtXG4gICAgc291cmNlTm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgIHRocmVzaG9sZCA9IHRocmVzaG9sZCB8fCAtNTA7XG4gIH1cblxuICBzb3VyY2VOb2RlLmNvbm5lY3QoYW5hbHlzZXIpO1xuICBpZiAocGxheSkgYW5hbHlzZXIuY29ubmVjdChhdWRpb0NvbnRleHQuZGVzdGluYXRpb24pO1xuXG4gIGhhcmtlci5zcGVha2luZyA9IGZhbHNlO1xuXG4gIGhhcmtlci5zdXNwZW5kID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGF1ZGlvQ29udGV4dC5zdXNwZW5kKCk7XG4gIH1cbiAgaGFya2VyLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhdWRpb0NvbnRleHQucmVzdW1lKCk7XG4gIH1cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGhhcmtlciwgJ3N0YXRlJywgeyBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhdWRpb0NvbnRleHQuc3RhdGU7XG4gIH19KTtcbiAgYXVkaW9Db250ZXh0Lm9uc3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcbiAgICBoYXJrZXIuZW1pdCgnc3RhdGVfY2hhbmdlJywgYXVkaW9Db250ZXh0LnN0YXRlKTtcbiAgfVxuXG4gIGhhcmtlci5zZXRUaHJlc2hvbGQgPSBmdW5jdGlvbih0KSB7XG4gICAgdGhyZXNob2xkID0gdDtcbiAgfTtcblxuICBoYXJrZXIuc2V0SW50ZXJ2YWwgPSBmdW5jdGlvbihpKSB7XG4gICAgaW50ZXJ2YWwgPSBpO1xuICB9O1xuXG4gIGhhcmtlci5zdG9wID0gZnVuY3Rpb24oKSB7XG4gICAgcnVubmluZyA9IGZhbHNlO1xuICAgIGhhcmtlci5lbWl0KCd2b2x1bWVfY2hhbmdlJywgLTEwMCwgdGhyZXNob2xkKTtcbiAgICBpZiAoaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICBoYXJrZXIuc3BlYWtpbmcgPSBmYWxzZTtcbiAgICAgIGhhcmtlci5lbWl0KCdzdG9wcGVkX3NwZWFraW5nJyk7XG4gICAgfVxuICAgIGFuYWx5c2VyLmRpc2Nvbm5lY3QoKTtcbiAgICBzb3VyY2VOb2RlLmRpc2Nvbm5lY3QoKTtcbiAgfTtcbiAgaGFya2VyLnNwZWFraW5nSGlzdG9yeSA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGhpc3Rvcnk7IGkrKykge1xuICAgICAgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5wdXNoKDApO1xuICB9XG5cbiAgLy8gUG9sbCB0aGUgYW5hbHlzZXIgbm9kZSB0byBkZXRlcm1pbmUgaWYgc3BlYWtpbmdcbiAgLy8gYW5kIGVtaXQgZXZlbnRzIGlmIGNoYW5nZWRcbiAgdmFyIGxvb3BlciA9IGZ1bmN0aW9uKCkge1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cbiAgICAgIC8vY2hlY2sgaWYgc3RvcCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgIGlmKCFydW5uaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGN1cnJlbnRWb2x1bWUgPSBnZXRNYXhWb2x1bWUoYW5hbHlzZXIsIGZmdEJpbnMpO1xuXG4gICAgICBoYXJrZXIuZW1pdCgndm9sdW1lX2NoYW5nZScsIGN1cnJlbnRWb2x1bWUsIHRocmVzaG9sZCk7XG5cbiAgICAgIHZhciBoaXN0b3J5ID0gMDtcbiAgICAgIGlmIChjdXJyZW50Vm9sdW1lID4gdGhyZXNob2xkICYmICFoYXJrZXIuc3BlYWtpbmcpIHtcbiAgICAgICAgLy8gdHJpZ2dlciBxdWlja2x5LCBzaG9ydCBoaXN0b3J5XG4gICAgICAgIGZvciAodmFyIGkgPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aCAtIDM7IGkgPCBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaGlzdG9yeSArPSBoYXJrZXIuc3BlYWtpbmdIaXN0b3J5W2ldO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoaXN0b3J5ID49IDIpIHtcbiAgICAgICAgICBoYXJrZXIuc3BlYWtpbmcgPSB0cnVlO1xuICAgICAgICAgIGhhcmtlci5lbWl0KCdzcGVha2luZycpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGN1cnJlbnRWb2x1bWUgPCB0aHJlc2hvbGQgJiYgaGFya2VyLnNwZWFraW5nKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGhpc3RvcnkgKz0gaGFya2VyLnNwZWFraW5nSGlzdG9yeVtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGlzdG9yeSA9PSAwKSB7XG4gICAgICAgICAgaGFya2VyLnNwZWFraW5nID0gZmFsc2U7XG4gICAgICAgICAgaGFya2VyLmVtaXQoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5zaGlmdCgpO1xuICAgICAgaGFya2VyLnNwZWFraW5nSGlzdG9yeS5wdXNoKDAgKyAoY3VycmVudFZvbHVtZSA+IHRocmVzaG9sZCkpO1xuXG4gICAgICBsb29wZXIoKTtcbiAgICB9LCBpbnRlcnZhbCk7XG4gIH07XG4gIGxvb3BlcigpO1xuXG4gIHJldHVybiBoYXJrZXI7XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBpZiAoc3VwZXJDdG9yKSB7XG4gICAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgICAgY3Rvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ3Rvci5wcm90b3R5cGUsIHtcbiAgICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGlmIChzdXBlckN0b3IpIHtcbiAgICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZVxuICAgICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gICAgfVxuICB9XG59XG4iLCIvKiBcclxuICogSlNOTG9nIDIuMzAuMFxyXG4gKiBPcGVuIHNvdXJjZSB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqIENvcHlyaWdodCAyMDEyLTIwMTcgTWF0dGlqcyBQZXJkZWNrIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqL1xyXG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XHJcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XHJcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbiAgICB9O1xyXG59KSgpO1xyXG5mdW5jdGlvbiBKTChsb2dnZXJOYW1lKSB7XHJcbiAgICAvLyBJZiBuYW1lIGlzIGVtcHR5LCByZXR1cm4gdGhlIHJvb3QgbG9nZ2VyXHJcbiAgICBpZiAoIWxvZ2dlck5hbWUpIHtcclxuICAgICAgICByZXR1cm4gSkwuX187XHJcbiAgICB9XHJcbiAgICAvLyBJbXBsZW1lbnRzIEFycmF5LnJlZHVjZS4gSlNOTG9nIHN1cHBvcnRzIElFOCsgYW5kIHJlZHVjZSBpcyBub3Qgc3VwcG9ydGVkIGluIHRoYXQgYnJvd3Nlci5cclxuICAgIC8vIFNhbWUgaW50ZXJmYWNlIGFzIHRoZSBzdGFuZGFyZCByZWR1Y2UsIGV4Y2VwdCB0aGF0IFxyXG4gICAgaWYgKCFBcnJheS5wcm90b3R5cGUucmVkdWNlKSB7XHJcbiAgICAgICAgQXJyYXkucHJvdG90eXBlLnJlZHVjZSA9IGZ1bmN0aW9uIChjYWxsYmFjaywgaW5pdGlhbFZhbHVlKSB7XHJcbiAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gaW5pdGlhbFZhbHVlO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUgPSBjYWxsYmFjayhwcmV2aW91c1ZhbHVlLCB0aGlzW2ldLCBpLCB0aGlzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG4gICAgdmFyIGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSA9ICcnO1xyXG4gICAgdmFyIGxvZ2dlciA9ICgnLicgKyBsb2dnZXJOYW1lKS5zcGxpdCgnLicpLnJlZHVjZShmdW5jdGlvbiAocHJldiwgY3VyciwgaWR4LCBhcnIpIHtcclxuICAgICAgICAvLyBpZiBsb2dnZXJuYW1lIGlzIGEuYi5jLCB0aGFuIGN1cnJlbnRMb2dnZXIgd2lsbCBiZSBzZXQgdG8gdGhlIGxvZ2dlcnNcclxuICAgICAgICAvLyByb290ICAgKHByZXY6IEpMLCBjdXJyOiAnJylcclxuICAgICAgICAvLyBhICAgICAgKHByZXY6IEpMLl9fLCBjdXJyOiAnYScpXHJcbiAgICAgICAgLy8gYS5iICAgIChwcmV2OiBKTC5fXy5fX2EsIGN1cnI6ICdiJylcclxuICAgICAgICAvLyBhLmIuYyAgKHByZXY6IEpMLl9fLl9fYS5fX2EuYiwgY3VycjogJ2MnKVxyXG4gICAgICAgIC8vIE5vdGUgdGhhdCB3aGVuIGEgbmV3IGxvZ2dlciBuYW1lIGlzIGVuY291bnRlcmVkIChzdWNoIGFzICdhLmIuYycpLFxyXG4gICAgICAgIC8vIGEgbmV3IGxvZ2dlciBvYmplY3QgaXMgY3JlYXRlZCBhbmQgYWRkZWQgYXMgYSBwcm9wZXJ0eSB0byB0aGUgcGFyZW50ICgnYS5iJykuXHJcbiAgICAgICAgLy8gVGhlIHJvb3QgbG9nZ2VyIGlzIGFkZGVkIGFzIGEgcHJvcGVydHkgb2YgdGhlIEpMIG9iamVjdCBpdHNlbGYuXHJcbiAgICAgICAgLy8gSXQgaXMgZXNzZW50aWFsIHRoYXQgdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IGNvbnRhaW5pbmcgdGhlIGNoaWxkIGxvZ2dlclxyXG4gICAgICAgIC8vIGNvbnRhaW5zIHRoZSBmdWxsICdwYXRoJyBuYW1lIG9mIHRoZSBjaGlsZCBsb2dnZXIgKCdhLmIuYycpIGluc3RlYWQgb2ZcclxuICAgICAgICAvLyBqdXN0IHRoZSBiaXQgYWZ0ZXIgdGhlIGxhc3QgcGVyaW9kICgnYycpLlxyXG4gICAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSB0aGUgcGFyZW50IGluaGVyaXRzIHByb3BlcnRpZXMgZnJvbSBpdHMgYW5jZXN0b3JzLlxyXG4gICAgICAgIC8vIFNvIGlmIHRoZSByb290IGhhcyBhIGNoaWxkIGxvZ2dlciAnYycgKHN0b3JlZCBpbiBhIHByb3BlcnR5ICdjJyBvZiB0aGUgcm9vdCBsb2dnZXIpLFxyXG4gICAgICAgIC8vIHRoZW4gbG9nZ2VyICdhLmInIGhhcyB0aGF0IHNhbWUgcHJvcGVydHkgJ2MnIHRocm91Z2ggaW5oZXJpdGFuY2UuXHJcbiAgICAgICAgLy8gVGhlIG5hbWVzIG9mIHRoZSBsb2dnZXIgcHJvcGVydGllcyBzdGFydCB3aXRoIF9fLCBzbyB0aGUgcm9vdCBsb2dnZXIgXHJcbiAgICAgICAgLy8gKHdoaWNoIGhhcyBuYW1lICcnKSwgaGFzIGEgbmljZSBwcm9wZXJ0eSBuYW1lICdfXycuICAgICAgICAgICAgICBcclxuICAgICAgICAvLyBhY2N1bXVsYXRlZExvZ2dlck5hbWUgZXZhbHVhdGVzIGZhbHNlICgnJyBpcyBmYWxzeSkgaW4gZmlyc3QgaXRlcmF0aW9uIHdoZW4gcHJldiBpcyB0aGUgcm9vdCBsb2dnZXIuXHJcbiAgICAgICAgLy8gYWNjdW11bGF0ZWRMb2dnZXJOYW1lIHdpbGwgYmUgdGhlIGxvZ2dlciBuYW1lIGNvcnJlc3BvbmRpbmcgd2l0aCB0aGUgbG9nZ2VyIGluIGN1cnJlbnRMb2dnZXIuXHJcbiAgICAgICAgLy8gS2VlcCBpbiBtaW5kIHRoYXQgdGhlIGN1cnJlbnRMb2dnZXIgbWF5IG5vdCBiZSBkZWZpbmVkIHlldCwgc28gY2FuJ3QgZ2V0IHRoZSBuYW1lIGZyb21cclxuICAgICAgICAvLyB0aGUgY3VycmVudExvZ2dlciBvYmplY3QgaXRzZWxmLiBcclxuICAgICAgICBpZiAoYWNjdW11bGF0ZWRMb2dnZXJOYW1lKSB7XHJcbiAgICAgICAgICAgIGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSArPSAnLicgKyBjdXJyO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgYWNjdW11bGF0ZWRMb2dnZXJOYW1lID0gY3VycjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGN1cnJlbnRMb2dnZXIgPSBwcmV2WydfXycgKyBhY2N1bXVsYXRlZExvZ2dlck5hbWVdO1xyXG4gICAgICAgIC8vIElmIHRoZSBjdXJyZW50TG9nZ2VyIChvciB0aGUgYWN0dWFsIGxvZ2dlciBiZWluZyBzb3VnaHQpIGRvZXMgbm90IHlldCBleGlzdCwgXHJcbiAgICAgICAgLy8gY3JlYXRlIGl0IG5vdy5cclxuICAgICAgICBpZiAoY3VycmVudExvZ2dlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIC8vIFNldCB0aGUgcHJvdG90eXBlIG9mIHRoZSBMb2dnZXIgY29uc3RydWN0b3IgZnVuY3Rpb24gdG8gdGhlIHBhcmVudCBvZiB0aGUgbG9nZ2VyXHJcbiAgICAgICAgICAgIC8vIHRvIGJlIGNyZWF0ZWQuIFRoaXMgd2F5LCBfX3Byb3RvIG9mIHRoZSBuZXcgbG9nZ2VyIG9iamVjdCB3aWxsIHBvaW50IGF0IHRoZSBwYXJlbnQuXHJcbiAgICAgICAgICAgIC8vIFdoZW4gbG9nZ2VyLmxldmVsIGlzIGV2YWx1YXRlZCBhbmQgaXMgbm90IHByZXNlbnQsIHRoZSBKYXZhU2NyaXB0IHJ1bnRpbWUgd2lsbCBcclxuICAgICAgICAgICAgLy8gd2FsayBkb3duIHRoZSBwcm90b3R5cGUgY2hhaW4gdG8gZmluZCB0aGUgZmlyc3QgYW5jZXN0b3Igd2l0aCBhIGxldmVsIHByb3BlcnR5LlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgcHJldiBhdCB0aGlzIHBvaW50IHJlZmVycyB0byB0aGUgcGFyZW50IGxvZ2dlci5cclxuICAgICAgICAgICAgSkwuTG9nZ2VyLnByb3RvdHlwZSA9IHByZXY7XHJcbiAgICAgICAgICAgIGN1cnJlbnRMb2dnZXIgPSBuZXcgSkwuTG9nZ2VyKGFjY3VtdWxhdGVkTG9nZ2VyTmFtZSk7XHJcbiAgICAgICAgICAgIHByZXZbJ19fJyArIGFjY3VtdWxhdGVkTG9nZ2VyTmFtZV0gPSBjdXJyZW50TG9nZ2VyO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gY3VycmVudExvZ2dlcjtcclxuICAgIH0sIEpMLl9fKTtcclxuICAgIHJldHVybiBsb2dnZXI7XHJcbn1cclxuKGZ1bmN0aW9uIChKTCkge1xyXG4gICAgLy8gSW5pdGlhbGlzZSByZXF1ZXN0SWQgdG8gZW1wdHkgc3RyaW5nLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyBhbmQgdGhlIHVzZXJcclxuICAgIC8vIGRvZXMgbm90IHNldCBpdCB2aWEgc2V0T3B0aW9ucywgdGhlbiB0aGUgSlNOTG9nLVJlcXVlc3RJZCBoZWFkZXIgd2lsbFxyXG4gICAgLy8gaGF2ZSB2YWx1ZSBcInVuZGVmaW5lZFwiLCB3aGljaCBkb2Vzbid0IGxvb2sgZ29vZCBpbiBhIGxvZy5cclxuICAgIC8vXHJcbiAgICAvLyBOb3RlIHRoYXQgeW91IGFsd2F5cyB3YW50IHRvIHNlbmQgYSByZXF1ZXN0SWQgYXMgcGFydCBvZiBsb2cgcmVxdWVzdHMsXHJcbiAgICAvLyBvdGhlcndpc2UgdGhlIHNlcnZlciBzaWRlIGNvbXBvbmVudCBkb2Vzbid0IGtub3cgdGhpcyBpcyBhIGxvZyByZXF1ZXN0XHJcbiAgICAvLyBhbmQgbWF5IGNyZWF0ZSBhIG5ldyByZXF1ZXN0IGlkIGZvciB0aGUgbG9nIHJlcXVlc3QsIGNhdXNpbmcgY29uZnVzaW9uXHJcbiAgICAvLyBpbiB0aGUgbG9nLlxyXG4gICAgSkwucmVxdWVzdElkID0gJyc7XHJcbiAgICAvLyBOdW1iZXIgdW5pcXVlbHkgaWRlbnRpZnlpbmcgZXZlcnkgbG9nIGVudHJ5IHdpdGhpbiB0aGUgcmVxdWVzdC5cclxuICAgIEpMLmVudHJ5SWQgPSAwO1xyXG4gICAgLy8gQWxsb3cgcHJvcGVydHkgaW5qZWN0aW9uIG9mIHRoZXNlIGNsYXNzZXMsIHRvIGVuYWJsZSB1bml0IHRlc3RpbmdcclxuICAgIEpMLl9jcmVhdGVYTUxIdHRwUmVxdWVzdCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG5ldyBYTUxIdHRwUmVxdWVzdCgpOyB9O1xyXG4gICAgSkwuX2dldFRpbWUgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAobmV3IERhdGUpLmdldFRpbWUoKTsgfTtcclxuICAgIEpMLl9jb25zb2xlID0gY29uc29sZTtcclxuICAgIC8vIC0tLS0tIHByaXZhdGUgdmFyaWFibGVzXHJcbiAgICBKTC5fYXBwZW5kZXJOYW1lcyA9IFtdO1xyXG4gICAgLyoqXHJcbiAgICBDb3BpZXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgZnJvbSBvbmUgb2JqZWN0IHRvIHRoZSBvdGhlci5cclxuICAgIFRoaXMgaXMgdXNlZCB0byBjb3B5IHByb3BlcnR5IHZhbHVlcyBhcyBwYXJ0IG9mIHNldE9wdGlvbiBmb3IgbG9nZ2VycyBhbmQgYXBwZW5kZXJzLlxyXG5cclxuICAgIEJlY2F1c2UgbG9nZ2VycyBpbmhlcml0IHByb3BlcnR5IHZhbHVlcyBmcm9tIHRoZWlyIHBhcmVudHMsIGl0IGlzIGltcG9ydGFudCBuZXZlciB0b1xyXG4gICAgY3JlYXRlIGEgcHJvcGVydHkgb24gYSBsb2dnZXIgaWYgdGhlIGludGVudCBpcyB0byBpbmhlcml0IGZyb20gdGhlIHBhcmVudC5cclxuXHJcbiAgICBDb3B5aW5nIHJ1bGVzOlxyXG4gICAgMSkgaWYgdGhlIGZyb20gcHJvcGVydHkgaXMgdW5kZWZpbmVkIChmb3IgZXhhbXBsZSwgbm90IG1lbnRpb25lZCBpbiBhIEpTT04gb2JqZWN0KSwgdGhlXHJcbiAgICAgICB0byBwcm9wZXJ0eSBpcyBub3QgYWZmZWN0ZWQgYXQgYWxsLlxyXG4gICAgMikgaWYgdGhlIGZyb20gcHJvcGVydHkgaXMgbnVsbCwgdGhlIHRvIHByb3BlcnR5IGlzIGRlbGV0ZWQgKHNvIHRoZSBsb2dnZXIgd2lsbCBpbmhlcml0IGZyb21cclxuICAgICAgIGl0cyBwYXJlbnQpLlxyXG4gICAgMykgT3RoZXJ3aXNlLCB0aGUgZnJvbSBwcm9wZXJ0eSBpcyBjb3BpZWQgdG8gdGhlIHRvIHByb3BlcnR5LlxyXG4gICAgKi9cclxuICAgIGZ1bmN0aW9uIGNvcHlQcm9wZXJ0eShwcm9wZXJ0eU5hbWUsIGZyb20sIHRvKSB7XHJcbiAgICAgICAgaWYgKGZyb21bcHJvcGVydHlOYW1lXSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGZyb21bcHJvcGVydHlOYW1lXSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICBkZWxldGUgdG9bcHJvcGVydHlOYW1lXTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0b1twcm9wZXJ0eU5hbWVdID0gZnJvbVtwcm9wZXJ0eU5hbWVdO1xyXG4gICAgfVxyXG4gICAgLyoqXHJcbiAgICBSZXR1cm5zIHRydWUgaWYgYSBsb2cgc2hvdWxkIGdvIGFoZWFkLlxyXG4gICAgRG9lcyBub3QgY2hlY2sgbGV2ZWwuXHJcblxyXG4gICAgQHBhcmFtIGZpbHRlcnNcclxuICAgICAgICBGaWx0ZXJzIHRoYXQgZGV0ZXJtaW5lIHdoZXRoZXIgYSBsb2cgY2FuIGdvIGFoZWFkLlxyXG4gICAgKi9cclxuICAgIGZ1bmN0aW9uIGFsbG93KGZpbHRlcnMpIHtcclxuICAgICAgICAvLyBJZiBlbmFibGVkIGlzIG5vdCBudWxsIG9yIHVuZGVmaW5lZCwgdGhlbiBpZiBpdCBpcyBmYWxzZSwgdGhlbiByZXR1cm4gZmFsc2VcclxuICAgICAgICAvLyBOb3RlIHRoYXQgdW5kZWZpbmVkPT1udWxsICghKVxyXG4gICAgICAgIGlmICghKEpMLmVuYWJsZWQgPT0gbnVsbCkpIHtcclxuICAgICAgICAgICAgaWYgKCFKTC5lbmFibGVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gSWYgdGhlIHJlZ2V4IGNvbnRhaW5zIGEgYnVnLCB0aGF0IHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uLlxyXG4gICAgICAgIC8vIElnbm9yZSB0aGlzLCBhbmQgcGFzcyB0aGUgbG9nIGl0ZW0gKGJldHRlciB0b28gbXVjaCB0aGFuIHRvbyBsaXR0bGUpLlxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmaWx0ZXJzLnVzZXJBZ2VudFJlZ2V4KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIW5ldyBSZWdFeHAoZmlsdGVycy51c2VyQWdlbnRSZWdleCkudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBjYXRjaCAoZSkgeyB9XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGZpbHRlcnMuaXBSZWdleCAmJiBKTC5jbGllbnRJUCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFuZXcgUmVnRXhwKGZpbHRlcnMuaXBSZWdleCkudGVzdChKTC5jbGllbnRJUCkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG4gICAgLyoqXHJcbiAgICBSZXR1cm5zIHRydWUgaWYgYSBsb2cgc2hvdWxkIGdvIGFoZWFkLCBiYXNlZCBvbiB0aGUgbWVzc2FnZS5cclxuXHJcbiAgICBAcGFyYW0gZmlsdGVyc1xyXG4gICAgICAgIEZpbHRlcnMgdGhhdCBkZXRlcm1pbmUgd2hldGhlciBhIGxvZyBjYW4gZ28gYWhlYWQuXHJcblxyXG4gICAgQHBhcmFtIG1lc3NhZ2VcclxuICAgICAgICBNZXNzYWdlIHRvIGJlIGxvZ2dlZC5cclxuICAgICovXHJcbiAgICBmdW5jdGlvbiBhbGxvd01lc3NhZ2UoZmlsdGVycywgbWVzc2FnZSkge1xyXG4gICAgICAgIC8vIElmIHRoZSByZWdleCBjb250YWlucyBhIGJ1ZywgdGhhdCB3aWxsIHRocm93IGFuIGV4Y2VwdGlvbi5cclxuICAgICAgICAvLyBJZ25vcmUgdGhpcywgYW5kIHBhc3MgdGhlIGxvZyBpdGVtIChiZXR0ZXIgdG9vIG11Y2ggdGhhbiB0b28gbGl0dGxlKS5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZmlsdGVycy5kaXNhbGxvdykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG5ldyBSZWdFeHAoZmlsdGVycy5kaXNhbGxvdykudGVzdChtZXNzYWdlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBjYXRjaCAoZSkgeyB9XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICAvLyBJZiBsb2dPYmplY3QgaXMgYSBmdW5jdGlvbiwgdGhlIGZ1bmN0aW9uIGlzIGV2YWx1YXRlZCAod2l0aG91dCBwYXJhbWV0ZXJzKVxyXG4gICAgLy8gYW5kIHRoZSByZXN1bHQgcmV0dXJuZWQuXHJcbiAgICAvLyBPdGhlcndpc2UsIGxvZ09iamVjdCBpdHNlbGYgaXMgcmV0dXJuZWQuXHJcbiAgICBmdW5jdGlvbiBzdHJpbmdpZnlMb2dPYmplY3RGdW5jdGlvbihsb2dPYmplY3QpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGxvZ09iamVjdCA9PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICAgICAgaWYgKGxvZ09iamVjdCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvZ09iamVjdC50b1N0cmluZygpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvZ09iamVjdCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBsb2dPYmplY3Q7XHJcbiAgICB9XHJcbiAgICB2YXIgU3RyaW5naWZpZWRMb2dPYmplY3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gKiBtc2cgLSBcclxuICAgICAgICAvLyAgICAgIGlmIHRoZSBsb2dPYmplY3QgaXMgYSBzY2FsYXIgKGFmdGVyIHBvc3NpYmxlIGZ1bmN0aW9uIGV2YWx1YXRpb24pLCB0aGlzIGlzIHNldCB0b1xyXG4gICAgICAgIC8vICAgICAgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgc2NhbGFyLiBPdGhlcndpc2UgaXQgaXMgbGVmdCB1bmRlZmluZWQuXHJcbiAgICAgICAgLy8gKiBtZXRhIC1cclxuICAgICAgICAvLyAgICAgIGlmIHRoZSBsb2dPYmplY3QgaXMgYW4gb2JqZWN0IChhZnRlciBwb3NzaWJsZSBmdW5jdGlvbiBldmFsdWF0aW9uKSwgdGhpcyBpcyBzZXQgdG9cclxuICAgICAgICAvLyAgICAgIHRoYXQgb2JqZWN0LiBPdGhlcndpc2UgaXQgaXMgbGVmdCB1bmRlZmluZWQuXHJcbiAgICAgICAgLy8gKiBmaW5hbFN0cmluZyAtXHJcbiAgICAgICAgLy8gICAgICBUaGlzIGlzIHNldCB0byB0aGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGxvZ09iamVjdCAoYWZ0ZXIgcG9zc2libGUgZnVuY3Rpb24gZXZhbHVhdGlvbiksXHJcbiAgICAgICAgLy8gICAgICByZWdhcmRsZXNzIG9mIHdoZXRoZXIgaXQgaXMgYW4gc2NhbGFyIG9yIGFuIG9iamVjdC4gQW4gb2JqZWN0IGlzIHN0cmluZ2lmaWVkIHRvIGEgSlNPTiBzdHJpbmcuXHJcbiAgICAgICAgLy8gICAgICBOb3RlIHRoYXQgeW91IGNhbid0IGNhbGwgdGhpcyBmaWVsZCBcImZpbmFsXCIsIGJlY2F1c2UgYXMgc29tZSBwb2ludCB0aGlzIHdhcyBhIHJlc2VydmVkXHJcbiAgICAgICAgLy8gICAgICBKYXZhU2NyaXB0IGtleXdvcmQgYW5kIHVzaW5nIGZpbmFsIHRyaXBzIHVwIHNvbWUgbWluaWZpZXJzLlxyXG4gICAgICAgIGZ1bmN0aW9uIFN0cmluZ2lmaWVkTG9nT2JqZWN0KG1zZywgbWV0YSwgZmluYWxTdHJpbmcpIHtcclxuICAgICAgICAgICAgdGhpcy5tc2cgPSBtc2c7XHJcbiAgICAgICAgICAgIHRoaXMubWV0YSA9IG1ldGE7XHJcbiAgICAgICAgICAgIHRoaXMuZmluYWxTdHJpbmcgPSBmaW5hbFN0cmluZztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIFN0cmluZ2lmaWVkTG9nT2JqZWN0O1xyXG4gICAgfSgpKTtcclxuICAgIC8vIFRha2VzIGEgbG9nT2JqZWN0LCB3aGljaCBjYW4gYmUgXHJcbiAgICAvLyAqIGEgc2NhbGFyXHJcbiAgICAvLyAqIGFuIG9iamVjdFxyXG4gICAgLy8gKiBhIHBhcmFtZXRlcmxlc3MgZnVuY3Rpb24sIHdoaWNoIHJldHVybnMgdGhlIHNjYWxhciBvciBvYmplY3QgdG8gbG9nLlxyXG4gICAgLy8gUmV0dXJucyBhIHN0cmluZ2lmaWVkTG9nT2JqZWN0XHJcbiAgICBmdW5jdGlvbiBzdHJpbmdpZnlMb2dPYmplY3QobG9nT2JqZWN0KSB7XHJcbiAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgd29ya3MgaWYgbG9nT2JqZWN0IGlzIG51bGwuXHJcbiAgICAgICAgLy8gdHlwZW9mIG51bGwgaXMgb2JqZWN0LlxyXG4gICAgICAgIC8vIEpTT04uc3RyaW5naWZ5KG51bGwpIHJldHVybnMgXCJudWxsXCIuXHJcbiAgICAgICAgdmFyIGFjdHVhbExvZ09iamVjdCA9IHN0cmluZ2lmeUxvZ09iamVjdEZ1bmN0aW9uKGxvZ09iamVjdCk7XHJcbiAgICAgICAgdmFyIGZpbmFsU3RyaW5nO1xyXG4gICAgICAgIC8vIE5vdGUgdGhhdCB0eXBlb2YgYWN0dWFsTG9nT2JqZWN0IHNob3VsZCBub3QgYmUgXCJmdW5jdGlvblwiLCBiZWNhdXNlIHRoYXQgaGFzIFxyXG4gICAgICAgIC8vIGJlZW4gcmVzb2x2ZWQgd2l0aCBzdHJpbmdpZnlMb2dPYmplY3RGdW5jdGlvbi5cclxuICAgICAgICBzd2l0Y2ggKHR5cGVvZiBhY3R1YWxMb2dPYmplY3QpIHtcclxuICAgICAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChhY3R1YWxMb2dPYmplY3QsIG51bGwsIGFjdHVhbExvZ09iamVjdCk7XHJcbiAgICAgICAgICAgIGNhc2UgXCJudW1iZXJcIjpcclxuICAgICAgICAgICAgICAgIGZpbmFsU3RyaW5nID0gYWN0dWFsTG9nT2JqZWN0LnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZ2lmaWVkTG9nT2JqZWN0KGZpbmFsU3RyaW5nLCBudWxsLCBmaW5hbFN0cmluZyk7XHJcbiAgICAgICAgICAgIGNhc2UgXCJib29sZWFuXCI6XHJcbiAgICAgICAgICAgICAgICBmaW5hbFN0cmluZyA9IGFjdHVhbExvZ09iamVjdC50b1N0cmluZygpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChmaW5hbFN0cmluZywgbnVsbCwgZmluYWxTdHJpbmcpO1xyXG4gICAgICAgICAgICBjYXNlIFwidW5kZWZpbmVkXCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZ2lmaWVkTG9nT2JqZWN0KFwidW5kZWZpbmVkXCIsIG51bGwsIFwidW5kZWZpbmVkXCIpO1xyXG4gICAgICAgICAgICBjYXNlIFwib2JqZWN0XCI6XHJcbiAgICAgICAgICAgICAgICBpZiAoKGFjdHVhbExvZ09iamVjdCBpbnN0YW5jZW9mIFJlZ0V4cCkgfHxcclxuICAgICAgICAgICAgICAgICAgICAoYWN0dWFsTG9nT2JqZWN0IGluc3RhbmNlb2YgU3RyaW5nKSB8fFxyXG4gICAgICAgICAgICAgICAgICAgIChhY3R1YWxMb2dPYmplY3QgaW5zdGFuY2VvZiBOdW1iZXIpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgKGFjdHVhbExvZ09iamVjdCBpbnN0YW5jZW9mIEJvb2xlYW4pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmluYWxTdHJpbmcgPSBhY3R1YWxMb2dPYmplY3QudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZ2lmaWVkTG9nT2JqZWN0KGZpbmFsU3RyaW5nLCBudWxsLCBmaW5hbFN0cmluZyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEpMLnNlcmlhbGl6ZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFN0cmluZyA9IEpMLnNlcmlhbGl6ZS5jYWxsKHRoaXMsIGFjdHVhbExvZ09iamVjdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFN0cmluZyA9IEpTT04uc3RyaW5naWZ5KGFjdHVhbExvZ09iamVjdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgbXNnIGZpZWxkIHRvIFwiXCIgaW5zdGVhZCBvZiBudWxsLiBTb21lIFdpbnN0b24gdHJhbnNwb3J0c1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGFzc3VtZSB0aGF0IHRoZSBtc2cgZmllbGQgaXMgbm90IG51bGwuXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdpZmllZExvZ09iamVjdChcIlwiLCBhY3R1YWxMb2dPYmplY3QsIGZpbmFsU3RyaW5nKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5naWZpZWRMb2dPYmplY3QoXCJ1bmtub3duXCIsIG51bGwsIFwidW5rbm93blwiKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBzZXRPcHRpb25zKG9wdGlvbnMpIHtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJlbmFibGVkXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgIGNvcHlQcm9wZXJ0eShcIm1heE1lc3NhZ2VzXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgIGNvcHlQcm9wZXJ0eShcImRlZmF1bHRBamF4VXJsXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgIGNvcHlQcm9wZXJ0eShcImNsaWVudElQXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgIGNvcHlQcm9wZXJ0eShcInJlcXVlc3RJZFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJkZWZhdWx0QmVmb3JlU2VuZFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICBjb3B5UHJvcGVydHkoXCJzZXJpYWxpemVcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9XHJcbiAgICBKTC5zZXRPcHRpb25zID0gc2V0T3B0aW9ucztcclxuICAgIGZ1bmN0aW9uIGdldEFsbExldmVsKCkgeyByZXR1cm4gLTIxNDc0ODM2NDg7IH1cclxuICAgIEpMLmdldEFsbExldmVsID0gZ2V0QWxsTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRUcmFjZUxldmVsKCkgeyByZXR1cm4gMTAwMDsgfVxyXG4gICAgSkwuZ2V0VHJhY2VMZXZlbCA9IGdldFRyYWNlTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXREZWJ1Z0xldmVsKCkgeyByZXR1cm4gMjAwMDsgfVxyXG4gICAgSkwuZ2V0RGVidWdMZXZlbCA9IGdldERlYnVnTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRJbmZvTGV2ZWwoKSB7IHJldHVybiAzMDAwOyB9XHJcbiAgICBKTC5nZXRJbmZvTGV2ZWwgPSBnZXRJbmZvTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRXYXJuTGV2ZWwoKSB7IHJldHVybiA0MDAwOyB9XHJcbiAgICBKTC5nZXRXYXJuTGV2ZWwgPSBnZXRXYXJuTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRFcnJvckxldmVsKCkgeyByZXR1cm4gNTAwMDsgfVxyXG4gICAgSkwuZ2V0RXJyb3JMZXZlbCA9IGdldEVycm9yTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRGYXRhbExldmVsKCkgeyByZXR1cm4gNjAwMDsgfVxyXG4gICAgSkwuZ2V0RmF0YWxMZXZlbCA9IGdldEZhdGFsTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBnZXRPZmZMZXZlbCgpIHsgcmV0dXJuIDIxNDc0ODM2NDc7IH1cclxuICAgIEpMLmdldE9mZkxldmVsID0gZ2V0T2ZmTGV2ZWw7XHJcbiAgICBmdW5jdGlvbiBsZXZlbFRvU3RyaW5nKGxldmVsKSB7XHJcbiAgICAgICAgaWYgKGxldmVsIDw9IDEwMDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwidHJhY2VcIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGxldmVsIDw9IDIwMDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwiZGVidWdcIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGxldmVsIDw9IDMwMDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIFwiaW5mb1wiO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAobGV2ZWwgPD0gNDAwMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gXCJ3YXJuXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChsZXZlbCA8PSA1MDAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBcImVycm9yXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBcImZhdGFsXCI7XHJcbiAgICB9XHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIHZhciBFeGNlcHRpb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gZGF0YSByZXBsYWNlcyBtZXNzYWdlLiBJdCB0YWtlcyBub3QganVzdCBzdHJpbmdzLCBidXQgYWxzbyBvYmplY3RzIGFuZCBmdW5jdGlvbnMsIGp1c3QgbGlrZSB0aGUgbG9nIGZ1bmN0aW9uLlxyXG4gICAgICAgIC8vIGludGVybmFsbHksIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gaXMgc3RvcmVkIGluIHRoZSBtZXNzYWdlIHByb3BlcnR5IChpbmhlcml0ZWQgZnJvbSBFcnJvcilcclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIGlubmVyOiBpbm5lciBleGNlcHRpb24uIENhbiBiZSBudWxsIG9yIHVuZGVmaW5lZC4gXHJcbiAgICAgICAgZnVuY3Rpb24gRXhjZXB0aW9uKGRhdGEsIGlubmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaW5uZXIgPSBpbm5lcjtcclxuICAgICAgICAgICAgdGhpcy5uYW1lID0gXCJKTC5FeGNlcHRpb25cIjtcclxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gc3RyaW5naWZ5TG9nT2JqZWN0KGRhdGEpLmZpbmFsU3RyaW5nO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gRXhjZXB0aW9uO1xyXG4gICAgfSgpKTtcclxuICAgIEpMLkV4Y2VwdGlvbiA9IEV4Y2VwdGlvbjtcclxuICAgIC8vIERlcml2ZSBFeGNlcHRpb24gZnJvbSBFcnJvciAoYSBIb3N0IG9iamVjdCksIHNvIGJyb3dzZXJzXHJcbiAgICAvLyBhcmUgbW9yZSBsaWtlbHkgdG8gcHJvZHVjZSBhIHN0YWNrIHRyYWNlIGZvciBpdCBpbiB0aGVpciBjb25zb2xlLlxyXG4gICAgLy9cclxuICAgIC8vIE5vdGUgdGhhdCBpbnN0YW5jZW9mIGFnYWluc3QgYW4gb2JqZWN0IGNyZWF0ZWQgd2l0aCB0aGlzIGNvbnN0cnVjdG9yXHJcbiAgICAvLyB3aWxsIHJldHVybiB0cnVlIGluIHRoZXNlIGNhc2VzOlxyXG4gICAgLy8gPG9iamVjdD4gaW5zdGFuY2VvZiBKTC5FeGNlcHRpb24pO1xyXG4gICAgLy8gPG9iamVjdD4gaW5zdGFuY2VvZiBFcnJvcik7XHJcbiAgICBFeGNlcHRpb24ucHJvdG90eXBlID0gbmV3IEVycm9yKCk7XHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIHZhciBMb2dJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIC8vIGw6IGxldmVsXHJcbiAgICAgICAgLy8gbTogbWVzc2FnZVxyXG4gICAgICAgIC8vIG46IGxvZ2dlciBuYW1lXHJcbiAgICAgICAgLy8gdCAodGltZVN0YW1wKSBpcyBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHNpbmNlIDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQ1xyXG4gICAgICAgIC8vIHU6IG51bWJlciB1bmlxdWVseSBpZGVudGlmeWluZyB0aGlzIGVudHJ5IGZvciB0aGlzIHJlcXVlc3QuXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBLZWVwaW5nIHRoZSBwcm9wZXJ0eSBuYW1lcyByZWFsbHkgc2hvcnQsIGJlY2F1c2UgdGhleSB3aWxsIGJlIHNlbnQgaW4gdGhlXHJcbiAgICAgICAgLy8gSlNPTiBwYXlsb2FkIHRvIHRoZSBzZXJ2ZXIuXHJcbiAgICAgICAgZnVuY3Rpb24gTG9nSXRlbShsLCBtLCBuLCB0LCB1KSB7XHJcbiAgICAgICAgICAgIHRoaXMubCA9IGw7XHJcbiAgICAgICAgICAgIHRoaXMubSA9IG07XHJcbiAgICAgICAgICAgIHRoaXMubiA9IG47XHJcbiAgICAgICAgICAgIHRoaXMudCA9IHQ7XHJcbiAgICAgICAgICAgIHRoaXMudSA9IHU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBMb2dJdGVtO1xyXG4gICAgfSgpKTtcclxuICAgIEpMLkxvZ0l0ZW0gPSBMb2dJdGVtO1xyXG4gICAgZnVuY3Rpb24gbmV3TG9nSXRlbShsZXZlbE5iciwgbWVzc2FnZSwgbG9nZ2VyTmFtZSkge1xyXG4gICAgICAgIEpMLmVudHJ5SWQrKztcclxuICAgICAgICByZXR1cm4gbmV3IExvZ0l0ZW0obGV2ZWxOYnIsIG1lc3NhZ2UsIGxvZ2dlck5hbWUsIEpMLl9nZXRUaW1lKCksIEpMLmVudHJ5SWQpO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gY2xlYXJUaW1lcih0aW1lcikge1xyXG4gICAgICAgIGlmICh0aW1lci5pZCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIuaWQpO1xyXG4gICAgICAgICAgICB0aW1lci5pZCA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gc2V0VGltZXIodGltZXIsIHRpbWVvdXRNcywgY2FsbGJhY2spIHtcclxuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XHJcbiAgICAgICAgaWYgKCF0aW1lci5pZCkge1xyXG4gICAgICAgICAgICB0aW1lci5pZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgLy8gdXNlIGNhbGwgdG8gZW5zdXJlIHRoYXQgdGhlIHRoaXMgYXMgdXNlZCBpbnNpZGUgc2VuZEJhdGNoIHdoZW4gaXQgcnVucyBpcyB0aGVcclxuICAgICAgICAgICAgICAgIC8vIHNhbWUgdGhpcyBhdCB0aGlzIHBvaW50LlxyXG4gICAgICAgICAgICAgICAgY2FsbGJhY2suY2FsbCh0aGF0KTtcclxuICAgICAgICAgICAgfSwgdGltZW91dE1zKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICB2YXIgQXBwZW5kZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy8gc2VuZExvZ0l0ZW1zIHRha2VzIGFuIGFycmF5IG9mIGxvZyBpdGVtcy4gSXQgd2lsbCBiZSBjYWxsZWQgd2hlblxyXG4gICAgICAgIC8vIHRoZSBhcHBlbmRlciBoYXMgaXRlbXMgdG8gcHJvY2VzcyAoc3VjaCBhcywgc2VuZCB0byB0aGUgc2VydmVyKS5cclxuICAgICAgICAvLyBzZW5kTG9nSXRlbXMgd2lsbCBjYWxsIHN1Y2Nlc3NDYWxsYmFjayBhZnRlciB0aGUgaXRlbXMgaGF2ZSBiZWVuIHN1Y2Nlc3NmdWxseSBzZW50LlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gTm90ZSB0aGF0IGFmdGVyIHNlbmRMb2dJdGVtcyByZXR1cm5zLCB0aGUgYXBwZW5kZXIgbWF5IHRydW5jYXRlXHJcbiAgICAgICAgLy8gdGhlIExvZ0l0ZW0gYXJyYXksIHNvIHRoZSBmdW5jdGlvbiBoYXMgdG8gY29weSB0aGUgY29udGVudCBvZiB0aGUgYXJyYXlcclxuICAgICAgICAvLyBpbiBzb21lIGZhc2hpb24gKGVnLiBzZXJpYWxpemUpIGJlZm9yZSByZXR1cm5pbmcuXHJcbiAgICAgICAgZnVuY3Rpb24gQXBwZW5kZXIoYXBwZW5kZXJOYW1lLCBzZW5kTG9nSXRlbXMpIHtcclxuICAgICAgICAgICAgdGhpcy5hcHBlbmRlck5hbWUgPSBhcHBlbmRlck5hbWU7XHJcbiAgICAgICAgICAgIHRoaXMuc2VuZExvZ0l0ZW1zID0gc2VuZExvZ0l0ZW1zO1xyXG4gICAgICAgICAgICB0aGlzLmxldmVsID0gSkwuZ2V0VHJhY2VMZXZlbCgpO1xyXG4gICAgICAgICAgICAvLyBzZXQgdG8gc3VwZXIgaGlnaCBsZXZlbCwgc28gaWYgdXNlciBpbmNyZWFzZXMgbGV2ZWwsIGxldmVsIGlzIHVubGlrZWx5IHRvIGdldCBcclxuICAgICAgICAgICAgLy8gYWJvdmUgc2VuZFdpdGhCdWZmZXJMZXZlbFxyXG4gICAgICAgICAgICB0aGlzLnNlbmRXaXRoQnVmZmVyTGV2ZWwgPSAyMTQ3NDgzNjQ3O1xyXG4gICAgICAgICAgICB0aGlzLnN0b3JlSW5CdWZmZXJMZXZlbCA9IC0yMTQ3NDgzNjQ4O1xyXG4gICAgICAgICAgICB0aGlzLmJ1ZmZlclNpemUgPSAwOyAvLyBidWZmZXJpbmcgc3dpdGNoIG9mZiBieSBkZWZhdWx0XHJcbiAgICAgICAgICAgIHRoaXMuYmF0Y2hTaXplID0gMTtcclxuICAgICAgICAgICAgdGhpcy5tYXhCYXRjaFNpemUgPSAyMDtcclxuICAgICAgICAgICAgdGhpcy5iYXRjaFRpbWVvdXQgPSAyMTQ3NDgzNjQ3O1xyXG4gICAgICAgICAgICB0aGlzLnNlbmRUaW1lb3V0ID0gNTAwMDtcclxuICAgICAgICAgICAgLy8gSG9sZHMgYWxsIGxvZyBpdGVtcyB3aXRoIGxldmVscyBoaWdoZXIgdGhhbiBzdG9yZUluQnVmZmVyTGV2ZWwgXHJcbiAgICAgICAgICAgIC8vIGJ1dCBsb3dlciB0aGFuIGxldmVsLiBUaGVzZSBpdGVtcyBtYXkgbmV2ZXIgYmUgc2VudC5cclxuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSBbXTtcclxuICAgICAgICAgICAgLy8gSG9sZHMgYWxsIGl0ZW1zIHRoYXQgd2UgZG8gd2FudCB0byBzZW5kLCB1bnRpbCB3ZSBoYXZlIGEgZnVsbFxyXG4gICAgICAgICAgICAvLyBiYXRjaCAoYXMgZGV0ZXJtaW5lZCBieSBiYXRjaFNpemUpLlxyXG4gICAgICAgICAgICB0aGlzLmJhdGNoQnVmZmVyID0gW107XHJcbiAgICAgICAgICAgIC8vIEhvbGRzIHRoZSBpZCBvZiB0aGUgdGltZXIgaW1wbGVtZW50aW5nIHRoZSBiYXRjaCB0aW1lb3V0LlxyXG4gICAgICAgICAgICAvLyBDYW4gYmUgbnVsbC5cclxuICAgICAgICAgICAgLy8gVGhpcyBpcyBhbiBvYmplY3QsIHNvIGl0IGNhbiBiZSBwYXNzZWQgdG8gYSBtZXRob2QgdGhhdCB1cGRhdGVkIHRoZSB0aW1lciB2YXJpYWJsZS5cclxuICAgICAgICAgICAgdGhpcy5iYXRjaFRpbWVvdXRUaW1lciA9IHsgaWQ6IG51bGwgfTtcclxuICAgICAgICAgICAgLy8gSG9sZHMgdGhlIGlkIG9mIHRoZSB0aW1lciBpbXBsZW1lbnRpbmcgdGhlIHNlbmQgdGltZW91dC5cclxuICAgICAgICAgICAgLy8gQ2FuIGJlIG51bGwuXHJcbiAgICAgICAgICAgIHRoaXMuc2VuZFRpbWVvdXRUaW1lciA9IHsgaWQ6IG51bGwgfTtcclxuICAgICAgICAgICAgLy8gTnVtYmVyIG9mIGxvZyBpdGVtcyB0aGF0IGhhcyBiZWVuIHNraXBwZWQgZHVlIHRvIGJhdGNoIGJ1ZmZlciBhdCBtYXggc2l6ZSxcclxuICAgICAgICAgICAgLy8gc2luY2UgYXBwZW5kZXIgY3JlYXRpb24gb3Igc2luY2UgY3JlYXRpb24gb2YgdGhlIGxhc3QgXCJza2lwcGVkXCIgd2FybmluZyBsb2cgZW50cnkuXHJcbiAgICAgICAgICAgIHRoaXMubmJyTG9nSXRlbXNTa2lwcGVkID0gMDtcclxuICAgICAgICAgICAgLy8gV2lsbCBiZSAwIGlmIG5vIGxvZyByZXF1ZXN0IGlzIG91dHN0YW5kaW5nIGF0IHRoZSBtb21lbnQuXHJcbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSB0aGUgbnVtYmVyIG9mIGxvZyBpdGVtcyBpbiB0aGUgb3V0c3RhbmRpbmcgcmVxdWVzdC5cclxuICAgICAgICAgICAgdGhpcy5uYnJMb2dJdGVtc0JlaW5nU2VudCA9IDA7XHJcbiAgICAgICAgICAgIHZhciBlbXB0eU5hbWVFcnJvck1lc3NhZ2UgPSBcIlRyeWluZyB0byBjcmVhdGUgYW4gYXBwZW5kZXIgd2l0aG91dCBhIG5hbWUgb3Igd2l0aCBhbiBlbXB0eSBuYW1lXCI7XHJcbiAgICAgICAgICAgIC8vIFRoaXMgZXZhbHVhdGVzIHRvIHRydWUgaWYgYXBwZW5kZXJOYW1lIGlzIGVpdGhlciBudWxsIG9yIHVuZGVmaW5lZCFcclxuICAgICAgICAgICAgLy8gRG8gbm90IGNoZWNrIGhlcmUgaWYgdGhlIG5hbWUgaXMgXCJcIiwgYmVjYXVzZSB0aGF0IHdvdWxkIHN0b3AgeW91IGNyZWF0aW5nIHRoZSBcclxuICAgICAgICAgICAgLy8gZGVmYXVsdCBhcHBlbmRlci5cclxuICAgICAgICAgICAgaWYgKGFwcGVuZGVyTmFtZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IGVtcHR5TmFtZUVycm9yTWVzc2FnZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoSkwuX2FwcGVuZGVyTmFtZXMuaW5kZXhPZihhcHBlbmRlck5hbWUpICE9IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBJZiB1c2VyIHBhc3NlZCBpbiBcIlwiLCB0aGF0IHdpbGwgbm93IGhhdmUgYmVlbiBwaWNrZWQgdXAgYXMgYSBkdXBsaWNhdGVcclxuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2UgZGVmYXVsdCBhcHBlbmRlciBhbHNvIHVzZXMgXCJcIi5cclxuICAgICAgICAgICAgICAgIGlmICghYXBwZW5kZXJOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZW1wdHlOYW1lRXJyb3JNZXNzYWdlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgXCJNdWx0aXBsZSBhcHBlbmRlcnMgdXNlIHRoZSBzYW1lIG5hbWUgXCIgKyBhcHBlbmRlck5hbWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgSkwuX2FwcGVuZGVyTmFtZXMucHVzaChhcHBlbmRlck5hbWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUuYWRkTG9nSXRlbXNUb0J1ZmZlciA9IGZ1bmN0aW9uIChsb2dJdGVtcykge1xyXG4gICAgICAgICAgICAvLyBJZiB0aGUgYmF0Y2ggYnVmZmVyIGhhcyByZWFjaGVkIGl0cyBtYXhpbXVtIGxpbWl0LCBcclxuICAgICAgICAgICAgLy8gc2tpcCB0aGUgbG9nIGl0ZW0gYW5kIGluY3JlYXNlIHRoZSBcInNraXBwZWQgaXRlbXNcIiBjb3VudGVyLlxyXG4gICAgICAgICAgICBpZiAodGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGggPj0gdGhpcy5tYXhCYXRjaFNpemUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubmJyTG9nSXRlbXNTa2lwcGVkICs9IGxvZ0l0ZW1zLmxlbmd0aDtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBJZiBtYXhNZXNzYWdlcyBpcyBub3QgbnVsbCBvciB1bmRlZmluZWQsIHRoZW4gZGVjcmVhc2UgaXQgYnkgdGhlIGJhdGNoIHNpemUuXHJcbiAgICAgICAgICAgIC8vIFRoaXMgY2FuIHJlc3VsdCBpbiBhIG5lZ2F0aXZlIG1heE1lc3NhZ2VzLlxyXG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgdW5kZWZpbmVkPT1udWxsICghKVxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgd2UgbWF5IGJlIHNlbmRpbmcgbW9yZSBtZXNzYWdlcyB0aGFuIHRoZSBtYXhNZXNzYWdlcyBsaW1pdCBhbGxvd3MsXHJcbiAgICAgICAgICAgIC8vIGlmIHdlIHN0b3JlZCB0cmFjZSBtZXNzYWdlcy4gUmF0aW9uYWxlIGlzIHRoZSBidWZmZXIgZm9yIHRyYWNlIG1lc3NhZ2VzIGlzIGxpbWl0ZWQsXHJcbiAgICAgICAgICAgIC8vIGFuZCBpZiB3ZSBjdXQgb2ZmIGF0IGV4YWN0bHkgbWF4TWVzc2FnZXMsIHdlJ2QgYWxzbyBsb29zZSB0aGUgaGlnaCBzZXZlcml0eSBtZXNzYWdlXHJcbiAgICAgICAgICAgIC8vIHRoYXQgY2F1c2VkIHRoZSB0cmFjZSBtZXNzYWdlcyB0byBiZSBzZW50ICh1bmxlc3Mgd2UgY2F0ZXIgZm9yIHRoaXMgc3BlY2lmaWNhbGx5LCB3aGljaFxyXG4gICAgICAgICAgICAvLyBpcyBtb3JlIGNvbXBsZXhpdHkpLlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgYXBwZW5kZXJzIHNlbmRpbmcgdGhlIHNhbWUgbWVzc2FnZSwgbWF4TWVzc2FnZSB3aWxsIGJlIGRlY3JlYXNlZFxyXG4gICAgICAgICAgICAvLyBieSBlYWNoIGFwcGVuZGVyIGZvciB0aGUgc2FtZSBtZXNzYWdlLiBUaGlzIGlzOlxyXG4gICAgICAgICAgICAvLyAxKSBvbmx5IGFwcGVuZGVycyBrbm93IHdoZXRoZXIgYSBtZXNzYWdlIHdpbGwgYWN0dWFsbHkgYmUgc2VudCAoYmFzZWQgb24gc3RvcmVJbkJ1ZmZlckxldmVsKSxcclxuICAgICAgICAgICAgLy8gICAgc28gdGhlIGxvZ2dlcnMgY291bGRuJ3QgZG8gdGhpcyB1cGRhdGU7XHJcbiAgICAgICAgICAgIC8vIDIpIGlmIHlvdSBoYXZlIG11bHRpcGxlIGFwcGVuZGVycyBoaXR0aW5nIHRoZSBzYW1lIHNlcnZlciwgdGhpcyBtYXkgYmUgd2hhdCB5b3Ugd2FudC5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gSW4gbW9zdCBjYXNlcyB0aGVyZSBpcyBvbmx5IDEgYXBwZW5kZXIsIHNvIHRoaXMgdGhlbiBkb2Vzbid0IG1hdHRlci5cclxuICAgICAgICAgICAgaWYgKCEoSkwubWF4TWVzc2FnZXMgPT0gbnVsbCkpIHtcclxuICAgICAgICAgICAgICAgIGlmIChKTC5tYXhNZXNzYWdlcyA8IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBKTC5tYXhNZXNzYWdlcyAtPSBsb2dJdGVtcy5sZW5ndGg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5iYXRjaEJ1ZmZlciA9IHRoaXMuYmF0Y2hCdWZmZXIuY29uY2F0KGxvZ0l0ZW1zKTtcclxuICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgYnVmZmVyLCBzZXQgdGhlIHRpbWVyXHJcbiAgICAgICAgICAgIC8vIHRvIGVuc3VyZSBpdCB3aWxsIGJlIHNlbnQgd2l0aGluIHRoZSB0aW1lb3V0IHBlcmlvZC5cclxuICAgICAgICAgICAgLy8gSWYgaXQgaXMgbm90IHRoZSBmaXJzdCBpdGVtLCBsZWF2ZSB0aGUgdGltZXIgYWxvbmUgc28gdG8gbm90IHRvIFxyXG4gICAgICAgICAgICAvLyBpbmNyZWFzZSB0aGUgdGltZW91dCBmb3IgdGhlIGZpcnN0IGl0ZW0uXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIFRvIGRldGVybWluZSBpZiB0aGlzIGlzIHRoZSBmaXJzdCBpdGVtLCBsb29rIGF0IHRoZSB0aW1lciB2YXJpYWJsZS5cclxuICAgICAgICAgICAgLy8gRG8gbm90IGxvb2sgYXQgdGhlIGJ1ZmZlciBsZW5ndGgsIGJlY2F1c2Ugd2UgYWxzbyBwdXQgaXRlbXMgaW4gdGhlIGJ1ZmZlclxyXG4gICAgICAgICAgICAvLyB2aWEgYSBjb25jYXQgKGJ5cGFzc2luZyB0aGlzIGZ1bmN0aW9uKS5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gVGhlIHNldFRpbWVyIG1ldGhvZCBvbmx5IHNldHMgdGhlIHRpbWVyIGlmIGl0IGlzIG5vdCBhbHJlYWR5IHJ1bm5pbmcuXHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcclxuICAgICAgICAgICAgc2V0VGltZXIodGhpcy5iYXRjaFRpbWVvdXRUaW1lciwgdGhpcy5iYXRjaFRpbWVvdXQsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHRoYXQuc2VuZEJhdGNoLmNhbGwodGhhdCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgO1xyXG4gICAgICAgIEFwcGVuZGVyLnByb3RvdHlwZS5iYXRjaEJ1ZmZlckhhc092ZXJkdWVNZXNzYWdlcyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmJhdGNoQnVmZmVyLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZUFnZU1zID0gSkwuX2dldFRpbWUoKSAtIHRoaXMuYmF0Y2hCdWZmZXJbaV0udDtcclxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlQWdlTXMgPiB0aGlzLmJhdGNoVGltZW91dCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiBubyBtb3JlIG1lc3NhZ2Ugd2lsbCBldmVyIGJlIGFkZGVkIHRvIHRoZSBiYXRjaCBidWZmZXIsXHJcbiAgICAgICAgLy8gYnV0IHRoZSBiYXRjaCBidWZmZXIgaGFzIG1lc3NhZ2VzIG5vdyAtIHNvIGlmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHRvIG1ha2UgdXAgYSBiYXRjaCxcclxuICAgICAgICAvLyBhbmQgdGhlcmUgaXMgbm8gYmF0Y2ggdGltZW91dCwgdGhlbiB0aGV5IHdpbGwgbmV2ZXIgYmUgc2VudC4gVGhpcyBpcyBlc3BlY2lhbGx5IGltcG9ydGFudCBpZiBcclxuICAgICAgICAvLyBtYXhNZXNzYWdlcyB3YXMgcmVhY2hlZCB3aGlsZSBqc25sb2cuanMgd2FzIHJldHJ5aW5nIHNlbmRpbmcgbWVzc2FnZXMgdG8gdGhlIHNlcnZlci5cclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUuYmF0Y2hCdWZmZXJIYXNTdHJhbmRlZE1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAoIShKTC5tYXhNZXNzYWdlcyA9PSBudWxsKSkgJiYgKEpMLm1heE1lc3NhZ2VzIDwgMSkgJiYgKHRoaXMuYmF0Y2hCdWZmZXIubGVuZ3RoID4gMCk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUuc2VuZEJhdGNoSWZDb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKCh0aGlzLmJhdGNoQnVmZmVyLmxlbmd0aCA+PSB0aGlzLmJhdGNoU2l6ZSkgfHxcclxuICAgICAgICAgICAgICAgIHRoaXMuYmF0Y2hCdWZmZXJIYXNPdmVyZHVlTWVzc2FnZXMoKSB8fFxyXG4gICAgICAgICAgICAgICAgdGhpcy5iYXRjaEJ1ZmZlckhhc1N0cmFuZGVkTWVzc2FnZSgpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRCYXRjaCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICBBcHBlbmRlci5wcm90b3R5cGUub25TZW5kaW5nRW5kZWQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGNsZWFyVGltZXIodGhpcy5zZW5kVGltZW91dFRpbWVyKTtcclxuICAgICAgICAgICAgdGhpcy5uYnJMb2dJdGVtc0JlaW5nU2VudCA9IDA7XHJcbiAgICAgICAgICAgIHRoaXMuc2VuZEJhdGNoSWZDb21wbGV0ZSgpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLnNldE9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJsZXZlbFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiaXBSZWdleFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwidXNlckFnZW50UmVnZXhcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImRpc2FsbG93XCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJzZW5kV2l0aEJ1ZmZlckxldmVsXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJzdG9yZUluQnVmZmVyTGV2ZWxcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImJ1ZmZlclNpemVcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcImJhdGNoU2l6ZVwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwibWF4QmF0Y2hTaXplXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJiYXRjaFRpbWVvdXRcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcInNlbmRUaW1lb3V0XCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5idWZmZXJTaXplIDwgdGhpcy5idWZmZXIubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5sZW5ndGggPSB0aGlzLmJ1ZmZlclNpemU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMubWF4QmF0Y2hTaXplIDwgdGhpcy5iYXRjaFNpemUpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBKTC5FeGNlcHRpb24oe1xyXG4gICAgICAgICAgICAgICAgICAgIFwibWVzc2FnZVwiOiBcIm1heEJhdGNoU2l6ZSBjYW5ub3QgYmUgc21hbGxlciB0aGFuIGJhdGNoU2l6ZVwiLFxyXG4gICAgICAgICAgICAgICAgICAgIFwibWF4QmF0Y2hTaXplXCI6IHRoaXMubWF4QmF0Y2hTaXplLFxyXG4gICAgICAgICAgICAgICAgICAgIFwiYmF0Y2hTaXplXCI6IHRoaXMuYmF0Y2hTaXplXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKlxyXG4gICAgICAgIENhbGxlZCBieSBhIGxvZ2dlciB0byBsb2cgYSBsb2cgaXRlbS5cclxuICAgICAgICBJZiBpbiByZXNwb25zZSB0byB0aGlzIGNhbGwgb25lIG9yIG1vcmUgbG9nIGl0ZW1zIG5lZWQgdG8gYmUgcHJvY2Vzc2VkXHJcbiAgICAgICAgKGVnLiwgc2VudCB0byB0aGUgc2VydmVyKSwgdGhpcyBtZXRob2QgY2FsbHMgdGhpcy5zZW5kTG9nSXRlbXNcclxuICAgICAgICB3aXRoIGFuIGFycmF5IHdpdGggYWxsIGl0ZW1zIHRvIGJlIHByb2Nlc3NlZC5cclxuXHJcbiAgICAgICAgTm90ZSB0aGF0IHRoZSBuYW1lIGFuZCBwYXJhbWV0ZXJzIG9mIHRoaXMgZnVuY3Rpb24gbXVzdCBtYXRjaCB0aG9zZSBvZiB0aGUgbG9nIGZ1bmN0aW9uIG9mXHJcbiAgICAgICAgYSBXaW5zdG9uIHRyYW5zcG9ydCBvYmplY3QsIHNvIHRoYXQgdXNlcnMgY2FuIHVzZSB0aGVzZSB0cmFuc3BvcnRzIGFzIGFwcGVuZGVycy5cclxuICAgICAgICBUaGF0IGlzIHdoeSB0aGVyZSBhcmUgbWFueSBwYXJhbWV0ZXJzIHRoYXQgYXJlIG5vdCBhY3R1YWxseSB1c2VkIGJ5IHRoaXMgZnVuY3Rpb24uXHJcblxyXG4gICAgICAgIGxldmVsIC0gc3RyaW5nIHdpdGggdGhlIGxldmVsIChcInRyYWNlXCIsIFwiZGVidWdcIiwgZXRjLikgT25seSB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBtc2cgLSBodW1hbiByZWFkYWJsZSBtZXNzYWdlLiBVbmRlZmluZWQgaWYgdGhlIGxvZyBpdGVtIGlzIGFuIG9iamVjdC4gT25seSB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBtZXRhIC0gbG9nIG9iamVjdC4gQWx3YXlzIGRlZmluZWQsIGJlY2F1c2UgYXQgbGVhc3QgaXQgY29udGFpbnMgdGhlIGxvZ2dlciBuYW1lLiBPbmx5IHVzZWQgYnkgV2luc3RvbiB0cmFuc3BvcnRzLlxyXG4gICAgICAgIGNhbGxiYWNrIC0gZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgbG9nIGl0ZW0gaGFzIGJlZW4gbG9nZ2VkLiBPbmx5IHVzZWQgYnkgV2luc3RvbiB0cmFuc3BvcnRzLlxyXG4gICAgICAgIGxldmVsTmJyIC0gbGV2ZWwgYXMgYSBudW1iZXIuIE5vdCB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICBtZXNzYWdlIC0gbG9nIGl0ZW0uIElmIHRoZSB1c2VyIGxvZ2dlZCBhbiBvYmplY3QsIHRoaXMgaXMgdGhlIEpTT04gc3RyaW5nLiAgTm90IHVzZWQgYnkgV2luc3RvbiB0cmFuc3BvcnRzLlxyXG4gICAgICAgIGxvZ2dlck5hbWU6IG5hbWUgb2YgdGhlIGxvZ2dlci4gIE5vdCB1c2VkIGJ5IFdpbnN0b24gdHJhbnNwb3J0cy5cclxuICAgICAgICAqL1xyXG4gICAgICAgIEFwcGVuZGVyLnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiAobGV2ZWwsIG1zZywgbWV0YSwgY2FsbGJhY2ssIGxldmVsTmJyLCBtZXNzYWdlLCBsb2dnZXJOYW1lKSB7XHJcbiAgICAgICAgICAgIHZhciBsb2dJdGVtO1xyXG4gICAgICAgICAgICBpZiAoIWFsbG93KHRoaXMpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCFhbGxvd01lc3NhZ2UodGhpcywgbWVzc2FnZSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAobGV2ZWxOYnIgPCB0aGlzLnN0b3JlSW5CdWZmZXJMZXZlbCkge1xyXG4gICAgICAgICAgICAgICAgLy8gSWdub3JlIHRoZSBsb2cgaXRlbSBjb21wbGV0ZWx5XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbG9nSXRlbSA9IG5ld0xvZ0l0ZW0obGV2ZWxOYnIsIG1lc3NhZ2UsIGxvZ2dlck5hbWUpO1xyXG4gICAgICAgICAgICBpZiAobGV2ZWxOYnIgPCB0aGlzLmxldmVsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTdG9yZSBpbiB0aGUgaG9sZCBidWZmZXIuIERvIG5vdCBzZW5kLlxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuYnVmZmVyU2l6ZSA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5wdXNoKGxvZ0l0ZW0pO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGV4Y2VlZGVkIG1heCBidWZmZXIgc2l6ZSwgcmVtb3ZlIG9sZGVzdCBpdGVtXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYnVmZmVyLmxlbmd0aCA+IHRoaXMuYnVmZmVyU2l6ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5zaGlmdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBXYW50IHRvIHNlbmQgdGhlIGl0ZW1cclxuICAgICAgICAgICAgdGhpcy5hZGRMb2dJdGVtc1RvQnVmZmVyKFtsb2dJdGVtXSk7XHJcbiAgICAgICAgICAgIGlmIChsZXZlbE5iciA+PSB0aGlzLnNlbmRXaXRoQnVmZmVyTGV2ZWwpIHtcclxuICAgICAgICAgICAgICAgIC8vIFdhbnQgdG8gc2VuZCB0aGUgY29udGVudHMgb2YgdGhlIGJ1ZmZlci5cclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyBTZW5kIHRoZSBidWZmZXIgQUZURVIgc2VuZGluZyB0aGUgaGlnaCBwcmlvcml0eSBpdGVtLlxyXG4gICAgICAgICAgICAgICAgLy8gSWYgeW91IHdlcmUgdG8gc2VuZCB0aGUgaGlnaCBwcmlvcml0eSBpdGVtIGFmdGVyIHRoZSBidWZmZXIsXHJcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSdyZSBjbG9zZSB0byBtYXhNZXNzYWdlcyBvciBtYXhCYXRjaFNpemUsXHJcbiAgICAgICAgICAgICAgICAvLyB0aGVuIHRoZSB0cmFjZSBtZXNzYWdlcyBpbiB0aGUgYnVmZmVyIGNvdWxkIGNyb3dkIG91dCB0aGUgYWN0dWFsIGhpZ2ggcHJpb3JpdHkgaXRlbS5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmJ1ZmZlci5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZExvZ0l0ZW1zVG9CdWZmZXIodGhpcy5idWZmZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZmVyLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5zZW5kQmF0Y2hJZkNvbXBsZXRlKCk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICA7XHJcbiAgICAgICAgLy8gUHJvY2Vzc2VzIHRoZSBiYXRjaCBidWZmZXJcclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIE1ha2UgdGhpcyBwdWJsaWMsIHNvIGl0IGNhbiBiZSBjYWxsZWQgZnJvbSBvdXRzaWRlIHRoZSBsaWJyYXJ5LFxyXG4gICAgICAgIC8vIHdoZW4gdGhlIHBhZ2UgaXMgdW5sb2FkZWQuXHJcbiAgICAgICAgQXBwZW5kZXIucHJvdG90eXBlLnNlbmRCYXRjaCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgLy8gRG8gbm90IGNsZWFyIHRoZSBiYXRjaCB0aW1lciBpZiB5b3UgZG9uJ3QgZ28gYWhlYWQgaGVyZSBiZWNhdXNlXHJcbiAgICAgICAgICAgIC8vIGEgc2VuZCBpcyBhbHJlYWR5IGluIHByb2dyZXNzLiBPdGhlcndpc2UgdGhlIG1lc3NhZ2VzIHRoYXQgd2VyZSBzdG9wcGVkIGZyb20gZ29pbmcgb3V0XHJcbiAgICAgICAgICAgIC8vIG1heSBnZXQgaWdub3JlZCBiZWNhdXNlIHRoZSBiYXRjaCB0aW1lciBuZXZlciB3ZW50IG9mZi5cclxuICAgICAgICAgICAgaWYgKHRoaXMubmJyTG9nSXRlbXNCZWluZ1NlbnQgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2xlYXJUaW1lcih0aGlzLmJhdGNoVGltZW91dFRpbWVyKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuYmF0Y2hCdWZmZXIubGVuZ3RoID09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBEZWNpZGVkIGF0IHRoaXMgcG9pbnQgdG8gc2VuZCBjb250ZW50cyBvZiB0aGUgYnVmZmVyXHJcbiAgICAgICAgICAgIHRoaXMubmJyTG9nSXRlbXNCZWluZ1NlbnQgPSB0aGlzLmJhdGNoQnVmZmVyLmxlbmd0aDtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xyXG4gICAgICAgICAgICBzZXRUaW1lcih0aGlzLnNlbmRUaW1lb3V0VGltZXIsIHRoaXMuc2VuZFRpbWVvdXQsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHRoYXQub25TZW5kaW5nRW5kZWQuY2FsbCh0aGF0KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHRoaXMuc2VuZExvZ0l0ZW1zKHRoaXMuYmF0Y2hCdWZmZXIsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIC8vIExvZyBlbnRyaWVzIGhhdmUgYmVlbiBzdWNjZXNzZnVsbHkgc2VudCB0byBzZXJ2ZXJcclxuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgZmlyc3QgKG5ickxvZ0l0ZW1zQmVpbmdTZW50KSBpdGVtcyBpbiB0aGUgYmF0Y2ggYnVmZmVyLCBiZWNhdXNlIHRoZXkgYXJlIHRoZSBvbmVzXHJcbiAgICAgICAgICAgICAgICAvLyB0aGF0IHdlcmUgc2VudC5cclxuICAgICAgICAgICAgICAgIHRoYXQuYmF0Y2hCdWZmZXIuc3BsaWNlKDAsIHRoYXQubmJyTG9nSXRlbXNCZWluZ1NlbnQpO1xyXG4gICAgICAgICAgICAgICAgLy8gSWYgaXRlbXMgaGFkIHRvIGJlIHNraXBwZWQsIGFkZCBhIFdBUk4gbWVzc2FnZVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoYXQubmJyTG9nSXRlbXNTa2lwcGVkID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuYmF0Y2hCdWZmZXIucHVzaChuZXdMb2dJdGVtKGdldFdhcm5MZXZlbCgpLCBcIkxvc3QgXCIgKyB0aGF0Lm5ickxvZ0l0ZW1zU2tpcHBlZCArIFwiIG1lc3NhZ2VzLiBFaXRoZXIgY29ubmVjdGlvbiB3aXRoIHRoZSBzZXJ2ZXIgd2FzIGRvd24gb3IgbG9nZ2luZyB3YXMgZGlzYWJsZWQgdmlhIHRoZSBlbmFibGVkIG9wdGlvbi4gUmVkdWNlIGxvc3QgbWVzc2FnZXMgYnkgaW5jcmVhc2luZyB0aGUgYWpheEFwcGVuZGVyIG9wdGlvbiBtYXhCYXRjaFNpemUuXCIsIHRoYXQuYXBwZW5kZXJOYW1lKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5uYnJMb2dJdGVtc1NraXBwZWQgPSAwO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhhdC5vblNlbmRpbmdFbmRlZC5jYWxsKHRoYXQpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJldHVybiBBcHBlbmRlcjtcclxuICAgIH0oKSk7XHJcbiAgICBKTC5BcHBlbmRlciA9IEFwcGVuZGVyO1xyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICB2YXIgQWpheEFwcGVuZGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xyXG4gICAgICAgIF9fZXh0ZW5kcyhBamF4QXBwZW5kZXIsIF9zdXBlcik7XHJcbiAgICAgICAgZnVuY3Rpb24gQWpheEFwcGVuZGVyKGFwcGVuZGVyTmFtZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgYXBwZW5kZXJOYW1lLCBBamF4QXBwZW5kZXIucHJvdG90eXBlLnNlbmRMb2dJdGVtc0FqYXgpIHx8IHRoaXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIEFqYXhBcHBlbmRlci5wcm90b3R5cGUuc2V0T3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcInVybFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiYmVmb3JlU2VuZFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5zZXRPcHRpb25zLmNhbGwodGhpcywgb3B0aW9ucyk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgQWpheEFwcGVuZGVyLnByb3RvdHlwZS5zZW5kTG9nSXRlbXNBamF4ID0gZnVuY3Rpb24gKGxvZ0l0ZW1zLCBzdWNjZXNzQ2FsbGJhY2spIHtcclxuICAgICAgICAgICAgLy8gSlNPTi5zdHJpbmdpZnkgaXMgb25seSBzdXBwb3J0ZWQgb24gSUU4K1xyXG4gICAgICAgICAgICAvLyBVc2UgdHJ5LWNhdGNoIGluIGNhc2Ugd2UgZ2V0IGFuIGV4Y2VwdGlvbiBoZXJlLlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBUaGUgXCJyXCIgZmllbGQgaXMgbm93IG9ic29sZXRlLiBXaGVuIHdyaXRpbmcgYSBzZXJ2ZXIgc2lkZSBjb21wb25lbnQsIFxyXG4gICAgICAgICAgICAvLyByZWFkIHRoZSBIVFRQIGhlYWRlciBcIkpTTkxvZy1SZXF1ZXN0SWRcIlxyXG4gICAgICAgICAgICAvLyB0byBnZXQgdGhlIHJlcXVlc3QgaWQuXHJcbiAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgIC8vIFRoZSAuTmV0IHNlcnZlciBzaWRlIGNvbXBvbmVudFxyXG4gICAgICAgICAgICAvLyBub3cgdXNlcyB0aGUgSlNOTG9nLVJlcXVlc3RJZCBIVFRQIEhlYWRlciwgYmVjYXVzZSB0aGlzIGFsbG93cyBpdCB0b1xyXG4gICAgICAgICAgICAvLyBkZXRlY3Qgd2hldGhlciB0aGUgaW5jb21pbmcgcmVxdWVzdCBoYXMgYSByZXF1ZXN0IGlkLlxyXG4gICAgICAgICAgICAvLyBJZiB0aGUgcmVxdWVzdCBpZCB3ZXJlIGluIHRoZSBqc29uIHBheWxvYWQsIGl0IHdvdWxkIGhhdmUgdG8gcmVhZCB0aGUganNvblxyXG4gICAgICAgICAgICAvLyBmcm9tIHRoZSBzdHJlYW0sIGludGVyZmVyaW5nIHdpdGggbm9ybWFsIG5vbi1sb2dnaW5nIHJlcXVlc3RzLlxyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBUbyBzZWUgd2hhdCBjaGFyYWN0ZXJzIHlvdSBjYW4gdXNlIGluIHRoZSBIVFRQIGhlYWRlciwgdmlzaXQ6XHJcbiAgICAgICAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzU2MTM4MS9jdXN0b20taHR0cC1oZWFkZXJzLW5hbWluZy1jb252ZW50aW9ucy8zNTYxMzk5IzM1NjEzOTlcclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gSXQgbmVlZHMgdGhpcyBhYmlsaXR5LCBzbyB1c2VycyBvZiBOTG9nIGNhbiBzZXQgYSByZXF1ZXN0SWQgdmFyaWFibGUgaW4gTkxvZ1xyXG4gICAgICAgICAgICAvLyBiZWZvcmUgdGhlIHNlcnZlciBzaWRlIGNvbXBvbmVudCB0cmllcyB0byBsb2cgdGhlIGNsaWVudCBzaWRlIGxvZyBtZXNzYWdlXHJcbiAgICAgICAgICAgIC8vIHRocm91Z2ggYW4gTkxvZyBsb2dnZXIuXHJcbiAgICAgICAgICAgIC8vIFVubGlrZSBMb2c0TmV0LCBOTG9nIGRvZXNuJ3QgYWxsb3cgeW91IHRvIHJlZ2lzdGVyIGFuIG9iamVjdCB3aG9zZSBUb1N0cmluZygpXHJcbiAgICAgICAgICAgIC8vIGlzIG9ubHkgY2FsbGVkIHdoZW4gaXQgdHJpZXMgdG8gbG9nIHNvbWV0aGluZywgc28gdGhlIHJlcXVlc3RJZCBoYXMgdG8gYmUgXHJcbiAgICAgICAgICAgIC8vIGRldGVybWluZWQgcmlnaHQgYXQgdGhlIHN0YXJ0IG9mIHJlcXVlc3QgcHJvY2Vzc2luZy5cclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBzZW5kIGxvZ3MsIGlmIEpMLmVuYWJsZWQgaXMgc2V0IHRvIGZhbHNlLlxyXG4gICAgICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBjYWxsIHN1Y2Nlc3NDYWxsYmFjayBoZXJlLiBBZnRlciBlYWNoIHRpbWVvdXQsIGpzbmxvZyB3aWxsIHJldHJ5IHNlbmRpbmcgdGhlIG1lc3NhZ2UuXHJcbiAgICAgICAgICAgICAgICAvLyBJZiBqc25sb2cgZ2V0cyByZS1lbmFibGVkLCBpdCB3aWxsIHRoZW4gbG9nIHRoZSBudW1iZXIgb2YgbWVzc2FnZXMgbG9nZ2VkLlxyXG4gICAgICAgICAgICAgICAgLy8gSWYgaXQgZG9lc24ndCBnZXQgcmUtZW5hYmxlZCwgYW1vdW50IG9mIGNwdSBjeWNsZXMgd2FzdGVkIGlzIG1pbmltYWwuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWFsbG93KHRoaXMpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8gSWYgYSByZXF1ZXN0IGlzIGluIHByb2dyZXNzLCBhYm9ydCBpdC5cclxuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSwgaXQgbWF5IGNhbGwgdGhlIHN1Y2Nlc3MgY2FsbGJhY2ssIHdoaWNoIHdpbGwgYmUgdmVyeSBjb25mdXNpbmcuXHJcbiAgICAgICAgICAgICAgICAvLyBJdCBtYXkgYWxzbyBzdG9wIHRoZSBpbmZsaWdodCByZXF1ZXN0IGZyb20gcmVzdWx0aW5nIGluIGEgbG9nIGF0IHRoZSBzZXJ2ZXIuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy54aHIgJiYgKHRoaXMueGhyLnJlYWR5U3RhdGUgIT0gMCkgJiYgKHRoaXMueGhyLnJlYWR5U3RhdGUgIT0gNCkpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnhoci5hYm9ydCgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8gQmVjYXVzZSBhIHJlYWN0LW5hdGl2ZSBYTUxIdHRwUmVxdWVzdCBjYW5ub3QgYmUgcmV1c2VkIGl0IG5lZWRzIHRvIGJlIHJlY3JlYXRlZCB3aXRoIGVhY2ggcmVxdWVzdFxyXG4gICAgICAgICAgICAgICAgdGhpcy54aHIgPSBKTC5fY3JlYXRlWE1MSHR0cFJlcXVlc3QoKTtcclxuICAgICAgICAgICAgICAgIC8vIE9ubHkgZGV0ZXJtaW5lIHRoZSB1cmwgcmlnaHQgYmVmb3JlIHlvdSBzZW5kIGEgbG9nIHJlcXVlc3QuXHJcbiAgICAgICAgICAgICAgICAvLyBEbyBub3Qgc2V0IHRoZSB1cmwgd2hlbiBjb25zdHJ1Y3RpbmcgdGhlIGFwcGVuZGVyLlxyXG4gICAgICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSB0aGUgc2VydmVyIHNpZGUgY29tcG9uZW50IHNldHMgZGVmYXVsdEFqYXhVcmxcclxuICAgICAgICAgICAgICAgIC8vIGluIGEgY2FsbCB0byBzZXRPcHRpb25zLCBBRlRFUiB0aGUgSkwgb2JqZWN0IGFuZCB0aGUgZGVmYXVsdCBhcHBlbmRlclxyXG4gICAgICAgICAgICAgICAgLy8gaGF2ZSBiZWVuIGNyZWF0ZWQuIFxyXG4gICAgICAgICAgICAgICAgdmFyIGFqYXhVcmwgPSBcIi9qc25sb2cubG9nZ2VyXCI7XHJcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGV2YWx1YXRlcyB0byB0cnVlIGlmIGRlZmF1bHRBamF4VXJsIGlzIG51bGwgb3IgdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICBpZiAoIShKTC5kZWZhdWx0QWpheFVybCA9PSBudWxsKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGFqYXhVcmwgPSBKTC5kZWZhdWx0QWpheFVybDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnVybCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGFqYXhVcmwgPSB0aGlzLnVybDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRoaXMueGhyLm9wZW4oJ1BPU1QnLCBhamF4VXJsKTtcclxuICAgICAgICAgICAgICAgIHRoaXMueGhyLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnhoci5zZXRSZXF1ZXN0SGVhZGVyKCdKU05Mb2ctUmVxdWVzdElkJywgSkwucmVxdWVzdElkKTtcclxuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcclxuICAgICAgICAgICAgICAgIHRoaXMueGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBPbiBtb3N0IGJyb3dzZXJzLCBpZiB0aGUgcmVxdWVzdCBmYWlscyAoZWcuIGludGVybmV0IGlzIGdvbmUpLFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIGl0IHdpbGwgc2V0IHhoci5yZWFkeVN0YXRlID09IDQgYW5kIHhoci5zdGF0dXMgIT0gMjAwICgwIGlmIHJlcXVlc3QgY291bGQgbm90IGJlIHNlbnQpIGltbWVkaWF0ZWx5LlxyXG4gICAgICAgICAgICAgICAgICAgIC8vIEhvd2V2ZXIsIEVkZ2UgYW5kIElFIHdpbGwgbm90IGNoYW5nZSB0aGUgcmVhZHlTdGF0ZSBhdCBhbGwgaWYgdGhlIGludGVybmV0IGdvZXMgYXdheSB3aGlsZSB3YWl0aW5nXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yIGEgcmVzcG9uc2UuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gU29tZSBzZXJ2ZXJzIHdpbGwgcmV0dXJuIGEgMjA0IChzdWNjZXNzLCBubyBjb250ZW50KSB3aGVuIHRoZSBKU05Mb2cgZW5kcG9pbnRcclxuICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm5zIHRoZSBlbXB0eSByZXNwb25zZS4gU28gY2hlY2sgb24gYW55IGNvZGUgaW4gdGhlIDIuLiByYW5nZSwgbm90IGp1c3QgMjAwLlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICgodGhhdC54aHIucmVhZHlTdGF0ZSA9PSA0KSAmJiAodGhhdC54aHIuc3RhdHVzID49IDIwMCAmJiB0aGF0Lnhoci5zdGF0dXMgPCAzMDApKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjaygpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICB2YXIganNvbiA9IHtcclxuICAgICAgICAgICAgICAgICAgICByOiBKTC5yZXF1ZXN0SWQsXHJcbiAgICAgICAgICAgICAgICAgICAgbGc6IGxvZ0l0ZW1zXHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgLy8gY2FsbCBiZWZvcmVTZW5kIGNhbGxiYWNrXHJcbiAgICAgICAgICAgICAgICAvLyBmaXJzdCB0cnkgdGhlIGNhbGxiYWNrIG9uIHRoZSBhcHBlbmRlclxyXG4gICAgICAgICAgICAgICAgLy8gdGhlbiB0aGUgZ2xvYmFsIGRlZmF1bHRCZWZvcmVTZW5kIGNhbGxiYWNrXHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuYmVmb3JlU2VuZCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYmVmb3JlU2VuZC5jYWxsKHRoaXMsIHRoaXMueGhyLCBqc29uKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBKTC5kZWZhdWx0QmVmb3JlU2VuZCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgICAgICAgIEpMLmRlZmF1bHRCZWZvcmVTZW5kLmNhbGwodGhpcywgdGhpcy54aHIsIGpzb24pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdmFyIGZpbmFsbXNnID0gSlNPTi5zdHJpbmdpZnkoanNvbik7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnhoci5zZW5kKGZpbmFsbXNnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXRjaCAoZSkgeyB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICByZXR1cm4gQWpheEFwcGVuZGVyO1xyXG4gICAgfShBcHBlbmRlcikpO1xyXG4gICAgSkwuQWpheEFwcGVuZGVyID0gQWpheEFwcGVuZGVyO1xyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICB2YXIgQ29uc29sZUFwcGVuZGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xyXG4gICAgICAgIF9fZXh0ZW5kcyhDb25zb2xlQXBwZW5kZXIsIF9zdXBlcik7XHJcbiAgICAgICAgZnVuY3Rpb24gQ29uc29sZUFwcGVuZGVyKGFwcGVuZGVyTmFtZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgYXBwZW5kZXJOYW1lLCBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLnNlbmRMb2dJdGVtc0NvbnNvbGUpIHx8IHRoaXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIENvbnNvbGVBcHBlbmRlci5wcm90b3R5cGUuY2xvZyA9IGZ1bmN0aW9uIChsb2dFbnRyeSkge1xyXG4gICAgICAgICAgICBKTC5fY29uc29sZS5sb2cobG9nRW50cnkpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgQ29uc29sZUFwcGVuZGVyLnByb3RvdHlwZS5jZXJyb3IgPSBmdW5jdGlvbiAobG9nRW50cnkpIHtcclxuICAgICAgICAgICAgaWYgKEpMLl9jb25zb2xlLmVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICBKTC5fY29uc29sZS5lcnJvcihsb2dFbnRyeSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNsb2cobG9nRW50cnkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLmN3YXJuID0gZnVuY3Rpb24gKGxvZ0VudHJ5KSB7XHJcbiAgICAgICAgICAgIGlmIChKTC5fY29uc29sZS53YXJuKSB7XHJcbiAgICAgICAgICAgICAgICBKTC5fY29uc29sZS53YXJuKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2xvZyhsb2dFbnRyeSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICAgIENvbnNvbGVBcHBlbmRlci5wcm90b3R5cGUuY2luZm8gPSBmdW5jdGlvbiAobG9nRW50cnkpIHtcclxuICAgICAgICAgICAgaWYgKEpMLl9jb25zb2xlLmluZm8pIHtcclxuICAgICAgICAgICAgICAgIEpMLl9jb25zb2xlLmluZm8obG9nRW50cnkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbG9nKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgLy8gSUUxMSBoYXMgYSBjb25zb2xlLmRlYnVnIGZ1bmN0aW9uLiBCdXQgaXRzIGNvbnNvbGUgZG9lc24ndCBoYXZlIFxyXG4gICAgICAgIC8vIHRoZSBvcHRpb24gdG8gc2hvdy9oaWRlIGRlYnVnIG1lc3NhZ2VzICh0aGUgc2FtZSB3YXkgQ2hyb21lIGFuZCBGRiBkbyksXHJcbiAgICAgICAgLy8gZXZlbiB0aG91Z2ggaXQgZG9lcyBoYXZlIHN1Y2ggYnV0dG9ucyBmb3IgRXJyb3IsIFdhcm4sIEluZm8uXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBGb3Igbm93LCB0aGlzIG1lYW5zIHRoYXQgZGVidWcgbWVzc2FnZXMgY2FuIG5vdCBiZSBoaWRkZW4gb24gSUUuXHJcbiAgICAgICAgLy8gTGl2ZSB3aXRoIHRoaXMsIHNlZWluZyB0aGF0IGl0IHdvcmtzIGZpbmUgb24gRkYgYW5kIENocm9tZSwgd2hpY2hcclxuICAgICAgICAvLyB3aWxsIGJlIG11Y2ggbW9yZSBwb3B1bGFyIHdpdGggZGV2ZWxvcGVycy5cclxuICAgICAgICBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLmNkZWJ1ZyA9IGZ1bmN0aW9uIChsb2dFbnRyeSkge1xyXG4gICAgICAgICAgICBpZiAoSkwuX2NvbnNvbGUuZGVidWcpIHtcclxuICAgICAgICAgICAgICAgIEpMLl9jb25zb2xlLmRlYnVnKGxvZ0VudHJ5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY2luZm8obG9nRW50cnkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICBDb25zb2xlQXBwZW5kZXIucHJvdG90eXBlLnNlbmRMb2dJdGVtc0NvbnNvbGUgPSBmdW5jdGlvbiAobG9nSXRlbXMsIHN1Y2Nlc3NDYWxsYmFjaykge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgLy8gRG8gbm90IHNlbmQgbG9ncywgaWYgSkwuZW5hYmxlZCBpcyBzZXQgdG8gZmFsc2VcclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyBEbyBub3QgY2FsbCBzdWNjZXNzQ2FsbGJhY2sgaGVyZS4gQWZ0ZXIgZWFjaCB0aW1lb3V0LCBqc25sb2cgd2lsbCByZXRyeSBzZW5kaW5nIHRoZSBtZXNzYWdlLlxyXG4gICAgICAgICAgICAgICAgLy8gSWYganNubG9nIGdldHMgcmUtZW5hYmxlZCwgaXQgd2lsbCB0aGVuIGxvZyB0aGUgbnVtYmVyIG9mIG1lc3NhZ2VzIGxvZ2dlZC5cclxuICAgICAgICAgICAgICAgIC8vIElmIGl0IGRvZXNuJ3QgZ2V0IHJlLWVuYWJsZWQsIGFtb3VudCBvZiBjcHUgY3ljbGVzIHdhc3RlZCBpcyBtaW5pbWFsLlxyXG4gICAgICAgICAgICAgICAgaWYgKCFhbGxvdyh0aGlzKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICghSkwuX2NvbnNvbGUpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgaTtcclxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsb2dJdGVtcy5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBsaSA9IGxvZ0l0ZW1zW2ldO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBtc2cgPSBsaS5uICsgXCI6IFwiICsgbGkubTtcclxuICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGxvZyB0aGUgdGltZXN0YW1wIGlmIHdlJ3JlIG9uIHRoZSBzZXJ2ZXJcclxuICAgICAgICAgICAgICAgICAgICAvLyAod2luZG93IGlzIHVuZGVmaW5lZCkuIE9uIHRoZSBicm93c2VyLCB0aGUgdXNlclxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHNlZXMgdGhlIGxvZyBlbnRyeSBwcm9iYWJseSBpbW1lZGlhdGVseSwgc28gaW4gdGhhdCBjYXNlXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHRpbWVzdGFtcCBpcyBjbHV0dGVyLlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBuZXcgRGF0ZShsaS50KSArIFwiIHwgXCIgKyBtc2c7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChsaS5sIDw9IEpMLmdldERlYnVnTGV2ZWwoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNkZWJ1Zyhtc2cpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChsaS5sIDw9IEpMLmdldEluZm9MZXZlbCgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2luZm8obXNnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAobGkubCA8PSBKTC5nZXRXYXJuTGV2ZWwoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN3YXJuKG1zZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNlcnJvcihtc2cpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjaygpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmV0dXJuIENvbnNvbGVBcHBlbmRlcjtcclxuICAgIH0oQXBwZW5kZXIpKTtcclxuICAgIEpMLkNvbnNvbGVBcHBlbmRlciA9IENvbnNvbGVBcHBlbmRlcjtcclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICB2YXIgTG9nZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIExvZ2dlcihsb2dnZXJOYW1lKSB7XHJcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyTmFtZSA9IGxvZ2dlck5hbWU7XHJcbiAgICAgICAgICAgIC8vIENyZWF0ZSBzZWVuUmV4ZXMsIG90aGVyd2lzZSB0aGlzIGxvZ2dlciB3aWxsIHVzZSB0aGUgc2VlblJleGVzXHJcbiAgICAgICAgICAgIC8vIG9mIGl0cyBwYXJlbnQgdmlhIHRoZSBwcm90b3R5cGUgY2hhaW4uXHJcbiAgICAgICAgICAgIHRoaXMuc2VlblJlZ2V4ZXMgPSBbXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5zZXRPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwibGV2ZWxcIiwgb3B0aW9ucywgdGhpcyk7XHJcbiAgICAgICAgICAgIGNvcHlQcm9wZXJ0eShcInVzZXJBZ2VudFJlZ2V4XCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJkaXNhbGxvd1wiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiaXBSZWdleFwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgY29weVByb3BlcnR5KFwiYXBwZW5kZXJzXCIsIG9wdGlvbnMsIHRoaXMpO1xyXG4gICAgICAgICAgICBjb3B5UHJvcGVydHkoXCJvbmNlT25seVwiLCBvcHRpb25zLCB0aGlzKTtcclxuICAgICAgICAgICAgLy8gUmVzZXQgc2VlblJlZ2V4ZXMsIGluIGNhc2Ugb25jZU9ubHkgaGFzIGJlZW4gY2hhbmdlZC5cclxuICAgICAgICAgICAgdGhpcy5zZWVuUmVnZXhlcyA9IFtdO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8vIFR1cm5zIGFuIGV4Y2VwdGlvbiBpbnRvIGFuIG9iamVjdCB0aGF0IGNhbiBiZSBzZW50IHRvIHRoZSBzZXJ2ZXIuXHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5idWlsZEV4Y2VwdGlvbk9iamVjdCA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgIHZhciBleGNPYmplY3QgPSB7fTtcclxuICAgICAgICAgICAgaWYgKGUuc3RhY2spIHtcclxuICAgICAgICAgICAgICAgIGV4Y09iamVjdC5zdGFjayA9IGUuc3RhY2s7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBleGNPYmplY3QuZSA9IGU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGUubWVzc2FnZSkge1xyXG4gICAgICAgICAgICAgICAgZXhjT2JqZWN0Lm1lc3NhZ2UgPSBlLm1lc3NhZ2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGUubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgZXhjT2JqZWN0Lm5hbWUgPSBlLm5hbWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGUuZGF0YSkge1xyXG4gICAgICAgICAgICAgICAgZXhjT2JqZWN0LmRhdGEgPSBlLmRhdGE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGUuaW5uZXIpIHtcclxuICAgICAgICAgICAgICAgIGV4Y09iamVjdC5pbm5lciA9IHRoaXMuYnVpbGRFeGNlcHRpb25PYmplY3QoZS5pbm5lcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGV4Y09iamVjdDtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8vIExvZ3MgYSBsb2cgaXRlbS5cclxuICAgICAgICAvLyBQYXJhbWV0ZXIgZSBjb250YWlucyBhbiBleGNlcHRpb24gKG9yIG51bGwgb3IgdW5kZWZpbmVkKS5cclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIFJlYXNvbiB0aGF0IHByb2Nlc3NpbmcgZXhjZXB0aW9ucyBpcyBkb25lIGF0IHRoaXMgbG93IGxldmVsIGlzIHRoYXRcclxuICAgICAgICAvLyAxKSBubyBuZWVkIHRvIHNwZW5kIHRoZSBjcHUgY3ljbGVzIGlmIHRoZSBsb2dnZXIgaXMgc3dpdGNoZWQgb2ZmXHJcbiAgICAgICAgLy8gMikgZmF0YWxFeGNlcHRpb24gdGFrZXMgYm90aCBhIGxvZ09iamVjdCBhbmQgYW4gZXhjZXB0aW9uLCBhbmQgdGhlIGxvZ09iamVjdFxyXG4gICAgICAgIC8vICAgIG1heSBiZSBhIGZ1bmN0aW9uIHRoYXQgc2hvdWxkIG9ubHkgYmUgZXhlY3V0ZWQgaWYgdGhlIGxvZ2dlciBpcyBzd2l0Y2hlZCBvbi5cclxuICAgICAgICAvL1xyXG4gICAgICAgIC8vIElmIGFuIGV4Y2VwdGlvbiBpcyBwYXNzZWQgaW4sIHRoZSBjb250ZW50cyBvZiBsb2dPYmplY3QgaXMgYXR0YWNoZWQgdG8gdGhlIGV4Y2VwdGlvblxyXG4gICAgICAgIC8vIG9iamVjdCBpbiBhIG5ldyBwcm9wZXJ0eSBsb2dEYXRhLlxyXG4gICAgICAgIC8vIFRoZSByZXN1bHRpbmcgZXhjZXB0aW9uIG9iamVjdCBpcyB0aGFuIHdvcmtlZCBpbnRvIGEgbWVzc2FnZSB0byB0aGUgc2VydmVyLlxyXG4gICAgICAgIC8vXHJcbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgbm8gZXhjZXB0aW9uLCBsb2dPYmplY3QgaXRzZWxmIGlzIHdvcmtlZCBpbnRvIHRoZSBtZXNzYWdlIHRvIHRoZSBzZXJ2ZXIuXHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiAobGV2ZWwsIGxvZ09iamVjdCwgZSkge1xyXG4gICAgICAgICAgICB2YXIgaSA9IDA7XHJcbiAgICAgICAgICAgIHZhciBjb21wb3NpdGVNZXNzYWdlO1xyXG4gICAgICAgICAgICB2YXIgZXhjT2JqZWN0O1xyXG4gICAgICAgICAgICAvLyBJZiB3ZSBjYW4ndCBmaW5kIGFueSBhcHBlbmRlcnMsIGRvIG5vdGhpbmdcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmFwcGVuZGVycykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCgobGV2ZWwgPj0gdGhpcy5sZXZlbCkpICYmIGFsbG93KHRoaXMpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGV4Y09iamVjdCA9IHRoaXMuYnVpbGRFeGNlcHRpb25PYmplY3QoZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgZXhjT2JqZWN0LmxvZ0RhdGEgPSBzdHJpbmdpZnlMb2dPYmplY3RGdW5jdGlvbihsb2dPYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZXhjT2JqZWN0ID0gbG9nT2JqZWN0O1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgY29tcG9zaXRlTWVzc2FnZSA9IHN0cmluZ2lmeUxvZ09iamVjdChleGNPYmplY3QpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFsbG93TWVzc2FnZSh0aGlzLCBjb21wb3NpdGVNZXNzYWdlLmZpbmFsU3RyaW5nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIFNlZSB3aGV0aGVyIG1lc3NhZ2UgaXMgYSBkdXBsaWNhdGVcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5vbmNlT25seSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gdGhpcy5vbmNlT25seS5sZW5ndGggLSAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaSA+PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3IFJlZ0V4cCh0aGlzLm9uY2VPbmx5W2ldKS50ZXN0KGNvbXBvc2l0ZU1lc3NhZ2UuZmluYWxTdHJpbmcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VlblJlZ2V4ZXNbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VlblJlZ2V4ZXNbaV0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaS0tO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgbWVzc2FnZSB0byBhbGwgYXBwZW5kZXJzXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHRoZXNlIGFwcGVuZGVycyBjb3VsZCBiZSBXaW5zdG9uIHRyYW5zcG9ydHNcclxuICAgICAgICAgICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZmxhdGlyb24vd2luc3RvblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvc2l0ZU1lc3NhZ2UubWV0YSA9IGNvbXBvc2l0ZU1lc3NhZ2UubWV0YSB8fCB7fTtcclxuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgaWYgdGhlIHVzZXIgaXMgbG9nZ2luZyBhbiBvYmplY3QsIGNvbXBvc2l0ZU1lc3NhZ2UubWV0YSB3aWxsIGhvbGQgYSByZWZlcmVuY2UgdG8gdGhhdCBvYmplY3QuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gRG8gbm90IGFkZCBmaWVsZHMgdG8gY29tcG9zaXRlTWVzc2FnZS5tZXRhLCBvdGhlcndpc2UgdGhlIHVzZXIncyBvYmplY3Qgd2lsbCBnZXQgdGhhdCBmaWVsZCBvdXQgb2YgdGhlIGJsdWUuXHJcbiAgICAgICAgICAgICAgICAgICAgaSA9IHRoaXMuYXBwZW5kZXJzLmxlbmd0aCAtIDE7XHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkgPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFwcGVuZGVyc1tpXS5sb2cobGV2ZWxUb1N0cmluZyhsZXZlbCksIGNvbXBvc2l0ZU1lc3NhZ2UubXNnLCBjb21wb3NpdGVNZXNzYWdlLm1ldGEsIGZ1bmN0aW9uICgpIHsgfSwgbGV2ZWwsIGNvbXBvc2l0ZU1lc3NhZ2UuZmluYWxTdHJpbmcsIHRoaXMubG9nZ2VyTmFtZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfTtcclxuICAgICAgICBMb2dnZXIucHJvdG90eXBlLnRyYWNlID0gZnVuY3Rpb24gKGxvZ09iamVjdCkgeyByZXR1cm4gdGhpcy5sb2coZ2V0VHJhY2VMZXZlbCgpLCBsb2dPYmplY3QpOyB9O1xyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiAobG9nT2JqZWN0KSB7IHJldHVybiB0aGlzLmxvZyhnZXREZWJ1Z0xldmVsKCksIGxvZ09iamVjdCk7IH07XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5pbmZvID0gZnVuY3Rpb24gKGxvZ09iamVjdCkgeyByZXR1cm4gdGhpcy5sb2coZ2V0SW5mb0xldmVsKCksIGxvZ09iamVjdCk7IH07XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS53YXJuID0gZnVuY3Rpb24gKGxvZ09iamVjdCkgeyByZXR1cm4gdGhpcy5sb2coZ2V0V2FybkxldmVsKCksIGxvZ09iamVjdCk7IH07XHJcbiAgICAgICAgTG9nZ2VyLnByb3RvdHlwZS5lcnJvciA9IGZ1bmN0aW9uIChsb2dPYmplY3QpIHsgcmV0dXJuIHRoaXMubG9nKGdldEVycm9yTGV2ZWwoKSwgbG9nT2JqZWN0KTsgfTtcclxuICAgICAgICBMb2dnZXIucHJvdG90eXBlLmZhdGFsID0gZnVuY3Rpb24gKGxvZ09iamVjdCkgeyByZXR1cm4gdGhpcy5sb2coZ2V0RmF0YWxMZXZlbCgpLCBsb2dPYmplY3QpOyB9O1xyXG4gICAgICAgIExvZ2dlci5wcm90b3R5cGUuZmF0YWxFeGNlcHRpb24gPSBmdW5jdGlvbiAobG9nT2JqZWN0LCBlKSB7IHJldHVybiB0aGlzLmxvZyhnZXRGYXRhbExldmVsKCksIGxvZ09iamVjdCwgZSk7IH07XHJcbiAgICAgICAgcmV0dXJuIExvZ2dlcjtcclxuICAgIH0oKSk7XHJcbiAgICBKTC5Mb2dnZXIgPSBMb2dnZXI7XHJcbiAgICBmdW5jdGlvbiBjcmVhdGVBamF4QXBwZW5kZXIoYXBwZW5kZXJOYW1lKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBBamF4QXBwZW5kZXIoYXBwZW5kZXJOYW1lKTtcclxuICAgIH1cclxuICAgIEpMLmNyZWF0ZUFqYXhBcHBlbmRlciA9IGNyZWF0ZUFqYXhBcHBlbmRlcjtcclxuICAgIGZ1bmN0aW9uIGNyZWF0ZUNvbnNvbGVBcHBlbmRlcihhcHBlbmRlck5hbWUpIHtcclxuICAgICAgICByZXR1cm4gbmV3IENvbnNvbGVBcHBlbmRlcihhcHBlbmRlck5hbWUpO1xyXG4gICAgfVxyXG4gICAgSkwuY3JlYXRlQ29uc29sZUFwcGVuZGVyID0gY3JlYXRlQ29uc29sZUFwcGVuZGVyO1xyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIC8vIEluIHRoZSBicm93c2VyLCB0aGUgZGVmYXVsdCBhcHBlbmRlciBpcyB0aGUgQWpheEFwcGVuZGVyLlxyXG4gICAgLy8gVW5kZXIgbm9kZWpzICh3aGVyZSB0aGVyZSBpcyBubyBcIndpbmRvd1wiKSwgdXNlIHRoZSBDb25zb2xlQXBwZW5kZXIgaW5zdGVhZC5cclxuICAgIC8vIFxyXG4gICAgLy8gRG8gTk9UIGNyZWF0ZSBhbiBBamF4QXBwZW5kZXIgb2JqZWN0IGlmIHlvdSBhcmUgbm90IG9uIGEgYnJvd3NlciAodGhhdCBpcywgd2luZG93IGlzIG5vdCBkZWZpbmVkKS5cclxuICAgIC8vIFRoYXQgd291bGQgdHJ5IHRvIGNyZWF0ZSBhbiBYbWxIdHRwUmVxdWVzdCBvYmplY3QsIHdoaWNoIHdpbGwgY3Jhc2ggb3V0c2lkZSBhIGJyb3dzZXIuXHJcbiAgICB2YXIgZGVmYXVsdEFwcGVuZGVyO1xyXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgZGVmYXVsdEFwcGVuZGVyID0gbmV3IEFqYXhBcHBlbmRlcihcIlwiKTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGRlZmF1bHRBcHBlbmRlciA9IG5ldyBDb25zb2xlQXBwZW5kZXIoXCJcIik7XHJcbiAgICB9XHJcbiAgICAvLyBDcmVhdGUgcm9vdCBsb2dnZXJcclxuICAgIC8vXHJcbiAgICAvLyBOb3RlIHRoYXQgdGhpcyBpcyB0aGUgcGFyZW50IG9mIGFsbCBvdGhlciBsb2dnZXJzLlxyXG4gICAgLy8gTG9nZ2VyIFwieFwiIHdpbGwgYmUgc3RvcmVkIGF0XHJcbiAgICAvLyBKTC5fXy54XHJcbiAgICAvLyBMb2dnZXIgXCJ4LnlcIiBhdFxyXG4gICAgLy8gSkwuX18ueC55XHJcbiAgICBKTC5fXyA9IG5ldyBKTC5Mb2dnZXIoXCJcIik7XHJcbiAgICBKTC5fXy5zZXRPcHRpb25zKHtcclxuICAgICAgICBsZXZlbDogSkwuZ2V0RGVidWdMZXZlbCgpLFxyXG4gICAgICAgIGFwcGVuZGVyczogW2RlZmF1bHRBcHBlbmRlcl1cclxuICAgIH0pO1xyXG59KShKTCB8fCAoSkwgPSB7fSkpO1xyXG5pZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAvLyBBbGxvd3MgU3lzdGVtSnMgdG8gaW1wb3J0IGpzbmxvZy5qcy4gU2VlXHJcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbXBlcmRlY2svanNubG9nLmpzL2lzc3Vlcy81NlxyXG4gICAgZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcclxuICAgIGV4cG9ydHMuSkwgPSBKTDtcclxufVxyXG4vLyBTdXBwb3J0IEFNRCBtb2R1bGUgZm9ybWF0XHJcbnZhciBkZWZpbmU7XHJcbmlmICh0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xyXG4gICAgZGVmaW5lKCdqc25sb2cnLCBbXSwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiBKTDtcclxuICAgIH0pO1xyXG59XHJcbi8vIElmIHRoZSBfX2pzbmxvZ19jb25maWd1cmUgZ2xvYmFsIGZ1bmN0aW9uIGhhcyBiZWVuXHJcbi8vIGNyZWF0ZWQsIGNhbGwgaXQgbm93LiBUaGlzIGFsbG93cyB5b3UgdG8gY3JlYXRlIGEgZ2xvYmFsIGZ1bmN0aW9uXHJcbi8vIHNldHRpbmcgbG9nZ2VyIG9wdGlvbnMgZXRjLiBpbmxpbmUgaW4gdGhlIHBhZ2UgYmVmb3JlIGpzbmxvZy5qc1xyXG4vLyBoYXMgYmVlbiBsb2FkZWQuXHJcbmlmICh0eXBlb2YgX19qc25sb2dfY29uZmlndXJlID09ICdmdW5jdGlvbicpIHtcclxuICAgIF9fanNubG9nX2NvbmZpZ3VyZShKTCk7XHJcbn1cclxuLy8gQ3JlYXRlIG9uZXJyb3IgaGFuZGxlciB0byBsb2cgdW5jYXVnaHQgZXhjZXB0aW9ucyB0byB0aGUgc2VydmVyIHNpZGUgbG9nLCBidXQgb25seSBpZiB0aGVyZSBcclxuLy8gaXMgbm8gc3VjaCBoYW5kbGVyIGFscmVhZHkuXHJcbi8vIE11c3QgdXNlIFwidHlwZW9mIHdpbmRvd1wiIGhlcmUsIGJlY2F1c2UgaW4gTm9kZUpzLCB3aW5kb3cgaXMgbm90IGRlZmluZWQgYXQgYWxsLCBzbyBjYW5ub3QgcmVmZXIgdG8gd2luZG93IGluIGFueSB3YXkuXHJcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiAhd2luZG93Lm9uZXJyb3IpIHtcclxuICAgIHdpbmRvdy5vbmVycm9yID0gZnVuY3Rpb24gKGVycm9yTXNnLCB1cmwsIGxpbmVOdW1iZXIsIGNvbHVtbiwgZXJyb3JPYmopIHtcclxuICAgICAgICAvLyBTZW5kIG9iamVjdCB3aXRoIGFsbCBkYXRhIHRvIHNlcnZlciBzaWRlIGxvZywgdXNpbmcgc2V2ZXJpdHkgZmF0YWwsIFxyXG4gICAgICAgIC8vIGZyb20gbG9nZ2VyIFwib25lcnJvckxvZ2dlclwiXHJcbiAgICAgICAgLy9cclxuICAgICAgICAvLyBVc2UgZXJyb3JNc2cubWVzc2FnZSBpZiBhdmFpbGFibGUsIHNvIEFuZ3VsYXIgNCB0ZW1wbGF0ZSBlcnJvcnMgd2lsbCBiZSBsb2dnZWQuXHJcbiAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tcGVyZGVjay9qc25sb2cuanMvcHVsbC82OFxyXG4gICAgICAgIEpMKFwib25lcnJvckxvZ2dlclwiKS5mYXRhbEV4Y2VwdGlvbih7XHJcbiAgICAgICAgICAgIFwibXNnXCI6IFwiVW5jYXVnaHQgRXhjZXB0aW9uXCIsXHJcbiAgICAgICAgICAgIFwiZXJyb3JNc2dcIjogZXJyb3JNc2cgPyAoZXJyb3JNc2cubWVzc2FnZSB8fCBlcnJvck1zZykgOiAnJyxcclxuICAgICAgICAgICAgXCJ1cmxcIjogdXJsLFxyXG4gICAgICAgICAgICBcImxpbmUgbnVtYmVyXCI6IGxpbmVOdW1iZXIsIFwiY29sdW1uXCI6IGNvbHVtblxyXG4gICAgICAgIH0sIGVycm9yT2JqKTtcclxuICAgICAgICAvLyBUZWxsIGJyb3dzZXIgdG8gcnVuIGl0cyBvd24gZXJyb3IgaGFuZGxlciBhcyB3ZWxsICAgXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfTtcclxufVxyXG4vLyBEZWFsIHdpdGggdW5oYW5kbGVkIGV4Y2VwdGlvbnMgdGhyb3duIGluIHByb21pc2VzXHJcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiAhd2luZG93Lm9udW5oYW5kbGVkcmVqZWN0aW9uKSB7XHJcbiAgICB3aW5kb3cub251bmhhbmRsZWRyZWplY3Rpb24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICAvLyBTZW5kIG9iamVjdCB3aXRoIGFsbCBkYXRhIHRvIHNlcnZlciBzaWRlIGxvZywgdXNpbmcgc2V2ZXJpdHkgZmF0YWwsIFxyXG4gICAgICAgIC8vIGZyb20gbG9nZ2VyIFwib25lcnJvckxvZ2dlclwiLlxyXG4gICAgICAgIC8vIE5lZWQgdG8gY2hlY2sgYm90aCBldmVudC5yZWFzb24ubWVzc2FnZSBhbmQgZXZlbnQubWVzc2FnZSxcclxuICAgICAgICAvLyBiZWNhdXNlIFN5c3RlbUpzIHdyYXBzIGV4Y2VwdGlvbnMgYW5kIHRocm93cyBhIG5ldyBvYmplY3Qgd2hpY2ggZG9lc24ndCBoYXZlIGEgcmVhc29uIHByb3BlcnR5LlxyXG4gICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vc3lzdGVtanMvc3lzdGVtanMvaXNzdWVzLzEzMDlcclxuICAgICAgICBKTChcIm9uZXJyb3JMb2dnZXJcIikuZmF0YWxFeGNlcHRpb24oe1xyXG4gICAgICAgICAgICBcIm1zZ1wiOiBcInVuaGFuZGxlZHJlamVjdGlvblwiLFxyXG4gICAgICAgICAgICBcImVycm9yTXNnXCI6IGV2ZW50LnJlYXNvbiA/IGV2ZW50LnJlYXNvbi5tZXNzYWdlIDogZXZlbnQubWVzc2FnZSB8fCBudWxsXHJcbiAgICAgICAgfSwgZXZlbnQucmVhc29uKTtcclxuICAgIH07XHJcbn1cclxuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEBwYXJhbSB0eXBlTWFwIFtPYmplY3RdIE1hcCBvZiBNSU1FIHR5cGUgLT4gQXJyYXlbZXh0ZW5zaW9uc11cbiAqIEBwYXJhbSAuLi5cbiAqL1xuZnVuY3Rpb24gTWltZSgpIHtcbiAgdGhpcy5fdHlwZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB0aGlzLl9leHRlbnNpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIHRoaXMuZGVmaW5lKGFyZ3VtZW50c1tpXSk7XG4gIH1cblxuICB0aGlzLmRlZmluZSA9IHRoaXMuZGVmaW5lLmJpbmQodGhpcyk7XG4gIHRoaXMuZ2V0VHlwZSA9IHRoaXMuZ2V0VHlwZS5iaW5kKHRoaXMpO1xuICB0aGlzLmdldEV4dGVuc2lvbiA9IHRoaXMuZ2V0RXh0ZW5zaW9uLmJpbmQodGhpcyk7XG59XG5cbi8qKlxuICogRGVmaW5lIG1pbWV0eXBlIC0+IGV4dGVuc2lvbiBtYXBwaW5ncy4gIEVhY2gga2V5IGlzIGEgbWltZS10eXBlIHRoYXQgbWFwc1xuICogdG8gYW4gYXJyYXkgb2YgZXh0ZW5zaW9ucyBhc3NvY2lhdGVkIHdpdGggdGhlIHR5cGUuICBUaGUgZmlyc3QgZXh0ZW5zaW9uIGlzXG4gKiB1c2VkIGFzIHRoZSBkZWZhdWx0IGV4dGVuc2lvbiBmb3IgdGhlIHR5cGUuXG4gKlxuICogZS5nLiBtaW1lLmRlZmluZSh7J2F1ZGlvL29nZycsIFsnb2dhJywgJ29nZycsICdzcHgnXX0pO1xuICpcbiAqIElmIGEgdHlwZSBkZWNsYXJlcyBhbiBleHRlbnNpb24gdGhhdCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQsIGFuIGVycm9yIHdpbGxcbiAqIGJlIHRocm93bi4gIFRvIHN1cHByZXNzIHRoaXMgZXJyb3IgYW5kIGZvcmNlIHRoZSBleHRlbnNpb24gdG8gYmUgYXNzb2NpYXRlZFxuICogd2l0aCB0aGUgbmV3IHR5cGUsIHBhc3MgYGZvcmNlYD10cnVlLiAgQWx0ZXJuYXRpdmVseSwgeW91IG1heSBwcmVmaXggdGhlXG4gKiBleHRlbnNpb24gd2l0aCBcIipcIiB0byBtYXAgdGhlIHR5cGUgdG8gZXh0ZW5zaW9uLCB3aXRob3V0IG1hcHBpbmcgdGhlXG4gKiBleHRlbnNpb24gdG8gdGhlIHR5cGUuXG4gKlxuICogZS5nLiBtaW1lLmRlZmluZSh7J2F1ZGlvL3dhdicsIFsnd2F2J119LCB7J2F1ZGlvL3gtd2F2JywgWycqd2F2J119KTtcbiAqXG4gKlxuICogQHBhcmFtIG1hcCAoT2JqZWN0KSB0eXBlIGRlZmluaXRpb25zXG4gKiBAcGFyYW0gZm9yY2UgKEJvb2xlYW4pIGlmIHRydWUsIGZvcmNlIG92ZXJyaWRpbmcgb2YgZXhpc3RpbmcgZGVmaW5pdGlvbnNcbiAqL1xuTWltZS5wcm90b3R5cGUuZGVmaW5lID0gZnVuY3Rpb24odHlwZU1hcCwgZm9yY2UpIHtcbiAgZm9yIChsZXQgdHlwZSBpbiB0eXBlTWFwKSB7XG4gICAgbGV0IGV4dGVuc2lvbnMgPSB0eXBlTWFwW3R5cGVdLm1hcChmdW5jdGlvbih0KSB7XG4gICAgICByZXR1cm4gdC50b0xvd2VyQ2FzZSgpO1xuICAgIH0pO1xuICAgIHR5cGUgPSB0eXBlLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4dGVuc2lvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGV4dCA9IGV4dGVuc2lvbnNbaV07XG5cbiAgICAgIC8vICcqJyBwcmVmaXggPSBub3QgdGhlIHByZWZlcnJlZCB0eXBlIGZvciB0aGlzIGV4dGVuc2lvbi4gIFNvIGZpeHVwIHRoZVxuICAgICAgLy8gZXh0ZW5zaW9uLCBhbmQgc2tpcCBpdC5cbiAgICAgIGlmIChleHRbMF0gPT09ICcqJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFmb3JjZSAmJiAoZXh0IGluIHRoaXMuX3R5cGVzKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ0F0dGVtcHQgdG8gY2hhbmdlIG1hcHBpbmcgZm9yIFwiJyArIGV4dCArXG4gICAgICAgICAgJ1wiIGV4dGVuc2lvbiBmcm9tIFwiJyArIHRoaXMuX3R5cGVzW2V4dF0gKyAnXCIgdG8gXCInICsgdHlwZSArXG4gICAgICAgICAgJ1wiLiBQYXNzIGBmb3JjZT10cnVlYCB0byBhbGxvdyB0aGlzLCBvdGhlcndpc2UgcmVtb3ZlIFwiJyArIGV4dCArXG4gICAgICAgICAgJ1wiIGZyb20gdGhlIGxpc3Qgb2YgZXh0ZW5zaW9ucyBmb3IgXCInICsgdHlwZSArICdcIi4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3R5cGVzW2V4dF0gPSB0eXBlO1xuICAgIH1cblxuICAgIC8vIFVzZSBmaXJzdCBleHRlbnNpb24gYXMgZGVmYXVsdFxuICAgIGlmIChmb3JjZSB8fCAhdGhpcy5fZXh0ZW5zaW9uc1t0eXBlXSkge1xuICAgICAgY29uc3QgZXh0ID0gZXh0ZW5zaW9uc1swXTtcbiAgICAgIHRoaXMuX2V4dGVuc2lvbnNbdHlwZV0gPSAoZXh0WzBdICE9PSAnKicpID8gZXh0IDogZXh0LnN1YnN0cigxKTtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogTG9va3VwIGEgbWltZSB0eXBlIGJhc2VkIG9uIGV4dGVuc2lvblxuICovXG5NaW1lLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24ocGF0aCkge1xuICBwYXRoID0gU3RyaW5nKHBhdGgpO1xuICBsZXQgbGFzdCA9IHBhdGgucmVwbGFjZSgvXi4qWy9cXFxcXS8sICcnKS50b0xvd2VyQ2FzZSgpO1xuICBsZXQgZXh0ID0gbGFzdC5yZXBsYWNlKC9eLipcXC4vLCAnJykudG9Mb3dlckNhc2UoKTtcblxuICBsZXQgaGFzUGF0aCA9IGxhc3QubGVuZ3RoIDwgcGF0aC5sZW5ndGg7XG4gIGxldCBoYXNEb3QgPSBleHQubGVuZ3RoIDwgbGFzdC5sZW5ndGggLSAxO1xuXG4gIHJldHVybiAoaGFzRG90IHx8ICFoYXNQYXRoKSAmJiB0aGlzLl90eXBlc1tleHRdIHx8IG51bGw7XG59O1xuXG4vKipcbiAqIFJldHVybiBmaWxlIGV4dGVuc2lvbiBhc3NvY2lhdGVkIHdpdGggYSBtaW1lIHR5cGVcbiAqL1xuTWltZS5wcm90b3R5cGUuZ2V0RXh0ZW5zaW9uID0gZnVuY3Rpb24odHlwZSkge1xuICB0eXBlID0gL15cXHMqKFteO1xcc10qKS8udGVzdCh0eXBlKSAmJiBSZWdFeHAuJDE7XG4gIHJldHVybiB0eXBlICYmIHRoaXMuX2V4dGVuc2lvbnNbdHlwZS50b0xvd2VyQ2FzZSgpXSB8fCBudWxsO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNaW1lO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5sZXQgTWltZSA9IHJlcXVpcmUoJy4vTWltZScpO1xubW9kdWxlLmV4cG9ydHMgPSBuZXcgTWltZShyZXF1aXJlKCcuL3R5cGVzL3N0YW5kYXJkJykpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XCJhcHBsaWNhdGlvbi9hbmRyZXctaW5zZXRcIjpbXCJlelwiXSxcImFwcGxpY2F0aW9uL2FwcGxpeHdhcmVcIjpbXCJhd1wiXSxcImFwcGxpY2F0aW9uL2F0b20reG1sXCI6W1wiYXRvbVwiXSxcImFwcGxpY2F0aW9uL2F0b21jYXQreG1sXCI6W1wiYXRvbWNhdFwiXSxcImFwcGxpY2F0aW9uL2F0b21kZWxldGVkK3htbFwiOltcImF0b21kZWxldGVkXCJdLFwiYXBwbGljYXRpb24vYXRvbXN2Yyt4bWxcIjpbXCJhdG9tc3ZjXCJdLFwiYXBwbGljYXRpb24vYXRzYy1kd2QreG1sXCI6W1wiZHdkXCJdLFwiYXBwbGljYXRpb24vYXRzYy1oZWxkK3htbFwiOltcImhlbGRcIl0sXCJhcHBsaWNhdGlvbi9hdHNjLXJzYXQreG1sXCI6W1wicnNhdFwiXSxcImFwcGxpY2F0aW9uL2Jkb2NcIjpbXCJiZG9jXCJdLFwiYXBwbGljYXRpb24vY2FsZW5kYXIreG1sXCI6W1wieGNzXCJdLFwiYXBwbGljYXRpb24vY2N4bWwreG1sXCI6W1wiY2N4bWxcIl0sXCJhcHBsaWNhdGlvbi9jZGZ4K3htbFwiOltcImNkZnhcIl0sXCJhcHBsaWNhdGlvbi9jZG1pLWNhcGFiaWxpdHlcIjpbXCJjZG1pYVwiXSxcImFwcGxpY2F0aW9uL2NkbWktY29udGFpbmVyXCI6W1wiY2RtaWNcIl0sXCJhcHBsaWNhdGlvbi9jZG1pLWRvbWFpblwiOltcImNkbWlkXCJdLFwiYXBwbGljYXRpb24vY2RtaS1vYmplY3RcIjpbXCJjZG1pb1wiXSxcImFwcGxpY2F0aW9uL2NkbWktcXVldWVcIjpbXCJjZG1pcVwiXSxcImFwcGxpY2F0aW9uL2N1LXNlZW1lXCI6W1wiY3VcIl0sXCJhcHBsaWNhdGlvbi9kYXNoK3htbFwiOltcIm1wZFwiXSxcImFwcGxpY2F0aW9uL2Rhdm1vdW50K3htbFwiOltcImRhdm1vdW50XCJdLFwiYXBwbGljYXRpb24vZG9jYm9vayt4bWxcIjpbXCJkYmtcIl0sXCJhcHBsaWNhdGlvbi9kc3NjK2RlclwiOltcImRzc2NcIl0sXCJhcHBsaWNhdGlvbi9kc3NjK3htbFwiOltcInhkc3NjXCJdLFwiYXBwbGljYXRpb24vZWNtYXNjcmlwdFwiOltcImVzXCIsXCJlY21hXCJdLFwiYXBwbGljYXRpb24vZW1tYSt4bWxcIjpbXCJlbW1hXCJdLFwiYXBwbGljYXRpb24vZW1vdGlvbm1sK3htbFwiOltcImVtb3Rpb25tbFwiXSxcImFwcGxpY2F0aW9uL2VwdWIremlwXCI6W1wiZXB1YlwiXSxcImFwcGxpY2F0aW9uL2V4aVwiOltcImV4aVwiXSxcImFwcGxpY2F0aW9uL2V4cHJlc3NcIjpbXCJleHBcIl0sXCJhcHBsaWNhdGlvbi9mZHQreG1sXCI6W1wiZmR0XCJdLFwiYXBwbGljYXRpb24vZm9udC10ZHBmclwiOltcInBmclwiXSxcImFwcGxpY2F0aW9uL2dlbytqc29uXCI6W1wiZ2VvanNvblwiXSxcImFwcGxpY2F0aW9uL2dtbCt4bWxcIjpbXCJnbWxcIl0sXCJhcHBsaWNhdGlvbi9ncHgreG1sXCI6W1wiZ3B4XCJdLFwiYXBwbGljYXRpb24vZ3hmXCI6W1wiZ3hmXCJdLFwiYXBwbGljYXRpb24vZ3ppcFwiOltcImd6XCJdLFwiYXBwbGljYXRpb24vaGpzb25cIjpbXCJoanNvblwiXSxcImFwcGxpY2F0aW9uL2h5cGVyc3R1ZGlvXCI6W1wic3RrXCJdLFwiYXBwbGljYXRpb24vaW5rbWwreG1sXCI6W1wiaW5rXCIsXCJpbmttbFwiXSxcImFwcGxpY2F0aW9uL2lwZml4XCI6W1wiaXBmaXhcIl0sXCJhcHBsaWNhdGlvbi9pdHMreG1sXCI6W1wiaXRzXCJdLFwiYXBwbGljYXRpb24vamF2YS1hcmNoaXZlXCI6W1wiamFyXCIsXCJ3YXJcIixcImVhclwiXSxcImFwcGxpY2F0aW9uL2phdmEtc2VyaWFsaXplZC1vYmplY3RcIjpbXCJzZXJcIl0sXCJhcHBsaWNhdGlvbi9qYXZhLXZtXCI6W1wiY2xhc3NcIl0sXCJhcHBsaWNhdGlvbi9qYXZhc2NyaXB0XCI6W1wianNcIixcIm1qc1wiXSxcImFwcGxpY2F0aW9uL2pzb25cIjpbXCJqc29uXCIsXCJtYXBcIl0sXCJhcHBsaWNhdGlvbi9qc29uNVwiOltcImpzb241XCJdLFwiYXBwbGljYXRpb24vanNvbm1sK2pzb25cIjpbXCJqc29ubWxcIl0sXCJhcHBsaWNhdGlvbi9sZCtqc29uXCI6W1wianNvbmxkXCJdLFwiYXBwbGljYXRpb24vbGdyK3htbFwiOltcImxnclwiXSxcImFwcGxpY2F0aW9uL2xvc3QreG1sXCI6W1wibG9zdHhtbFwiXSxcImFwcGxpY2F0aW9uL21hYy1iaW5oZXg0MFwiOltcImhxeFwiXSxcImFwcGxpY2F0aW9uL21hYy1jb21wYWN0cHJvXCI6W1wiY3B0XCJdLFwiYXBwbGljYXRpb24vbWFkcyt4bWxcIjpbXCJtYWRzXCJdLFwiYXBwbGljYXRpb24vbWFuaWZlc3QranNvblwiOltcIndlYm1hbmlmZXN0XCJdLFwiYXBwbGljYXRpb24vbWFyY1wiOltcIm1yY1wiXSxcImFwcGxpY2F0aW9uL21hcmN4bWwreG1sXCI6W1wibXJjeFwiXSxcImFwcGxpY2F0aW9uL21hdGhlbWF0aWNhXCI6W1wibWFcIixcIm5iXCIsXCJtYlwiXSxcImFwcGxpY2F0aW9uL21hdGhtbCt4bWxcIjpbXCJtYXRobWxcIl0sXCJhcHBsaWNhdGlvbi9tYm94XCI6W1wibWJveFwiXSxcImFwcGxpY2F0aW9uL21lZGlhc2VydmVyY29udHJvbCt4bWxcIjpbXCJtc2NtbFwiXSxcImFwcGxpY2F0aW9uL21ldGFsaW5rK3htbFwiOltcIm1ldGFsaW5rXCJdLFwiYXBwbGljYXRpb24vbWV0YWxpbms0K3htbFwiOltcIm1ldGE0XCJdLFwiYXBwbGljYXRpb24vbWV0cyt4bWxcIjpbXCJtZXRzXCJdLFwiYXBwbGljYXRpb24vbW10LWFlaSt4bWxcIjpbXCJtYWVpXCJdLFwiYXBwbGljYXRpb24vbW10LXVzZCt4bWxcIjpbXCJtdXNkXCJdLFwiYXBwbGljYXRpb24vbW9kcyt4bWxcIjpbXCJtb2RzXCJdLFwiYXBwbGljYXRpb24vbXAyMVwiOltcIm0yMVwiLFwibXAyMVwiXSxcImFwcGxpY2F0aW9uL21wNFwiOltcIm1wNHNcIixcIm00cFwiXSxcImFwcGxpY2F0aW9uL21zd29yZFwiOltcImRvY1wiLFwiZG90XCJdLFwiYXBwbGljYXRpb24vbXhmXCI6W1wibXhmXCJdLFwiYXBwbGljYXRpb24vbi1xdWFkc1wiOltcIm5xXCJdLFwiYXBwbGljYXRpb24vbi10cmlwbGVzXCI6W1wibnRcIl0sXCJhcHBsaWNhdGlvbi9ub2RlXCI6W1wiY2pzXCJdLFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCI6W1wiYmluXCIsXCJkbXNcIixcImxyZlwiLFwibWFyXCIsXCJzb1wiLFwiZGlzdFwiLFwiZGlzdHpcIixcInBrZ1wiLFwiYnBrXCIsXCJkdW1wXCIsXCJlbGNcIixcImRlcGxveVwiLFwiZXhlXCIsXCJkbGxcIixcImRlYlwiLFwiZG1nXCIsXCJpc29cIixcImltZ1wiLFwibXNpXCIsXCJtc3BcIixcIm1zbVwiLFwiYnVmZmVyXCJdLFwiYXBwbGljYXRpb24vb2RhXCI6W1wib2RhXCJdLFwiYXBwbGljYXRpb24vb2VicHMtcGFja2FnZSt4bWxcIjpbXCJvcGZcIl0sXCJhcHBsaWNhdGlvbi9vZ2dcIjpbXCJvZ3hcIl0sXCJhcHBsaWNhdGlvbi9vbWRvYyt4bWxcIjpbXCJvbWRvY1wiXSxcImFwcGxpY2F0aW9uL29uZW5vdGVcIjpbXCJvbmV0b2NcIixcIm9uZXRvYzJcIixcIm9uZXRtcFwiLFwib25lcGtnXCJdLFwiYXBwbGljYXRpb24vb3hwc1wiOltcIm94cHNcIl0sXCJhcHBsaWNhdGlvbi9wMnAtb3ZlcmxheSt4bWxcIjpbXCJyZWxvXCJdLFwiYXBwbGljYXRpb24vcGF0Y2gtb3BzLWVycm9yK3htbFwiOltcInhlclwiXSxcImFwcGxpY2F0aW9uL3BkZlwiOltcInBkZlwiXSxcImFwcGxpY2F0aW9uL3BncC1lbmNyeXB0ZWRcIjpbXCJwZ3BcIl0sXCJhcHBsaWNhdGlvbi9wZ3Atc2lnbmF0dXJlXCI6W1wiYXNjXCIsXCJzaWdcIl0sXCJhcHBsaWNhdGlvbi9waWNzLXJ1bGVzXCI6W1wicHJmXCJdLFwiYXBwbGljYXRpb24vcGtjczEwXCI6W1wicDEwXCJdLFwiYXBwbGljYXRpb24vcGtjczctbWltZVwiOltcInA3bVwiLFwicDdjXCJdLFwiYXBwbGljYXRpb24vcGtjczctc2lnbmF0dXJlXCI6W1wicDdzXCJdLFwiYXBwbGljYXRpb24vcGtjczhcIjpbXCJwOFwiXSxcImFwcGxpY2F0aW9uL3BraXgtYXR0ci1jZXJ0XCI6W1wiYWNcIl0sXCJhcHBsaWNhdGlvbi9wa2l4LWNlcnRcIjpbXCJjZXJcIl0sXCJhcHBsaWNhdGlvbi9wa2l4LWNybFwiOltcImNybFwiXSxcImFwcGxpY2F0aW9uL3BraXgtcGtpcGF0aFwiOltcInBraXBhdGhcIl0sXCJhcHBsaWNhdGlvbi9wa2l4Y21wXCI6W1wicGtpXCJdLFwiYXBwbGljYXRpb24vcGxzK3htbFwiOltcInBsc1wiXSxcImFwcGxpY2F0aW9uL3Bvc3RzY3JpcHRcIjpbXCJhaVwiLFwiZXBzXCIsXCJwc1wiXSxcImFwcGxpY2F0aW9uL3Byb3ZlbmFuY2UreG1sXCI6W1wicHJvdnhcIl0sXCJhcHBsaWNhdGlvbi9wc2tjK3htbFwiOltcInBza2N4bWxcIl0sXCJhcHBsaWNhdGlvbi9yYW1sK3lhbWxcIjpbXCJyYW1sXCJdLFwiYXBwbGljYXRpb24vcmRmK3htbFwiOltcInJkZlwiLFwib3dsXCJdLFwiYXBwbGljYXRpb24vcmVnaW5mbyt4bWxcIjpbXCJyaWZcIl0sXCJhcHBsaWNhdGlvbi9yZWxheC1uZy1jb21wYWN0LXN5bnRheFwiOltcInJuY1wiXSxcImFwcGxpY2F0aW9uL3Jlc291cmNlLWxpc3RzK3htbFwiOltcInJsXCJdLFwiYXBwbGljYXRpb24vcmVzb3VyY2UtbGlzdHMtZGlmZit4bWxcIjpbXCJybGRcIl0sXCJhcHBsaWNhdGlvbi9ybHMtc2VydmljZXMreG1sXCI6W1wicnNcIl0sXCJhcHBsaWNhdGlvbi9yb3V0ZS1hcGQreG1sXCI6W1wicmFwZFwiXSxcImFwcGxpY2F0aW9uL3JvdXRlLXMtdHNpZCt4bWxcIjpbXCJzbHNcIl0sXCJhcHBsaWNhdGlvbi9yb3V0ZS11c2QreG1sXCI6W1wicnVzZFwiXSxcImFwcGxpY2F0aW9uL3Jwa2ktZ2hvc3RidXN0ZXJzXCI6W1wiZ2JyXCJdLFwiYXBwbGljYXRpb24vcnBraS1tYW5pZmVzdFwiOltcIm1mdFwiXSxcImFwcGxpY2F0aW9uL3Jwa2ktcm9hXCI6W1wicm9hXCJdLFwiYXBwbGljYXRpb24vcnNkK3htbFwiOltcInJzZFwiXSxcImFwcGxpY2F0aW9uL3Jzcyt4bWxcIjpbXCJyc3NcIl0sXCJhcHBsaWNhdGlvbi9ydGZcIjpbXCJydGZcIl0sXCJhcHBsaWNhdGlvbi9zYm1sK3htbFwiOltcInNibWxcIl0sXCJhcHBsaWNhdGlvbi9zY3ZwLWN2LXJlcXVlc3RcIjpbXCJzY3FcIl0sXCJhcHBsaWNhdGlvbi9zY3ZwLWN2LXJlc3BvbnNlXCI6W1wic2NzXCJdLFwiYXBwbGljYXRpb24vc2N2cC12cC1yZXF1ZXN0XCI6W1wic3BxXCJdLFwiYXBwbGljYXRpb24vc2N2cC12cC1yZXNwb25zZVwiOltcInNwcFwiXSxcImFwcGxpY2F0aW9uL3NkcFwiOltcInNkcFwiXSxcImFwcGxpY2F0aW9uL3Nlbm1sK3htbFwiOltcInNlbm1seFwiXSxcImFwcGxpY2F0aW9uL3NlbnNtbCt4bWxcIjpbXCJzZW5zbWx4XCJdLFwiYXBwbGljYXRpb24vc2V0LXBheW1lbnQtaW5pdGlhdGlvblwiOltcInNldHBheVwiXSxcImFwcGxpY2F0aW9uL3NldC1yZWdpc3RyYXRpb24taW5pdGlhdGlvblwiOltcInNldHJlZ1wiXSxcImFwcGxpY2F0aW9uL3NoZit4bWxcIjpbXCJzaGZcIl0sXCJhcHBsaWNhdGlvbi9zaWV2ZVwiOltcInNpdlwiLFwic2lldmVcIl0sXCJhcHBsaWNhdGlvbi9zbWlsK3htbFwiOltcInNtaVwiLFwic21pbFwiXSxcImFwcGxpY2F0aW9uL3NwYXJxbC1xdWVyeVwiOltcInJxXCJdLFwiYXBwbGljYXRpb24vc3BhcnFsLXJlc3VsdHMreG1sXCI6W1wic3J4XCJdLFwiYXBwbGljYXRpb24vc3Jnc1wiOltcImdyYW1cIl0sXCJhcHBsaWNhdGlvbi9zcmdzK3htbFwiOltcImdyeG1sXCJdLFwiYXBwbGljYXRpb24vc3J1K3htbFwiOltcInNydVwiXSxcImFwcGxpY2F0aW9uL3NzZGwreG1sXCI6W1wic3NkbFwiXSxcImFwcGxpY2F0aW9uL3NzbWwreG1sXCI6W1wic3NtbFwiXSxcImFwcGxpY2F0aW9uL3N3aWQreG1sXCI6W1wic3dpZHRhZ1wiXSxcImFwcGxpY2F0aW9uL3RlaSt4bWxcIjpbXCJ0ZWlcIixcInRlaWNvcnB1c1wiXSxcImFwcGxpY2F0aW9uL3RocmF1ZCt4bWxcIjpbXCJ0ZmlcIl0sXCJhcHBsaWNhdGlvbi90aW1lc3RhbXBlZC1kYXRhXCI6W1widHNkXCJdLFwiYXBwbGljYXRpb24vdG9tbFwiOltcInRvbWxcIl0sXCJhcHBsaWNhdGlvbi90cmlnXCI6W1widHJpZ1wiXSxcImFwcGxpY2F0aW9uL3R0bWwreG1sXCI6W1widHRtbFwiXSxcImFwcGxpY2F0aW9uL3VianNvblwiOltcInVialwiXSxcImFwcGxpY2F0aW9uL3VyYy1yZXNzaGVldCt4bWxcIjpbXCJyc2hlZXRcIl0sXCJhcHBsaWNhdGlvbi91cmMtdGFyZ2V0ZGVzYyt4bWxcIjpbXCJ0ZFwiXSxcImFwcGxpY2F0aW9uL3ZvaWNleG1sK3htbFwiOltcInZ4bWxcIl0sXCJhcHBsaWNhdGlvbi93YXNtXCI6W1wid2FzbVwiXSxcImFwcGxpY2F0aW9uL3dpZGdldFwiOltcIndndFwiXSxcImFwcGxpY2F0aW9uL3dpbmhscFwiOltcImhscFwiXSxcImFwcGxpY2F0aW9uL3dzZGwreG1sXCI6W1wid3NkbFwiXSxcImFwcGxpY2F0aW9uL3dzcG9saWN5K3htbFwiOltcIndzcG9saWN5XCJdLFwiYXBwbGljYXRpb24veGFtbCt4bWxcIjpbXCJ4YW1sXCJdLFwiYXBwbGljYXRpb24veGNhcC1hdHQreG1sXCI6W1wieGF2XCJdLFwiYXBwbGljYXRpb24veGNhcC1jYXBzK3htbFwiOltcInhjYVwiXSxcImFwcGxpY2F0aW9uL3hjYXAtZGlmZit4bWxcIjpbXCJ4ZGZcIl0sXCJhcHBsaWNhdGlvbi94Y2FwLWVsK3htbFwiOltcInhlbFwiXSxcImFwcGxpY2F0aW9uL3hjYXAtbnMreG1sXCI6W1wieG5zXCJdLFwiYXBwbGljYXRpb24veGVuYyt4bWxcIjpbXCJ4ZW5jXCJdLFwiYXBwbGljYXRpb24veGh0bWwreG1sXCI6W1wieGh0bWxcIixcInhodFwiXSxcImFwcGxpY2F0aW9uL3hsaWZmK3htbFwiOltcInhsZlwiXSxcImFwcGxpY2F0aW9uL3htbFwiOltcInhtbFwiLFwieHNsXCIsXCJ4c2RcIixcInJuZ1wiXSxcImFwcGxpY2F0aW9uL3htbC1kdGRcIjpbXCJkdGRcIl0sXCJhcHBsaWNhdGlvbi94b3AreG1sXCI6W1wieG9wXCJdLFwiYXBwbGljYXRpb24veHByb2MreG1sXCI6W1wieHBsXCJdLFwiYXBwbGljYXRpb24veHNsdCt4bWxcIjpbXCIqeHNsXCIsXCJ4c2x0XCJdLFwiYXBwbGljYXRpb24veHNwZit4bWxcIjpbXCJ4c3BmXCJdLFwiYXBwbGljYXRpb24veHYreG1sXCI6W1wibXhtbFwiLFwieGh2bWxcIixcInh2bWxcIixcInh2bVwiXSxcImFwcGxpY2F0aW9uL3lhbmdcIjpbXCJ5YW5nXCJdLFwiYXBwbGljYXRpb24veWluK3htbFwiOltcInlpblwiXSxcImFwcGxpY2F0aW9uL3ppcFwiOltcInppcFwiXSxcImF1ZGlvLzNncHBcIjpbXCIqM2dwcFwiXSxcImF1ZGlvL2FkcGNtXCI6W1wiYWRwXCJdLFwiYXVkaW8vYW1yXCI6W1wiYW1yXCJdLFwiYXVkaW8vYmFzaWNcIjpbXCJhdVwiLFwic25kXCJdLFwiYXVkaW8vbWlkaVwiOltcIm1pZFwiLFwibWlkaVwiLFwia2FyXCIsXCJybWlcIl0sXCJhdWRpby9tb2JpbGUteG1mXCI6W1wibXhtZlwiXSxcImF1ZGlvL21wM1wiOltcIiptcDNcIl0sXCJhdWRpby9tcDRcIjpbXCJtNGFcIixcIm1wNGFcIl0sXCJhdWRpby9tcGVnXCI6W1wibXBnYVwiLFwibXAyXCIsXCJtcDJhXCIsXCJtcDNcIixcIm0yYVwiLFwibTNhXCJdLFwiYXVkaW8vb2dnXCI6W1wib2dhXCIsXCJvZ2dcIixcInNweFwiLFwib3B1c1wiXSxcImF1ZGlvL3MzbVwiOltcInMzbVwiXSxcImF1ZGlvL3NpbGtcIjpbXCJzaWxcIl0sXCJhdWRpby93YXZcIjpbXCJ3YXZcIl0sXCJhdWRpby93YXZlXCI6W1wiKndhdlwiXSxcImF1ZGlvL3dlYm1cIjpbXCJ3ZWJhXCJdLFwiYXVkaW8veG1cIjpbXCJ4bVwiXSxcImZvbnQvY29sbGVjdGlvblwiOltcInR0Y1wiXSxcImZvbnQvb3RmXCI6W1wib3RmXCJdLFwiZm9udC90dGZcIjpbXCJ0dGZcIl0sXCJmb250L3dvZmZcIjpbXCJ3b2ZmXCJdLFwiZm9udC93b2ZmMlwiOltcIndvZmYyXCJdLFwiaW1hZ2UvYWNlc1wiOltcImV4clwiXSxcImltYWdlL2FwbmdcIjpbXCJhcG5nXCJdLFwiaW1hZ2UvYXZpZlwiOltcImF2aWZcIl0sXCJpbWFnZS9ibXBcIjpbXCJibXBcIl0sXCJpbWFnZS9jZ21cIjpbXCJjZ21cIl0sXCJpbWFnZS9kaWNvbS1ybGVcIjpbXCJkcmxlXCJdLFwiaW1hZ2UvZW1mXCI6W1wiZW1mXCJdLFwiaW1hZ2UvZml0c1wiOltcImZpdHNcIl0sXCJpbWFnZS9nM2ZheFwiOltcImczXCJdLFwiaW1hZ2UvZ2lmXCI6W1wiZ2lmXCJdLFwiaW1hZ2UvaGVpY1wiOltcImhlaWNcIl0sXCJpbWFnZS9oZWljLXNlcXVlbmNlXCI6W1wiaGVpY3NcIl0sXCJpbWFnZS9oZWlmXCI6W1wiaGVpZlwiXSxcImltYWdlL2hlaWYtc2VxdWVuY2VcIjpbXCJoZWlmc1wiXSxcImltYWdlL2hlajJrXCI6W1wiaGVqMlwiXSxcImltYWdlL2hzajJcIjpbXCJoc2oyXCJdLFwiaW1hZ2UvaWVmXCI6W1wiaWVmXCJdLFwiaW1hZ2UvamxzXCI6W1wiamxzXCJdLFwiaW1hZ2UvanAyXCI6W1wianAyXCIsXCJqcGcyXCJdLFwiaW1hZ2UvanBlZ1wiOltcImpwZWdcIixcImpwZ1wiLFwianBlXCJdLFwiaW1hZ2UvanBoXCI6W1wianBoXCJdLFwiaW1hZ2UvanBoY1wiOltcImpoY1wiXSxcImltYWdlL2pwbVwiOltcImpwbVwiXSxcImltYWdlL2pweFwiOltcImpweFwiLFwianBmXCJdLFwiaW1hZ2UvanhyXCI6W1wianhyXCJdLFwiaW1hZ2UvanhyYVwiOltcImp4cmFcIl0sXCJpbWFnZS9qeHJzXCI6W1wianhyc1wiXSxcImltYWdlL2p4c1wiOltcImp4c1wiXSxcImltYWdlL2p4c2NcIjpbXCJqeHNjXCJdLFwiaW1hZ2UvanhzaVwiOltcImp4c2lcIl0sXCJpbWFnZS9qeHNzXCI6W1wianhzc1wiXSxcImltYWdlL2t0eFwiOltcImt0eFwiXSxcImltYWdlL2t0eDJcIjpbXCJrdHgyXCJdLFwiaW1hZ2UvcG5nXCI6W1wicG5nXCJdLFwiaW1hZ2Uvc2dpXCI6W1wic2dpXCJdLFwiaW1hZ2Uvc3ZnK3htbFwiOltcInN2Z1wiLFwic3ZnelwiXSxcImltYWdlL3QzOFwiOltcInQzOFwiXSxcImltYWdlL3RpZmZcIjpbXCJ0aWZcIixcInRpZmZcIl0sXCJpbWFnZS90aWZmLWZ4XCI6W1widGZ4XCJdLFwiaW1hZ2Uvd2VicFwiOltcIndlYnBcIl0sXCJpbWFnZS93bWZcIjpbXCJ3bWZcIl0sXCJtZXNzYWdlL2Rpc3Bvc2l0aW9uLW5vdGlmaWNhdGlvblwiOltcImRpc3Bvc2l0aW9uLW5vdGlmaWNhdGlvblwiXSxcIm1lc3NhZ2UvZ2xvYmFsXCI6W1widThtc2dcIl0sXCJtZXNzYWdlL2dsb2JhbC1kZWxpdmVyeS1zdGF0dXNcIjpbXCJ1OGRzblwiXSxcIm1lc3NhZ2UvZ2xvYmFsLWRpc3Bvc2l0aW9uLW5vdGlmaWNhdGlvblwiOltcInU4bWRuXCJdLFwibWVzc2FnZS9nbG9iYWwtaGVhZGVyc1wiOltcInU4aGRyXCJdLFwibWVzc2FnZS9yZmM4MjJcIjpbXCJlbWxcIixcIm1pbWVcIl0sXCJtb2RlbC8zbWZcIjpbXCIzbWZcIl0sXCJtb2RlbC9nbHRmK2pzb25cIjpbXCJnbHRmXCJdLFwibW9kZWwvZ2x0Zi1iaW5hcnlcIjpbXCJnbGJcIl0sXCJtb2RlbC9pZ2VzXCI6W1wiaWdzXCIsXCJpZ2VzXCJdLFwibW9kZWwvbWVzaFwiOltcIm1zaFwiLFwibWVzaFwiLFwic2lsb1wiXSxcIm1vZGVsL210bFwiOltcIm10bFwiXSxcIm1vZGVsL29ialwiOltcIm9ialwiXSxcIm1vZGVsL3N0ZXAreG1sXCI6W1wic3RweFwiXSxcIm1vZGVsL3N0ZXAremlwXCI6W1wic3RwelwiXSxcIm1vZGVsL3N0ZXAteG1sK3ppcFwiOltcInN0cHh6XCJdLFwibW9kZWwvc3RsXCI6W1wic3RsXCJdLFwibW9kZWwvdnJtbFwiOltcIndybFwiLFwidnJtbFwiXSxcIm1vZGVsL3gzZCtiaW5hcnlcIjpbXCIqeDNkYlwiLFwieDNkYnpcIl0sXCJtb2RlbC94M2QrZmFzdGluZm9zZXRcIjpbXCJ4M2RiXCJdLFwibW9kZWwveDNkK3ZybWxcIjpbXCIqeDNkdlwiLFwieDNkdnpcIl0sXCJtb2RlbC94M2QreG1sXCI6W1wieDNkXCIsXCJ4M2R6XCJdLFwibW9kZWwveDNkLXZybWxcIjpbXCJ4M2R2XCJdLFwidGV4dC9jYWNoZS1tYW5pZmVzdFwiOltcImFwcGNhY2hlXCIsXCJtYW5pZmVzdFwiXSxcInRleHQvY2FsZW5kYXJcIjpbXCJpY3NcIixcImlmYlwiXSxcInRleHQvY29mZmVlc2NyaXB0XCI6W1wiY29mZmVlXCIsXCJsaXRjb2ZmZWVcIl0sXCJ0ZXh0L2Nzc1wiOltcImNzc1wiXSxcInRleHQvY3N2XCI6W1wiY3N2XCJdLFwidGV4dC9odG1sXCI6W1wiaHRtbFwiLFwiaHRtXCIsXCJzaHRtbFwiXSxcInRleHQvamFkZVwiOltcImphZGVcIl0sXCJ0ZXh0L2pzeFwiOltcImpzeFwiXSxcInRleHQvbGVzc1wiOltcImxlc3NcIl0sXCJ0ZXh0L21hcmtkb3duXCI6W1wibWFya2Rvd25cIixcIm1kXCJdLFwidGV4dC9tYXRobWxcIjpbXCJtbWxcIl0sXCJ0ZXh0L21keFwiOltcIm1keFwiXSxcInRleHQvbjNcIjpbXCJuM1wiXSxcInRleHQvcGxhaW5cIjpbXCJ0eHRcIixcInRleHRcIixcImNvbmZcIixcImRlZlwiLFwibGlzdFwiLFwibG9nXCIsXCJpblwiLFwiaW5pXCJdLFwidGV4dC9yaWNodGV4dFwiOltcInJ0eFwiXSxcInRleHQvcnRmXCI6W1wiKnJ0ZlwiXSxcInRleHQvc2dtbFwiOltcInNnbWxcIixcInNnbVwiXSxcInRleHQvc2hleFwiOltcInNoZXhcIl0sXCJ0ZXh0L3NsaW1cIjpbXCJzbGltXCIsXCJzbG1cIl0sXCJ0ZXh0L3NwZHhcIjpbXCJzcGR4XCJdLFwidGV4dC9zdHlsdXNcIjpbXCJzdHlsdXNcIixcInN0eWxcIl0sXCJ0ZXh0L3RhYi1zZXBhcmF0ZWQtdmFsdWVzXCI6W1widHN2XCJdLFwidGV4dC90cm9mZlwiOltcInRcIixcInRyXCIsXCJyb2ZmXCIsXCJtYW5cIixcIm1lXCIsXCJtc1wiXSxcInRleHQvdHVydGxlXCI6W1widHRsXCJdLFwidGV4dC91cmktbGlzdFwiOltcInVyaVwiLFwidXJpc1wiLFwidXJsc1wiXSxcInRleHQvdmNhcmRcIjpbXCJ2Y2FyZFwiXSxcInRleHQvdnR0XCI6W1widnR0XCJdLFwidGV4dC94bWxcIjpbXCIqeG1sXCJdLFwidGV4dC95YW1sXCI6W1wieWFtbFwiLFwieW1sXCJdLFwidmlkZW8vM2dwcFwiOltcIjNncFwiLFwiM2dwcFwiXSxcInZpZGVvLzNncHAyXCI6W1wiM2cyXCJdLFwidmlkZW8vaDI2MVwiOltcImgyNjFcIl0sXCJ2aWRlby9oMjYzXCI6W1wiaDI2M1wiXSxcInZpZGVvL2gyNjRcIjpbXCJoMjY0XCJdLFwidmlkZW8vaXNvLnNlZ21lbnRcIjpbXCJtNHNcIl0sXCJ2aWRlby9qcGVnXCI6W1wianBndlwiXSxcInZpZGVvL2pwbVwiOltcIipqcG1cIixcImpwZ21cIl0sXCJ2aWRlby9tajJcIjpbXCJtajJcIixcIm1qcDJcIl0sXCJ2aWRlby9tcDJ0XCI6W1widHNcIl0sXCJ2aWRlby9tcDRcIjpbXCJtcDRcIixcIm1wNHZcIixcIm1wZzRcIl0sXCJ2aWRlby9tcGVnXCI6W1wibXBlZ1wiLFwibXBnXCIsXCJtcGVcIixcIm0xdlwiLFwibTJ2XCJdLFwidmlkZW8vb2dnXCI6W1wib2d2XCJdLFwidmlkZW8vcXVpY2t0aW1lXCI6W1wicXRcIixcIm1vdlwiXSxcInZpZGVvL3dlYm1cIjpbXCJ3ZWJtXCJdfTsiLCIvKipcbiAgIyBub3JtYWxpY2VcblxuICBOb3JtYWxpemUgYW4gaWNlIHNlcnZlciBjb25maWd1cmF0aW9uIG9iamVjdCAob3IgcGxhaW4gb2xkIHN0cmluZykgaW50byBhIGZvcm1hdFxuICB0aGF0IGlzIHVzYWJsZSBpbiBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBXZWJSVEMuICBQcmltYXJpbHkgdGhpcyBtb2R1bGUgaXMgZGVzaWduZWRcbiAgdG8gaGVscCB3aXRoIHRoZSB0cmFuc2l0aW9uIG9mIHRoZSBgdXJsYCBhdHRyaWJ1dGUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gb2JqZWN0IHRvXG4gIHRoZSBgdXJsc2AgYXR0cmlidXRlLlxuXG4gICMjIEV4YW1wbGUgVXNhZ2VcblxuICA8PDwgZXhhbXBsZXMvc2ltcGxlLmpzXG5cbioqL1xuXG52YXIgcHJvdG9jb2xzID0gW1xuICAnc3R1bjonLFxuICAndHVybjonXG5dO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIHZhciB1cmwgPSAoaW5wdXQgfHwge30pLnVybCB8fCBpbnB1dDtcbiAgdmFyIHByb3RvY29sO1xuICB2YXIgcGFydHM7XG4gIHZhciBvdXRwdXQgPSB7fTtcblxuICAvLyBpZiB3ZSBkb24ndCBoYXZlIGEgc3RyaW5nIHVybCwgdGhlbiBhbGxvdyB0aGUgaW5wdXQgdG8gcGFzc3Rocm91Z2hcbiAgaWYgKHR5cGVvZiB1cmwgIT0gJ3N0cmluZycgJiYgKCEgKHVybCBpbnN0YW5jZW9mIFN0cmluZykpKSB7XG4gICAgcmV0dXJuIGlucHV0O1xuICB9XG5cbiAgLy8gdHJpbSB0aGUgdXJsIHN0cmluZywgYW5kIGNvbnZlcnQgdG8gYW4gYXJyYXlcbiAgdXJsID0gdXJsLnRyaW0oKTtcblxuICAvLyBpZiB0aGUgcHJvdG9jb2wgaXMgbm90IGtub3duLCB0aGVuIHBhc3N0aHJvdWdoXG4gIHByb3RvY29sID0gcHJvdG9jb2xzW3Byb3RvY29scy5pbmRleE9mKHVybC5zbGljZSgwLCA1KSldO1xuICBpZiAoISBwcm90b2NvbCkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfVxuXG4gIC8vIG5vdyBsZXQncyBhdHRhY2sgdGhlIHJlbWFpbmluZyB1cmwgcGFydHNcbiAgdXJsID0gdXJsLnNsaWNlKDUpO1xuICBwYXJ0cyA9IHVybC5zcGxpdCgnQCcpO1xuXG4gIG91dHB1dC51c2VybmFtZSA9IGlucHV0LnVzZXJuYW1lO1xuICBvdXRwdXQuY3JlZGVudGlhbCA9IGlucHV0LmNyZWRlbnRpYWw7XG4gIC8vIGlmIHdlIGhhdmUgYW4gYXV0aGVudGljYXRpb24gcGFydCwgdGhlbiBzZXQgdGhlIGNyZWRlbnRpYWxzXG4gIGlmIChwYXJ0cy5sZW5ndGggPiAxKSB7XG4gICAgdXJsID0gcGFydHNbMV07XG4gICAgcGFydHMgPSBwYXJ0c1swXS5zcGxpdCgnOicpO1xuXG4gICAgLy8gYWRkIHRoZSBvdXRwdXQgY3JlZGVudGlhbCBhbmQgdXNlcm5hbWVcbiAgICBvdXRwdXQudXNlcm5hbWUgPSBwYXJ0c1swXTtcbiAgICBvdXRwdXQuY3JlZGVudGlhbCA9IChpbnB1dCB8fCB7fSkuY3JlZGVudGlhbCB8fCBwYXJ0c1sxXSB8fCAnJztcbiAgfVxuXG4gIG91dHB1dC51cmwgPSBwcm90b2NvbCArIHVybDtcbiAgb3V0cHV0LnVybHMgPSBbIG91dHB1dC51cmwgXTtcblxuICByZXR1cm4gb3V0cHV0O1xufTtcbiIsIi8qIVxuICogUGxhdGZvcm0uanMgdjEuMy42XG4gKiBDb3B5cmlnaHQgMjAxNC0yMDIwIEJlbmphbWluIFRhblxuICogQ29weXJpZ2h0IDIwMTEtMjAxMyBKb2huLURhdmlkIERhbHRvblxuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlXG4gKi9cbjsoZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBgT2JqZWN0YC4gKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdmdW5jdGlvbic6IHRydWUsXG4gICAgJ29iamVjdCc6IHRydWVcbiAgfTtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBCYWNrdXAgcG9zc2libGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIG9sZFJvb3QgPSByb290O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG4gIHZhciBmcmVlRXhwb3J0cyA9IG9iamVjdFR5cGVzW3R5cGVvZiBleHBvcnRzXSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcyBvciBCcm93c2VyaWZpZWQgY29kZSBhbmQgdXNlIGl0IGFzIGByb290YC4gKi9cbiAgdmFyIGZyZWVHbG9iYWwgPSBmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlICYmIHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSkge1xuICAgIHJvb3QgPSBmcmVlR2xvYmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYXMgdGhlIG1heGltdW0gbGVuZ3RoIG9mIGFuIGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgKiBTZWUgdGhlIFtFUzYgc3BlY10oaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGgpXG4gICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAqL1xuICB2YXIgbWF4U2FmZUludGVnZXIgPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuXG4gIC8qKiBSZWd1bGFyIGV4cHJlc3Npb24gdG8gZGV0ZWN0IE9wZXJhLiAqL1xuICB2YXIgcmVPcGVyYSA9IC9cXGJPcGVyYS87XG5cbiAgLyoqIFBvc3NpYmxlIGdsb2JhbCBvYmplY3QuICovXG4gIHZhciB0aGlzQmluZGluZyA9IHRoaXM7XG5cbiAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuICAvKiogVXNlZCB0byBjaGVjayBmb3Igb3duIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LiAqL1xuICB2YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBpbnRlcm5hbCBgW1tDbGFzc11dYCBvZiB2YWx1ZXMuICovXG4gIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBDYXBpdGFsaXplcyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjYXBpdGFsaXplZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgIHN0cmluZyA9IFN0cmluZyhzdHJpbmcpO1xuICAgIHJldHVybiBzdHJpbmcuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHJpbmcuc2xpY2UoMSk7XG4gIH1cblxuICAvKipcbiAgICogQSB1dGlsaXR5IGZ1bmN0aW9uIHRvIGNsZWFuIHVwIHRoZSBPUyBuYW1lLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3MgVGhlIE9TIG5hbWUgdG8gY2xlYW4gdXAuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVybl0gQSBgUmVnRXhwYCBwYXR0ZXJuIG1hdGNoaW5nIHRoZSBPUyBuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xhYmVsXSBBIGxhYmVsIGZvciB0aGUgT1MuXG4gICAqL1xuICBmdW5jdGlvbiBjbGVhbnVwT1Mob3MsIHBhdHRlcm4sIGxhYmVsKSB7XG4gICAgLy8gUGxhdGZvcm0gdG9rZW5zIGFyZSBkZWZpbmVkIGF0OlxuICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIC8vIGh0dHA6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMDgxMTIyMDUzOTUwL2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNzUwMyhWUy44NSkuYXNweFxuICAgIHZhciBkYXRhID0ge1xuICAgICAgJzEwLjAnOiAnMTAnLFxuICAgICAgJzYuNCc6ICAnMTAgVGVjaG5pY2FsIFByZXZpZXcnLFxuICAgICAgJzYuMyc6ICAnOC4xJyxcbiAgICAgICc2LjInOiAgJzgnLFxuICAgICAgJzYuMSc6ICAnU2VydmVyIDIwMDggUjIgLyA3JyxcbiAgICAgICc2LjAnOiAgJ1NlcnZlciAyMDA4IC8gVmlzdGEnLFxuICAgICAgJzUuMic6ICAnU2VydmVyIDIwMDMgLyBYUCA2NC1iaXQnLFxuICAgICAgJzUuMSc6ICAnWFAnLFxuICAgICAgJzUuMDEnOiAnMjAwMCBTUDEnLFxuICAgICAgJzUuMCc6ICAnMjAwMCcsXG4gICAgICAnNC4wJzogICdOVCcsXG4gICAgICAnNC45MCc6ICdNRSdcbiAgICB9O1xuICAgIC8vIERldGVjdCBXaW5kb3dzIHZlcnNpb24gZnJvbSBwbGF0Zm9ybSB0b2tlbnMuXG4gICAgaWYgKHBhdHRlcm4gJiYgbGFiZWwgJiYgL15XaW4vaS50ZXN0KG9zKSAmJiAhL15XaW5kb3dzIFBob25lIC9pLnRlc3Qob3MpICYmXG4gICAgICAgIChkYXRhID0gZGF0YVsvW1xcZC5dKyQvLmV4ZWMob3MpXSkpIHtcbiAgICAgIG9zID0gJ1dpbmRvd3MgJyArIGRhdGE7XG4gICAgfVxuICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgIG9zID0gU3RyaW5nKG9zKTtcblxuICAgIGlmIChwYXR0ZXJuICYmIGxhYmVsKSB7XG4gICAgICBvcyA9IG9zLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGxhYmVsKTtcbiAgICB9XG5cbiAgICBvcyA9IGZvcm1hdChcbiAgICAgIG9zLnJlcGxhY2UoLyBjZSQvaSwgJyBDRScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJocHcvaSwgJ3dlYicpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWNpbnRvc2hcXGIvLCAnTWFjIE9TJylcbiAgICAgICAgLnJlcGxhY2UoL19Qb3dlclBDXFxiL2ksICcgT1MnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKE9TIFgpIFteIFxcZF0rL2ksICckMScpXG4gICAgICAgIC5yZXBsYWNlKC9cXGJNYWMgKE9TIFgpXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcLyhcXGQpLywgJyAkMScpXG4gICAgICAgIC5yZXBsYWNlKC9fL2csICcuJylcbiAgICAgICAgLnJlcGxhY2UoLyg/OiBCZVBDfFsgLl0qZmNbIFxcZC5dKykkL2ksICcnKVxuICAgICAgICAucmVwbGFjZSgvXFxieDg2XFwuNjRcXGIvZ2ksICd4ODZfNjQnKVxuICAgICAgICAucmVwbGFjZSgvXFxiKFdpbmRvd3MgUGhvbmUpIE9TXFxiLywgJyQxJylcbiAgICAgICAgLnJlcGxhY2UoL1xcYihDaHJvbWUgT1MgXFx3KykgW1xcZC5dK1xcYi8sICckMScpXG4gICAgICAgIC5zcGxpdCgnIG9uICcpWzBdXG4gICAgKTtcblxuICAgIHJldHVybiBvcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpdGVyYXRpb24gdXRpbGl0eSBmb3IgYXJyYXlzIGFuZCBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAqL1xuICBmdW5jdGlvbiBlYWNoKG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gb2JqZWN0ID8gb2JqZWN0Lmxlbmd0aCA6IDA7XG5cbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPiAtMSAmJiBsZW5ndGggPD0gbWF4U2FmZUludGVnZXIpIHtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtpbmRleF0sIGluZGV4LCBvYmplY3QpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3JPd24ob2JqZWN0LCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaW0gYW5kIGNvbmRpdGlvbmFsbHkgY2FwaXRhbGl6ZSBzdHJpbmcgdmFsdWVzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAgICovXG4gIGZ1bmN0aW9uIGZvcm1hdChzdHJpbmcpIHtcbiAgICBzdHJpbmcgPSB0cmltKHN0cmluZyk7XG4gICAgcmV0dXJuIC9eKD86d2ViT1N8aSg/Ok9TfFApKS8udGVzdChzdHJpbmcpXG4gICAgICA/IHN0cmluZ1xuICAgICAgOiBjYXBpdGFsaXplKHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZXMgb3ZlciBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgZXhlY3V0aW5nIHRoZSBgY2FsbGJhY2tgIGZvciBlYWNoLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gZXhlY3V0ZWQgcGVyIG93biBwcm9wZXJ0eS5cbiAgICovXG4gIGZ1bmN0aW9uIGZvck93bihvYmplY3QsIGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICAgIGNhbGxiYWNrKG9iamVjdFtrZXldLCBrZXksIG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGludGVybmFsIGBbW0NsYXNzXV1gIG9mIGEgdmFsdWUuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgYFtbQ2xhc3NdXWAuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRDbGFzc09mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGxcbiAgICAgID8gY2FwaXRhbGl6ZSh2YWx1ZSlcbiAgICAgIDogdG9TdHJpbmcuY2FsbCh2YWx1ZSkuc2xpY2UoOCwgLTEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvc3Qgb2JqZWN0cyBjYW4gcmV0dXJuIHR5cGUgdmFsdWVzIHRoYXQgYXJlIGRpZmZlcmVudCBmcm9tIHRoZWlyIGFjdHVhbFxuICAgKiBkYXRhIHR5cGUuIFRoZSBvYmplY3RzIHdlIGFyZSBjb25jZXJuZWQgd2l0aCB1c3VhbGx5IHJldHVybiBub24tcHJpbWl0aXZlXG4gICAqIHR5cGVzIG9mIFwib2JqZWN0XCIsIFwiZnVuY3Rpb25cIiwgb3IgXCJ1bmtub3duXCIuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Kn0gb2JqZWN0IFRoZSBvd25lciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkgdG8gY2hlY2suXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcHJvcGVydHkgdmFsdWUgaXMgYSBub24tcHJpbWl0aXZlLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBpc0hvc3RUeXBlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICB2YXIgdHlwZSA9IG9iamVjdCAhPSBudWxsID8gdHlwZW9mIG9iamVjdFtwcm9wZXJ0eV0gOiAnbnVtYmVyJztcbiAgICByZXR1cm4gIS9eKD86Ym9vbGVhbnxudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZCkkLy50ZXN0KHR5cGUpICYmXG4gICAgICAodHlwZSA9PSAnb2JqZWN0JyA/ICEhb2JqZWN0W3Byb3BlcnR5XSA6IHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBhcmVzIGEgc3RyaW5nIGZvciB1c2UgaW4gYSBgUmVnRXhwYCBieSBtYWtpbmcgaHlwaGVucyBhbmQgc3BhY2VzIG9wdGlvbmFsLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcXVhbGlmeS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHF1YWxpZmllZCBzdHJpbmcuXG4gICAqL1xuICBmdW5jdGlvbiBxdWFsaWZ5KHN0cmluZykge1xuICAgIHJldHVybiBTdHJpbmcoc3RyaW5nKS5yZXBsYWNlKC8oWyAtXSkoPyEkKS9nLCAnJDE/Jyk7XG4gIH1cblxuICAvKipcbiAgICogQSBiYXJlLWJvbmVzIGBBcnJheSNyZWR1Y2VgIGxpa2UgdXRpbGl0eSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Kn0gVGhlIGFjY3VtdWxhdGVkIHJlc3VsdC5cbiAgICovXG4gIGZ1bmN0aW9uIHJlZHVjZShhcnJheSwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWNjdW11bGF0b3IgPSBudWxsO1xuICAgIGVhY2goYXJyYXksIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBhcnJheSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIHRyaW1tZWQgc3RyaW5nLlxuICAgKi9cbiAgZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZSgvXiArfCArJC9nLCAnJyk7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbGF0Zm9ybSBvYmplY3QuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgKiBAcGFyYW0ge09iamVjdHxzdHJpbmd9IFt1YT1uYXZpZ2F0b3IudXNlckFnZW50XSBUaGUgdXNlciBhZ2VudCBzdHJpbmcgb3JcbiAgICogIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBIHBsYXRmb3JtIG9iamVjdC5cbiAgICovXG4gIGZ1bmN0aW9uIHBhcnNlKHVhKSB7XG5cbiAgICAvKiogVGhlIGVudmlyb25tZW50IGNvbnRleHQgb2JqZWN0LiAqL1xuICAgIHZhciBjb250ZXh0ID0gcm9vdDtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBhIGN1c3RvbSBjb250ZXh0IGlzIHByb3ZpZGVkLiAqL1xuICAgIHZhciBpc0N1c3RvbUNvbnRleHQgPSB1YSAmJiB0eXBlb2YgdWEgPT0gJ29iamVjdCcgJiYgZ2V0Q2xhc3NPZih1YSkgIT0gJ1N0cmluZyc7XG5cbiAgICAvLyBKdWdnbGUgYXJndW1lbnRzLlxuICAgIGlmIChpc0N1c3RvbUNvbnRleHQpIHtcbiAgICAgIGNvbnRleHQgPSB1YTtcbiAgICAgIHVhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKiogQnJvd3NlciBuYXZpZ2F0b3Igb2JqZWN0LiAqL1xuICAgIHZhciBuYXYgPSBjb250ZXh0Lm5hdmlnYXRvciB8fCB7fTtcblxuICAgIC8qKiBCcm93c2VyIHVzZXIgYWdlbnQgc3RyaW5nLiAqL1xuICAgIHZhciB1c2VyQWdlbnQgPSBuYXYudXNlckFnZW50IHx8ICcnO1xuXG4gICAgdWEgfHwgKHVhID0gdXNlckFnZW50KTtcblxuICAgIC8qKiBVc2VkIHRvIGZsYWcgd2hlbiBgdGhpc0JpbmRpbmdgIGlzIHRoZSBbTW9kdWxlU2NvcGVdLiAqL1xuICAgIHZhciBpc01vZHVsZVNjb3BlID0gaXNDdXN0b21Db250ZXh0IHx8IHRoaXNCaW5kaW5nID09IG9sZFJvb3Q7XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYnJvd3NlciBpcyBsaWtlIENocm9tZS4gKi9cbiAgICB2YXIgbGlrZUNocm9tZSA9IGlzQ3VzdG9tQ29udGV4dFxuICAgICAgPyAhIW5hdi5saWtlQ2hyb21lXG4gICAgICA6IC9cXGJDaHJvbWVcXGIvLnRlc3QodWEpICYmICEvaW50ZXJuYWx8XFxuL2kudGVzdCh0b1N0cmluZy50b1N0cmluZygpKTtcblxuICAgIC8qKiBJbnRlcm5hbCBgW1tDbGFzc11dYCB2YWx1ZSBzaG9ydGN1dHMuICovXG4gICAgdmFyIG9iamVjdENsYXNzID0gJ09iamVjdCcsXG4gICAgICAgIGFpclJ1bnRpbWVDbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ1NjcmlwdEJyaWRnaW5nUHJveHlPYmplY3QnLFxuICAgICAgICBlbnZpcm9DbGFzcyA9IGlzQ3VzdG9tQ29udGV4dCA/IG9iamVjdENsYXNzIDogJ0Vudmlyb25tZW50JyxcbiAgICAgICAgamF2YUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBjb250ZXh0LmphdmEpID8gJ0phdmFQYWNrYWdlJyA6IGdldENsYXNzT2YoY29udGV4dC5qYXZhKSxcbiAgICAgICAgcGhhbnRvbUNsYXNzID0gaXNDdXN0b21Db250ZXh0ID8gb2JqZWN0Q2xhc3MgOiAnUnVudGltZU9iamVjdCc7XG5cbiAgICAvKiogRGV0ZWN0IEphdmEgZW52aXJvbm1lbnRzLiAqL1xuICAgIHZhciBqYXZhID0gL1xcYkphdmEvLnRlc3QoamF2YUNsYXNzKSAmJiBjb250ZXh0LmphdmE7XG5cbiAgICAvKiogRGV0ZWN0IFJoaW5vLiAqL1xuICAgIHZhciByaGlubyA9IGphdmEgJiYgZ2V0Q2xhc3NPZihjb250ZXh0LmVudmlyb25tZW50KSA9PSBlbnZpcm9DbGFzcztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYWxwaGEuICovXG4gICAgdmFyIGFscGhhID0gamF2YSA/ICdhJyA6ICdcXHUwM2IxJztcblxuICAgIC8qKiBBIGNoYXJhY3RlciB0byByZXByZXNlbnQgYmV0YS4gKi9cbiAgICB2YXIgYmV0YSA9IGphdmEgPyAnYicgOiAnXFx1MDNiMic7XG5cbiAgICAvKiogQnJvd3NlciBkb2N1bWVudCBvYmplY3QuICovXG4gICAgdmFyIGRvYyA9IGNvbnRleHQuZG9jdW1lbnQgfHwge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgT3BlcmEgYnJvd3NlciAoUHJlc3RvLWJhc2VkKS5cbiAgICAgKiBodHRwOi8vd3d3Lmhvd3RvY3JlYXRlLmNvLnVrL29wZXJhU3R1ZmYvb3BlcmFPYmplY3QuaHRtbFxuICAgICAqIGh0dHA6Ly9kZXYub3BlcmEuY29tL2FydGljbGVzL3ZpZXcvb3BlcmEtbWluaS13ZWItY29udGVudC1hdXRob3JpbmctZ3VpZGVsaW5lcy8jb3BlcmFtaW5pXG4gICAgICovXG4gICAgdmFyIG9wZXJhID0gY29udGV4dC5vcGVyYW1pbmkgfHwgY29udGV4dC5vcGVyYTtcblxuICAgIC8qKiBPcGVyYSBgW1tDbGFzc11dYC4gKi9cbiAgICB2YXIgb3BlcmFDbGFzcyA9IHJlT3BlcmEudGVzdChvcGVyYUNsYXNzID0gKGlzQ3VzdG9tQ29udGV4dCAmJiBvcGVyYSkgPyBvcGVyYVsnW1tDbGFzc11dJ10gOiBnZXRDbGFzc09mKG9wZXJhKSlcbiAgICAgID8gb3BlcmFDbGFzc1xuICAgICAgOiAob3BlcmEgPSBudWxsKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKiBUZW1wb3JhcnkgdmFyaWFibGUgdXNlZCBvdmVyIHRoZSBzY3JpcHQncyBsaWZldGltZS4gKi9cbiAgICB2YXIgZGF0YTtcblxuICAgIC8qKiBUaGUgQ1BVIGFyY2hpdGVjdHVyZS4gKi9cbiAgICB2YXIgYXJjaCA9IHVhO1xuXG4gICAgLyoqIFBsYXRmb3JtIGRlc2NyaXB0aW9uIGFycmF5LiAqL1xuICAgIHZhciBkZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgLyoqIFBsYXRmb3JtIGFscGhhL2JldGEgaW5kaWNhdG9yLiAqL1xuICAgIHZhciBwcmVyZWxlYXNlID0gbnVsbDtcblxuICAgIC8qKiBBIGZsYWcgdG8gaW5kaWNhdGUgdGhhdCBlbnZpcm9ubWVudCBmZWF0dXJlcyBzaG91bGQgYmUgdXNlZCB0byByZXNvbHZlIHRoZSBwbGF0Zm9ybS4gKi9cbiAgICB2YXIgdXNlRmVhdHVyZXMgPSB1YSA9PSB1c2VyQWdlbnQ7XG5cbiAgICAvKiogVGhlIGJyb3dzZXIvZW52aXJvbm1lbnQgdmVyc2lvbi4gKi9cbiAgICB2YXIgdmVyc2lvbiA9IHVzZUZlYXR1cmVzICYmIG9wZXJhICYmIHR5cGVvZiBvcGVyYS52ZXJzaW9uID09ICdmdW5jdGlvbicgJiYgb3BlcmEudmVyc2lvbigpO1xuXG4gICAgLyoqIEEgZmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgT1MgZW5kcyB3aXRoIFwiLyBWZXJzaW9uXCIgKi9cbiAgICB2YXIgaXNTcGVjaWFsQ2FzZWRPUztcblxuICAgIC8qIERldGVjdGFibGUgbGF5b3V0IGVuZ2luZXMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIGxheW91dCA9IGdldExheW91dChbXG4gICAgICB7ICdsYWJlbCc6ICdFZGdlSFRNTCcsICdwYXR0ZXJuJzogJ0VkZ2UnIH0sXG4gICAgICAnVHJpZGVudCcsXG4gICAgICB7ICdsYWJlbCc6ICdXZWJLaXQnLCAncGF0dGVybic6ICdBcHBsZVdlYktpdCcgfSxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdQcmVzdG8nLFxuICAgICAgJ05ldEZyb250JyxcbiAgICAgICdUYXNtYW4nLFxuICAgICAgJ0tIVE1MJyxcbiAgICAgICdHZWNrbydcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgYnJvd3NlciBuYW1lcyAob3JkZXIgaXMgaW1wb3J0YW50KS4gKi9cbiAgICB2YXIgbmFtZSA9IGdldE5hbWUoW1xuICAgICAgJ0Fkb2JlIEFJUicsXG4gICAgICAnQXJvcmEnLFxuICAgICAgJ0F2YW50IEJyb3dzZXInLFxuICAgICAgJ0JyZWFjaCcsXG4gICAgICAnQ2FtaW5vJyxcbiAgICAgICdFbGVjdHJvbicsXG4gICAgICAnRXBpcGhhbnknLFxuICAgICAgJ0Zlbm5lYycsXG4gICAgICAnRmxvY2snLFxuICAgICAgJ0dhbGVvbicsXG4gICAgICAnR3JlZW5Ccm93c2VyJyxcbiAgICAgICdpQ2FiJyxcbiAgICAgICdJY2V3ZWFzZWwnLFxuICAgICAgJ0stTWVsZW9uJyxcbiAgICAgICdLb25xdWVyb3InLFxuICAgICAgJ0x1bmFzY2FwZScsXG4gICAgICAnTWF4dGhvbicsXG4gICAgICB7ICdsYWJlbCc6ICdNaWNyb3NvZnQgRWRnZScsICdwYXR0ZXJuJzogJyg/OkVkZ2V8RWRnfEVkZ0F8RWRnaU9TKScgfSxcbiAgICAgICdNaWRvcmknLFxuICAgICAgJ05vb2sgQnJvd3NlcicsXG4gICAgICAnUGFsZU1vb24nLFxuICAgICAgJ1BoYW50b21KUycsXG4gICAgICAnUmF2ZW4nLFxuICAgICAgJ1Jla29ucScsXG4gICAgICAnUm9ja01lbHQnLFxuICAgICAgeyAnbGFiZWwnOiAnU2Ftc3VuZyBJbnRlcm5ldCcsICdwYXR0ZXJuJzogJ1NhbXN1bmdCcm93c2VyJyB9LFxuICAgICAgJ1NlYU1vbmtleScsXG4gICAgICB7ICdsYWJlbCc6ICdTaWxrJywgJ3BhdHRlcm4nOiAnKD86Q2xvdWQ5fFNpbGstQWNjZWxlcmF0ZWQpJyB9LFxuICAgICAgJ1NsZWlwbmlyJyxcbiAgICAgICdTbGltQnJvd3NlcicsXG4gICAgICB7ICdsYWJlbCc6ICdTUldhcmUgSXJvbicsICdwYXR0ZXJuJzogJ0lyb24nIH0sXG4gICAgICAnU3VucmlzZScsXG4gICAgICAnU3dpZnRmb3gnLFxuICAgICAgJ1ZpdmFsZGknLFxuICAgICAgJ1dhdGVyZm94JyxcbiAgICAgICdXZWJQb3NpdGl2ZScsXG4gICAgICB7ICdsYWJlbCc6ICdZYW5kZXggQnJvd3NlcicsICdwYXR0ZXJuJzogJ1lhQnJvd3NlcicgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ1VDIEJyb3dzZXInLCAncGF0dGVybic6ICdVQ0Jyb3dzZXInIH0sXG4gICAgICAnT3BlcmEgTWluaScsXG4gICAgICB7ICdsYWJlbCc6ICdPcGVyYSBNaW5pJywgJ3BhdHRlcm4nOiAnT1BpT1MnIH0sXG4gICAgICAnT3BlcmEnLFxuICAgICAgeyAnbGFiZWwnOiAnT3BlcmEnLCAncGF0dGVybic6ICdPUFInIH0sXG4gICAgICAnQ2hyb21pdW0nLFxuICAgICAgJ0Nocm9tZScsXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUnLCAncGF0dGVybic6ICcoPzpIZWFkbGVzc0Nocm9tZSknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdDaHJvbWUgTW9iaWxlJywgJ3BhdHRlcm4nOiAnKD86Q3JpT1N8Q3JNbyknIH0sXG4gICAgICB7ICdsYWJlbCc6ICdGaXJlZm94JywgJ3BhdHRlcm4nOiAnKD86RmlyZWZveHxNaW5lZmllbGQpJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnRmlyZWZveCBmb3IgaU9TJywgJ3BhdHRlcm4nOiAnRnhpT1MnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdJRScsICdwYXR0ZXJuJzogJ0lFTW9iaWxlJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnSUUnLCAncGF0dGVybic6ICdNU0lFJyB9LFxuICAgICAgJ1NhZmFyaSdcbiAgICBdKTtcblxuICAgIC8qIERldGVjdGFibGUgcHJvZHVjdHMgKG9yZGVyIGlzIGltcG9ydGFudCkuICovXG4gICAgdmFyIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFtcbiAgICAgIHsgJ2xhYmVsJzogJ0JsYWNrQmVycnknLCAncGF0dGVybic6ICdCQjEwJyB9LFxuICAgICAgJ0JsYWNrQmVycnknLFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMnLCAncGF0dGVybic6ICdHVC1JOTAwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTMicsICdwYXR0ZXJuJzogJ0dULUk5MTAwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFMzJywgJ3BhdHRlcm4nOiAnR1QtSTkzMDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzQnLCAncGF0dGVybic6ICdHVC1JOTUwMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNScsICdwYXR0ZXJuJzogJ1NNLUc5MDAnIH0sXG4gICAgICB7ICdsYWJlbCc6ICdHYWxheHkgUzYnLCAncGF0dGVybic6ICdTTS1HOTIwJyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM2IEVkZ2UnLCAncGF0dGVybic6ICdTTS1HOTI1JyB9LFxuICAgICAgeyAnbGFiZWwnOiAnR2FsYXh5IFM3JywgJ3BhdHRlcm4nOiAnU00tRzkzMCcgfSxcbiAgICAgIHsgJ2xhYmVsJzogJ0dhbGF4eSBTNyBFZGdlJywgJ3BhdHRlcm4nOiAnU00tRzkzNScgfSxcbiAgICAgICdHb29nbGUgVFYnLFxuICAgICAgJ0x1bWlhJyxcbiAgICAgICdpUGFkJyxcbiAgICAgICdpUG9kJyxcbiAgICAgICdpUGhvbmUnLFxuICAgICAgJ0tpbmRsZScsXG4gICAgICB7ICdsYWJlbCc6ICdLaW5kbGUgRmlyZScsICdwYXR0ZXJuJzogJyg/OkNsb3VkOXxTaWxrLUFjY2VsZXJhdGVkKScgfSxcbiAgICAgICdOZXh1cycsXG4gICAgICAnTm9vaycsXG4gICAgICAnUGxheUJvb2snLFxuICAgICAgJ1BsYXlTdGF0aW9uIFZpdGEnLFxuICAgICAgJ1BsYXlTdGF0aW9uJyxcbiAgICAgICdUb3VjaFBhZCcsXG4gICAgICAnVHJhbnNmb3JtZXInLFxuICAgICAgeyAnbGFiZWwnOiAnV2lpIFUnLCAncGF0dGVybic6ICdXaWlVJyB9LFxuICAgICAgJ1dpaScsXG4gICAgICAnWGJveCBPbmUnLFxuICAgICAgeyAnbGFiZWwnOiAnWGJveCAzNjAnLCAncGF0dGVybic6ICdYYm94JyB9LFxuICAgICAgJ1hvb20nXG4gICAgXSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG1hbnVmYWN0dXJlcnMuICovXG4gICAgdmFyIG1hbnVmYWN0dXJlciA9IGdldE1hbnVmYWN0dXJlcih7XG4gICAgICAnQXBwbGUnOiB7ICdpUGFkJzogMSwgJ2lQaG9uZSc6IDEsICdpUG9kJzogMSB9LFxuICAgICAgJ0FsY2F0ZWwnOiB7fSxcbiAgICAgICdBcmNob3MnOiB7fSxcbiAgICAgICdBbWF6b24nOiB7ICdLaW5kbGUnOiAxLCAnS2luZGxlIEZpcmUnOiAxIH0sXG4gICAgICAnQXN1cyc6IHsgJ1RyYW5zZm9ybWVyJzogMSB9LFxuICAgICAgJ0Jhcm5lcyAmIE5vYmxlJzogeyAnTm9vayc6IDEgfSxcbiAgICAgICdCbGFja0JlcnJ5JzogeyAnUGxheUJvb2snOiAxIH0sXG4gICAgICAnR29vZ2xlJzogeyAnR29vZ2xlIFRWJzogMSwgJ05leHVzJzogMSB9LFxuICAgICAgJ0hQJzogeyAnVG91Y2hQYWQnOiAxIH0sXG4gICAgICAnSFRDJzoge30sXG4gICAgICAnSHVhd2VpJzoge30sXG4gICAgICAnTGVub3ZvJzoge30sXG4gICAgICAnTEcnOiB7fSxcbiAgICAgICdNaWNyb3NvZnQnOiB7ICdYYm94JzogMSwgJ1hib3ggT25lJzogMSB9LFxuICAgICAgJ01vdG9yb2xhJzogeyAnWG9vbSc6IDEgfSxcbiAgICAgICdOaW50ZW5kbyc6IHsgJ1dpaSBVJzogMSwgICdXaWknOiAxIH0sXG4gICAgICAnTm9raWEnOiB7ICdMdW1pYSc6IDEgfSxcbiAgICAgICdPcHBvJzoge30sXG4gICAgICAnU2Ftc3VuZyc6IHsgJ0dhbGF4eSBTJzogMSwgJ0dhbGF4eSBTMic6IDEsICdHYWxheHkgUzMnOiAxLCAnR2FsYXh5IFM0JzogMSB9LFxuICAgICAgJ1NvbnknOiB7ICdQbGF5U3RhdGlvbic6IDEsICdQbGF5U3RhdGlvbiBWaXRhJzogMSB9LFxuICAgICAgJ1hpYW9taSc6IHsgJ01pJzogMSwgJ1JlZG1pJzogMSB9XG4gICAgfSk7XG5cbiAgICAvKiBEZXRlY3RhYmxlIG9wZXJhdGluZyBzeXN0ZW1zIChvcmRlciBpcyBpbXBvcnRhbnQpLiAqL1xuICAgIHZhciBvcyA9IGdldE9TKFtcbiAgICAgICdXaW5kb3dzIFBob25lJyxcbiAgICAgICdLYWlPUycsXG4gICAgICAnQW5kcm9pZCcsXG4gICAgICAnQ2VudE9TJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0Nocm9tZSBPUycsICdwYXR0ZXJuJzogJ0NyT1MnIH0sXG4gICAgICAnRGViaWFuJyxcbiAgICAgIHsgJ2xhYmVsJzogJ0RyYWdvbkZseSBCU0QnLCAncGF0dGVybic6ICdEcmFnb25GbHknIH0sXG4gICAgICAnRmVkb3JhJyxcbiAgICAgICdGcmVlQlNEJyxcbiAgICAgICdHZW50b28nLFxuICAgICAgJ0hhaWt1JyxcbiAgICAgICdLdWJ1bnR1JyxcbiAgICAgICdMaW51eCBNaW50JyxcbiAgICAgICdPcGVuQlNEJyxcbiAgICAgICdSZWQgSGF0JyxcbiAgICAgICdTdVNFJyxcbiAgICAgICdVYnVudHUnLFxuICAgICAgJ1h1YnVudHUnLFxuICAgICAgJ0N5Z3dpbicsXG4gICAgICAnU3ltYmlhbiBPUycsXG4gICAgICAnaHB3T1MnLFxuICAgICAgJ3dlYk9TICcsXG4gICAgICAnd2ViT1MnLFxuICAgICAgJ1RhYmxldCBPUycsXG4gICAgICAnVGl6ZW4nLFxuICAgICAgJ0xpbnV4JyxcbiAgICAgICdNYWMgT1MgWCcsXG4gICAgICAnTWFjaW50b3NoJyxcbiAgICAgICdNYWMnLFxuICAgICAgJ1dpbmRvd3MgOTg7JyxcbiAgICAgICdXaW5kb3dzICdcbiAgICBdKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBsYXlvdXQgZW5naW5lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGxheW91dCBlbmdpbmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0KGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBtYW51ZmFjdHVyZXIgZnJvbSBhbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBndWVzc2VzIEFuIG9iamVjdCBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIG1hbnVmYWN0dXJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRNYW51ZmFjdHVyZXIoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgICAgLy8gTG9va3VwIHRoZSBtYW51ZmFjdHVyZXIgYnkgcHJvZHVjdCBvciBzY2FuIHRoZSBVQSBmb3IgdGhlIG1hbnVmYWN0dXJlci5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoXG4gICAgICAgICAgdmFsdWVbcHJvZHVjdF0gfHxcbiAgICAgICAgICB2YWx1ZVsvXlthLXpdKyg/OiArW2Etel0rXFxiKSovaS5leGVjKHByb2R1Y3QpXSB8fFxuICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcXVhbGlmeShrZXkpICsgJyg/OlxcXFxifFxcXFx3KlxcXFxkKScsICdpJykuZXhlYyh1YSlcbiAgICAgICAgKSAmJiBrZXk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQaWNrcyB0aGUgYnJvd3NlciBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIGJyb3dzZXIgbmFtZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYW1lKGd1ZXNzZXMpIHtcbiAgICAgIHJldHVybiByZWR1Y2UoZ3Vlc3NlcywgZnVuY3Rpb24ocmVzdWx0LCBndWVzcykge1xuICAgICAgICByZXR1cm4gcmVzdWx0IHx8IFJlZ0V4cCgnXFxcXGInICsgKFxuICAgICAgICAgIGd1ZXNzLnBhdHRlcm4gfHwgcXVhbGlmeShndWVzcylcbiAgICAgICAgKSArICdcXFxcYicsICdpJykuZXhlYyh1YSkgJiYgKGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBpY2tzIHRoZSBPUyBuYW1lIGZyb20gYW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gZ3Vlc3NlcyBBbiBhcnJheSBvZiBndWVzc2VzLlxuICAgICAqIEByZXR1cm5zIHtudWxsfHN0cmluZ30gVGhlIGRldGVjdGVkIE9TIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T1MoZ3Vlc3Nlcykge1xuICAgICAgcmV0dXJuIHJlZHVjZShndWVzc2VzLCBmdW5jdGlvbihyZXN1bHQsIGd1ZXNzKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gZ3Vlc3MucGF0dGVybiB8fCBxdWFsaWZ5KGd1ZXNzKTtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgKHJlc3VsdCA9XG4gICAgICAgICAgICAgIFJlZ0V4cCgnXFxcXGInICsgcGF0dGVybiArICcoPzovW1xcXFxkLl0rfFsgXFxcXHcuXSopJywgJ2knKS5leGVjKHVhKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGNsZWFudXBPUyhyZXN1bHQsIHBhdHRlcm4sIGd1ZXNzLmxhYmVsIHx8IGd1ZXNzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGlja3MgdGhlIHByb2R1Y3QgbmFtZSBmcm9tIGFuIGFycmF5IG9mIGd1ZXNzZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGd1ZXNzZXMgQW4gYXJyYXkgb2YgZ3Vlc3Nlcy5cbiAgICAgKiBAcmV0dXJucyB7bnVsbHxzdHJpbmd9IFRoZSBkZXRlY3RlZCBwcm9kdWN0IG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UHJvZHVjdChndWVzc2VzKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKGd1ZXNzZXMsIGZ1bmN0aW9uKHJlc3VsdCwgZ3Vlc3MpIHtcbiAgICAgICAgdmFyIHBhdHRlcm4gPSBndWVzcy5wYXR0ZXJuIHx8IHF1YWxpZnkoZ3Vlc3MpO1xuICAgICAgICBpZiAoIXJlc3VsdCAmJiAocmVzdWx0ID1cbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXGQrWy5cXFxcd19dKicsICdpJykuZXhlYyh1YSkgfHxcbiAgICAgICAgICAgICAgUmVnRXhwKCdcXFxcYicgKyBwYXR0ZXJuICsgJyAqXFxcXHcrLVtcXFxcd10qJywgJ2knKS5leGVjKHVhKSB8fFxuICAgICAgICAgICAgICBSZWdFeHAoJ1xcXFxiJyArIHBhdHRlcm4gKyAnKD86OyAqKD86W2Etel0rW18tXSk/W2Etel0rXFxcXGQrfFteICgpOy1dKiknLCAnaScpLmV4ZWModWEpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgLy8gU3BsaXQgYnkgZm9yd2FyZCBzbGFzaCBhbmQgYXBwZW5kIHByb2R1Y3QgdmVyc2lvbiBpZiBuZWVkZWQuXG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBTdHJpbmcoKGd1ZXNzLmxhYmVsICYmICFSZWdFeHAocGF0dGVybiwgJ2knKS50ZXN0KGd1ZXNzLmxhYmVsKSkgPyBndWVzcy5sYWJlbCA6IHJlc3VsdCkuc3BsaXQoJy8nKSlbMV0gJiYgIS9bXFxkLl0rLy50ZXN0KHJlc3VsdFswXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSArPSAnICcgKyByZXN1bHRbMV07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIENvcnJlY3QgY2hhcmFjdGVyIGNhc2UgYW5kIGNsZWFudXAgc3RyaW5nLlxuICAgICAgICAgIGd1ZXNzID0gZ3Vlc3MubGFiZWwgfHwgZ3Vlc3M7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0KHJlc3VsdFswXVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKHBhdHRlcm4sICdpJyksIGd1ZXNzKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCc7ICooPzonICsgZ3Vlc3MgKyAnW18tXSk/JywgJ2knKSwgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCcoJyArIGd1ZXNzICsgJylbLV8uXT8oXFxcXHcpJywgJ2knKSwgJyQxICQyJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyB0aGUgdmVyc2lvbiB1c2luZyBhbiBhcnJheSBvZiBVQSBwYXR0ZXJucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0dGVybnMgQW4gYXJyYXkgb2YgVUEgcGF0dGVybnMuXG4gICAgICogQHJldHVybnMge251bGx8c3RyaW5nfSBUaGUgZGV0ZWN0ZWQgdmVyc2lvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRWZXJzaW9uKHBhdHRlcm5zKSB7XG4gICAgICByZXR1cm4gcmVkdWNlKHBhdHRlcm5zLCBmdW5jdGlvbihyZXN1bHQsIHBhdHRlcm4pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCB8fCAoUmVnRXhwKHBhdHRlcm4gK1xuICAgICAgICAgICcoPzotW1xcXFxkLl0rL3woPzogZm9yIFtcXFxcdy1dKyk/WyAvLV0pKFtcXFxcZC5dK1teICgpOy9fLV0qKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHwgbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHBsYXRmb3JtLmRlc2NyaXB0aW9uYCB3aGVuIHRoZSBwbGF0Zm9ybSBvYmplY3QgaXMgY29lcmNlZCB0byBhIHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBuYW1lIHRvU3RyaW5nXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyBgcGxhdGZvcm0uZGVzY3JpcHRpb25gIGlmIGF2YWlsYWJsZSwgZWxzZSBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9TdHJpbmdQbGF0Zm9ybSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8vIENvbnZlcnQgbGF5b3V0IHRvIGFuIGFycmF5IHNvIHdlIGNhbiBhZGQgZXh0cmEgZGV0YWlscy5cbiAgICBsYXlvdXQgJiYgKGxheW91dCA9IFtsYXlvdXRdKTtcblxuICAgIC8vIERldGVjdCBBbmRyb2lkIHByb2R1Y3RzLlxuICAgIC8vIEJyb3dzZXJzIG9uIEFuZHJvaWQgZGV2aWNlcyB0eXBpY2FsbHkgcHJvdmlkZSB0aGVpciBwcm9kdWN0IElEUyBhZnRlciBcIkFuZHJvaWQ7XCJcbiAgICAvLyB1cCB0byBcIkJ1aWxkXCIgb3IgXCIpIEFwcGxlV2ViS2l0XCIuXG4gICAgLy8gRXhhbXBsZTpcbiAgICAvLyBcIk1vemlsbGEvNS4wIChMaW51eDsgQW5kcm9pZCA4LjEuMDsgTW90byBHICg1KSBQbHVzKSBBcHBsZVdlYktpdC81MzcuMzZcbiAgICAvLyAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS83MC4wLjM1MzguODAgTW9iaWxlIFNhZmFyaS81MzcuMzZcIlxuICAgIGlmICgvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgJiYgIXByb2R1Y3QgJiZcbiAgICAgICAgKGRhdGEgPSAvXFxiQW5kcm9pZFteO10qOyguKj8pKD86QnVpbGR8XFwpIEFwcGxlV2ViS2l0KVxcYi9pLmV4ZWModWEpKSkge1xuICAgICAgcHJvZHVjdCA9IHRyaW0oZGF0YVsxXSlcbiAgICAgICAgLy8gUmVwbGFjZSBhbnkgbGFuZ3VhZ2UgY29kZXMgKGVnLiBcImVuLVVTXCIpLlxuICAgICAgICAucmVwbGFjZSgvXlthLXpdezJ9LVthLXpdezJ9O1xccyovaSwgJycpXG4gICAgICAgIHx8IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBwcm9kdWN0IG5hbWVzIHRoYXQgY29udGFpbiB0aGVpciBtYW51ZmFjdHVyZXIncyBuYW1lLlxuICAgIGlmIChtYW51ZmFjdHVyZXIgJiYgIXByb2R1Y3QpIHtcbiAgICAgIHByb2R1Y3QgPSBnZXRQcm9kdWN0KFttYW51ZmFjdHVyZXJdKTtcbiAgICB9IGVsc2UgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0KSB7XG4gICAgICBwcm9kdWN0ID0gcHJvZHVjdFxuICAgICAgICAucmVwbGFjZShSZWdFeHAoJ14oJyArIHF1YWxpZnkobWFudWZhY3R1cmVyKSArICcpWy1fLlxcXFxzXScsICdpJyksIG1hbnVmYWN0dXJlciArICcgJylcbiAgICAgICAgLnJlcGxhY2UoUmVnRXhwKCdeKCcgKyBxdWFsaWZ5KG1hbnVmYWN0dXJlcikgKyAnKVstXy5dPyhcXFxcdyknLCAnaScpLCBtYW51ZmFjdHVyZXIgKyAnICQyJyk7XG4gICAgfVxuICAgIC8vIENsZWFuIHVwIEdvb2dsZSBUVi5cbiAgICBpZiAoKGRhdGEgPSAvXFxiR29vZ2xlIFRWXFxiLy5leGVjKHByb2R1Y3QpKSkge1xuICAgICAgcHJvZHVjdCA9IGRhdGFbMF07XG4gICAgfVxuICAgIC8vIERldGVjdCBzaW11bGF0b3JzLlxuICAgIGlmICgvXFxiU2ltdWxhdG9yXFxiL2kudGVzdCh1YSkpIHtcbiAgICAgIHByb2R1Y3QgPSAocHJvZHVjdCA/IHByb2R1Y3QgKyAnICcgOiAnJykgKyAnU2ltdWxhdG9yJztcbiAgICB9XG4gICAgLy8gRGV0ZWN0IE9wZXJhIE1pbmkgOCsgcnVubmluZyBpbiBUdXJiby9VbmNvbXByZXNzZWQgbW9kZSBvbiBpT1MuXG4gICAgaWYgKG5hbWUgPT0gJ09wZXJhIE1pbmknICYmIC9cXGJPUGlPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ3J1bm5pbmcgaW4gVHVyYm8vVW5jb21wcmVzc2VkIG1vZGUnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIE1vYmlsZSAxMS5cbiAgICBpZiAobmFtZSA9PSAnSUUnICYmIC9cXGJsaWtlIGlQaG9uZSBPU1xcYi8udGVzdCh1YSkpIHtcbiAgICAgIGRhdGEgPSBwYXJzZSh1YS5yZXBsYWNlKC9saWtlIGlQaG9uZSBPUy8sICcnKSk7XG4gICAgICBtYW51ZmFjdHVyZXIgPSBkYXRhLm1hbnVmYWN0dXJlcjtcbiAgICAgIHByb2R1Y3QgPSBkYXRhLnByb2R1Y3Q7XG4gICAgfVxuICAgIC8vIERldGVjdCBpT1MuXG4gICAgZWxzZSBpZiAoL15pUC8udGVzdChwcm9kdWN0KSkge1xuICAgICAgbmFtZSB8fCAobmFtZSA9ICdTYWZhcmknKTtcbiAgICAgIG9zID0gJ2lPUycgKyAoKGRhdGEgPSAvIE9TIChbXFxkX10rKS9pLmV4ZWModWEpKVxuICAgICAgICA/ICcgJyArIGRhdGFbMV0ucmVwbGFjZSgvXy9nLCAnLicpXG4gICAgICAgIDogJycpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgS3VidW50dS5cbiAgICBlbHNlIGlmIChuYW1lID09ICdLb25xdWVyb3InICYmIC9eTGludXhcXGIvaS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSAnS3VidW50dSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBBbmRyb2lkIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKChtYW51ZmFjdHVyZXIgJiYgbWFudWZhY3R1cmVyICE9ICdHb29nbGUnICYmXG4gICAgICAgICgoL0Nocm9tZS8udGVzdChuYW1lKSAmJiAhL1xcYk1vYmlsZSBTYWZhcmlcXGIvaS50ZXN0KHVhKSkgfHwgL1xcYlZpdGFcXGIvLnRlc3QocHJvZHVjdCkpKSB8fFxuICAgICAgICAoL1xcYkFuZHJvaWRcXGIvLnRlc3Qob3MpICYmIC9eQ2hyb21lLy50ZXN0KG5hbWUpICYmIC9cXGJWZXJzaW9uXFwvL2kudGVzdCh1YSkpKSB7XG4gICAgICBuYW1lID0gJ0FuZHJvaWQgQnJvd3Nlcic7XG4gICAgICBvcyA9IC9cXGJBbmRyb2lkXFxiLy50ZXN0KG9zKSA/IG9zIDogJ0FuZHJvaWQnO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgU2lsayBkZXNrdG9wL2FjY2VsZXJhdGVkIG1vZGVzLlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ1NpbGsnKSB7XG4gICAgICBpZiAoIS9cXGJNb2JpL2kudGVzdCh1YSkpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZCc7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgICAgfVxuICAgICAgaWYgKC9BY2NlbGVyYXRlZCAqPSAqdHJ1ZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2FjY2VsZXJhdGVkJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBVQyBCcm93c2VyIHNwZWVkIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnVUMgQnJvd3NlcicgJiYgL1xcYlVDV0VCXFxiLy50ZXN0KHVhKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnc3BlZWQgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgUGFsZU1vb24gaWRlbnRpZnlpbmcgYXMgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdQYWxlTW9vbicgJiYgKGRhdGEgPSAvXFxiRmlyZWZveFxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkpKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyBGaXJlZm94ICcgKyBkYXRhWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggT1MgYW5kIHByb2R1Y3RzIHJ1bm5pbmcgRmlyZWZveC5cbiAgICBlbHNlIGlmIChuYW1lID09ICdGaXJlZm94JyAmJiAoZGF0YSA9IC9cXGIoTW9iaWxlfFRhYmxldHxUVilcXGIvaS5leGVjKHVhKSkpIHtcbiAgICAgIG9zIHx8IChvcyA9ICdGaXJlZm94IE9TJyk7XG4gICAgICBwcm9kdWN0IHx8IChwcm9kdWN0ID0gZGF0YVsxXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBmYWxzZSBwb3NpdGl2ZXMgZm9yIEZpcmVmb3gvU2FmYXJpLlxuICAgIGVsc2UgaWYgKCFuYW1lIHx8IChkYXRhID0gIS9cXGJNaW5lZmllbGRcXGIvaS50ZXN0KHVhKSAmJiAvXFxiKD86RmlyZWZveHxTYWZhcmkpXFxiLy5leGVjKG5hbWUpKSkge1xuICAgICAgLy8gRXNjYXBlIHRoZSBgL2AgZm9yIEZpcmVmb3ggMS5cbiAgICAgIGlmIChuYW1lICYmICFwcm9kdWN0ICYmIC9bXFwvLF18XlteKF0rP1xcKS8udGVzdCh1YS5zbGljZSh1YS5pbmRleE9mKGRhdGEgKyAnLycpICsgOCkpKSB7XG4gICAgICAgIC8vIENsZWFyIG5hbWUgb2YgZmFsc2UgcG9zaXRpdmVzLlxuICAgICAgICBuYW1lID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFJlYXNzaWduIGEgZ2VuZXJpYyBuYW1lLlxuICAgICAgaWYgKChkYXRhID0gcHJvZHVjdCB8fCBtYW51ZmFjdHVyZXIgfHwgb3MpICYmXG4gICAgICAgICAgKHByb2R1Y3QgfHwgbWFudWZhY3R1cmVyIHx8IC9cXGIoPzpBbmRyb2lkfFN5bWJpYW4gT1N8VGFibGV0IE9TfHdlYk9TKVxcYi8udGVzdChvcykpKSB7XG4gICAgICAgIG5hbWUgPSAvW2Etel0rKD86IEhhdCk/L2kuZXhlYygvXFxiQW5kcm9pZFxcYi8udGVzdChvcykgPyBvcyA6IGRhdGEpICsgJyBCcm93c2VyJztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQWRkIENocm9tZSB2ZXJzaW9uIHRvIGRlc2NyaXB0aW9uIGZvciBFbGVjdHJvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdFbGVjdHJvbicgJiYgKGRhdGEgPSAoL1xcYkNocm9tZVxcLyhbXFxkLl0rKVxcYi8uZXhlYyh1YSkgfHwgMClbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCdDaHJvbWl1bSAnICsgZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBub24tT3BlcmEgKFByZXN0by1iYXNlZCkgdmVyc2lvbnMgKG9yZGVyIGlzIGltcG9ydGFudCkuXG4gICAgaWYgKCF2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gZ2V0VmVyc2lvbihbXG4gICAgICAgICcoPzpDbG91ZDl8Q3JpT1N8Q3JNb3xFZGdlfEVkZ3xFZGdBfEVkZ2lPU3xGeGlPU3xIZWFkbGVzc0Nocm9tZXxJRU1vYmlsZXxJcm9ufE9wZXJhID9NaW5pfE9QaU9TfE9QUnxSYXZlbnxTYW1zdW5nQnJvd3NlcnxTaWxrKD8hL1tcXFxcZC5dKyQpfFVDQnJvd3NlcnxZYUJyb3dzZXIpJyxcbiAgICAgICAgJ1ZlcnNpb24nLFxuICAgICAgICBxdWFsaWZ5KG5hbWUpLFxuICAgICAgICAnKD86RmlyZWZveHxNaW5lZmllbGR8TmV0RnJvbnQpJ1xuICAgICAgXSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBzdHViYm9ybiBsYXlvdXQgZW5naW5lcy5cbiAgICBpZiAoKGRhdGEgPVxuICAgICAgICAgIGxheW91dCA9PSAnaUNhYicgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+IDMgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAvXFxiT3BlcmFcXGIvLnRlc3QobmFtZSkgJiYgKC9cXGJPUFJcXGIvLnRlc3QodWEpID8gJ0JsaW5rJyA6ICdQcmVzdG8nKSB8fFxuICAgICAgICAgIC9cXGIoPzpNaWRvcml8Tm9va3xTYWZhcmkpXFxiL2kudGVzdCh1YSkgJiYgIS9eKD86VHJpZGVudHxFZGdlSFRNTCkkLy50ZXN0KGxheW91dCkgJiYgJ1dlYktpdCcgfHxcbiAgICAgICAgICAhbGF5b3V0ICYmIC9cXGJNU0lFXFxiL2kudGVzdCh1YSkgJiYgKG9zID09ICdNYWMgT1MnID8gJ1Rhc21hbicgOiAnVHJpZGVudCcpIHx8XG4gICAgICAgICAgbGF5b3V0ID09ICdXZWJLaXQnICYmIC9cXGJQbGF5U3RhdGlvblxcYig/ISBWaXRhXFxiKS9pLnRlc3QobmFtZSkgJiYgJ05ldEZyb250J1xuICAgICAgICApKSB7XG4gICAgICBsYXlvdXQgPSBbZGF0YV07XG4gICAgfVxuICAgIC8vIERldGVjdCBXaW5kb3dzIFBob25lIDcgZGVza3RvcCBtb2RlLlxuICAgIGlmIChuYW1lID09ICdJRScgJiYgKGRhdGEgPSAoLzsgKig/OlhCTFdQfFp1bmVXUCkoXFxkKykvaS5leGVjKHVhKSB8fCAwKVsxXSkpIHtcbiAgICAgIG5hbWUgKz0gJyBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSAnICsgKC9cXCskLy50ZXN0KGRhdGEpID8gZGF0YSA6IGRhdGEgKyAnLngnKTtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2Rlc2t0b3AgbW9kZScpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgV2luZG93cyBQaG9uZSA4LnggZGVza3RvcCBtb2RlLlxuICAgIGVsc2UgaWYgKC9cXGJXUERlc2t0b3BcXGIvaS50ZXN0KHVhKSkge1xuICAgICAgbmFtZSA9ICdJRSBNb2JpbGUnO1xuICAgICAgb3MgPSAnV2luZG93cyBQaG9uZSA4LngnO1xuICAgICAgZGVzY3JpcHRpb24udW5zaGlmdCgnZGVza3RvcCBtb2RlJyk7XG4gICAgICB2ZXJzaW9uIHx8ICh2ZXJzaW9uID0gKC9cXGJydjooW1xcZC5dKykvLmV4ZWModWEpIHx8IDApWzFdKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IElFIDExIGlkZW50aWZ5aW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgIGVsc2UgaWYgKG5hbWUgIT0gJ0lFJyAmJiBsYXlvdXQgPT0gJ1RyaWRlbnQnICYmIChkYXRhID0gL1xcYnJ2OihbXFxkLl0rKS8uZXhlYyh1YSkpKSB7XG4gICAgICBpZiAobmFtZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdpZGVudGlmeWluZyBhcyAnICsgbmFtZSArICh2ZXJzaW9uID8gJyAnICsgdmVyc2lvbiA6ICcnKSk7XG4gICAgICB9XG4gICAgICBuYW1lID0gJ0lFJztcbiAgICAgIHZlcnNpb24gPSBkYXRhWzFdO1xuICAgIH1cbiAgICAvLyBMZXZlcmFnZSBlbnZpcm9ubWVudCBmZWF0dXJlcy5cbiAgICBpZiAodXNlRmVhdHVyZXMpIHtcbiAgICAgIC8vIERldGVjdCBzZXJ2ZXItc2lkZSBlbnZpcm9ubWVudHMuXG4gICAgICAvLyBSaGlubyBoYXMgYSBnbG9iYWwgZnVuY3Rpb24gd2hpbGUgb3RoZXJzIGhhdmUgYSBnbG9iYWwgb2JqZWN0LlxuICAgICAgaWYgKGlzSG9zdFR5cGUoY29udGV4dCwgJ2dsb2JhbCcpKSB7XG4gICAgICAgIGlmIChqYXZhKSB7XG4gICAgICAgICAgZGF0YSA9IGphdmEubGFuZy5TeXN0ZW07XG4gICAgICAgICAgYXJjaCA9IGRhdGEuZ2V0UHJvcGVydHkoJ29zLmFyY2gnKTtcbiAgICAgICAgICBvcyA9IG9zIHx8IGRhdGEuZ2V0UHJvcGVydHkoJ29zLm5hbWUnKSArICcgJyArIGRhdGEuZ2V0UHJvcGVydHkoJ29zLnZlcnNpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmhpbm8pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmVyc2lvbiA9IGNvbnRleHQucmVxdWlyZSgncmluZ28vZW5naW5lJykudmVyc2lvbi5qb2luKCcuJyk7XG4gICAgICAgICAgICBuYW1lID0gJ1JpbmdvSlMnO1xuICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgaWYgKChkYXRhID0gY29udGV4dC5zeXN0ZW0pICYmIGRhdGEuZ2xvYmFsLnN5c3RlbSA9PSBjb250ZXh0LnN5c3RlbSkge1xuICAgICAgICAgICAgICBuYW1lID0gJ05hcndoYWwnO1xuICAgICAgICAgICAgICBvcyB8fCAob3MgPSBkYXRhWzBdLm9zIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnUmhpbm8nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgY29udGV4dC5wcm9jZXNzID09ICdvYmplY3QnICYmICFjb250ZXh0LnByb2Nlc3MuYnJvd3NlciAmJlxuICAgICAgICAgIChkYXRhID0gY29udGV4dC5wcm9jZXNzKVxuICAgICAgICApIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGEudmVyc2lvbnMgPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS52ZXJzaW9ucy5lbGVjdHJvbiA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICBkZXNjcmlwdGlvbi5wdXNoKCdOb2RlICcgKyBkYXRhLnZlcnNpb25zLm5vZGUpO1xuICAgICAgICAgICAgICBuYW1lID0gJ0VsZWN0cm9uJztcbiAgICAgICAgICAgICAgdmVyc2lvbiA9IGRhdGEudmVyc2lvbnMuZWxlY3Ryb247XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhLnZlcnNpb25zLm53ID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0Nocm9taXVtICcgKyB2ZXJzaW9uLCAnTm9kZSAnICsgZGF0YS52ZXJzaW9ucy5ub2RlKTtcbiAgICAgICAgICAgICAgbmFtZSA9ICdOVy5qcyc7XG4gICAgICAgICAgICAgIHZlcnNpb24gPSBkYXRhLnZlcnNpb25zLm53O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIG5hbWUgPSAnTm9kZS5qcyc7XG4gICAgICAgICAgICBhcmNoID0gZGF0YS5hcmNoO1xuICAgICAgICAgICAgb3MgPSBkYXRhLnBsYXRmb3JtO1xuICAgICAgICAgICAgdmVyc2lvbiA9IC9bXFxkLl0rLy5leGVjKGRhdGEudmVyc2lvbik7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbiA/IHZlcnNpb25bMF0gOiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IEFkb2JlIEFJUi5cbiAgICAgIGVsc2UgaWYgKGdldENsYXNzT2YoKGRhdGEgPSBjb250ZXh0LnJ1bnRpbWUpKSA9PSBhaXJSdW50aW1lQ2xhc3MpIHtcbiAgICAgICAgbmFtZSA9ICdBZG9iZSBBSVInO1xuICAgICAgICBvcyA9IGRhdGEuZmxhc2guc3lzdGVtLkNhcGFiaWxpdGllcy5vcztcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBQaGFudG9tSlMuXG4gICAgICBlbHNlIGlmIChnZXRDbGFzc09mKChkYXRhID0gY29udGV4dC5waGFudG9tKSkgPT0gcGhhbnRvbUNsYXNzKSB7XG4gICAgICAgIG5hbWUgPSAnUGhhbnRvbUpTJztcbiAgICAgICAgdmVyc2lvbiA9IChkYXRhID0gZGF0YS52ZXJzaW9uIHx8IG51bGwpICYmIChkYXRhLm1ham9yICsgJy4nICsgZGF0YS5taW5vciArICcuJyArIGRhdGEucGF0Y2gpO1xuICAgICAgfVxuICAgICAgLy8gRGV0ZWN0IElFIGNvbXBhdGliaWxpdHkgbW9kZXMuXG4gICAgICBlbHNlIGlmICh0eXBlb2YgZG9jLmRvY3VtZW50TW9kZSA9PSAnbnVtYmVyJyAmJiAoZGF0YSA9IC9cXGJUcmlkZW50XFwvKFxcZCspL2kuZXhlYyh1YSkpKSB7XG4gICAgICAgIC8vIFdlJ3JlIGluIGNvbXBhdGliaWxpdHkgbW9kZSB3aGVuIHRoZSBUcmlkZW50IHZlcnNpb24gKyA0IGRvZXNuJ3RcbiAgICAgICAgLy8gZXF1YWwgdGhlIGRvY3VtZW50IG1vZGUuXG4gICAgICAgIHZlcnNpb24gPSBbdmVyc2lvbiwgZG9jLmRvY3VtZW50TW9kZV07XG4gICAgICAgIGlmICgoZGF0YSA9ICtkYXRhWzFdICsgNCkgIT0gdmVyc2lvblsxXSkge1xuICAgICAgICAgIGRlc2NyaXB0aW9uLnB1c2goJ0lFICcgKyB2ZXJzaW9uWzFdICsgJyBtb2RlJyk7XG4gICAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnJyk7XG4gICAgICAgICAgdmVyc2lvblsxXSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgdmVyc2lvbiA9IG5hbWUgPT0gJ0lFJyA/IFN0cmluZyh2ZXJzaW9uWzFdLnRvRml4ZWQoMSkpIDogdmVyc2lvblswXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBJRSAxMSBtYXNraW5nIGFzIG90aGVyIGJyb3dzZXJzLlxuICAgICAgZWxzZSBpZiAodHlwZW9mIGRvYy5kb2N1bWVudE1vZGUgPT0gJ251bWJlcicgJiYgL14oPzpDaHJvbWV8RmlyZWZveClcXGIvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24ucHVzaCgnbWFza2luZyBhcyAnICsgbmFtZSArICcgJyArIHZlcnNpb24pO1xuICAgICAgICBuYW1lID0gJ0lFJztcbiAgICAgICAgdmVyc2lvbiA9ICcxMS4wJztcbiAgICAgICAgbGF5b3V0ID0gWydUcmlkZW50J107XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcyAmJiBmb3JtYXQob3MpO1xuICAgIH1cbiAgICAvLyBEZXRlY3QgcHJlcmVsZWFzZSBwaGFzZXMuXG4gICAgaWYgKHZlcnNpb24gJiYgKGRhdGEgPVxuICAgICAgICAgIC8oPzpbYWJdfGRwfHByZXxbYWJdXFxkK3ByZSkoPzpcXGQrXFwrPyk/JC9pLmV4ZWModmVyc2lvbikgfHxcbiAgICAgICAgICAvKD86YWxwaGF8YmV0YSkoPzogP1xcZCk/L2kuZXhlYyh1YSArICc7JyArICh1c2VGZWF0dXJlcyAmJiBuYXYuYXBwTWlub3JWZXJzaW9uKSkgfHxcbiAgICAgICAgICAvXFxiTWluZWZpZWxkXFxiL2kudGVzdCh1YSkgJiYgJ2EnXG4gICAgICAgICkpIHtcbiAgICAgIHByZXJlbGVhc2UgPSAvYi9pLnRlc3QoZGF0YSkgPyAnYmV0YScgOiAnYWxwaGEnO1xuICAgICAgdmVyc2lvbiA9IHZlcnNpb24ucmVwbGFjZShSZWdFeHAoZGF0YSArICdcXFxcKz8kJyksICcnKSArXG4gICAgICAgIChwcmVyZWxlYXNlID09ICdiZXRhJyA/IGJldGEgOiBhbHBoYSkgKyAoL1xcZCtcXCs/Ly5leGVjKGRhdGEpIHx8ICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IEZpcmVmb3ggTW9iaWxlLlxuICAgIGlmIChuYW1lID09ICdGZW5uZWMnIHx8IG5hbWUgPT0gJ0ZpcmVmb3gnICYmIC9cXGIoPzpBbmRyb2lkfEZpcmVmb3ggT1N8S2FpT1MpXFxiLy50ZXN0KG9zKSkge1xuICAgICAgbmFtZSA9ICdGaXJlZm94IE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIE9ic2N1cmUgTWF4dGhvbidzIHVucmVsaWFibGUgdmVyc2lvbi5cbiAgICBlbHNlIGlmIChuYW1lID09ICdNYXh0aG9uJyAmJiB2ZXJzaW9uKSB7XG4gICAgICB2ZXJzaW9uID0gdmVyc2lvbi5yZXBsYWNlKC9cXC5bXFxkLl0rLywgJy54Jyk7XG4gICAgfVxuICAgIC8vIERldGVjdCBYYm94IDM2MCBhbmQgWGJveCBPbmUuXG4gICAgZWxzZSBpZiAoL1xcYlhib3hcXGIvaS50ZXN0KHByb2R1Y3QpKSB7XG4gICAgICBpZiAocHJvZHVjdCA9PSAnWGJveCAzNjAnKSB7XG4gICAgICAgIG9zID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9kdWN0ID09ICdYYm94IDM2MCcgJiYgL1xcYklFTW9iaWxlXFxiLy50ZXN0KHVhKSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdtb2JpbGUgbW9kZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBBZGQgbW9iaWxlIHBvc3RmaXguXG4gICAgZWxzZSBpZiAoKC9eKD86Q2hyb21lfElFfE9wZXJhKSQvLnRlc3QobmFtZSkgfHwgbmFtZSAmJiAhcHJvZHVjdCAmJiAhL0Jyb3dzZXJ8TW9iaS8udGVzdChuYW1lKSkgJiZcbiAgICAgICAgKG9zID09ICdXaW5kb3dzIENFJyB8fCAvTW9iaS9pLnRlc3QodWEpKSkge1xuICAgICAgbmFtZSArPSAnIE1vYmlsZSc7XG4gICAgfVxuICAgIC8vIERldGVjdCBJRSBwbGF0Zm9ybSBwcmV2aWV3LlxuICAgIGVsc2UgaWYgKG5hbWUgPT0gJ0lFJyAmJiB1c2VGZWF0dXJlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGNvbnRleHQuZXh0ZXJuYWwgPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdwbGF0Zm9ybSBwcmV2aWV3Jyk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdlbWJlZGRlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBEZXRlY3QgQmxhY2tCZXJyeSBPUyB2ZXJzaW9uLlxuICAgIC8vIGh0dHA6Ly9kb2NzLmJsYWNrYmVycnkuY29tL2VuL2RldmVsb3BlcnMvZGVsaXZlcmFibGVzLzE4MTY5L0hUVFBfaGVhZGVyc19zZW50X2J5X0JCX0Jyb3dzZXJfMTIzNDkxMV8xMS5qc3BcbiAgICBlbHNlIGlmICgoL1xcYkJsYWNrQmVycnlcXGIvLnRlc3QocHJvZHVjdCkgfHwgL1xcYkJCMTBcXGIvLnRlc3QodWEpKSAmJiAoZGF0YSA9XG4gICAgICAgICAgKFJlZ0V4cChwcm9kdWN0LnJlcGxhY2UoLyArL2csICcgKicpICsgJy8oWy5cXFxcZF0rKScsICdpJykuZXhlYyh1YSkgfHwgMClbMV0gfHxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICkpIHtcbiAgICAgIGRhdGEgPSBbZGF0YSwgL0JCMTAvLnRlc3QodWEpXTtcbiAgICAgIG9zID0gKGRhdGFbMV0gPyAocHJvZHVjdCA9IG51bGwsIG1hbnVmYWN0dXJlciA9ICdCbGFja0JlcnJ5JykgOiAnRGV2aWNlIFNvZnR3YXJlJykgKyAnICcgKyBkYXRhWzBdO1xuICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBpZGVudGlmeWluZy9tYXNraW5nIGl0c2VsZiBhcyBhbm90aGVyIGJyb3dzZXIuXG4gICAgLy8gaHR0cDovL3d3dy5vcGVyYS5jb20vc3VwcG9ydC9rYi92aWV3Lzg0My9cbiAgICBlbHNlIGlmICh0aGlzICE9IGZvck93biAmJiBwcm9kdWN0ICE9ICdXaWknICYmIChcbiAgICAgICAgICAodXNlRmVhdHVyZXMgJiYgb3BlcmEpIHx8XG4gICAgICAgICAgKC9PcGVyYS8udGVzdChuYW1lKSAmJiAvXFxiKD86TVNJRXxGaXJlZm94KVxcYi9pLnRlc3QodWEpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdGaXJlZm94JyAmJiAvXFxiT1MgWCAoPzpcXGQrXFwuKXsyLH0vLnRlc3Qob3MpKSB8fFxuICAgICAgICAgIChuYW1lID09ICdJRScgJiYgKFxuICAgICAgICAgICAgKG9zICYmICEvXldpbi8udGVzdChvcykgJiYgdmVyc2lvbiA+IDUuNSkgfHxcbiAgICAgICAgICAgIC9cXGJXaW5kb3dzIFhQXFxiLy50ZXN0KG9zKSAmJiB2ZXJzaW9uID4gOCB8fFxuICAgICAgICAgICAgdmVyc2lvbiA9PSA4ICYmICEvXFxiVHJpZGVudFxcYi8udGVzdCh1YSlcbiAgICAgICAgICApKVxuICAgICAgICApICYmICFyZU9wZXJhLnRlc3QoKGRhdGEgPSBwYXJzZS5jYWxsKGZvck93biwgdWEucmVwbGFjZShyZU9wZXJhLCAnJykgKyAnOycpKSkgJiYgZGF0YS5uYW1lKSB7XG4gICAgICAvLyBXaGVuIFwiaWRlbnRpZnlpbmdcIiwgdGhlIFVBIGNvbnRhaW5zIGJvdGggT3BlcmEgYW5kIHRoZSBvdGhlciBicm93c2VyJ3MgbmFtZS5cbiAgICAgIGRhdGEgPSAnaW5nIGFzICcgKyBkYXRhLm5hbWUgKyAoKGRhdGEgPSBkYXRhLnZlcnNpb24pID8gJyAnICsgZGF0YSA6ICcnKTtcbiAgICAgIGlmIChyZU9wZXJhLnRlc3QobmFtZSkpIHtcbiAgICAgICAgaWYgKC9cXGJJRVxcYi8udGVzdChkYXRhKSAmJiBvcyA9PSAnTWFjIE9TJykge1xuICAgICAgICAgIG9zID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBkYXRhID0gJ2lkZW50aWZ5JyArIGRhdGE7XG4gICAgICB9XG4gICAgICAvLyBXaGVuIFwibWFza2luZ1wiLCB0aGUgVUEgY29udGFpbnMgb25seSB0aGUgb3RoZXIgYnJvd3NlcidzIG5hbWUuXG4gICAgICBlbHNlIHtcbiAgICAgICAgZGF0YSA9ICdtYXNrJyArIGRhdGE7XG4gICAgICAgIGlmIChvcGVyYUNsYXNzKSB7XG4gICAgICAgICAgbmFtZSA9IGZvcm1hdChvcGVyYUNsYXNzLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMSAkMicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lID0gJ09wZXJhJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcYklFXFxiLy50ZXN0KGRhdGEpKSB7XG4gICAgICAgICAgb3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdXNlRmVhdHVyZXMpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGF5b3V0ID0gWydQcmVzdG8nXTtcbiAgICAgIGRlc2NyaXB0aW9uLnB1c2goZGF0YSk7XG4gICAgfVxuICAgIC8vIERldGVjdCBXZWJLaXQgTmlnaHRseSBhbmQgYXBwcm94aW1hdGUgQ2hyb21lL1NhZmFyaSB2ZXJzaW9ucy5cbiAgICBpZiAoKGRhdGEgPSAoL1xcYkFwcGxlV2ViS2l0XFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgLy8gQ29ycmVjdCBidWlsZCBudW1iZXIgZm9yIG51bWVyaWMgY29tcGFyaXNvbi5cbiAgICAgIC8vIChlLmcuIFwiNTMyLjVcIiBiZWNvbWVzIFwiNTMyLjA1XCIpXG4gICAgICBkYXRhID0gW3BhcnNlRmxvYXQoZGF0YS5yZXBsYWNlKC9cXC4oXFxkKSQvLCAnLjAkMScpKSwgZGF0YV07XG4gICAgICAvLyBOaWdodGx5IGJ1aWxkcyBhcmUgcG9zdGZpeGVkIHdpdGggYSBcIitcIi5cbiAgICAgIGlmIChuYW1lID09ICdTYWZhcmknICYmIGRhdGFbMV0uc2xpY2UoLTEpID09ICcrJykge1xuICAgICAgICBuYW1lID0gJ1dlYktpdCBOaWdodGx5JztcbiAgICAgICAgcHJlcmVsZWFzZSA9ICdhbHBoYSc7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhWzFdLnNsaWNlKDAsIC0xKTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFyIGluY29ycmVjdCBicm93c2VyIHZlcnNpb25zLlxuICAgICAgZWxzZSBpZiAodmVyc2lvbiA9PSBkYXRhWzFdIHx8XG4gICAgICAgICAgdmVyc2lvbiA9PSAoZGF0YVsyXSA9ICgvXFxiU2FmYXJpXFwvKFtcXGQuXStcXCs/KS9pLmV4ZWModWEpIHx8IDApWzFdKSkge1xuICAgICAgICB2ZXJzaW9uID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSB0aGUgZnVsbCBDaHJvbWUgdmVyc2lvbiB3aGVuIGF2YWlsYWJsZS5cbiAgICAgIGRhdGFbMV0gPSAoL1xcYig/OkhlYWRsZXNzKT9DaHJvbWVcXC8oW1xcZC5dKykvaS5leGVjKHVhKSB8fCAwKVsxXTtcbiAgICAgIC8vIERldGVjdCBCbGluayBsYXlvdXQgZW5naW5lLlxuICAgICAgaWYgKGRhdGFbMF0gPT0gNTM3LjM2ICYmIGRhdGFbMl0gPT0gNTM3LjM2ICYmIHBhcnNlRmxvYXQoZGF0YVsxXSkgPj0gMjggJiYgbGF5b3V0ID09ICdXZWJLaXQnKSB7XG4gICAgICAgIGxheW91dCA9IFsnQmxpbmsnXTtcbiAgICAgIH1cbiAgICAgIC8vIERldGVjdCBKYXZhU2NyaXB0Q29yZS5cbiAgICAgIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjc2ODQ3NC9ob3ctY2FuLWktZGV0ZWN0LXdoaWNoLWphdmFzY3JpcHQtZW5naW5lLXY4LW9yLWpzYy1pcy11c2VkLWF0LXJ1bnRpbWUtaW4tYW5kcm9pXG4gICAgICBpZiAoIXVzZUZlYXR1cmVzIHx8ICghbGlrZUNocm9tZSAmJiAhZGF0YVsxXSkpIHtcbiAgICAgICAgbGF5b3V0ICYmIChsYXlvdXRbMV0gPSAnbGlrZSBTYWZhcmknKTtcbiAgICAgICAgZGF0YSA9IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDQwMCA/IDEgOiBkYXRhIDwgNTAwID8gMiA6IGRhdGEgPCA1MjYgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0ID8gJzQrJyA6IGRhdGEgPCA1MzUgPyA1IDogZGF0YSA8IDUzNyA/IDYgOiBkYXRhIDwgNTM4ID8gNyA6IGRhdGEgPCA2MDEgPyA4IDogZGF0YSA8IDYwMiA/IDkgOiBkYXRhIDwgNjA0ID8gMTAgOiBkYXRhIDwgNjA2ID8gMTEgOiBkYXRhIDwgNjA4ID8gMTIgOiAnMTInKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdID0gJ2xpa2UgQ2hyb21lJyk7XG4gICAgICAgIGRhdGEgPSBkYXRhWzFdIHx8IChkYXRhID0gZGF0YVswXSwgZGF0YSA8IDUzMCA/IDEgOiBkYXRhIDwgNTMyID8gMiA6IGRhdGEgPCA1MzIuMDUgPyAzIDogZGF0YSA8IDUzMyA/IDQgOiBkYXRhIDwgNTM0LjAzID8gNSA6IGRhdGEgPCA1MzQuMDcgPyA2IDogZGF0YSA8IDUzNC4xMCA/IDcgOiBkYXRhIDwgNTM0LjEzID8gOCA6IGRhdGEgPCA1MzQuMTYgPyA5IDogZGF0YSA8IDUzNC4yNCA/IDEwIDogZGF0YSA8IDUzNC4zMCA/IDExIDogZGF0YSA8IDUzNS4wMSA/IDEyIDogZGF0YSA8IDUzNS4wMiA/ICcxMysnIDogZGF0YSA8IDUzNS4wNyA/IDE1IDogZGF0YSA8IDUzNS4xMSA/IDE2IDogZGF0YSA8IDUzNS4xOSA/IDE3IDogZGF0YSA8IDUzNi4wNSA/IDE4IDogZGF0YSA8IDUzNi4xMCA/IDE5IDogZGF0YSA8IDUzNy4wMSA/IDIwIDogZGF0YSA8IDUzNy4xMSA/ICcyMSsnIDogZGF0YSA8IDUzNy4xMyA/IDIzIDogZGF0YSA8IDUzNy4xOCA/IDI0IDogZGF0YSA8IDUzNy4yNCA/IDI1IDogZGF0YSA8IDUzNy4zNiA/IDI2IDogbGF5b3V0ICE9ICdCbGluaycgPyAnMjcnIDogJzI4Jyk7XG4gICAgICB9XG4gICAgICAvLyBBZGQgdGhlIHBvc3RmaXggb2YgXCIueFwiIG9yIFwiK1wiIGZvciBhcHByb3hpbWF0ZSB2ZXJzaW9ucy5cbiAgICAgIGxheW91dCAmJiAobGF5b3V0WzFdICs9ICcgJyArIChkYXRhICs9IHR5cGVvZiBkYXRhID09ICdudW1iZXInID8gJy54JyA6IC9bLitdLy50ZXN0KGRhdGEpID8gJycgOiAnKycpKTtcbiAgICAgIC8vIE9ic2N1cmUgdmVyc2lvbiBmb3Igc29tZSBTYWZhcmkgMS0yIHJlbGVhc2VzLlxuICAgICAgaWYgKG5hbWUgPT0gJ1NhZmFyaScgJiYgKCF2ZXJzaW9uIHx8IHBhcnNlSW50KHZlcnNpb24pID4gNDUpKSB7XG4gICAgICAgIHZlcnNpb24gPSBkYXRhO1xuICAgICAgfSBlbHNlIGlmIChuYW1lID09ICdDaHJvbWUnICYmIC9cXGJIZWFkbGVzc0Nocm9tZS9pLnRlc3QodWEpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQoJ2hlYWRsZXNzJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIERldGVjdCBPcGVyYSBkZXNrdG9wIG1vZGVzLlxuICAgIGlmIChuYW1lID09ICdPcGVyYScgJiYgIChkYXRhID0gL1xcYnpib3Z8enZhdiQvLmV4ZWMob3MpKSkge1xuICAgICAgbmFtZSArPSAnICc7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIGlmIChkYXRhID09ICd6dmF2Jykge1xuICAgICAgICBuYW1lICs9ICdNaW5pJztcbiAgICAgICAgdmVyc2lvbiA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuYW1lICs9ICdNb2JpbGUnO1xuICAgICAgfVxuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgZGF0YSArICckJyksICcnKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IENocm9tZSBkZXNrdG9wIG1vZGUuXG4gICAgZWxzZSBpZiAobmFtZSA9PSAnU2FmYXJpJyAmJiAvXFxiQ2hyb21lXFxiLy5leGVjKGxheW91dCAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCdkZXNrdG9wIG1vZGUnKTtcbiAgICAgIG5hbWUgPSAnQ2hyb21lIE1vYmlsZSc7XG4gICAgICB2ZXJzaW9uID0gbnVsbDtcblxuICAgICAgaWYgKC9cXGJPUyBYXFxiLy50ZXN0KG9zKSkge1xuICAgICAgICBtYW51ZmFjdHVyZXIgPSAnQXBwbGUnO1xuICAgICAgICBvcyA9ICdpT1MgNC4zKyc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIE5ld2VyIHZlcnNpb25zIG9mIFNSV2FyZSBJcm9uIHVzZXMgdGhlIENocm9tZSB0YWcgdG8gaW5kaWNhdGUgaXRzIHZlcnNpb24gbnVtYmVyLlxuICAgIGVsc2UgaWYgKC9cXGJTUldhcmUgSXJvblxcYi8udGVzdChuYW1lKSAmJiAhdmVyc2lvbikge1xuICAgICAgdmVyc2lvbiA9IGdldFZlcnNpb24oJ0Nocm9tZScpO1xuICAgIH1cbiAgICAvLyBTdHJpcCBpbmNvcnJlY3QgT1MgdmVyc2lvbnMuXG4gICAgaWYgKHZlcnNpb24gJiYgdmVyc2lvbi5pbmRleE9mKChkYXRhID0gL1tcXGQuXSskLy5leGVjKG9zKSkpID09IDAgJiZcbiAgICAgICAgdWEuaW5kZXhPZignLycgKyBkYXRhICsgJy0nKSA+IC0xKSB7XG4gICAgICBvcyA9IHRyaW0ob3MucmVwbGFjZShkYXRhLCAnJykpO1xuICAgIH1cbiAgICAvLyBFbnN1cmUgT1MgZG9lcyBub3QgaW5jbHVkZSB0aGUgYnJvd3NlciBuYW1lLlxuICAgIGlmIChvcyAmJiBvcy5pbmRleE9mKG5hbWUpICE9IC0xICYmICFSZWdFeHAobmFtZSArICcgT1MnKS50ZXN0KG9zKSkge1xuICAgICAgb3MgPSBvcy5yZXBsYWNlKFJlZ0V4cCgnIConICsgcXVhbGlmeShuYW1lKSArICcgKicpLCAnJyk7XG4gICAgfVxuICAgIC8vIEFkZCBsYXlvdXQgZW5naW5lLlxuICAgIGlmIChsYXlvdXQgJiYgIS9cXGIoPzpBdmFudHxOb29rKVxcYi8udGVzdChuYW1lKSAmJiAoXG4gICAgICAgIC9Ccm93c2VyfEx1bmFzY2FwZXxNYXh0aG9uLy50ZXN0KG5hbWUpIHx8XG4gICAgICAgIG5hbWUgIT0gJ1NhZmFyaScgJiYgL15pT1MvLnRlc3Qob3MpICYmIC9cXGJTYWZhcmlcXGIvLnRlc3QobGF5b3V0WzFdKSB8fFxuICAgICAgICAvXig/OkFkb2JlfEFyb3JhfEJyZWFjaHxNaWRvcml8T3BlcmF8UGhhbnRvbXxSZWtvbnF8Um9ja3xTYW1zdW5nIEludGVybmV0fFNsZWlwbmlyfFNSV2FyZSBJcm9ufFZpdmFsZGl8V2ViKS8udGVzdChuYW1lKSAmJiBsYXlvdXRbMV0pKSB7XG4gICAgICAvLyBEb24ndCBhZGQgbGF5b3V0IGRldGFpbHMgdG8gZGVzY3JpcHRpb24gaWYgdGhleSBhcmUgZmFsc2V5LlxuICAgICAgKGRhdGEgPSBsYXlvdXRbbGF5b3V0Lmxlbmd0aCAtIDFdKSAmJiBkZXNjcmlwdGlvbi5wdXNoKGRhdGEpO1xuICAgIH1cbiAgICAvLyBDb21iaW5lIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgZGVzY3JpcHRpb24gPSBbJygnICsgZGVzY3JpcHRpb24uam9pbignOyAnKSArICcpJ107XG4gICAgfVxuICAgIC8vIEFwcGVuZCBtYW51ZmFjdHVyZXIgdG8gZGVzY3JpcHRpb24uXG4gICAgaWYgKG1hbnVmYWN0dXJlciAmJiBwcm9kdWN0ICYmIHByb2R1Y3QuaW5kZXhPZihtYW51ZmFjdHVyZXIpIDwgMCkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaCgnb24gJyArIG1hbnVmYWN0dXJlcik7XG4gICAgfVxuICAgIC8vIEFwcGVuZCBwcm9kdWN0IHRvIGRlc2NyaXB0aW9uLlxuICAgIGlmIChwcm9kdWN0KSB7XG4gICAgICBkZXNjcmlwdGlvbi5wdXNoKCgvXm9uIC8udGVzdChkZXNjcmlwdGlvbltkZXNjcmlwdGlvbi5sZW5ndGggLSAxXSkgPyAnJyA6ICdvbiAnKSArIHByb2R1Y3QpO1xuICAgIH1cbiAgICAvLyBQYXJzZSB0aGUgT1MgaW50byBhbiBvYmplY3QuXG4gICAgaWYgKG9zKSB7XG4gICAgICBkYXRhID0gLyAoW1xcZC4rXSspJC8uZXhlYyhvcyk7XG4gICAgICBpc1NwZWNpYWxDYXNlZE9TID0gZGF0YSAmJiBvcy5jaGFyQXQob3MubGVuZ3RoIC0gZGF0YVswXS5sZW5ndGggLSAxKSA9PSAnLyc7XG4gICAgICBvcyA9IHtcbiAgICAgICAgJ2FyY2hpdGVjdHVyZSc6IDMyLFxuICAgICAgICAnZmFtaWx5JzogKGRhdGEgJiYgIWlzU3BlY2lhbENhc2VkT1MpID8gb3MucmVwbGFjZShkYXRhWzBdLCAnJykgOiBvcyxcbiAgICAgICAgJ3ZlcnNpb24nOiBkYXRhID8gZGF0YVsxXSA6IG51bGwsXG4gICAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB2ZXJzaW9uID0gdGhpcy52ZXJzaW9uO1xuICAgICAgICAgIHJldHVybiB0aGlzLmZhbWlseSArICgodmVyc2lvbiAmJiAhaXNTcGVjaWFsQ2FzZWRPUykgPyAnICcgKyB2ZXJzaW9uIDogJycpICsgKHRoaXMuYXJjaGl0ZWN0dXJlID09IDY0ID8gJyA2NC1iaXQnIDogJycpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBBZGQgYnJvd3Nlci9PUyBhcmNoaXRlY3R1cmUuXG4gICAgaWYgKChkYXRhID0gL1xcYig/OkFNRHxJQXxXaW58V09XfHg4Nl98eCk2NFxcYi9pLmV4ZWMoYXJjaCkpICYmICEvXFxiaTY4NlxcYi9pLnRlc3QoYXJjaCkpIHtcbiAgICAgIGlmIChvcykge1xuICAgICAgICBvcy5hcmNoaXRlY3R1cmUgPSA2NDtcbiAgICAgICAgb3MuZmFtaWx5ID0gb3MuZmFtaWx5LnJlcGxhY2UoUmVnRXhwKCcgKicgKyBkYXRhKSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICAgIG5hbWUgJiYgKC9cXGJXT1c2NFxcYi9pLnRlc3QodWEpIHx8XG4gICAgICAgICAgKHVzZUZlYXR1cmVzICYmIC9cXHcoPzo4NnwzMikkLy50ZXN0KG5hdi5jcHVDbGFzcyB8fCBuYXYucGxhdGZvcm0pICYmICEvXFxiV2luNjQ7IHg2NFxcYi9pLnRlc3QodWEpKSlcbiAgICAgICkge1xuICAgICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KCczMi1iaXQnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQ2hyb21lIDM5IGFuZCBhYm92ZSBvbiBPUyBYIGlzIGFsd2F5cyA2NC1iaXQuXG4gICAgZWxzZSBpZiAoXG4gICAgICAgIG9zICYmIC9eT1MgWC8udGVzdChvcy5mYW1pbHkpICYmXG4gICAgICAgIG5hbWUgPT0gJ0Nocm9tZScgJiYgcGFyc2VGbG9hdCh2ZXJzaW9uKSA+PSAzOVxuICAgICkge1xuICAgICAgb3MuYXJjaGl0ZWN0dXJlID0gNjQ7XG4gICAgfVxuXG4gICAgdWEgfHwgKHVhID0gbnVsbCk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxhdGZvcm0gb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgcGxhdGZvcm0gPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF0Zm9ybSBkZXNjcmlwdGlvbi5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBicm93c2VyJ3MgbGF5b3V0IGVuZ2luZS5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBsYXlvdXQgZW5naW5lcyBpbmNsdWRlOlxuICAgICAqIFwiQmxpbmtcIiwgXCJFZGdlSFRNTFwiLCBcIkdlY2tvXCIsIFwiVHJpZGVudFwiIGFuZCBcIldlYktpdFwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLmxheW91dCA9IGxheW91dCAmJiBsYXlvdXRbMF07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCdzIG1hbnVmYWN0dXJlci5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIG1hbnVmYWN0dXJlcnMgaW5jbHVkZTpcbiAgICAgKiBcIkFwcGxlXCIsIFwiQXJjaG9zXCIsIFwiQW1hem9uXCIsIFwiQXN1c1wiLCBcIkJhcm5lcyAmIE5vYmxlXCIsIFwiQmxhY2tCZXJyeVwiLFxuICAgICAqIFwiR29vZ2xlXCIsIFwiSFBcIiwgXCJIVENcIiwgXCJMR1wiLCBcIk1pY3Jvc29mdFwiLCBcIk1vdG9yb2xhXCIsIFwiTmludGVuZG9cIixcbiAgICAgKiBcIk5va2lhXCIsIFwiU2Ftc3VuZ1wiIGFuZCBcIlNvbnlcIlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIHBsYXRmb3JtXG4gICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgKi9cbiAgICBwbGF0Zm9ybS5tYW51ZmFjdHVyZXIgPSBtYW51ZmFjdHVyZXI7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgYnJvd3Nlci9lbnZpcm9ubWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBsaXN0IG9mIGNvbW1vbiBicm93c2VyIG5hbWVzIGluY2x1ZGU6XG4gICAgICogXCJDaHJvbWVcIiwgXCJFbGVjdHJvblwiLCBcIkZpcmVmb3hcIiwgXCJGaXJlZm94IGZvciBpT1NcIiwgXCJJRVwiLFxuICAgICAqIFwiTWljcm9zb2Z0IEVkZ2VcIiwgXCJQaGFudG9tSlNcIiwgXCJTYWZhcmlcIiwgXCJTZWFNb25rZXlcIiwgXCJTaWxrXCIsXG4gICAgICogXCJPcGVyYSBNaW5pXCIgYW5kIFwiT3BlcmFcIlxuICAgICAqXG4gICAgICogTW9iaWxlIHZlcnNpb25zIG9mIHNvbWUgYnJvd3NlcnMgaGF2ZSBcIk1vYmlsZVwiIGFwcGVuZGVkIHRvIHRoZWlyIG5hbWU6XG4gICAgICogZWcuIFwiQ2hyb21lIE1vYmlsZVwiLCBcIkZpcmVmb3ggTW9iaWxlXCIsIFwiSUUgTW9iaWxlXCIgYW5kIFwiT3BlcmEgTW9iaWxlXCJcbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ubmFtZSA9IG5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYWxwaGEvYmV0YSByZWxlYXNlIGluZGljYXRvci5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0ucHJlcmVsZWFzZSA9IHByZXJlbGVhc2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgcHJvZHVjdCBob3N0aW5nIHRoZSBicm93c2VyLlxuICAgICAqXG4gICAgICogVGhlIGxpc3Qgb2YgY29tbW9uIHByb2R1Y3RzIGluY2x1ZGU6XG4gICAgICpcbiAgICAgKiBcIkJsYWNrQmVycnlcIiwgXCJHYWxheHkgUzRcIiwgXCJMdW1pYVwiLCBcImlQYWRcIiwgXCJpUG9kXCIsIFwiaVBob25lXCIsIFwiS2luZGxlXCIsXG4gICAgICogXCJLaW5kbGUgRmlyZVwiLCBcIk5leHVzXCIsIFwiTm9va1wiLCBcIlBsYXlCb29rXCIsIFwiVG91Y2hQYWRcIiBhbmQgXCJUcmFuc2Zvcm1lclwiXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnByb2R1Y3QgPSBwcm9kdWN0O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJyb3dzZXIncyB1c2VyIGFnZW50IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIHN0cmluZ3xudWxsXG4gICAgICovXG4gICAgcGxhdGZvcm0udWEgPSB1YTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBicm93c2VyL2Vudmlyb25tZW50IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm1cbiAgICAgKiBAdHlwZSBzdHJpbmd8bnVsbFxuICAgICAqL1xuICAgIHBsYXRmb3JtLnZlcnNpb24gPSBuYW1lICYmIHZlcnNpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKlxuICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybVxuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIHBsYXRmb3JtLm9zID0gb3MgfHwge1xuXG4gICAgICAvKipcbiAgICAgICAqIFRoZSBDUFUgYXJjaGl0ZWN0dXJlIHRoZSBPUyBpcyBidWlsdCBmb3IuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIHBsYXRmb3JtLm9zXG4gICAgICAgKiBAdHlwZSBudW1iZXJ8bnVsbFxuICAgICAgICovXG4gICAgICAnYXJjaGl0ZWN0dXJlJzogbnVsbCxcblxuICAgICAgLyoqXG4gICAgICAgKiBUaGUgZmFtaWx5IG9mIHRoZSBPUy5cbiAgICAgICAqXG4gICAgICAgKiBDb21tb24gdmFsdWVzIGluY2x1ZGU6XG4gICAgICAgKiBcIldpbmRvd3NcIiwgXCJXaW5kb3dzIFNlcnZlciAyMDA4IFIyIC8gN1wiLCBcIldpbmRvd3MgU2VydmVyIDIwMDggLyBWaXN0YVwiLFxuICAgICAgICogXCJXaW5kb3dzIFhQXCIsIFwiT1MgWFwiLCBcIkxpbnV4XCIsIFwiVWJ1bnR1XCIsIFwiRGViaWFuXCIsIFwiRmVkb3JhXCIsIFwiUmVkIEhhdFwiLFxuICAgICAgICogXCJTdVNFXCIsIFwiQW5kcm9pZFwiLCBcImlPU1wiIGFuZCBcIldpbmRvd3MgUGhvbmVcIlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ2ZhbWlseSc6IG51bGwsXG5cbiAgICAgIC8qKlxuICAgICAgICogVGhlIHZlcnNpb24gb2YgdGhlIE9TLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBwbGF0Zm9ybS5vc1xuICAgICAgICogQHR5cGUgc3RyaW5nfG51bGxcbiAgICAgICAqL1xuICAgICAgJ3ZlcnNpb24nOiBudWxsLFxuXG4gICAgICAvKipcbiAgICAgICAqIFJldHVybnMgdGhlIE9TIHN0cmluZy5cbiAgICAgICAqXG4gICAgICAgKiBAbWVtYmVyT2YgcGxhdGZvcm0ub3NcbiAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBPUyBzdHJpbmcuXG4gICAgICAgKi9cbiAgICAgICd0b1N0cmluZyc6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ251bGwnOyB9XG4gICAgfTtcblxuICAgIHBsYXRmb3JtLnBhcnNlID0gcGFyc2U7XG4gICAgcGxhdGZvcm0udG9TdHJpbmcgPSB0b1N0cmluZ1BsYXRmb3JtO1xuXG4gICAgaWYgKHBsYXRmb3JtLnZlcnNpb24pIHtcbiAgICAgIGRlc2NyaXB0aW9uLnVuc2hpZnQodmVyc2lvbik7XG4gICAgfVxuICAgIGlmIChwbGF0Zm9ybS5uYW1lKSB7XG4gICAgICBkZXNjcmlwdGlvbi51bnNoaWZ0KG5hbWUpO1xuICAgIH1cbiAgICBpZiAob3MgJiYgbmFtZSAmJiAhKG9zID09IFN0cmluZyhvcykuc3BsaXQoJyAnKVswXSAmJiAob3MgPT0gbmFtZS5zcGxpdCgnICcpWzBdIHx8IHByb2R1Y3QpKSkge1xuICAgICAgZGVzY3JpcHRpb24ucHVzaChwcm9kdWN0ID8gJygnICsgb3MgKyAnKScgOiAnb24gJyArIG9zKTtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCkge1xuICAgICAgcGxhdGZvcm0uZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbi5qb2luKCcgJyk7XG4gICAgfVxuICAgIHJldHVybiBwbGF0Zm9ybTtcbiAgfVxuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8vIEV4cG9ydCBwbGF0Zm9ybS5cbiAgdmFyIHBsYXRmb3JtID0gcGFyc2UoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZSB0aGUgZm9sbG93aW5nOlxuICBpZiAodHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBFeHBvc2UgcGxhdGZvcm0gb24gdGhlIGdsb2JhbCBvYmplY3QgdG8gcHJldmVudCBlcnJvcnMgd2hlbiBwbGF0Zm9ybSBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICByb290LnBsYXRmb3JtID0gcGxhdGZvcm07XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbyBwbGF0Zm9ybSBjYW4gYmUgYWxpYXNlZCB0aHJvdWdoIHBhdGggbWFwcGluZy5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcGxhdGZvcm07XG4gICAgfSk7XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGBleHBvcnRzYCBhZnRlciBgZGVmaW5lYCBpbiBjYXNlIGEgYnVpbGQgb3B0aW1pemVyIGFkZHMgYW4gYGV4cG9ydHNgIG9iamVjdC5cbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgQ29tbW9uSlMgc3VwcG9ydC5cbiAgICBmb3JPd24ocGxhdGZvcm0sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgIGZyZWVFeHBvcnRzW2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBFeHBvcnQgdG8gdGhlIGdsb2JhbCBvYmplY3QuXG4gICAgcm9vdC5wbGF0Zm9ybSA9IHBsYXRmb3JtO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsImNvbnN0IGRlYnVnID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvZGVidWcnKVxuY29uc3QgeyBNQVhfTEVOR1RILCBNQVhfU0FGRV9JTlRFR0VSIH0gPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9jb25zdGFudHMnKVxuY29uc3QgeyByZSwgdCB9ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvcmUnKVxuXG5jb25zdCBwYXJzZU9wdGlvbnMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9wYXJzZS1vcHRpb25zJylcbmNvbnN0IHsgY29tcGFyZUlkZW50aWZpZXJzIH0gPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pZGVudGlmaWVycycpXG5jbGFzcyBTZW1WZXIge1xuICBjb25zdHJ1Y3RvciAodmVyc2lvbiwgb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBwYXJzZU9wdGlvbnMob3B0aW9ucylcblxuICAgIGlmICh2ZXJzaW9uIGluc3RhbmNlb2YgU2VtVmVyKSB7XG4gICAgICBpZiAodmVyc2lvbi5sb29zZSA9PT0gISFvcHRpb25zLmxvb3NlICYmXG4gICAgICAgICAgdmVyc2lvbi5pbmNsdWRlUHJlcmVsZWFzZSA9PT0gISFvcHRpb25zLmluY2x1ZGVQcmVyZWxlYXNlKSB7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2ZXJzaW9uID0gdmVyc2lvbi52ZXJzaW9uXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmVyc2lvbiAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEludmFsaWQgVmVyc2lvbjogJHt2ZXJzaW9ufWApXG4gICAgfVxuXG4gICAgaWYgKHZlcnNpb24ubGVuZ3RoID4gTUFYX0xFTkdUSCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgYHZlcnNpb24gaXMgbG9uZ2VyIHRoYW4gJHtNQVhfTEVOR1RIfSBjaGFyYWN0ZXJzYFxuICAgICAgKVxuICAgIH1cblxuICAgIGRlYnVnKCdTZW1WZXInLCB2ZXJzaW9uLCBvcHRpb25zKVxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnNcbiAgICB0aGlzLmxvb3NlID0gISFvcHRpb25zLmxvb3NlXG4gICAgLy8gdGhpcyBpc24ndCBhY3R1YWxseSByZWxldmFudCBmb3IgdmVyc2lvbnMsIGJ1dCBrZWVwIGl0IHNvIHRoYXQgd2VcbiAgICAvLyBkb24ndCBydW4gaW50byB0cm91YmxlIHBhc3NpbmcgdGhpcy5vcHRpb25zIGFyb3VuZC5cbiAgICB0aGlzLmluY2x1ZGVQcmVyZWxlYXNlID0gISFvcHRpb25zLmluY2x1ZGVQcmVyZWxlYXNlXG5cbiAgICBjb25zdCBtID0gdmVyc2lvbi50cmltKCkubWF0Y2gob3B0aW9ucy5sb29zZSA/IHJlW3QuTE9PU0VdIDogcmVbdC5GVUxMXSlcblxuICAgIGlmICghbSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBWZXJzaW9uOiAke3ZlcnNpb259YClcbiAgICB9XG5cbiAgICB0aGlzLnJhdyA9IHZlcnNpb25cblxuICAgIC8vIHRoZXNlIGFyZSBhY3R1YWxseSBudW1iZXJzXG4gICAgdGhpcy5tYWpvciA9ICttWzFdXG4gICAgdGhpcy5taW5vciA9ICttWzJdXG4gICAgdGhpcy5wYXRjaCA9ICttWzNdXG5cbiAgICBpZiAodGhpcy5tYWpvciA+IE1BWF9TQUZFX0lOVEVHRVIgfHwgdGhpcy5tYWpvciA8IDApIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0ludmFsaWQgbWFqb3IgdmVyc2lvbicpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMubWlub3IgPiBNQVhfU0FGRV9JTlRFR0VSIHx8IHRoaXMubWlub3IgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIG1pbm9yIHZlcnNpb24nKVxuICAgIH1cblxuICAgIGlmICh0aGlzLnBhdGNoID4gTUFYX1NBRkVfSU5URUdFUiB8fCB0aGlzLnBhdGNoIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCBwYXRjaCB2ZXJzaW9uJylcbiAgICB9XG5cbiAgICAvLyBudW1iZXJpZnkgYW55IHByZXJlbGVhc2UgbnVtZXJpYyBpZHNcbiAgICBpZiAoIW1bNF0pIHtcbiAgICAgIHRoaXMucHJlcmVsZWFzZSA9IFtdXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHJlcmVsZWFzZSA9IG1bNF0uc3BsaXQoJy4nKS5tYXAoKGlkKSA9PiB7XG4gICAgICAgIGlmICgvXlswLTldKyQvLnRlc3QoaWQpKSB7XG4gICAgICAgICAgY29uc3QgbnVtID0gK2lkXG4gICAgICAgICAgaWYgKG51bSA+PSAwICYmIG51bSA8IE1BWF9TQUZFX0lOVEVHRVIpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlkXG4gICAgICB9KVxuICAgIH1cblxuICAgIHRoaXMuYnVpbGQgPSBtWzVdID8gbVs1XS5zcGxpdCgnLicpIDogW11cbiAgICB0aGlzLmZvcm1hdCgpXG4gIH1cblxuICBmb3JtYXQgKCkge1xuICAgIHRoaXMudmVyc2lvbiA9IGAke3RoaXMubWFqb3J9LiR7dGhpcy5taW5vcn0uJHt0aGlzLnBhdGNofWBcbiAgICBpZiAodGhpcy5wcmVyZWxlYXNlLmxlbmd0aCkge1xuICAgICAgdGhpcy52ZXJzaW9uICs9IGAtJHt0aGlzLnByZXJlbGVhc2Uuam9pbignLicpfWBcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmVyc2lvblxuICB9XG5cbiAgdG9TdHJpbmcgKCkge1xuICAgIHJldHVybiB0aGlzLnZlcnNpb25cbiAgfVxuXG4gIGNvbXBhcmUgKG90aGVyKSB7XG4gICAgZGVidWcoJ1NlbVZlci5jb21wYXJlJywgdGhpcy52ZXJzaW9uLCB0aGlzLm9wdGlvbnMsIG90aGVyKVxuICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgU2VtVmVyKSkge1xuICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gJ3N0cmluZycgJiYgb3RoZXIgPT09IHRoaXMudmVyc2lvbikge1xuICAgICAgICByZXR1cm4gMFxuICAgICAgfVxuICAgICAgb3RoZXIgPSBuZXcgU2VtVmVyKG90aGVyLCB0aGlzLm9wdGlvbnMpXG4gICAgfVxuXG4gICAgaWYgKG90aGVyLnZlcnNpb24gPT09IHRoaXMudmVyc2lvbikge1xuICAgICAgcmV0dXJuIDBcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb21wYXJlTWFpbihvdGhlcikgfHwgdGhpcy5jb21wYXJlUHJlKG90aGVyKVxuICB9XG5cbiAgY29tcGFyZU1haW4gKG90aGVyKSB7XG4gICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBTZW1WZXIpKSB7XG4gICAgICBvdGhlciA9IG5ldyBTZW1WZXIob3RoZXIsIHRoaXMub3B0aW9ucylcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgY29tcGFyZUlkZW50aWZpZXJzKHRoaXMubWFqb3IsIG90aGVyLm1ham9yKSB8fFxuICAgICAgY29tcGFyZUlkZW50aWZpZXJzKHRoaXMubWlub3IsIG90aGVyLm1pbm9yKSB8fFxuICAgICAgY29tcGFyZUlkZW50aWZpZXJzKHRoaXMucGF0Y2gsIG90aGVyLnBhdGNoKVxuICAgIClcbiAgfVxuXG4gIGNvbXBhcmVQcmUgKG90aGVyKSB7XG4gICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBTZW1WZXIpKSB7XG4gICAgICBvdGhlciA9IG5ldyBTZW1WZXIob3RoZXIsIHRoaXMub3B0aW9ucylcbiAgICB9XG5cbiAgICAvLyBOT1QgaGF2aW5nIGEgcHJlcmVsZWFzZSBpcyA+IGhhdmluZyBvbmVcbiAgICBpZiAodGhpcy5wcmVyZWxlYXNlLmxlbmd0aCAmJiAhb3RoZXIucHJlcmVsZWFzZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiAtMVxuICAgIH0gZWxzZSBpZiAoIXRoaXMucHJlcmVsZWFzZS5sZW5ndGggJiYgb3RoZXIucHJlcmVsZWFzZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiAxXG4gICAgfSBlbHNlIGlmICghdGhpcy5wcmVyZWxlYXNlLmxlbmd0aCAmJiAhb3RoZXIucHJlcmVsZWFzZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiAwXG4gICAgfVxuXG4gICAgbGV0IGkgPSAwXG4gICAgZG8ge1xuICAgICAgY29uc3QgYSA9IHRoaXMucHJlcmVsZWFzZVtpXVxuICAgICAgY29uc3QgYiA9IG90aGVyLnByZXJlbGVhc2VbaV1cbiAgICAgIGRlYnVnKCdwcmVyZWxlYXNlIGNvbXBhcmUnLCBpLCBhLCBiKVxuICAgICAgaWYgKGEgPT09IHVuZGVmaW5lZCAmJiBiID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIDBcbiAgICAgIH0gZWxzZSBpZiAoYiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiAxXG4gICAgICB9IGVsc2UgaWYgKGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gYikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNvbXBhcmVJZGVudGlmaWVycyhhLCBiKVxuICAgICAgfVxuICAgIH0gd2hpbGUgKCsraSlcbiAgfVxuXG4gIGNvbXBhcmVCdWlsZCAob3RoZXIpIHtcbiAgICBpZiAoIShvdGhlciBpbnN0YW5jZW9mIFNlbVZlcikpIHtcbiAgICAgIG90aGVyID0gbmV3IFNlbVZlcihvdGhlciwgdGhpcy5vcHRpb25zKVxuICAgIH1cblxuICAgIGxldCBpID0gMFxuICAgIGRvIHtcbiAgICAgIGNvbnN0IGEgPSB0aGlzLmJ1aWxkW2ldXG4gICAgICBjb25zdCBiID0gb3RoZXIuYnVpbGRbaV1cbiAgICAgIGRlYnVnKCdwcmVyZWxlYXNlIGNvbXBhcmUnLCBpLCBhLCBiKVxuICAgICAgaWYgKGEgPT09IHVuZGVmaW5lZCAmJiBiID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIDBcbiAgICAgIH0gZWxzZSBpZiAoYiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiAxXG4gICAgICB9IGVsc2UgaWYgKGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gYikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNvbXBhcmVJZGVudGlmaWVycyhhLCBiKVxuICAgICAgfVxuICAgIH0gd2hpbGUgKCsraSlcbiAgfVxuXG4gIC8vIHByZW1pbm9yIHdpbGwgYnVtcCB0aGUgdmVyc2lvbiB1cCB0byB0aGUgbmV4dCBtaW5vciByZWxlYXNlLCBhbmQgaW1tZWRpYXRlbHlcbiAgLy8gZG93biB0byBwcmUtcmVsZWFzZS4gcHJlbWFqb3IgYW5kIHByZXBhdGNoIHdvcmsgdGhlIHNhbWUgd2F5LlxuICBpbmMgKHJlbGVhc2UsIGlkZW50aWZpZXIpIHtcbiAgICBzd2l0Y2ggKHJlbGVhc2UpIHtcbiAgICAgIGNhc2UgJ3ByZW1ham9yJzpcbiAgICAgICAgdGhpcy5wcmVyZWxlYXNlLmxlbmd0aCA9IDBcbiAgICAgICAgdGhpcy5wYXRjaCA9IDBcbiAgICAgICAgdGhpcy5taW5vciA9IDBcbiAgICAgICAgdGhpcy5tYWpvcisrXG4gICAgICAgIHRoaXMuaW5jKCdwcmUnLCBpZGVudGlmaWVyKVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAncHJlbWlub3InOlxuICAgICAgICB0aGlzLnByZXJlbGVhc2UubGVuZ3RoID0gMFxuICAgICAgICB0aGlzLnBhdGNoID0gMFxuICAgICAgICB0aGlzLm1pbm9yKytcbiAgICAgICAgdGhpcy5pbmMoJ3ByZScsIGlkZW50aWZpZXIpXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdwcmVwYXRjaCc6XG4gICAgICAgIC8vIElmIHRoaXMgaXMgYWxyZWFkeSBhIHByZXJlbGVhc2UsIGl0IHdpbGwgYnVtcCB0byB0aGUgbmV4dCB2ZXJzaW9uXG4gICAgICAgIC8vIGRyb3AgYW55IHByZXJlbGVhc2VzIHRoYXQgbWlnaHQgYWxyZWFkeSBleGlzdCwgc2luY2UgdGhleSBhcmUgbm90XG4gICAgICAgIC8vIHJlbGV2YW50IGF0IHRoaXMgcG9pbnQuXG4gICAgICAgIHRoaXMucHJlcmVsZWFzZS5sZW5ndGggPSAwXG4gICAgICAgIHRoaXMuaW5jKCdwYXRjaCcsIGlkZW50aWZpZXIpXG4gICAgICAgIHRoaXMuaW5jKCdwcmUnLCBpZGVudGlmaWVyKVxuICAgICAgICBicmVha1xuICAgICAgLy8gSWYgdGhlIGlucHV0IGlzIGEgbm9uLXByZXJlbGVhc2UgdmVyc2lvbiwgdGhpcyBhY3RzIHRoZSBzYW1lIGFzXG4gICAgICAvLyBwcmVwYXRjaC5cbiAgICAgIGNhc2UgJ3ByZXJlbGVhc2UnOlxuICAgICAgICBpZiAodGhpcy5wcmVyZWxlYXNlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuaW5jKCdwYXRjaCcsIGlkZW50aWZpZXIpXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmMoJ3ByZScsIGlkZW50aWZpZXIpXG4gICAgICAgIGJyZWFrXG5cbiAgICAgIGNhc2UgJ21ham9yJzpcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhIHByZS1tYWpvciB2ZXJzaW9uLCBidW1wIHVwIHRvIHRoZSBzYW1lIG1ham9yIHZlcnNpb24uXG4gICAgICAgIC8vIE90aGVyd2lzZSBpbmNyZW1lbnQgbWFqb3IuXG4gICAgICAgIC8vIDEuMC4wLTUgYnVtcHMgdG8gMS4wLjBcbiAgICAgICAgLy8gMS4xLjAgYnVtcHMgdG8gMi4wLjBcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMubWlub3IgIT09IDAgfHxcbiAgICAgICAgICB0aGlzLnBhdGNoICE9PSAwIHx8XG4gICAgICAgICAgdGhpcy5wcmVyZWxlYXNlLmxlbmd0aCA9PT0gMFxuICAgICAgICApIHtcbiAgICAgICAgICB0aGlzLm1ham9yKytcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1pbm9yID0gMFxuICAgICAgICB0aGlzLnBhdGNoID0gMFxuICAgICAgICB0aGlzLnByZXJlbGVhc2UgPSBbXVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAnbWlub3InOlxuICAgICAgICAvLyBJZiB0aGlzIGlzIGEgcHJlLW1pbm9yIHZlcnNpb24sIGJ1bXAgdXAgdG8gdGhlIHNhbWUgbWlub3IgdmVyc2lvbi5cbiAgICAgICAgLy8gT3RoZXJ3aXNlIGluY3JlbWVudCBtaW5vci5cbiAgICAgICAgLy8gMS4yLjAtNSBidW1wcyB0byAxLjIuMFxuICAgICAgICAvLyAxLjIuMSBidW1wcyB0byAxLjMuMFxuICAgICAgICBpZiAodGhpcy5wYXRjaCAhPT0gMCB8fCB0aGlzLnByZXJlbGVhc2UubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5taW5vcisrXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXRjaCA9IDBcbiAgICAgICAgdGhpcy5wcmVyZWxlYXNlID0gW11cbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgJ3BhdGNoJzpcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBub3QgYSBwcmUtcmVsZWFzZSB2ZXJzaW9uLCBpdCB3aWxsIGluY3JlbWVudCB0aGUgcGF0Y2guXG4gICAgICAgIC8vIElmIGl0IGlzIGEgcHJlLXJlbGVhc2UgaXQgd2lsbCBidW1wIHVwIHRvIHRoZSBzYW1lIHBhdGNoIHZlcnNpb24uXG4gICAgICAgIC8vIDEuMi4wLTUgcGF0Y2hlcyB0byAxLjIuMFxuICAgICAgICAvLyAxLjIuMCBwYXRjaGVzIHRvIDEuMi4xXG4gICAgICAgIGlmICh0aGlzLnByZXJlbGVhc2UubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5wYXRjaCsrXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcmVyZWxlYXNlID0gW11cbiAgICAgICAgYnJlYWtcbiAgICAgIC8vIFRoaXMgcHJvYmFibHkgc2hvdWxkbid0IGJlIHVzZWQgcHVibGljbHkuXG4gICAgICAvLyAxLjAuMCAncHJlJyB3b3VsZCBiZWNvbWUgMS4wLjAtMCB3aGljaCBpcyB0aGUgd3JvbmcgZGlyZWN0aW9uLlxuICAgICAgY2FzZSAncHJlJzpcbiAgICAgICAgaWYgKHRoaXMucHJlcmVsZWFzZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLnByZXJlbGVhc2UgPSBbMF1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZXQgaSA9IHRoaXMucHJlcmVsZWFzZS5sZW5ndGhcbiAgICAgICAgICB3aGlsZSAoLS1pID49IDApIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5wcmVyZWxlYXNlW2ldID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICB0aGlzLnByZXJlbGVhc2VbaV0rK1xuICAgICAgICAgICAgICBpID0gLTJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGkgPT09IC0xKSB7XG4gICAgICAgICAgICAvLyBkaWRuJ3QgaW5jcmVtZW50IGFueXRoaW5nXG4gICAgICAgICAgICB0aGlzLnByZXJlbGVhc2UucHVzaCgwKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaWRlbnRpZmllcikge1xuICAgICAgICAgIC8vIDEuMi4wLWJldGEuMSBidW1wcyB0byAxLjIuMC1iZXRhLjIsXG4gICAgICAgICAgLy8gMS4yLjAtYmV0YS5mb29ibHogb3IgMS4yLjAtYmV0YSBidW1wcyB0byAxLjIuMC1iZXRhLjBcbiAgICAgICAgICBpZiAodGhpcy5wcmVyZWxlYXNlWzBdID09PSBpZGVudGlmaWVyKSB7XG4gICAgICAgICAgICBpZiAoaXNOYU4odGhpcy5wcmVyZWxlYXNlWzFdKSkge1xuICAgICAgICAgICAgICB0aGlzLnByZXJlbGVhc2UgPSBbaWRlbnRpZmllciwgMF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcmVyZWxlYXNlID0gW2lkZW50aWZpZXIsIDBdXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBpbmNyZW1lbnQgYXJndW1lbnQ6ICR7cmVsZWFzZX1gKVxuICAgIH1cbiAgICB0aGlzLmZvcm1hdCgpXG4gICAgdGhpcy5yYXcgPSB0aGlzLnZlcnNpb25cbiAgICByZXR1cm4gdGhpc1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2VtVmVyXG4iLCJjb25zdCBTZW1WZXIgPSByZXF1aXJlKCcuLi9jbGFzc2VzL3NlbXZlcicpXG5jb25zdCBtYWpvciA9IChhLCBsb29zZSkgPT4gbmV3IFNlbVZlcihhLCBsb29zZSkubWFqb3Jcbm1vZHVsZS5leHBvcnRzID0gbWFqb3JcbiIsImNvbnN0IFNlbVZlciA9IHJlcXVpcmUoJy4uL2NsYXNzZXMvc2VtdmVyJylcbmNvbnN0IG1pbm9yID0gKGEsIGxvb3NlKSA9PiBuZXcgU2VtVmVyKGEsIGxvb3NlKS5taW5vclxubW9kdWxlLmV4cG9ydHMgPSBtaW5vclxuIiwiLy8gTm90ZTogdGhpcyBpcyB0aGUgc2VtdmVyLm9yZyB2ZXJzaW9uIG9mIHRoZSBzcGVjIHRoYXQgaXQgaW1wbGVtZW50c1xuLy8gTm90IG5lY2Vzc2FyaWx5IHRoZSBwYWNrYWdlIHZlcnNpb24gb2YgdGhpcyBjb2RlLlxuY29uc3QgU0VNVkVSX1NQRUNfVkVSU0lPTiA9ICcyLjAuMCdcblxuY29uc3QgTUFYX0xFTkdUSCA9IDI1NlxuY29uc3QgTUFYX1NBRkVfSU5URUdFUiA9IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSIHx8XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIDkwMDcxOTkyNTQ3NDA5OTFcblxuLy8gTWF4IHNhZmUgc2VnbWVudCBsZW5ndGggZm9yIGNvZXJjaW9uLlxuY29uc3QgTUFYX1NBRkVfQ09NUE9ORU5UX0xFTkdUSCA9IDE2XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBTRU1WRVJfU1BFQ19WRVJTSU9OLFxuICBNQVhfTEVOR1RILFxuICBNQVhfU0FGRV9JTlRFR0VSLFxuICBNQVhfU0FGRV9DT01QT05FTlRfTEVOR1RIXG59XG4iLCJjb25zdCBkZWJ1ZyA9IChcbiAgdHlwZW9mIHByb2Nlc3MgPT09ICdvYmplY3QnICYmXG4gIHByb2Nlc3MuZW52ICYmXG4gIHByb2Nlc3MuZW52Lk5PREVfREVCVUcgJiZcbiAgL1xcYnNlbXZlclxcYi9pLnRlc3QocHJvY2Vzcy5lbnYuTk9ERV9ERUJVRylcbikgPyAoLi4uYXJncykgPT4gY29uc29sZS5lcnJvcignU0VNVkVSJywgLi4uYXJncylcbiAgOiAoKSA9PiB7fVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRlYnVnXG4iLCJjb25zdCBudW1lcmljID0gL15bMC05XSskL1xuY29uc3QgY29tcGFyZUlkZW50aWZpZXJzID0gKGEsIGIpID0+IHtcbiAgY29uc3QgYW51bSA9IG51bWVyaWMudGVzdChhKVxuICBjb25zdCBibnVtID0gbnVtZXJpYy50ZXN0KGIpXG5cbiAgaWYgKGFudW0gJiYgYm51bSkge1xuICAgIGEgPSArYVxuICAgIGIgPSArYlxuICB9XG5cbiAgcmV0dXJuIGEgPT09IGIgPyAwXG4gICAgOiAoYW51bSAmJiAhYm51bSkgPyAtMVxuICAgIDogKGJudW0gJiYgIWFudW0pID8gMVxuICAgIDogYSA8IGIgPyAtMVxuICAgIDogMVxufVxuXG5jb25zdCByY29tcGFyZUlkZW50aWZpZXJzID0gKGEsIGIpID0+IGNvbXBhcmVJZGVudGlmaWVycyhiLCBhKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY29tcGFyZUlkZW50aWZpZXJzLFxuICByY29tcGFyZUlkZW50aWZpZXJzXG59XG4iLCIvLyBwYXJzZSBvdXQganVzdCB0aGUgb3B0aW9ucyB3ZSBjYXJlIGFib3V0IHNvIHdlIGFsd2F5cyBnZXQgYSBjb25zaXN0ZW50XG4vLyBvYmogd2l0aCBrZXlzIGluIGEgY29uc2lzdGVudCBvcmRlci5cbmNvbnN0IG9wdHMgPSBbJ2luY2x1ZGVQcmVyZWxlYXNlJywgJ2xvb3NlJywgJ3J0bCddXG5jb25zdCBwYXJzZU9wdGlvbnMgPSBvcHRpb25zID0+XG4gICFvcHRpb25zID8ge31cbiAgOiB0eXBlb2Ygb3B0aW9ucyAhPT0gJ29iamVjdCcgPyB7IGxvb3NlOiB0cnVlIH1cbiAgOiBvcHRzLmZpbHRlcihrID0+IG9wdGlvbnNba10pLnJlZHVjZSgob3B0aW9ucywgaykgPT4ge1xuICAgIG9wdGlvbnNba10gPSB0cnVlXG4gICAgcmV0dXJuIG9wdGlvbnNcbiAgfSwge30pXG5tb2R1bGUuZXhwb3J0cyA9IHBhcnNlT3B0aW9uc1xuIiwiY29uc3QgeyBNQVhfU0FGRV9DT01QT05FTlRfTEVOR1RIIH0gPSByZXF1aXJlKCcuL2NvbnN0YW50cycpXG5jb25zdCBkZWJ1ZyA9IHJlcXVpcmUoJy4vZGVidWcnKVxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0ge31cblxuLy8gVGhlIGFjdHVhbCByZWdleHBzIGdvIG9uIGV4cG9ydHMucmVcbmNvbnN0IHJlID0gZXhwb3J0cy5yZSA9IFtdXG5jb25zdCBzcmMgPSBleHBvcnRzLnNyYyA9IFtdXG5jb25zdCB0ID0gZXhwb3J0cy50ID0ge31cbmxldCBSID0gMFxuXG5jb25zdCBjcmVhdGVUb2tlbiA9IChuYW1lLCB2YWx1ZSwgaXNHbG9iYWwpID0+IHtcbiAgY29uc3QgaW5kZXggPSBSKytcbiAgZGVidWcoaW5kZXgsIHZhbHVlKVxuICB0W25hbWVdID0gaW5kZXhcbiAgc3JjW2luZGV4XSA9IHZhbHVlXG4gIHJlW2luZGV4XSA9IG5ldyBSZWdFeHAodmFsdWUsIGlzR2xvYmFsID8gJ2cnIDogdW5kZWZpbmVkKVxufVxuXG4vLyBUaGUgZm9sbG93aW5nIFJlZ3VsYXIgRXhwcmVzc2lvbnMgY2FuIGJlIHVzZWQgZm9yIHRva2VuaXppbmcsXG4vLyB2YWxpZGF0aW5nLCBhbmQgcGFyc2luZyBTZW1WZXIgdmVyc2lvbiBzdHJpbmdzLlxuXG4vLyAjIyBOdW1lcmljIElkZW50aWZpZXJcbi8vIEEgc2luZ2xlIGAwYCwgb3IgYSBub24temVybyBkaWdpdCBmb2xsb3dlZCBieSB6ZXJvIG9yIG1vcmUgZGlnaXRzLlxuXG5jcmVhdGVUb2tlbignTlVNRVJJQ0lERU5USUZJRVInLCAnMHxbMS05XVxcXFxkKicpXG5jcmVhdGVUb2tlbignTlVNRVJJQ0lERU5USUZJRVJMT09TRScsICdbMC05XSsnKVxuXG4vLyAjIyBOb24tbnVtZXJpYyBJZGVudGlmaWVyXG4vLyBaZXJvIG9yIG1vcmUgZGlnaXRzLCBmb2xsb3dlZCBieSBhIGxldHRlciBvciBoeXBoZW4sIGFuZCB0aGVuIHplcm8gb3Jcbi8vIG1vcmUgbGV0dGVycywgZGlnaXRzLCBvciBoeXBoZW5zLlxuXG5jcmVhdGVUb2tlbignTk9OTlVNRVJJQ0lERU5USUZJRVInLCAnXFxcXGQqW2EtekEtWi1dW2EtekEtWjAtOS1dKicpXG5cbi8vICMjIE1haW4gVmVyc2lvblxuLy8gVGhyZWUgZG90LXNlcGFyYXRlZCBudW1lcmljIGlkZW50aWZpZXJzLlxuXG5jcmVhdGVUb2tlbignTUFJTlZFUlNJT04nLCBgKCR7c3JjW3QuTlVNRVJJQ0lERU5USUZJRVJdfSlcXFxcLmAgK1xuICAgICAgICAgICAgICAgICAgIGAoJHtzcmNbdC5OVU1FUklDSURFTlRJRklFUl19KVxcXFwuYCArXG4gICAgICAgICAgICAgICAgICAgYCgke3NyY1t0Lk5VTUVSSUNJREVOVElGSUVSXX0pYClcblxuY3JlYXRlVG9rZW4oJ01BSU5WRVJTSU9OTE9PU0UnLCBgKCR7c3JjW3QuTlVNRVJJQ0lERU5USUZJRVJMT09TRV19KVxcXFwuYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgKCR7c3JjW3QuTlVNRVJJQ0lERU5USUZJRVJMT09TRV19KVxcXFwuYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgKCR7c3JjW3QuTlVNRVJJQ0lERU5USUZJRVJMT09TRV19KWApXG5cbi8vICMjIFByZS1yZWxlYXNlIFZlcnNpb24gSWRlbnRpZmllclxuLy8gQSBudW1lcmljIGlkZW50aWZpZXIsIG9yIGEgbm9uLW51bWVyaWMgaWRlbnRpZmllci5cblxuY3JlYXRlVG9rZW4oJ1BSRVJFTEVBU0VJREVOVElGSUVSJywgYCg/OiR7c3JjW3QuTlVNRVJJQ0lERU5USUZJRVJdXG59fCR7c3JjW3QuTk9OTlVNRVJJQ0lERU5USUZJRVJdfSlgKVxuXG5jcmVhdGVUb2tlbignUFJFUkVMRUFTRUlERU5USUZJRVJMT09TRScsIGAoPzoke3NyY1t0Lk5VTUVSSUNJREVOVElGSUVSTE9PU0VdXG59fCR7c3JjW3QuTk9OTlVNRVJJQ0lERU5USUZJRVJdfSlgKVxuXG4vLyAjIyBQcmUtcmVsZWFzZSBWZXJzaW9uXG4vLyBIeXBoZW4sIGZvbGxvd2VkIGJ5IG9uZSBvciBtb3JlIGRvdC1zZXBhcmF0ZWQgcHJlLXJlbGVhc2UgdmVyc2lvblxuLy8gaWRlbnRpZmllcnMuXG5cbmNyZWF0ZVRva2VuKCdQUkVSRUxFQVNFJywgYCg/Oi0oJHtzcmNbdC5QUkVSRUxFQVNFSURFTlRJRklFUl1cbn0oPzpcXFxcLiR7c3JjW3QuUFJFUkVMRUFTRUlERU5USUZJRVJdfSkqKSlgKVxuXG5jcmVhdGVUb2tlbignUFJFUkVMRUFTRUxPT1NFJywgYCg/Oi0/KCR7c3JjW3QuUFJFUkVMRUFTRUlERU5USUZJRVJMT09TRV1cbn0oPzpcXFxcLiR7c3JjW3QuUFJFUkVMRUFTRUlERU5USUZJRVJMT09TRV19KSopKWApXG5cbi8vICMjIEJ1aWxkIE1ldGFkYXRhIElkZW50aWZpZXJcbi8vIEFueSBjb21iaW5hdGlvbiBvZiBkaWdpdHMsIGxldHRlcnMsIG9yIGh5cGhlbnMuXG5cbmNyZWF0ZVRva2VuKCdCVUlMRElERU5USUZJRVInLCAnWzAtOUEtWmEtei1dKycpXG5cbi8vICMjIEJ1aWxkIE1ldGFkYXRhXG4vLyBQbHVzIHNpZ24sIGZvbGxvd2VkIGJ5IG9uZSBvciBtb3JlIHBlcmlvZC1zZXBhcmF0ZWQgYnVpbGQgbWV0YWRhdGFcbi8vIGlkZW50aWZpZXJzLlxuXG5jcmVhdGVUb2tlbignQlVJTEQnLCBgKD86XFxcXCsoJHtzcmNbdC5CVUlMRElERU5USUZJRVJdXG59KD86XFxcXC4ke3NyY1t0LkJVSUxESURFTlRJRklFUl19KSopKWApXG5cbi8vICMjIEZ1bGwgVmVyc2lvbiBTdHJpbmdcbi8vIEEgbWFpbiB2ZXJzaW9uLCBmb2xsb3dlZCBvcHRpb25hbGx5IGJ5IGEgcHJlLXJlbGVhc2UgdmVyc2lvbiBhbmRcbi8vIGJ1aWxkIG1ldGFkYXRhLlxuXG4vLyBOb3RlIHRoYXQgdGhlIG9ubHkgbWFqb3IsIG1pbm9yLCBwYXRjaCwgYW5kIHByZS1yZWxlYXNlIHNlY3Rpb25zIG9mXG4vLyB0aGUgdmVyc2lvbiBzdHJpbmcgYXJlIGNhcHR1cmluZyBncm91cHMuICBUaGUgYnVpbGQgbWV0YWRhdGEgaXMgbm90IGFcbi8vIGNhcHR1cmluZyBncm91cCwgYmVjYXVzZSBpdCBzaG91bGQgbm90IGV2ZXIgYmUgdXNlZCBpbiB2ZXJzaW9uXG4vLyBjb21wYXJpc29uLlxuXG5jcmVhdGVUb2tlbignRlVMTFBMQUlOJywgYHY/JHtzcmNbdC5NQUlOVkVSU0lPTl1cbn0ke3NyY1t0LlBSRVJFTEVBU0VdfT8ke1xuICBzcmNbdC5CVUlMRF19P2ApXG5cbmNyZWF0ZVRva2VuKCdGVUxMJywgYF4ke3NyY1t0LkZVTExQTEFJTl19JGApXG5cbi8vIGxpa2UgZnVsbCwgYnV0IGFsbG93cyB2MS4yLjMgYW5kID0xLjIuMywgd2hpY2ggcGVvcGxlIGRvIHNvbWV0aW1lcy5cbi8vIGFsc28sIDEuMC4wYWxwaGExIChwcmVyZWxlYXNlIHdpdGhvdXQgdGhlIGh5cGhlbikgd2hpY2ggaXMgcHJldHR5XG4vLyBjb21tb24gaW4gdGhlIG5wbSByZWdpc3RyeS5cbmNyZWF0ZVRva2VuKCdMT09TRVBMQUlOJywgYFt2PVxcXFxzXSoke3NyY1t0Lk1BSU5WRVJTSU9OTE9PU0VdXG59JHtzcmNbdC5QUkVSRUxFQVNFTE9PU0VdfT8ke1xuICBzcmNbdC5CVUlMRF19P2ApXG5cbmNyZWF0ZVRva2VuKCdMT09TRScsIGBeJHtzcmNbdC5MT09TRVBMQUlOXX0kYClcblxuY3JlYXRlVG9rZW4oJ0dUTFQnLCAnKCg/Ojx8Pik/PT8pJylcblxuLy8gU29tZXRoaW5nIGxpa2UgXCIyLipcIiBvciBcIjEuMi54XCIuXG4vLyBOb3RlIHRoYXQgXCJ4LnhcIiBpcyBhIHZhbGlkIHhSYW5nZSBpZGVudGlmZXIsIG1lYW5pbmcgXCJhbnkgdmVyc2lvblwiXG4vLyBPbmx5IHRoZSBmaXJzdCBpdGVtIGlzIHN0cmljdGx5IHJlcXVpcmVkLlxuY3JlYXRlVG9rZW4oJ1hSQU5HRUlERU5USUZJRVJMT09TRScsIGAke3NyY1t0Lk5VTUVSSUNJREVOVElGSUVSTE9PU0VdfXx4fFh8XFxcXCpgKVxuY3JlYXRlVG9rZW4oJ1hSQU5HRUlERU5USUZJRVInLCBgJHtzcmNbdC5OVU1FUklDSURFTlRJRklFUl19fHh8WHxcXFxcKmApXG5cbmNyZWF0ZVRva2VuKCdYUkFOR0VQTEFJTicsIGBbdj1cXFxcc10qKCR7c3JjW3QuWFJBTkdFSURFTlRJRklFUl19KWAgK1xuICAgICAgICAgICAgICAgICAgIGAoPzpcXFxcLigke3NyY1t0LlhSQU5HRUlERU5USUZJRVJdfSlgICtcbiAgICAgICAgICAgICAgICAgICBgKD86XFxcXC4oJHtzcmNbdC5YUkFOR0VJREVOVElGSUVSXX0pYCArXG4gICAgICAgICAgICAgICAgICAgYCg/OiR7c3JjW3QuUFJFUkVMRUFTRV19KT8ke1xuICAgICAgICAgICAgICAgICAgICAgc3JjW3QuQlVJTERdfT9gICtcbiAgICAgICAgICAgICAgICAgICBgKT8pP2ApXG5cbmNyZWF0ZVRva2VuKCdYUkFOR0VQTEFJTkxPT1NFJywgYFt2PVxcXFxzXSooJHtzcmNbdC5YUkFOR0VJREVOVElGSUVSTE9PU0VdfSlgICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGAoPzpcXFxcLigke3NyY1t0LlhSQU5HRUlERU5USUZJRVJMT09TRV19KWAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgYCg/OlxcXFwuKCR7c3JjW3QuWFJBTkdFSURFTlRJRklFUkxPT1NFXX0pYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgKD86JHtzcmNbdC5QUkVSRUxFQVNFTE9PU0VdfSk/JHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjW3QuQlVJTERdfT9gICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGApPyk/YClcblxuY3JlYXRlVG9rZW4oJ1hSQU5HRScsIGBeJHtzcmNbdC5HVExUXX1cXFxccyoke3NyY1t0LlhSQU5HRVBMQUlOXX0kYClcbmNyZWF0ZVRva2VuKCdYUkFOR0VMT09TRScsIGBeJHtzcmNbdC5HVExUXX1cXFxccyoke3NyY1t0LlhSQU5HRVBMQUlOTE9PU0VdfSRgKVxuXG4vLyBDb2VyY2lvbi5cbi8vIEV4dHJhY3QgYW55dGhpbmcgdGhhdCBjb3VsZCBjb25jZWl2YWJseSBiZSBhIHBhcnQgb2YgYSB2YWxpZCBzZW12ZXJcbmNyZWF0ZVRva2VuKCdDT0VSQ0UnLCBgJHsnKF58W15cXFxcZF0pJyArXG4gICAgICAgICAgICAgICcoXFxcXGR7MSwnfSR7TUFYX1NBRkVfQ09NUE9ORU5UX0xFTkdUSH19KWAgK1xuICAgICAgICAgICAgICBgKD86XFxcXC4oXFxcXGR7MSwke01BWF9TQUZFX0NPTVBPTkVOVF9MRU5HVEh9fSkpP2AgK1xuICAgICAgICAgICAgICBgKD86XFxcXC4oXFxcXGR7MSwke01BWF9TQUZFX0NPTVBPTkVOVF9MRU5HVEh9fSkpP2AgK1xuICAgICAgICAgICAgICBgKD86JHxbXlxcXFxkXSlgKVxuY3JlYXRlVG9rZW4oJ0NPRVJDRVJUTCcsIHNyY1t0LkNPRVJDRV0sIHRydWUpXG5cbi8vIFRpbGRlIHJhbmdlcy5cbi8vIE1lYW5pbmcgaXMgXCJyZWFzb25hYmx5IGF0IG9yIGdyZWF0ZXIgdGhhblwiXG5jcmVhdGVUb2tlbignTE9ORVRJTERFJywgJyg/On4+PyknKVxuXG5jcmVhdGVUb2tlbignVElMREVUUklNJywgYChcXFxccyopJHtzcmNbdC5MT05FVElMREVdfVxcXFxzK2AsIHRydWUpXG5leHBvcnRzLnRpbGRlVHJpbVJlcGxhY2UgPSAnJDF+J1xuXG5jcmVhdGVUb2tlbignVElMREUnLCBgXiR7c3JjW3QuTE9ORVRJTERFXX0ke3NyY1t0LlhSQU5HRVBMQUlOXX0kYClcbmNyZWF0ZVRva2VuKCdUSUxERUxPT1NFJywgYF4ke3NyY1t0LkxPTkVUSUxERV19JHtzcmNbdC5YUkFOR0VQTEFJTkxPT1NFXX0kYClcblxuLy8gQ2FyZXQgcmFuZ2VzLlxuLy8gTWVhbmluZyBpcyBcImF0IGxlYXN0IGFuZCBiYWNrd2FyZHMgY29tcGF0aWJsZSB3aXRoXCJcbmNyZWF0ZVRva2VuKCdMT05FQ0FSRVQnLCAnKD86XFxcXF4pJylcblxuY3JlYXRlVG9rZW4oJ0NBUkVUVFJJTScsIGAoXFxcXHMqKSR7c3JjW3QuTE9ORUNBUkVUXX1cXFxccytgLCB0cnVlKVxuZXhwb3J0cy5jYXJldFRyaW1SZXBsYWNlID0gJyQxXidcblxuY3JlYXRlVG9rZW4oJ0NBUkVUJywgYF4ke3NyY1t0LkxPTkVDQVJFVF19JHtzcmNbdC5YUkFOR0VQTEFJTl19JGApXG5jcmVhdGVUb2tlbignQ0FSRVRMT09TRScsIGBeJHtzcmNbdC5MT05FQ0FSRVRdfSR7c3JjW3QuWFJBTkdFUExBSU5MT09TRV19JGApXG5cbi8vIEEgc2ltcGxlIGd0L2x0L2VxIHRoaW5nLCBvciBqdXN0IFwiXCIgdG8gaW5kaWNhdGUgXCJhbnkgdmVyc2lvblwiXG5jcmVhdGVUb2tlbignQ09NUEFSQVRPUkxPT1NFJywgYF4ke3NyY1t0LkdUTFRdfVxcXFxzKigke3NyY1t0LkxPT1NFUExBSU5dfSkkfF4kYClcbmNyZWF0ZVRva2VuKCdDT01QQVJBVE9SJywgYF4ke3NyY1t0LkdUTFRdfVxcXFxzKigke3NyY1t0LkZVTExQTEFJTl19KSR8XiRgKVxuXG4vLyBBbiBleHByZXNzaW9uIHRvIHN0cmlwIGFueSB3aGl0ZXNwYWNlIGJldHdlZW4gdGhlIGd0bHQgYW5kIHRoZSB0aGluZ1xuLy8gaXQgbW9kaWZpZXMsIHNvIHRoYXQgYD4gMS4yLjNgID09PiBgPjEuMi4zYFxuY3JlYXRlVG9rZW4oJ0NPTVBBUkFUT1JUUklNJywgYChcXFxccyopJHtzcmNbdC5HVExUXVxufVxcXFxzKigke3NyY1t0LkxPT1NFUExBSU5dfXwke3NyY1t0LlhSQU5HRVBMQUlOXX0pYCwgdHJ1ZSlcbmV4cG9ydHMuY29tcGFyYXRvclRyaW1SZXBsYWNlID0gJyQxJDIkMydcblxuLy8gU29tZXRoaW5nIGxpa2UgYDEuMi4zIC0gMS4yLjRgXG4vLyBOb3RlIHRoYXQgdGhlc2UgYWxsIHVzZSB0aGUgbG9vc2UgZm9ybSwgYmVjYXVzZSB0aGV5J2xsIGJlXG4vLyBjaGVja2VkIGFnYWluc3QgZWl0aGVyIHRoZSBzdHJpY3Qgb3IgbG9vc2UgY29tcGFyYXRvciBmb3JtXG4vLyBsYXRlci5cbmNyZWF0ZVRva2VuKCdIWVBIRU5SQU5HRScsIGBeXFxcXHMqKCR7c3JjW3QuWFJBTkdFUExBSU5dfSlgICtcbiAgICAgICAgICAgICAgICAgICBgXFxcXHMrLVxcXFxzK2AgK1xuICAgICAgICAgICAgICAgICAgIGAoJHtzcmNbdC5YUkFOR0VQTEFJTl19KWAgK1xuICAgICAgICAgICAgICAgICAgIGBcXFxccyokYClcblxuY3JlYXRlVG9rZW4oJ0hZUEhFTlJBTkdFTE9PU0UnLCBgXlxcXFxzKigke3NyY1t0LlhSQU5HRVBMQUlOTE9PU0VdfSlgICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGBcXFxccystXFxcXHMrYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgKCR7c3JjW3QuWFJBTkdFUExBSU5MT09TRV19KWAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgYFxcXFxzKiRgKVxuXG4vLyBTdGFyIHJhbmdlcyBiYXNpY2FsbHkganVzdCBhbGxvdyBhbnl0aGluZyBhdCBhbGwuXG5jcmVhdGVUb2tlbignU1RBUicsICcoPHw+KT89P1xcXFxzKlxcXFwqJylcbi8vID49MC4wLjAgaXMgbGlrZSBhIHN0YXJcbmNyZWF0ZVRva2VuKCdHVEUwJywgJ15cXFxccyo+PVxcXFxzKjBcXC4wXFwuMFxcXFxzKiQnKVxuY3JlYXRlVG9rZW4oJ0dURTBQUkUnLCAnXlxcXFxzKj49XFxcXHMqMFxcLjBcXC4wLTBcXFxccyokJylcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidjFcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3YuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ2M1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfdjIuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ2NFwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfdjMuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ2NVwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfdjQuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJOSUxcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX25pbC5kZWZhdWx0O1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInZlcnNpb25cIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3ZlcnNpb24uZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ2YWxpZGF0ZVwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfdmFsaWRhdGUuZGVmYXVsdDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJzdHJpbmdpZnlcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3N0cmluZ2lmeS5kZWZhdWx0O1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInBhcnNlXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9wYXJzZS5kZWZhdWx0O1xuICB9XG59KTtcblxudmFyIF92ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92MS5qc1wiKSk7XG5cbnZhciBfdjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3YzLmpzXCIpKTtcblxudmFyIF92MyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdjQuanNcIikpO1xuXG52YXIgX3Y0ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92NS5qc1wiKSk7XG5cbnZhciBfbmlsID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9uaWwuanNcIikpO1xuXG52YXIgX3ZlcnNpb24gPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3ZlcnNpb24uanNcIikpO1xuXG52YXIgX3ZhbGlkYXRlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi92YWxpZGF0ZS5qc1wiKSk7XG5cbnZhciBfc3RyaW5naWZ5ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zdHJpbmdpZnkuanNcIikpO1xuXG52YXIgX3BhcnNlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9wYXJzZS5qc1wiKSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbi8qXG4gKiBCcm93c2VyLWNvbXBhdGlibGUgSmF2YVNjcmlwdCBNRDVcbiAqXG4gKiBNb2RpZmljYXRpb24gb2YgSmF2YVNjcmlwdCBNRDVcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9ibHVlaW1wL0phdmFTY3JpcHQtTUQ1XG4gKlxuICogQ29weXJpZ2h0IDIwMTEsIFNlYmFzdGlhbiBUc2NoYW5cbiAqIGh0dHBzOi8vYmx1ZWltcC5uZXRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2U6XG4gKiBodHRwczovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL01JVFxuICpcbiAqIEJhc2VkIG9uXG4gKiBBIEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgdGhlIFJTQSBEYXRhIFNlY3VyaXR5LCBJbmMuIE1ENSBNZXNzYWdlXG4gKiBEaWdlc3QgQWxnb3JpdGhtLCBhcyBkZWZpbmVkIGluIFJGQyAxMzIxLlxuICogVmVyc2lvbiAyLjIgQ29weXJpZ2h0IChDKSBQYXVsIEpvaG5zdG9uIDE5OTkgLSAyMDA5XG4gKiBPdGhlciBjb250cmlidXRvcnM6IEdyZWcgSG9sdCwgQW5kcmV3IEtlcGVydCwgWWRuYXIsIExvc3RpbmV0XG4gKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQlNEIExpY2Vuc2VcbiAqIFNlZSBodHRwOi8vcGFqaG9tZS5vcmcudWsvY3J5cHQvbWQ1IGZvciBtb3JlIGluZm8uXG4gKi9cbmZ1bmN0aW9uIG1kNShieXRlcykge1xuICBpZiAodHlwZW9mIGJ5dGVzID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IG1zZyA9IHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChieXRlcykpOyAvLyBVVEY4IGVzY2FwZVxuXG4gICAgYnl0ZXMgPSBuZXcgVWludDhBcnJheShtc2cubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbXNnLmxlbmd0aDsgKytpKSB7XG4gICAgICBieXRlc1tpXSA9IG1zZy5jaGFyQ29kZUF0KGkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtZDVUb0hleEVuY29kZWRBcnJheSh3b3Jkc1RvTWQ1KGJ5dGVzVG9Xb3JkcyhieXRlcyksIGJ5dGVzLmxlbmd0aCAqIDgpKTtcbn1cbi8qXG4gKiBDb252ZXJ0IGFuIGFycmF5IG9mIGxpdHRsZS1lbmRpYW4gd29yZHMgdG8gYW4gYXJyYXkgb2YgYnl0ZXNcbiAqL1xuXG5cbmZ1bmN0aW9uIG1kNVRvSGV4RW5jb2RlZEFycmF5KGlucHV0KSB7XG4gIGNvbnN0IG91dHB1dCA9IFtdO1xuICBjb25zdCBsZW5ndGgzMiA9IGlucHV0Lmxlbmd0aCAqIDMyO1xuICBjb25zdCBoZXhUYWIgPSAnMDEyMzQ1Njc4OWFiY2RlZic7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGgzMjsgaSArPSA4KSB7XG4gICAgY29uc3QgeCA9IGlucHV0W2kgPj4gNV0gPj4+IGkgJSAzMiAmIDB4ZmY7XG4gICAgY29uc3QgaGV4ID0gcGFyc2VJbnQoaGV4VGFiLmNoYXJBdCh4ID4+PiA0ICYgMHgwZikgKyBoZXhUYWIuY2hhckF0KHggJiAweDBmKSwgMTYpO1xuICAgIG91dHB1dC5wdXNoKGhleCk7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufVxuLyoqXG4gKiBDYWxjdWxhdGUgb3V0cHV0IGxlbmd0aCB3aXRoIHBhZGRpbmcgYW5kIGJpdCBsZW5ndGhcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aDgpIHtcbiAgcmV0dXJuIChpbnB1dExlbmd0aDggKyA2NCA+Pj4gOSA8PCA0KSArIDE0ICsgMTtcbn1cbi8qXG4gKiBDYWxjdWxhdGUgdGhlIE1ENSBvZiBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzLCBhbmQgYSBiaXQgbGVuZ3RoLlxuICovXG5cblxuZnVuY3Rpb24gd29yZHNUb01kNSh4LCBsZW4pIHtcbiAgLyogYXBwZW5kIHBhZGRpbmcgKi9cbiAgeFtsZW4gPj4gNV0gfD0gMHg4MCA8PCBsZW4gJSAzMjtcbiAgeFtnZXRPdXRwdXRMZW5ndGgobGVuKSAtIDFdID0gbGVuO1xuICBsZXQgYSA9IDE3MzI1ODQxOTM7XG4gIGxldCBiID0gLTI3MTczMzg3OTtcbiAgbGV0IGMgPSAtMTczMjU4NDE5NDtcbiAgbGV0IGQgPSAyNzE3MzM4Nzg7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSArPSAxNikge1xuICAgIGNvbnN0IG9sZGEgPSBhO1xuICAgIGNvbnN0IG9sZGIgPSBiO1xuICAgIGNvbnN0IG9sZGMgPSBjO1xuICAgIGNvbnN0IG9sZGQgPSBkO1xuICAgIGEgPSBtZDVmZihhLCBiLCBjLCBkLCB4W2ldLCA3LCAtNjgwODc2OTM2KTtcbiAgICBkID0gbWQ1ZmYoZCwgYSwgYiwgYywgeFtpICsgMV0sIDEyLCAtMzg5NTY0NTg2KTtcbiAgICBjID0gbWQ1ZmYoYywgZCwgYSwgYiwgeFtpICsgMl0sIDE3LCA2MDYxMDU4MTkpO1xuICAgIGIgPSBtZDVmZihiLCBjLCBkLCBhLCB4W2kgKyAzXSwgMjIsIC0xMDQ0NTI1MzMwKTtcbiAgICBhID0gbWQ1ZmYoYSwgYiwgYywgZCwgeFtpICsgNF0sIDcsIC0xNzY0MTg4OTcpO1xuICAgIGQgPSBtZDVmZihkLCBhLCBiLCBjLCB4W2kgKyA1XSwgMTIsIDEyMDAwODA0MjYpO1xuICAgIGMgPSBtZDVmZihjLCBkLCBhLCBiLCB4W2kgKyA2XSwgMTcsIC0xNDczMjMxMzQxKTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgN10sIDIyLCAtNDU3MDU5ODMpO1xuICAgIGEgPSBtZDVmZihhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNywgMTc3MDAzNTQxNik7XG4gICAgZCA9IG1kNWZmKGQsIGEsIGIsIGMsIHhbaSArIDldLCAxMiwgLTE5NTg0MTQ0MTcpO1xuICAgIGMgPSBtZDVmZihjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE3LCAtNDIwNjMpO1xuICAgIGIgPSBtZDVmZihiLCBjLCBkLCBhLCB4W2kgKyAxMV0sIDIyLCAtMTk5MDQwNDE2Mik7XG4gICAgYSA9IG1kNWZmKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNywgMTgwNDYwMzY4Mik7XG4gICAgZCA9IG1kNWZmKGQsIGEsIGIsIGMsIHhbaSArIDEzXSwgMTIsIC00MDM0MTEwMSk7XG4gICAgYyA9IG1kNWZmKGMsIGQsIGEsIGIsIHhbaSArIDE0XSwgMTcsIC0xNTAyMDAyMjkwKTtcbiAgICBiID0gbWQ1ZmYoYiwgYywgZCwgYSwgeFtpICsgMTVdLCAyMiwgMTIzNjUzNTMyOSk7XG4gICAgYSA9IG1kNWdnKGEsIGIsIGMsIGQsIHhbaSArIDFdLCA1LCAtMTY1Nzk2NTEwKTtcbiAgICBkID0gbWQ1Z2coZCwgYSwgYiwgYywgeFtpICsgNl0sIDksIC0xMDY5NTAxNjMyKTtcbiAgICBjID0gbWQ1Z2coYywgZCwgYSwgYiwgeFtpICsgMTFdLCAxNCwgNjQzNzE3NzEzKTtcbiAgICBiID0gbWQ1Z2coYiwgYywgZCwgYSwgeFtpXSwgMjAsIC0zNzM4OTczMDIpO1xuICAgIGEgPSBtZDVnZyhhLCBiLCBjLCBkLCB4W2kgKyA1XSwgNSwgLTcwMTU1ODY5MSk7XG4gICAgZCA9IG1kNWdnKGQsIGEsIGIsIGMsIHhbaSArIDEwXSwgOSwgMzgwMTYwODMpO1xuICAgIGMgPSBtZDVnZyhjLCBkLCBhLCBiLCB4W2kgKyAxNV0sIDE0LCAtNjYwNDc4MzM1KTtcbiAgICBiID0gbWQ1Z2coYiwgYywgZCwgYSwgeFtpICsgNF0sIDIwLCAtNDA1NTM3ODQ4KTtcbiAgICBhID0gbWQ1Z2coYSwgYiwgYywgZCwgeFtpICsgOV0sIDUsIDU2ODQ0NjQzOCk7XG4gICAgZCA9IG1kNWdnKGQsIGEsIGIsIGMsIHhbaSArIDE0XSwgOSwgLTEwMTk4MDM2OTApO1xuICAgIGMgPSBtZDVnZyhjLCBkLCBhLCBiLCB4W2kgKyAzXSwgMTQsIC0xODczNjM5NjEpO1xuICAgIGIgPSBtZDVnZyhiLCBjLCBkLCBhLCB4W2kgKyA4XSwgMjAsIDExNjM1MzE1MDEpO1xuICAgIGEgPSBtZDVnZyhhLCBiLCBjLCBkLCB4W2kgKyAxM10sIDUsIC0xNDQ0NjgxNDY3KTtcbiAgICBkID0gbWQ1Z2coZCwgYSwgYiwgYywgeFtpICsgMl0sIDksIC01MTQwMzc4NCk7XG4gICAgYyA9IG1kNWdnKGMsIGQsIGEsIGIsIHhbaSArIDddLCAxNCwgMTczNTMyODQ3Myk7XG4gICAgYiA9IG1kNWdnKGIsIGMsIGQsIGEsIHhbaSArIDEyXSwgMjAsIC0xOTI2NjA3NzM0KTtcbiAgICBhID0gbWQ1aGgoYSwgYiwgYywgZCwgeFtpICsgNV0sIDQsIC0zNzg1NTgpO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2kgKyA4XSwgMTEsIC0yMDIyNTc0NDYzKTtcbiAgICBjID0gbWQ1aGgoYywgZCwgYSwgYiwgeFtpICsgMTFdLCAxNiwgMTgzOTAzMDU2Mik7XG4gICAgYiA9IG1kNWhoKGIsIGMsIGQsIGEsIHhbaSArIDE0XSwgMjMsIC0zNTMwOTU1Nik7XG4gICAgYSA9IG1kNWhoKGEsIGIsIGMsIGQsIHhbaSArIDFdLCA0LCAtMTUzMDk5MjA2MCk7XG4gICAgZCA9IG1kNWhoKGQsIGEsIGIsIGMsIHhbaSArIDRdLCAxMSwgMTI3Mjg5MzM1Myk7XG4gICAgYyA9IG1kNWhoKGMsIGQsIGEsIGIsIHhbaSArIDddLCAxNiwgLTE1NTQ5NzYzMik7XG4gICAgYiA9IG1kNWhoKGIsIGMsIGQsIGEsIHhbaSArIDEwXSwgMjMsIC0xMDk0NzMwNjQwKTtcbiAgICBhID0gbWQ1aGgoYSwgYiwgYywgZCwgeFtpICsgMTNdLCA0LCA2ODEyNzkxNzQpO1xuICAgIGQgPSBtZDVoaChkLCBhLCBiLCBjLCB4W2ldLCAxMSwgLTM1ODUzNzIyMik7XG4gICAgYyA9IG1kNWhoKGMsIGQsIGEsIGIsIHhbaSArIDNdLCAxNiwgLTcyMjUyMTk3OSk7XG4gICAgYiA9IG1kNWhoKGIsIGMsIGQsIGEsIHhbaSArIDZdLCAyMywgNzYwMjkxODkpO1xuICAgIGEgPSBtZDVoaChhLCBiLCBjLCBkLCB4W2kgKyA5XSwgNCwgLTY0MDM2NDQ4Nyk7XG4gICAgZCA9IG1kNWhoKGQsIGEsIGIsIGMsIHhbaSArIDEyXSwgMTEsIC00MjE4MTU4MzUpO1xuICAgIGMgPSBtZDVoaChjLCBkLCBhLCBiLCB4W2kgKyAxNV0sIDE2LCA1MzA3NDI1MjApO1xuICAgIGIgPSBtZDVoaChiLCBjLCBkLCBhLCB4W2kgKyAyXSwgMjMsIC05OTUzMzg2NTEpO1xuICAgIGEgPSBtZDVpaShhLCBiLCBjLCBkLCB4W2ldLCA2LCAtMTk4NjMwODQ0KTtcbiAgICBkID0gbWQ1aWkoZCwgYSwgYiwgYywgeFtpICsgN10sIDEwLCAxMTI2ODkxNDE1KTtcbiAgICBjID0gbWQ1aWkoYywgZCwgYSwgYiwgeFtpICsgMTRdLCAxNSwgLTE0MTYzNTQ5MDUpO1xuICAgIGIgPSBtZDVpaShiLCBjLCBkLCBhLCB4W2kgKyA1XSwgMjEsIC01NzQzNDA1NSk7XG4gICAgYSA9IG1kNWlpKGEsIGIsIGMsIGQsIHhbaSArIDEyXSwgNiwgMTcwMDQ4NTU3MSk7XG4gICAgZCA9IG1kNWlpKGQsIGEsIGIsIGMsIHhbaSArIDNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xuICAgIGMgPSBtZDVpaShjLCBkLCBhLCBiLCB4W2kgKyAxMF0sIDE1LCAtMTA1MTUyMyk7XG4gICAgYiA9IG1kNWlpKGIsIGMsIGQsIGEsIHhbaSArIDFdLCAyMSwgLTIwNTQ5MjI3OTkpO1xuICAgIGEgPSBtZDVpaShhLCBiLCBjLCBkLCB4W2kgKyA4XSwgNiwgMTg3MzMxMzM1OSk7XG4gICAgZCA9IG1kNWlpKGQsIGEsIGIsIGMsIHhbaSArIDE1XSwgMTAsIC0zMDYxMTc0NCk7XG4gICAgYyA9IG1kNWlpKGMsIGQsIGEsIGIsIHhbaSArIDZdLCAxNSwgLTE1NjAxOTgzODApO1xuICAgIGIgPSBtZDVpaShiLCBjLCBkLCBhLCB4W2kgKyAxM10sIDIxLCAxMzA5MTUxNjQ5KTtcbiAgICBhID0gbWQ1aWkoYSwgYiwgYywgZCwgeFtpICsgNF0sIDYsIC0xNDU1MjMwNzApO1xuICAgIGQgPSBtZDVpaShkLCBhLCBiLCBjLCB4W2kgKyAxMV0sIDEwLCAtMTEyMDIxMDM3OSk7XG4gICAgYyA9IG1kNWlpKGMsIGQsIGEsIGIsIHhbaSArIDJdLCAxNSwgNzE4Nzg3MjU5KTtcbiAgICBiID0gbWQ1aWkoYiwgYywgZCwgYSwgeFtpICsgOV0sIDIxLCAtMzQzNDg1NTUxKTtcbiAgICBhID0gc2FmZUFkZChhLCBvbGRhKTtcbiAgICBiID0gc2FmZUFkZChiLCBvbGRiKTtcbiAgICBjID0gc2FmZUFkZChjLCBvbGRjKTtcbiAgICBkID0gc2FmZUFkZChkLCBvbGRkKTtcbiAgfVxuXG4gIHJldHVybiBbYSwgYiwgYywgZF07XG59XG4vKlxuICogQ29udmVydCBhbiBhcnJheSBieXRlcyB0byBhbiBhcnJheSBvZiBsaXR0bGUtZW5kaWFuIHdvcmRzXG4gKiBDaGFyYWN0ZXJzID4yNTUgaGF2ZSB0aGVpciBoaWdoLWJ5dGUgc2lsZW50bHkgaWdub3JlZC5cbiAqL1xuXG5cbmZ1bmN0aW9uIGJ5dGVzVG9Xb3JkcyhpbnB1dCkge1xuICBpZiAoaW5wdXQubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgbGVuZ3RoOCA9IGlucHV0Lmxlbmd0aCAqIDg7XG4gIGNvbnN0IG91dHB1dCA9IG5ldyBVaW50MzJBcnJheShnZXRPdXRwdXRMZW5ndGgobGVuZ3RoOCkpO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoODsgaSArPSA4KSB7XG4gICAgb3V0cHV0W2kgPj4gNV0gfD0gKGlucHV0W2kgLyA4XSAmIDB4ZmYpIDw8IGkgJSAzMjtcbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59XG4vKlxuICogQWRkIGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjMyLiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnMgaW50ZXJuYWxseVxuICogdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAqL1xuXG5cbmZ1bmN0aW9uIHNhZmVBZGQoeCwgeSkge1xuICBjb25zdCBsc3cgPSAoeCAmIDB4ZmZmZikgKyAoeSAmIDB4ZmZmZik7XG4gIGNvbnN0IG1zdyA9ICh4ID4+IDE2KSArICh5ID4+IDE2KSArIChsc3cgPj4gMTYpO1xuICByZXR1cm4gbXN3IDw8IDE2IHwgbHN3ICYgMHhmZmZmO1xufVxuLypcbiAqIEJpdHdpc2Ugcm90YXRlIGEgMzItYml0IG51bWJlciB0byB0aGUgbGVmdC5cbiAqL1xuXG5cbmZ1bmN0aW9uIGJpdFJvdGF0ZUxlZnQobnVtLCBjbnQpIHtcbiAgcmV0dXJuIG51bSA8PCBjbnQgfCBudW0gPj4+IDMyIC0gY250O1xufVxuLypcbiAqIFRoZXNlIGZ1bmN0aW9ucyBpbXBsZW1lbnQgdGhlIGZvdXIgYmFzaWMgb3BlcmF0aW9ucyB0aGUgYWxnb3JpdGhtIHVzZXMuXG4gKi9cblxuXG5mdW5jdGlvbiBtZDVjbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuICByZXR1cm4gc2FmZUFkZChiaXRSb3RhdGVMZWZ0KHNhZmVBZGQoc2FmZUFkZChhLCBxKSwgc2FmZUFkZCh4LCB0KSksIHMpLCBiKTtcbn1cblxuZnVuY3Rpb24gbWQ1ZmYoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICByZXR1cm4gbWQ1Y21uKGIgJiBjIHwgfmIgJiBkLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuZnVuY3Rpb24gbWQ1Z2coYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICByZXR1cm4gbWQ1Y21uKGIgJiBkIHwgYyAmIH5kLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuZnVuY3Rpb24gbWQ1aGgoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICByZXR1cm4gbWQ1Y21uKGIgXiBjIF4gZCwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIG1kNWlpKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIG1kNWNtbihjIF4gKGIgfCB+ZCksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG52YXIgX2RlZmF1bHQgPSBtZDU7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcbnZhciBfZGVmYXVsdCA9ICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAnO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfdmFsaWRhdGUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3ZhbGlkYXRlLmpzXCIpKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gcGFyc2UodXVpZCkge1xuICBpZiAoISgwLCBfdmFsaWRhdGUuZGVmYXVsdCkodXVpZCkpIHtcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ0ludmFsaWQgVVVJRCcpO1xuICB9XG5cbiAgbGV0IHY7XG4gIGNvbnN0IGFyciA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gUGFyc2UgIyMjIyMjIyMtLi4uLi0uLi4uLS4uLi4tLi4uLi4uLi4uLi4uXG5cbiAgYXJyWzBdID0gKHYgPSBwYXJzZUludCh1dWlkLnNsaWNlKDAsIDgpLCAxNikpID4+PiAyNDtcbiAgYXJyWzFdID0gdiA+Pj4gMTYgJiAweGZmO1xuICBhcnJbMl0gPSB2ID4+PiA4ICYgMHhmZjtcbiAgYXJyWzNdID0gdiAmIDB4ZmY7IC8vIFBhcnNlIC4uLi4uLi4uLSMjIyMtLi4uLi0uLi4uLS4uLi4uLi4uLi4uLlxuXG4gIGFycls0XSA9ICh2ID0gcGFyc2VJbnQodXVpZC5zbGljZSg5LCAxMyksIDE2KSkgPj4+IDg7XG4gIGFycls1XSA9IHYgJiAweGZmOyAvLyBQYXJzZSAuLi4uLi4uLi0uLi4uLSMjIyMtLi4uLi0uLi4uLi4uLi4uLi5cblxuICBhcnJbNl0gPSAodiA9IHBhcnNlSW50KHV1aWQuc2xpY2UoMTQsIDE4KSwgMTYpKSA+Pj4gODtcbiAgYXJyWzddID0gdiAmIDB4ZmY7IC8vIFBhcnNlIC4uLi4uLi4uLS4uLi4tLi4uLi0jIyMjLS4uLi4uLi4uLi4uLlxuXG4gIGFycls4XSA9ICh2ID0gcGFyc2VJbnQodXVpZC5zbGljZSgxOSwgMjMpLCAxNikpID4+PiA4O1xuICBhcnJbOV0gPSB2ICYgMHhmZjsgLy8gUGFyc2UgLi4uLi4uLi4tLi4uLi0uLi4uLS4uLi4tIyMjIyMjIyMjIyMjXG4gIC8vIChVc2UgXCIvXCIgdG8gYXZvaWQgMzItYml0IHRydW5jYXRpb24gd2hlbiBiaXQtc2hpZnRpbmcgaGlnaC1vcmRlciBieXRlcylcblxuICBhcnJbMTBdID0gKHYgPSBwYXJzZUludCh1dWlkLnNsaWNlKDI0LCAzNiksIDE2KSkgLyAweDEwMDAwMDAwMDAwICYgMHhmZjtcbiAgYXJyWzExXSA9IHYgLyAweDEwMDAwMDAwMCAmIDB4ZmY7XG4gIGFyclsxMl0gPSB2ID4+PiAyNCAmIDB4ZmY7XG4gIGFyclsxM10gPSB2ID4+PiAxNiAmIDB4ZmY7XG4gIGFyclsxNF0gPSB2ID4+PiA4ICYgMHhmZjtcbiAgYXJyWzE1XSA9IHYgJiAweGZmO1xuICByZXR1cm4gYXJyO1xufVxuXG52YXIgX2RlZmF1bHQgPSBwYXJzZTtcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xudmFyIF9kZWZhdWx0ID0gL14oPzpbMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMS01XVswLTlhLWZdezN9LVs4OWFiXVswLTlhLWZdezN9LVswLTlhLWZdezEyfXwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDApJC9pO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSBybmc7XG4vLyBVbmlxdWUgSUQgY3JlYXRpb24gcmVxdWlyZXMgYSBoaWdoIHF1YWxpdHkgcmFuZG9tICMgZ2VuZXJhdG9yLiBJbiB0aGUgYnJvd3NlciB3ZSB0aGVyZWZvcmVcbi8vIHJlcXVpcmUgdGhlIGNyeXB0byBBUEkgYW5kIGRvIG5vdCBzdXBwb3J0IGJ1aWx0LWluIGZhbGxiYWNrIHRvIGxvd2VyIHF1YWxpdHkgcmFuZG9tIG51bWJlclxuLy8gZ2VuZXJhdG9ycyAobGlrZSBNYXRoLnJhbmRvbSgpKS5cbmxldCBnZXRSYW5kb21WYWx1ZXM7XG5jb25zdCBybmRzOCA9IG5ldyBVaW50OEFycmF5KDE2KTtcblxuZnVuY3Rpb24gcm5nKCkge1xuICAvLyBsYXp5IGxvYWQgc28gdGhhdCBlbnZpcm9ubWVudHMgdGhhdCBuZWVkIHRvIHBvbHlmaWxsIGhhdmUgYSBjaGFuY2UgdG8gZG8gc29cbiAgaWYgKCFnZXRSYW5kb21WYWx1ZXMpIHtcbiAgICAvLyBnZXRSYW5kb21WYWx1ZXMgbmVlZHMgdG8gYmUgaW52b2tlZCBpbiBhIGNvbnRleHQgd2hlcmUgXCJ0aGlzXCIgaXMgYSBDcnlwdG8gaW1wbGVtZW50YXRpb24uIEFsc28sXG4gICAgLy8gZmluZCB0aGUgY29tcGxldGUgaW1wbGVtZW50YXRpb24gb2YgY3J5cHRvIChtc0NyeXB0bykgb24gSUUxMS5cbiAgICBnZXRSYW5kb21WYWx1ZXMgPSB0eXBlb2YgY3J5cHRvICE9PSAndW5kZWZpbmVkJyAmJiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzICYmIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChjcnlwdG8pIHx8IHR5cGVvZiBtc0NyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIG1zQ3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJyAmJiBtc0NyeXB0by5nZXRSYW5kb21WYWx1ZXMuYmluZChtc0NyeXB0byk7XG5cbiAgICBpZiAoIWdldFJhbmRvbVZhbHVlcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKCkgbm90IHN1cHBvcnRlZC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS91dWlkanMvdXVpZCNnZXRyYW5kb212YWx1ZXMtbm90LXN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBnZXRSYW5kb21WYWx1ZXMocm5kczgpO1xufSIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuXG4vLyBBZGFwdGVkIGZyb20gQ2hyaXMgVmVuZXNzJyBTSEExIGNvZGUgYXRcbi8vIGh0dHA6Ly93d3cubW92YWJsZS10eXBlLmNvLnVrL3NjcmlwdHMvc2hhMS5odG1sXG5mdW5jdGlvbiBmKHMsIHgsIHksIHopIHtcbiAgc3dpdGNoIChzKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIHggJiB5IF4gfnggJiB6O1xuXG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIHggXiB5IF4gejtcblxuICAgIGNhc2UgMjpcbiAgICAgIHJldHVybiB4ICYgeSBeIHggJiB6IF4geSAmIHo7XG5cbiAgICBjYXNlIDM6XG4gICAgICByZXR1cm4geCBeIHkgXiB6O1xuICB9XG59XG5cbmZ1bmN0aW9uIFJPVEwoeCwgbikge1xuICByZXR1cm4geCA8PCBuIHwgeCA+Pj4gMzIgLSBuO1xufVxuXG5mdW5jdGlvbiBzaGExKGJ5dGVzKSB7XG4gIGNvbnN0IEsgPSBbMHg1YTgyNzk5OSwgMHg2ZWQ5ZWJhMSwgMHg4ZjFiYmNkYywgMHhjYTYyYzFkNl07XG4gIGNvbnN0IEggPSBbMHg2NzQ1MjMwMSwgMHhlZmNkYWI4OSwgMHg5OGJhZGNmZSwgMHgxMDMyNTQ3NiwgMHhjM2QyZTFmMF07XG5cbiAgaWYgKHR5cGVvZiBieXRlcyA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBtc2cgPSB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoYnl0ZXMpKTsgLy8gVVRGOCBlc2NhcGVcblxuICAgIGJ5dGVzID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1zZy5sZW5ndGg7ICsraSkge1xuICAgICAgYnl0ZXMucHVzaChtc2cuY2hhckNvZGVBdChpKSk7XG4gICAgfVxuICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KGJ5dGVzKSkge1xuICAgIC8vIENvbnZlcnQgQXJyYXktbGlrZSB0byBBcnJheVxuICAgIGJ5dGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYnl0ZXMpO1xuICB9XG5cbiAgYnl0ZXMucHVzaCgweDgwKTtcbiAgY29uc3QgbCA9IGJ5dGVzLmxlbmd0aCAvIDQgKyAyO1xuICBjb25zdCBOID0gTWF0aC5jZWlsKGwgLyAxNik7XG4gIGNvbnN0IE0gPSBuZXcgQXJyYXkoTik7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBOOyArK2kpIHtcbiAgICBjb25zdCBhcnIgPSBuZXcgVWludDMyQXJyYXkoMTYpO1xuXG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7XG4gICAgICBhcnJbal0gPSBieXRlc1tpICogNjQgKyBqICogNF0gPDwgMjQgfCBieXRlc1tpICogNjQgKyBqICogNCArIDFdIDw8IDE2IHwgYnl0ZXNbaSAqIDY0ICsgaiAqIDQgKyAyXSA8PCA4IHwgYnl0ZXNbaSAqIDY0ICsgaiAqIDQgKyAzXTtcbiAgICB9XG5cbiAgICBNW2ldID0gYXJyO1xuICB9XG5cbiAgTVtOIC0gMV1bMTRdID0gKGJ5dGVzLmxlbmd0aCAtIDEpICogOCAvIE1hdGgucG93KDIsIDMyKTtcbiAgTVtOIC0gMV1bMTRdID0gTWF0aC5mbG9vcihNW04gLSAxXVsxNF0pO1xuICBNW04gLSAxXVsxNV0gPSAoYnl0ZXMubGVuZ3RoIC0gMSkgKiA4ICYgMHhmZmZmZmZmZjtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IE47ICsraSkge1xuICAgIGNvbnN0IFcgPSBuZXcgVWludDMyQXJyYXkoODApO1xuXG4gICAgZm9yIChsZXQgdCA9IDA7IHQgPCAxNjsgKyt0KSB7XG4gICAgICBXW3RdID0gTVtpXVt0XTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCB0ID0gMTY7IHQgPCA4MDsgKyt0KSB7XG4gICAgICBXW3RdID0gUk9UTChXW3QgLSAzXSBeIFdbdCAtIDhdIF4gV1t0IC0gMTRdIF4gV1t0IC0gMTZdLCAxKTtcbiAgICB9XG5cbiAgICBsZXQgYSA9IEhbMF07XG4gICAgbGV0IGIgPSBIWzFdO1xuICAgIGxldCBjID0gSFsyXTtcbiAgICBsZXQgZCA9IEhbM107XG4gICAgbGV0IGUgPSBIWzRdO1xuXG4gICAgZm9yIChsZXQgdCA9IDA7IHQgPCA4MDsgKyt0KSB7XG4gICAgICBjb25zdCBzID0gTWF0aC5mbG9vcih0IC8gMjApO1xuICAgICAgY29uc3QgVCA9IFJPVEwoYSwgNSkgKyBmKHMsIGIsIGMsIGQpICsgZSArIEtbc10gKyBXW3RdID4+PiAwO1xuICAgICAgZSA9IGQ7XG4gICAgICBkID0gYztcbiAgICAgIGMgPSBST1RMKGIsIDMwKSA+Pj4gMDtcbiAgICAgIGIgPSBhO1xuICAgICAgYSA9IFQ7XG4gICAgfVxuXG4gICAgSFswXSA9IEhbMF0gKyBhID4+PiAwO1xuICAgIEhbMV0gPSBIWzFdICsgYiA+Pj4gMDtcbiAgICBIWzJdID0gSFsyXSArIGMgPj4+IDA7XG4gICAgSFszXSA9IEhbM10gKyBkID4+PiAwO1xuICAgIEhbNF0gPSBIWzRdICsgZSA+Pj4gMDtcbiAgfVxuXG4gIHJldHVybiBbSFswXSA+PiAyNCAmIDB4ZmYsIEhbMF0gPj4gMTYgJiAweGZmLCBIWzBdID4+IDggJiAweGZmLCBIWzBdICYgMHhmZiwgSFsxXSA+PiAyNCAmIDB4ZmYsIEhbMV0gPj4gMTYgJiAweGZmLCBIWzFdID4+IDggJiAweGZmLCBIWzFdICYgMHhmZiwgSFsyXSA+PiAyNCAmIDB4ZmYsIEhbMl0gPj4gMTYgJiAweGZmLCBIWzJdID4+IDggJiAweGZmLCBIWzJdICYgMHhmZiwgSFszXSA+PiAyNCAmIDB4ZmYsIEhbM10gPj4gMTYgJiAweGZmLCBIWzNdID4+IDggJiAweGZmLCBIWzNdICYgMHhmZiwgSFs0XSA+PiAyNCAmIDB4ZmYsIEhbNF0gPj4gMTYgJiAweGZmLCBIWzRdID4+IDggJiAweGZmLCBIWzRdICYgMHhmZl07XG59XG5cbnZhciBfZGVmYXVsdCA9IHNoYTE7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF92YWxpZGF0ZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdmFsaWRhdGUuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG4vKipcbiAqIENvbnZlcnQgYXJyYXkgb2YgMTYgYnl0ZSB2YWx1ZXMgdG8gVVVJRCBzdHJpbmcgZm9ybWF0IG9mIHRoZSBmb3JtOlxuICogWFhYWFhYWFgtWFhYWC1YWFhYLVhYWFgtWFhYWFhYWFhYWFhYXG4gKi9cbmNvbnN0IGJ5dGVUb0hleCA9IFtdO1xuXG5mb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgKytpKSB7XG4gIGJ5dGVUb0hleC5wdXNoKChpICsgMHgxMDApLnRvU3RyaW5nKDE2KS5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiBzdHJpbmdpZnkoYXJyLCBvZmZzZXQgPSAwKSB7XG4gIC8vIE5vdGU6IEJlIGNhcmVmdWwgZWRpdGluZyB0aGlzIGNvZGUhICBJdCdzIGJlZW4gdHVuZWQgZm9yIHBlcmZvcm1hbmNlXG4gIC8vIGFuZCB3b3JrcyBpbiB3YXlzIHlvdSBtYXkgbm90IGV4cGVjdC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS91dWlkanMvdXVpZC9wdWxsLzQzNFxuICBjb25zdCB1dWlkID0gKGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgMF1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxXV0gKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDJdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgM11dICsgJy0nICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyA0XV0gKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDVdXSArICctJyArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgNl1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyA3XV0gKyAnLScgKyBieXRlVG9IZXhbYXJyW29mZnNldCArIDhdXSArIGJ5dGVUb0hleFthcnJbb2Zmc2V0ICsgOV1dICsgJy0nICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxMF1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxMV1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxMl1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxM11dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxNF1dICsgYnl0ZVRvSGV4W2FycltvZmZzZXQgKyAxNV1dKS50b0xvd2VyQ2FzZSgpOyAvLyBDb25zaXN0ZW5jeSBjaGVjayBmb3IgdmFsaWQgVVVJRC4gIElmIHRoaXMgdGhyb3dzLCBpdCdzIGxpa2VseSBkdWUgdG8gb25lXG4gIC8vIG9mIHRoZSBmb2xsb3dpbmc6XG4gIC8vIC0gT25lIG9yIG1vcmUgaW5wdXQgYXJyYXkgdmFsdWVzIGRvbid0IG1hcCB0byBhIGhleCBvY3RldCAobGVhZGluZyB0b1xuICAvLyBcInVuZGVmaW5lZFwiIGluIHRoZSB1dWlkKVxuICAvLyAtIEludmFsaWQgaW5wdXQgdmFsdWVzIGZvciB0aGUgUkZDIGB2ZXJzaW9uYCBvciBgdmFyaWFudGAgZmllbGRzXG5cbiAgaWYgKCEoMCwgX3ZhbGlkYXRlLmRlZmF1bHQpKHV1aWQpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKCdTdHJpbmdpZmllZCBVVUlEIGlzIGludmFsaWQnKTtcbiAgfVxuXG4gIHJldHVybiB1dWlkO1xufVxuXG52YXIgX2RlZmF1bHQgPSBzdHJpbmdpZnk7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF9ybmcgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3JuZy5qc1wiKSk7XG5cbnZhciBfc3RyaW5naWZ5ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zdHJpbmdpZnkuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG4vLyAqKmB2MSgpYCAtIEdlbmVyYXRlIHRpbWUtYmFzZWQgVVVJRCoqXG4vL1xuLy8gSW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL0xpb3NLL1VVSUQuanNcbi8vIGFuZCBodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvdXVpZC5odG1sXG5sZXQgX25vZGVJZDtcblxubGV0IF9jbG9ja3NlcTsgLy8gUHJldmlvdXMgdXVpZCBjcmVhdGlvbiB0aW1lXG5cblxubGV0IF9sYXN0TVNlY3MgPSAwO1xubGV0IF9sYXN0TlNlY3MgPSAwOyAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3V1aWRqcy91dWlkIGZvciBBUEkgZGV0YWlsc1xuXG5mdW5jdGlvbiB2MShvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICBsZXQgaSA9IGJ1ZiAmJiBvZmZzZXQgfHwgMDtcbiAgY29uc3QgYiA9IGJ1ZiB8fCBuZXcgQXJyYXkoMTYpO1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgbGV0IG5vZGUgPSBvcHRpb25zLm5vZGUgfHwgX25vZGVJZDtcbiAgbGV0IGNsb2Nrc2VxID0gb3B0aW9ucy5jbG9ja3NlcSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbG9ja3NlcSA6IF9jbG9ja3NlcTsgLy8gbm9kZSBhbmQgY2xvY2tzZXEgbmVlZCB0byBiZSBpbml0aWFsaXplZCB0byByYW5kb20gdmFsdWVzIGlmIHRoZXkncmUgbm90XG4gIC8vIHNwZWNpZmllZC4gIFdlIGRvIHRoaXMgbGF6aWx5IHRvIG1pbmltaXplIGlzc3VlcyByZWxhdGVkIHRvIGluc3VmZmljaWVudFxuICAvLyBzeXN0ZW0gZW50cm9weS4gIFNlZSAjMTg5XG5cbiAgaWYgKG5vZGUgPT0gbnVsbCB8fCBjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgY29uc3Qgc2VlZEJ5dGVzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IF9ybmcuZGVmYXVsdCkoKTtcblxuICAgIGlmIChub2RlID09IG51bGwpIHtcbiAgICAgIC8vIFBlciA0LjUsIGNyZWF0ZSBhbmQgNDgtYml0IG5vZGUgaWQsICg0NyByYW5kb20gYml0cyArIG11bHRpY2FzdCBiaXQgPSAxKVxuICAgICAgbm9kZSA9IF9ub2RlSWQgPSBbc2VlZEJ5dGVzWzBdIHwgMHgwMSwgc2VlZEJ5dGVzWzFdLCBzZWVkQnl0ZXNbMl0sIHNlZWRCeXRlc1szXSwgc2VlZEJ5dGVzWzRdLCBzZWVkQnl0ZXNbNV1dO1xuICAgIH1cblxuICAgIGlmIChjbG9ja3NlcSA9PSBudWxsKSB7XG4gICAgICAvLyBQZXIgNC4yLjIsIHJhbmRvbWl6ZSAoMTQgYml0KSBjbG9ja3NlcVxuICAgICAgY2xvY2tzZXEgPSBfY2xvY2tzZXEgPSAoc2VlZEJ5dGVzWzZdIDw8IDggfCBzZWVkQnl0ZXNbN10pICYgMHgzZmZmO1xuICAgIH1cbiAgfSAvLyBVVUlEIHRpbWVzdGFtcHMgYXJlIDEwMCBuYW5vLXNlY29uZCB1bml0cyBzaW5jZSB0aGUgR3JlZ29yaWFuIGVwb2NoLFxuICAvLyAoMTU4Mi0xMC0xNSAwMDowMCkuICBKU051bWJlcnMgYXJlbid0IHByZWNpc2UgZW5vdWdoIGZvciB0aGlzLCBzb1xuICAvLyB0aW1lIGlzIGhhbmRsZWQgaW50ZXJuYWxseSBhcyAnbXNlY3MnIChpbnRlZ2VyIG1pbGxpc2Vjb25kcykgYW5kICduc2VjcydcbiAgLy8gKDEwMC1uYW5vc2Vjb25kcyBvZmZzZXQgZnJvbSBtc2Vjcykgc2luY2UgdW5peCBlcG9jaCwgMTk3MC0wMS0wMSAwMDowMC5cblxuXG4gIGxldCBtc2VjcyA9IG9wdGlvbnMubXNlY3MgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubXNlY3MgOiBEYXRlLm5vdygpOyAvLyBQZXIgNC4yLjEuMiwgdXNlIGNvdW50IG9mIHV1aWQncyBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBjdXJyZW50IGNsb2NrXG4gIC8vIGN5Y2xlIHRvIHNpbXVsYXRlIGhpZ2hlciByZXNvbHV0aW9uIGNsb2NrXG5cbiAgbGV0IG5zZWNzID0gb3B0aW9ucy5uc2VjcyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5uc2VjcyA6IF9sYXN0TlNlY3MgKyAxOyAvLyBUaW1lIHNpbmNlIGxhc3QgdXVpZCBjcmVhdGlvbiAoaW4gbXNlY3MpXG5cbiAgY29uc3QgZHQgPSBtc2VjcyAtIF9sYXN0TVNlY3MgKyAobnNlY3MgLSBfbGFzdE5TZWNzKSAvIDEwMDAwOyAvLyBQZXIgNC4yLjEuMiwgQnVtcCBjbG9ja3NlcSBvbiBjbG9jayByZWdyZXNzaW9uXG5cbiAgaWYgKGR0IDwgMCAmJiBvcHRpb25zLmNsb2Nrc2VxID09PSB1bmRlZmluZWQpIHtcbiAgICBjbG9ja3NlcSA9IGNsb2Nrc2VxICsgMSAmIDB4M2ZmZjtcbiAgfSAvLyBSZXNldCBuc2VjcyBpZiBjbG9jayByZWdyZXNzZXMgKG5ldyBjbG9ja3NlcSkgb3Igd2UndmUgbW92ZWQgb250byBhIG5ld1xuICAvLyB0aW1lIGludGVydmFsXG5cblxuICBpZiAoKGR0IDwgMCB8fCBtc2VjcyA+IF9sYXN0TVNlY3MpICYmIG9wdGlvbnMubnNlY3MgPT09IHVuZGVmaW5lZCkge1xuICAgIG5zZWNzID0gMDtcbiAgfSAvLyBQZXIgNC4yLjEuMiBUaHJvdyBlcnJvciBpZiB0b28gbWFueSB1dWlkcyBhcmUgcmVxdWVzdGVkXG5cblxuICBpZiAobnNlY3MgPj0gMTAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1dWlkLnYxKCk6IENhbid0IGNyZWF0ZSBtb3JlIHRoYW4gMTBNIHV1aWRzL3NlY1wiKTtcbiAgfVxuXG4gIF9sYXN0TVNlY3MgPSBtc2VjcztcbiAgX2xhc3ROU2VjcyA9IG5zZWNzO1xuICBfY2xvY2tzZXEgPSBjbG9ja3NlcTsgLy8gUGVyIDQuMS40IC0gQ29udmVydCBmcm9tIHVuaXggZXBvY2ggdG8gR3JlZ29yaWFuIGVwb2NoXG5cbiAgbXNlY3MgKz0gMTIyMTkyOTI4MDAwMDA7IC8vIGB0aW1lX2xvd2BcblxuICBjb25zdCB0bCA9ICgobXNlY3MgJiAweGZmZmZmZmYpICogMTAwMDAgKyBuc2VjcykgJSAweDEwMDAwMDAwMDtcbiAgYltpKytdID0gdGwgPj4+IDI0ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDE2ICYgMHhmZjtcbiAgYltpKytdID0gdGwgPj4+IDggJiAweGZmO1xuICBiW2krK10gPSB0bCAmIDB4ZmY7IC8vIGB0aW1lX21pZGBcblxuICBjb25zdCB0bWggPSBtc2VjcyAvIDB4MTAwMDAwMDAwICogMTAwMDAgJiAweGZmZmZmZmY7XG4gIGJbaSsrXSA9IHRtaCA+Pj4gOCAmIDB4ZmY7XG4gIGJbaSsrXSA9IHRtaCAmIDB4ZmY7IC8vIGB0aW1lX2hpZ2hfYW5kX3ZlcnNpb25gXG5cbiAgYltpKytdID0gdG1oID4+PiAyNCAmIDB4ZiB8IDB4MTA7IC8vIGluY2x1ZGUgdmVyc2lvblxuXG4gIGJbaSsrXSA9IHRtaCA+Pj4gMTYgJiAweGZmOyAvLyBgY2xvY2tfc2VxX2hpX2FuZF9yZXNlcnZlZGAgKFBlciA0LjIuMiAtIGluY2x1ZGUgdmFyaWFudClcblxuICBiW2krK10gPSBjbG9ja3NlcSA+Pj4gOCB8IDB4ODA7IC8vIGBjbG9ja19zZXFfbG93YFxuXG4gIGJbaSsrXSA9IGNsb2Nrc2VxICYgMHhmZjsgLy8gYG5vZGVgXG5cbiAgZm9yIChsZXQgbiA9IDA7IG4gPCA2OyArK24pIHtcbiAgICBiW2kgKyBuXSA9IG5vZGVbbl07XG4gIH1cblxuICByZXR1cm4gYnVmIHx8ICgwLCBfc3RyaW5naWZ5LmRlZmF1bHQpKGIpO1xufVxuXG52YXIgX2RlZmF1bHQgPSB2MTtcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kZWZhdWx0ID0gdm9pZCAwO1xuXG52YXIgX3YgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3YzNS5qc1wiKSk7XG5cbnZhciBfbWQgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL21kNS5qc1wiKSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmNvbnN0IHYzID0gKDAsIF92LmRlZmF1bHQpKCd2MycsIDB4MzAsIF9tZC5kZWZhdWx0KTtcbnZhciBfZGVmYXVsdCA9IHYzO1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDtcbmV4cG9ydHMuVVJMID0gZXhwb3J0cy5ETlMgPSB2b2lkIDA7XG5cbnZhciBfc3RyaW5naWZ5ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zdHJpbmdpZnkuanNcIikpO1xuXG52YXIgX3BhcnNlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9wYXJzZS5qc1wiKSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIHN0cmluZ1RvQnl0ZXMoc3RyKSB7XG4gIHN0ciA9IHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKTsgLy8gVVRGOCBlc2NhcGVcblxuICBjb25zdCBieXRlcyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgYnl0ZXMucHVzaChzdHIuY2hhckNvZGVBdChpKSk7XG4gIH1cblxuICByZXR1cm4gYnl0ZXM7XG59XG5cbmNvbnN0IEROUyA9ICc2YmE3YjgxMC05ZGFkLTExZDEtODBiNC0wMGMwNGZkNDMwYzgnO1xuZXhwb3J0cy5ETlMgPSBETlM7XG5jb25zdCBVUkwgPSAnNmJhN2I4MTEtOWRhZC0xMWQxLTgwYjQtMDBjMDRmZDQzMGM4JztcbmV4cG9ydHMuVVJMID0gVVJMO1xuXG5mdW5jdGlvbiBfZGVmYXVsdChuYW1lLCB2ZXJzaW9uLCBoYXNoZnVuYykge1xuICBmdW5jdGlvbiBnZW5lcmF0ZVVVSUQodmFsdWUsIG5hbWVzcGFjZSwgYnVmLCBvZmZzZXQpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgdmFsdWUgPSBzdHJpbmdUb0J5dGVzKHZhbHVlKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG5hbWVzcGFjZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG5hbWVzcGFjZSA9ICgwLCBfcGFyc2UuZGVmYXVsdCkobmFtZXNwYWNlKTtcbiAgICB9XG5cbiAgICBpZiAobmFtZXNwYWNlLmxlbmd0aCAhPT0gMTYpIHtcbiAgICAgIHRocm93IFR5cGVFcnJvcignTmFtZXNwYWNlIG11c3QgYmUgYXJyYXktbGlrZSAoMTYgaXRlcmFibGUgaW50ZWdlciB2YWx1ZXMsIDAtMjU1KScpO1xuICAgIH0gLy8gQ29tcHV0ZSBoYXNoIG9mIG5hbWVzcGFjZSBhbmQgdmFsdWUsIFBlciA0LjNcbiAgICAvLyBGdXR1cmU6IFVzZSBzcHJlYWQgc3ludGF4IHdoZW4gc3VwcG9ydGVkIG9uIGFsbCBwbGF0Zm9ybXMsIGUuZy4gYGJ5dGVzID1cbiAgICAvLyBoYXNoZnVuYyhbLi4ubmFtZXNwYWNlLCAuLi4gdmFsdWVdKWBcblxuXG4gICAgbGV0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoMTYgKyB2YWx1ZS5sZW5ndGgpO1xuICAgIGJ5dGVzLnNldChuYW1lc3BhY2UpO1xuICAgIGJ5dGVzLnNldCh2YWx1ZSwgbmFtZXNwYWNlLmxlbmd0aCk7XG4gICAgYnl0ZXMgPSBoYXNoZnVuYyhieXRlcyk7XG4gICAgYnl0ZXNbNl0gPSBieXRlc1s2XSAmIDB4MGYgfCB2ZXJzaW9uO1xuICAgIGJ5dGVzWzhdID0gYnl0ZXNbOF0gJiAweDNmIHwgMHg4MDtcblxuICAgIGlmIChidWYpIHtcbiAgICAgIG9mZnNldCA9IG9mZnNldCB8fCAwO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDE2OyArK2kpIHtcbiAgICAgICAgYnVmW29mZnNldCArIGldID0gYnl0ZXNbaV07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBidWY7XG4gICAgfVxuXG4gICAgcmV0dXJuICgwLCBfc3RyaW5naWZ5LmRlZmF1bHQpKGJ5dGVzKTtcbiAgfSAvLyBGdW5jdGlvbiNuYW1lIGlzIG5vdCBzZXR0YWJsZSBvbiBzb21lIHBsYXRmb3JtcyAoIzI3MClcblxuXG4gIHRyeSB7XG4gICAgZ2VuZXJhdGVVVUlELm5hbWUgPSBuYW1lOyAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZW1wdHlcbiAgfSBjYXRjaCAoZXJyKSB7fSAvLyBGb3IgQ29tbW9uSlMgZGVmYXVsdCBleHBvcnQgc3VwcG9ydFxuXG5cbiAgZ2VuZXJhdGVVVUlELkROUyA9IEROUztcbiAgZ2VuZXJhdGVVVUlELlVSTCA9IFVSTDtcbiAgcmV0dXJuIGdlbmVyYXRlVVVJRDtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF9ybmcgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3JuZy5qc1wiKSk7XG5cbnZhciBfc3RyaW5naWZ5ID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zdHJpbmdpZnkuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiB2NChvcHRpb25zLCBidWYsIG9mZnNldCkge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICBjb25zdCBybmRzID0gb3B0aW9ucy5yYW5kb20gfHwgKG9wdGlvbnMucm5nIHx8IF9ybmcuZGVmYXVsdCkoKTsgLy8gUGVyIDQuNCwgc2V0IGJpdHMgZm9yIHZlcnNpb24gYW5kIGBjbG9ja19zZXFfaGlfYW5kX3Jlc2VydmVkYFxuXG5cbiAgcm5kc1s2XSA9IHJuZHNbNl0gJiAweDBmIHwgMHg0MDtcbiAgcm5kc1s4XSA9IHJuZHNbOF0gJiAweDNmIHwgMHg4MDsgLy8gQ29weSBieXRlcyB0byBidWZmZXIsIGlmIHByb3ZpZGVkXG5cbiAgaWYgKGJ1Zikge1xuICAgIG9mZnNldCA9IG9mZnNldCB8fCAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxNjsgKytpKSB7XG4gICAgICBidWZbb2Zmc2V0ICsgaV0gPSBybmRzW2ldO1xuICAgIH1cblxuICAgIHJldHVybiBidWY7XG4gIH1cblxuICByZXR1cm4gKDAsIF9zdHJpbmdpZnkuZGVmYXVsdCkocm5kcyk7XG59XG5cbnZhciBfZGVmYXVsdCA9IHY0O1xuZXhwb3J0cy5kZWZhdWx0ID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZmF1bHQgPSB2b2lkIDA7XG5cbnZhciBfdiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdjM1LmpzXCIpKTtcblxudmFyIF9zaGEgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL3NoYTEuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5jb25zdCB2NSA9ICgwLCBfdi5kZWZhdWx0KSgndjUnLCAweDUwLCBfc2hhLmRlZmF1bHQpO1xudmFyIF9kZWZhdWx0ID0gdjU7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF9yZWdleCA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vcmVnZXguanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiB2YWxpZGF0ZSh1dWlkKSB7XG4gIHJldHVybiB0eXBlb2YgdXVpZCA9PT0gJ3N0cmluZycgJiYgX3JlZ2V4LmRlZmF1bHQudGVzdCh1dWlkKTtcbn1cblxudmFyIF9kZWZhdWx0ID0gdmFsaWRhdGU7XG5leHBvcnRzLmRlZmF1bHQgPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZGVmYXVsdCA9IHZvaWQgMDtcblxudmFyIF92YWxpZGF0ZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vdmFsaWRhdGUuanNcIikpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiB2ZXJzaW9uKHV1aWQpIHtcbiAgaWYgKCEoMCwgX3ZhbGlkYXRlLmRlZmF1bHQpKHV1aWQpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKCdJbnZhbGlkIFVVSUQnKTtcbiAgfVxuXG4gIHJldHVybiBwYXJzZUludCh1dWlkLnN1YnN0cigxNCwgMSksIDE2KTtcbn1cblxudmFyIF9kZWZhdWx0ID0gdmVyc2lvbjtcbmV4cG9ydHMuZGVmYXVsdCA9IF9kZWZhdWx0OyIsIi8qXG5XaWxkRW1pdHRlci5qcyBpcyBhIHNsaW0gbGl0dGxlIGV2ZW50IGVtaXR0ZXIgYnkgQGhlbnJpa2pvcmV0ZWcgbGFyZ2VseSBiYXNlZFxub24gQHZpc2lvbm1lZGlhJ3MgRW1pdHRlciBmcm9tIFVJIEtpdC5cblxuV2h5PyBJIHdhbnRlZCBpdCBzdGFuZGFsb25lLlxuXG5JIGFsc28gd2FudGVkIHN1cHBvcnQgZm9yIHdpbGRjYXJkIGVtaXR0ZXJzIGxpa2UgdGhpczpcblxuZW1pdHRlci5vbignKicsIGZ1bmN0aW9uIChldmVudE5hbWUsIG90aGVyLCBldmVudCwgcGF5bG9hZHMpIHtcblxufSk7XG5cbmVtaXR0ZXIub24oJ3NvbWVuYW1lc3BhY2UqJywgZnVuY3Rpb24gKGV2ZW50TmFtZSwgcGF5bG9hZHMpIHtcblxufSk7XG5cblBsZWFzZSBub3RlIHRoYXQgY2FsbGJhY2tzIHRyaWdnZXJlZCBieSB3aWxkY2FyZCByZWdpc3RlcmVkIGV2ZW50cyBhbHNvIGdldFxudGhlIGV2ZW50IG5hbWUgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LlxuKi9cblxubW9kdWxlLmV4cG9ydHMgPSBXaWxkRW1pdHRlcjtcblxuZnVuY3Rpb24gV2lsZEVtaXR0ZXIoKSB7IH1cblxuV2lsZEVtaXR0ZXIubWl4aW4gPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICB2YXIgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlIHx8IGNvbnN0cnVjdG9yO1xuXG4gICAgcHJvdG90eXBlLmlzV2lsZEVtaXR0ZXI9IHRydWU7XG5cbiAgICAvLyBMaXN0ZW4gb24gdGhlIGdpdmVuIGBldmVudGAgd2l0aCBgZm5gLiBTdG9yZSBhIGdyb3VwIG5hbWUgaWYgcHJlc2VudC5cbiAgICBwcm90b3R5cGUub24gPSBmdW5jdGlvbiAoZXZlbnQsIGdyb3VwTmFtZSwgZm4pIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcbiAgICAgICAgdmFyIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgZnVuYy5fZ3JvdXBOYW1lID0gZ3JvdXA7XG4gICAgICAgICh0aGlzLmNhbGxiYWNrc1tldmVudF0gPSB0aGlzLmNhbGxiYWNrc1tldmVudF0gfHwgW10pLnB1c2goZnVuYyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvLyBBZGRzIGFuIGBldmVudGAgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYSBzaW5nbGVcbiAgICAvLyB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxuICAgIHByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKGV2ZW50LCBncm91cE5hbWUsIGZuKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgICAgIGhhc0dyb3VwID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpLFxuICAgICAgICAgICAgZ3JvdXAgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGZ1bmMgPSBoYXNHcm91cCA/IGFyZ3VtZW50c1syXSA6IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgZnVuY3Rpb24gb24oKSB7XG4gICAgICAgICAgICBzZWxmLm9mZihldmVudCwgb24pO1xuICAgICAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub24oZXZlbnQsIGdyb3VwLCBvbik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvLyBVbmJpbmRzIGFuIGVudGlyZSBncm91cFxuICAgIHByb3RvdHlwZS5yZWxlYXNlR3JvdXAgPSBmdW5jdGlvbiAoZ3JvdXBOYW1lKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XG4gICAgICAgIHZhciBpdGVtLCBpLCBsZW4sIGhhbmRsZXJzO1xuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGhhbmRsZXJzID0gdGhpcy5jYWxsYmFja3NbaXRlbV07XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBoYW5kbGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyc1tpXS5fZ3JvdXBOYW1lID09PSBncm91cE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZygncmVtb3ZpbmcnKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0IGFuZCBzaG9ydGVuIHRoZSBhcnJheSB3ZSdyZSBsb29waW5nIHRocm91Z2hcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICBpLS07XG4gICAgICAgICAgICAgICAgICAgIGxlbi0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLy8gUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcbiAgICAvLyByZWdpc3RlcmVkIGNhbGxiYWNrcy5cbiAgICBwcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gKGV2ZW50LCBmbikge1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IHRoaXMuY2FsbGJhY2tzIHx8IHt9O1xuICAgICAgICB2YXIgY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3NbZXZlbnRdLFxuICAgICAgICAgICAgaTtcblxuICAgICAgICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgLy8gcmVtb3ZlIGFsbCBoYW5kbGVyc1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuY2FsbGJhY2tzW2V2ZW50XTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcbiAgICAgICAgaSA9IGNhbGxiYWNrcy5pbmRleE9mKGZuKTtcbiAgICAgICAgaWYgKGkgIT09IC0xKSB7XG4gICAgICAgICAgICBjYWxsYmFja3Muc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jYWxsYmFja3NbZXZlbnRdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvLy8gRW1pdCBgZXZlbnRgIHdpdGggdGhlIGdpdmVuIGFyZ3MuXG4gICAgLy8gYWxzbyBjYWxscyBhbnkgYCpgIGhhbmRsZXJzXG4gICAgcHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5jYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrcyB8fCB7fTtcbiAgICAgICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXG4gICAgICAgICAgICBjYWxsYmFja3MgPSB0aGlzLmNhbGxiYWNrc1tldmVudF0sXG4gICAgICAgICAgICBzcGVjaWFsQ2FsbGJhY2tzID0gdGhpcy5nZXRXaWxkY2FyZENhbGxiYWNrcyhldmVudCksXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbGVuLFxuICAgICAgICAgICAgaXRlbSxcbiAgICAgICAgICAgIGxpc3RlbmVycztcblxuICAgICAgICBpZiAoY2FsbGJhY2tzKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYWxsYmFja3Muc2xpY2UoKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICghbGlzdGVuZXJzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3BlY2lhbENhbGxiYWNrcykge1xuICAgICAgICAgICAgbGVuID0gc3BlY2lhbENhbGxiYWNrcy5sZW5ndGg7XG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBzcGVjaWFsQ2FsbGJhY2tzLnNsaWNlKCk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWxpc3RlbmVyc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIFtldmVudF0uY29uY2F0KGFyZ3MpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvLyBIZWxwZXIgZm9yIGZvciBmaW5kaW5nIHNwZWNpYWwgd2lsZGNhcmQgZXZlbnQgaGFuZGxlcnMgdGhhdCBtYXRjaCB0aGUgZXZlbnRcbiAgICBwcm90b3R5cGUuZ2V0V2lsZGNhcmRDYWxsYmFja3MgPSBmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgIHRoaXMuY2FsbGJhY2tzID0gdGhpcy5jYWxsYmFja3MgfHwge307XG4gICAgICAgIHZhciBpdGVtLFxuICAgICAgICAgICAgc3BsaXQsXG4gICAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgICBmb3IgKGl0ZW0gaW4gdGhpcy5jYWxsYmFja3MpIHtcbiAgICAgICAgICAgIHNwbGl0ID0gaXRlbS5zcGxpdCgnKicpO1xuICAgICAgICAgICAgaWYgKGl0ZW0gPT09ICcqJyB8fCAoc3BsaXQubGVuZ3RoID09PSAyICYmIGV2ZW50TmFtZS5zbGljZSgwLCBzcGxpdFswXS5sZW5ndGgpID09PSBzcGxpdFswXSkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuY29uY2F0KHRoaXMuY2FsbGJhY2tzW2l0ZW1dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbn07XG5cbldpbGRFbWl0dGVyLm1peGluKFdpbGRFbWl0dGVyKTtcbiIsIi8qIVxuICogRXZlbnRFbWl0dGVyIHY1LjIuOSAtIGdpdC5pby9lZVxuICogVW5saWNlbnNlIC0gaHR0cDovL3VubGljZW5zZS5vcmcvXG4gKiBPbGl2ZXIgQ2FsZHdlbGwgLSBodHRwczovL29saS5tZS51ay9cbiAqIEBwcmVzZXJ2ZVxuICovXG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgb3JpZ2luYWxHbG9iYWxWYWx1ZSA9IGV4cG9ydHMuRXZlbnRFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIGluZGV4IG9mIHRoZSBsaXN0ZW5lciBmb3IgdGhlIGV2ZW50IGluIGl0cyBzdG9yYWdlIGFycmF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBsaXN0ZW5lcnMgQXJyYXkgb2YgbGlzdGVuZXJzIHRvIHNlYXJjaCB0aHJvdWdoLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBsb29rIGZvci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IEluZGV4IG9mIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIsIC0xIGlmIG5vdCBmb3VuZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnMsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBhIG1ldGhvZCB3aGlsZSBrZWVwaW5nIHRoZSBjb250ZXh0IGNvcnJlY3QsIHRvIGFsbG93IGZvciBvdmVyd3JpdGluZyBvZiB0YXJnZXQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIHRhcmdldCBtZXRob2QuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBhbGlhc2VkIG1ldGhvZFxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsaWFzKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGFsaWFzQ2xvc3VyZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW25hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbGlzdGVuZXIgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2lsbCBpbml0aWFsaXNlIHRoZSBldmVudCBvYmplY3QgYW5kIGxpc3RlbmVyIGFycmF5cyBpZiByZXF1aXJlZC5cbiAgICAgKiBXaWxsIHJldHVybiBhbiBvYmplY3QgaWYgeW91IHVzZSBhIHJlZ2V4IHNlYXJjaC4gVGhlIG9iamVjdCBjb250YWlucyBrZXlzIGZvciBlYWNoIG1hdGNoZWQgZXZlbnQuIFNvIC9iYVtyel0vIG1pZ2h0IHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyBiYXIgYW5kIGJhei4gQnV0IG9ubHkgaWYgeW91IGhhdmUgZWl0aGVyIGRlZmluZWQgdGhlbSB3aXRoIGRlZmluZUV2ZW50IG9yIGFkZGVkIHNvbWUgbGlzdGVuZXJzIHRvIHRoZW0uXG4gICAgICogRWFjaCBwcm9wZXJ0eSBpbiB0aGUgb2JqZWN0IHJlc3BvbnNlIGlzIGFuIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJldHVybiB0aGUgbGlzdGVuZXJzIGZyb20uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXXxPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZXZ0KSB7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIC8vIFJldHVybiBhIGNvbmNhdGVuYXRlZCBhcnJheSBvZiBhbGwgbWF0Y2hpbmcgZXZlbnRzIGlmXG4gICAgICAgIC8vIHRoZSBzZWxlY3RvciBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIGV2ZW50cykge1xuICAgICAgICAgICAgICAgIGlmIChldmVudHMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBldnQudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlW2tleV0gPSBldmVudHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IGV2ZW50c1tldnRdIHx8IChldmVudHNbZXZ0XSA9IFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIGxpc3RlbmVyIG9iamVjdHMgYW5kIGZsYXR0ZW5zIGl0IGludG8gYSBsaXN0IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0W119IGxpc3RlbmVycyBSYXcgbGlzdGVuZXIgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbltdfSBKdXN0IHRoZSBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICovXG4gICAgcHJvdG8uZmxhdHRlbkxpc3RlbmVycyA9IGZ1bmN0aW9uIGZsYXR0ZW5MaXN0ZW5lcnMobGlzdGVuZXJzKSB7XG4gICAgICAgIHZhciBmbGF0TGlzdGVuZXJzID0gW107XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGZsYXRMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZsYXRMaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIHJlcXVlc3RlZCBsaXN0ZW5lcnMgdmlhIGdldExpc3RlbmVycyBidXQgd2lsbCBhbHdheXMgcmV0dXJuIHRoZSByZXN1bHRzIGluc2lkZSBhbiBvYmplY3QuIFRoaXMgaXMgbWFpbmx5IGZvciBpbnRlcm5hbCB1c2UgYnV0IG90aGVycyBtYXkgZmluZCBpdCB1c2VmdWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQWxsIGxpc3RlbmVyIGZ1bmN0aW9ucyBmb3IgYW4gZXZlbnQgaW4gYW4gb2JqZWN0LlxuICAgICAqL1xuICAgIHByb3RvLmdldExpc3RlbmVyc0FzT2JqZWN0ID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVycyhldnQpO1xuICAgICAgICB2YXIgcmVzcG9uc2U7XG5cbiAgICAgICAgaWYgKGxpc3RlbmVycyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IHt9O1xuICAgICAgICAgICAgcmVzcG9uc2VbZXZ0XSA9IGxpc3RlbmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNwb25zZSB8fCBsaXN0ZW5lcnM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGlzVmFsaWRMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJyB8fCBsaXN0ZW5lciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciAmJiB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNWYWxpZExpc3RlbmVyKGxpc3RlbmVyLmxpc3RlbmVyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIWlzVmFsaWRMaXN0ZW5lcihsaXN0ZW5lcikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVySXNXcmFwcGVkID0gdHlwZW9mIGxpc3RlbmVyID09PSAnb2JqZWN0JztcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSAmJiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzW2tleV0sIGxpc3RlbmVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5wdXNoKGxpc3RlbmVySXNXcmFwcGVkID8gbGlzdGVuZXIgOiB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgICAgICAgICAgb25jZTogZmFsc2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBhZGRMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9uID0gYWxpYXMoJ2FkZExpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBTZW1pLWFsaWFzIG9mIGFkZExpc3RlbmVyLiBJdCB3aWxsIGFkZCBhIGxpc3RlbmVyIHRoYXQgd2lsbCBiZVxuICAgICAqIGF1dG9tYXRpY2FsbHkgcmVtb3ZlZCBhZnRlciBpdHMgZmlyc3QgZXhlY3V0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gYXR0YWNoIHRoZSBsaXN0ZW5lciB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWQgYWZ0ZXIgY2FsbGluZy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5hZGRPbmNlTGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRPbmNlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRMaXN0ZW5lcihldnQsIHtcbiAgICAgICAgICAgIGxpc3RlbmVyOiBsaXN0ZW5lcixcbiAgICAgICAgICAgIG9uY2U6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZE9uY2VMaXN0ZW5lci5cbiAgICAgKi9cbiAgICBwcm90by5vbmNlID0gYWxpYXMoJ2FkZE9uY2VMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyBhbiBldmVudCBuYW1lLiBUaGlzIGlzIHJlcXVpcmVkIGlmIHlvdSB3YW50IHRvIHVzZSBhIHJlZ2V4IHRvIGFkZCBhIGxpc3RlbmVyIHRvIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBJZiB5b3UgZG9uJ3QgZG8gdGhpcyB0aGVuIGhvdyBkbyB5b3UgZXhwZWN0IGl0IHRvIGtub3cgd2hhdCBldmVudCB0byBhZGQgdG8/IFNob3VsZCBpdCBqdXN0IGFkZCB0byBldmVyeSBwb3NzaWJsZSBtYXRjaCBmb3IgYSByZWdleD8gTm8uIFRoYXQgaXMgc2NhcnkgYW5kIGJhZC5cbiAgICAgKiBZb3UgbmVlZCB0byB0ZWxsIGl0IHdoYXQgZXZlbnQgbmFtZXMgc2hvdWxkIGJlIG1hdGNoZWQgYnkgYSByZWdleC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gY3JlYXRlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50ID0gZnVuY3Rpb24gZGVmaW5lRXZlbnQoZXZ0KSB7XG4gICAgICAgIHRoaXMuZ2V0TGlzdGVuZXJzKGV2dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGRlZmluZUV2ZW50IHRvIGRlZmluZSBtdWx0aXBsZSBldmVudHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ1tdfSBldnRzIEFuIGFycmF5IG9mIGV2ZW50IG5hbWVzIHRvIGRlZmluZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5kZWZpbmVFdmVudHMgPSBmdW5jdGlvbiBkZWZpbmVFdmVudHMoZXZ0cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGV2dHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIHRoaXMuZGVmaW5lRXZlbnQoZXZ0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBsaXN0ZW5lciBmdW5jdGlvbiBmcm9tIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogV2hlbiBwYXNzZWQgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUsIGl0IHdpbGwgcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIgZnJvbS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gcmVtb3ZlIGZyb20gdGhlIGV2ZW50LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgZm9yIChrZXkgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNba2V5XS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVMaXN0ZW5lclxuICAgICAqL1xuICAgIHByb3RvLm9mZiA9IGFsaWFzKCdyZW1vdmVMaXN0ZW5lcicpO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBmaXJzdCBhcmd1bWVudCB5b3UgY2FuIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLiBUaGUgb2JqZWN0IHNob3VsZCBjb250YWluIGtleSB2YWx1ZSBwYWlycyBvZiBldmVudHMgYW5kIGxpc3RlbmVycyBvciBsaXN0ZW5lciBhcnJheXMuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYW4gZXZlbnQgbmFtZSBhbmQgYW4gYXJyYXkgb2YgbGlzdGVuZXJzIHRvIGJlIHJlbW92ZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lcnMgZnJvbSBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbltdfSBbbGlzdGVuZXJzXSBBbiBvcHRpb25hbCBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVycyhldnQsIGxpc3RlbmVycykge1xuICAgICAgICAvLyBQYXNzIHRocm91Z2ggdG8gbWFuaXB1bGF0ZUxpc3RlbmVyc1xuICAgICAgICByZXR1cm4gdGhpcy5tYW5pcHVsYXRlTGlzdGVuZXJzKHRydWUsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRWRpdHMgbGlzdGVuZXJzIGluIGJ1bGsuIFRoZSBhZGRMaXN0ZW5lcnMgYW5kIHJlbW92ZUxpc3RlbmVycyBtZXRob2RzIGJvdGggdXNlIHRoaXMgdG8gZG8gdGhlaXIgam9iLiBZb3Ugc2hvdWxkIHJlYWxseSB1c2UgdGhvc2UgaW5zdGVhZCwgdGhpcyBpcyBhIGxpdHRsZSBsb3dlciBsZXZlbC5cbiAgICAgKiBUaGUgZmlyc3QgYXJndW1lbnQgd2lsbCBkZXRlcm1pbmUgaWYgdGhlIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCAodHJ1ZSkgb3IgYWRkZWQgKGZhbHNlKS5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSBhZGRlZC9yZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIG1hbmlwdWxhdGUgdGhlIGxpc3RlbmVycyBvZiBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlbW92ZSBUcnVlIGlmIHlvdSB3YW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMsIGZhbHNlIGlmIHlvdSB3YW50IHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R8UmVnRXhwfSBldnQgQW4gZXZlbnQgbmFtZSBpZiB5b3Ugd2lsbCBwYXNzIGFuIGFycmF5IG9mIGxpc3RlbmVycyBuZXh0LiBBbiBvYmplY3QgaWYgeW91IHdpc2ggdG8gYWRkL3JlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIGFkZC9yZW1vdmUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ubWFuaXB1bGF0ZUxpc3RlbmVycyA9IGZ1bmN0aW9uIG1hbmlwdWxhdGVMaXN0ZW5lcnMocmVtb3ZlLCBldnQsIGxpc3RlbmVycykge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICB2YXIgc2luZ2xlID0gcmVtb3ZlID8gdGhpcy5yZW1vdmVMaXN0ZW5lciA6IHRoaXMuYWRkTGlzdGVuZXI7XG4gICAgICAgIHZhciBtdWx0aXBsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXJzIDogdGhpcy5hZGRMaXN0ZW5lcnM7XG5cbiAgICAgICAgLy8gSWYgZXZ0IGlzIGFuIG9iamVjdCB0aGVuIHBhc3MgZWFjaCBvZiBpdHMgcHJvcGVydGllcyB0byB0aGlzIG1ldGhvZFxuICAgICAgICBpZiAodHlwZW9mIGV2dCA9PT0gJ29iamVjdCcgJiYgIShldnQgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICBmb3IgKGkgaW4gZXZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSAmJiAodmFsdWUgPSBldnRbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgdGhlIHNpbmdsZSBsaXN0ZW5lciBzdHJhaWdodCB0aHJvdWdoIHRvIHRoZSBzaW5ndWxhciBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHBhc3MgYmFjayB0byB0aGUgbXVsdGlwbGUgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxlLmNhbGwodGhpcywgaSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU28gZXZ0IG11c3QgYmUgYSBzdHJpbmdcbiAgICAgICAgICAgIC8vIEFuZCBsaXN0ZW5lcnMgbXVzdCBiZSBhbiBhcnJheSBvZiBsaXN0ZW5lcnNcbiAgICAgICAgICAgIC8vIExvb3Agb3ZlciBpdCBhbmQgcGFzcyBlYWNoIG9uZSB0byB0aGUgbXVsdGlwbGUgbWV0aG9kXG4gICAgICAgICAgICBpID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBzaW5nbGUuY2FsbCh0aGlzLCBldnQsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGZyb20gYSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGFuIGV2ZW50IHRoZW4gYWxsIGxpc3RlbmVycyB3aWxsIGJlIHJlbW92ZWQuXG4gICAgICogVGhhdCBtZWFucyBldmVyeSBldmVudCB3aWxsIGJlIGVtcHRpZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWdleCB0byByZW1vdmUgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBbZXZ0XSBPcHRpb25hbCBuYW1lIG9mIHRoZSBldmVudCB0byByZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IuIFdpbGwgcmVtb3ZlIGZyb20gZXZlcnkgZXZlbnQgaWYgbm90IHBhc3NlZC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50KGV2dCkge1xuICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBldnQ7XG4gICAgICAgIHZhciBldmVudHMgPSB0aGlzLl9nZXRFdmVudHMoKTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZW1vdmUgZGlmZmVyZW50IHRoaW5ncyBkZXBlbmRpbmcgb24gdGhlIHN0YXRlIG9mIGV2dFxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50XG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW2V2dF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGV2ZW50cyBtYXRjaGluZyB0aGUgcmVnZXguXG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBsaXN0ZW5lcnMgaW4gYWxsIGV2ZW50c1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50cztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiByZW1vdmVFdmVudC5cbiAgICAgKlxuICAgICAqIEFkZGVkIHRvIG1pcnJvciB0aGUgbm9kZSBBUEkuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlQWxsTGlzdGVuZXJzID0gYWxpYXMoJ3JlbW92ZUV2ZW50Jyk7XG5cbiAgICAvKipcbiAgICAgKiBFbWl0cyBhbiBldmVudCBvZiB5b3VyIGNob2ljZS5cbiAgICAgKiBXaGVuIGVtaXR0ZWQsIGV2ZXJ5IGxpc3RlbmVyIGF0dGFjaGVkIHRvIHRoYXQgZXZlbnQgd2lsbCBiZSBleGVjdXRlZC5cbiAgICAgKiBJZiB5b3UgcGFzcyB0aGUgb3B0aW9uYWwgYXJndW1lbnQgYXJyYXkgdGhlbiB0aG9zZSBhcmd1bWVudHMgd2lsbCBiZSBwYXNzZWQgdG8gZXZlcnkgbGlzdGVuZXIgdXBvbiBleGVjdXRpb24uXG4gICAgICogQmVjYXVzZSBpdCB1c2VzIGBhcHBseWAsIHlvdXIgYXJyYXkgb2YgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIGFzIGlmIHlvdSB3cm90ZSB0aGVtIG91dCBzZXBhcmF0ZWx5LlxuICAgICAqIFNvIHRoZXkgd2lsbCBub3QgYXJyaXZlIHdpdGhpbiB0aGUgYXJyYXkgb24gdGhlIG90aGVyIHNpZGUsIHRoZXkgd2lsbCBiZSBzZXBhcmF0ZS5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnc10gT3B0aW9uYWwgYXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXRFdmVudCA9IGZ1bmN0aW9uIGVtaXRFdmVudChldnQsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyc01hcCA9IHRoaXMuZ2V0TGlzdGVuZXJzQXNPYmplY3QoZXZ0KTtcbiAgICAgICAgdmFyIGxpc3RlbmVycztcbiAgICAgICAgdmFyIGxpc3RlbmVyO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVyc01hcCkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc01hcC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzTWFwW2tleV0uc2xpY2UoMCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaXN0ZW5lciByZXR1cm5zIHRydWUgdGhlbiBpdCBzaGFsbCBiZSByZW1vdmVkIGZyb20gdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBlaXRoZXIgd2l0aCBhIGJhc2ljIGNhbGwgb3IgYW4gYXBwbHkgaWYgdGhlcmUgaXMgYW4gYXJncyBhcnJheVxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIub25jZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gbGlzdGVuZXIubGlzdGVuZXIuYXBwbHkodGhpcywgYXJncyB8fCBbXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSB0aGlzLl9nZXRPbmNlUmV0dXJuVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyLmxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBbGlhcyBvZiBlbWl0RXZlbnRcbiAgICAgKi9cbiAgICBwcm90by50cmlnZ2VyID0gYWxpYXMoJ2VtaXRFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogU3VidGx5IGRpZmZlcmVudCBmcm9tIGVtaXRFdmVudCBpbiB0aGF0IGl0IHdpbGwgcGFzcyBpdHMgYXJndW1lbnRzIG9uIHRvIHRoZSBsaXN0ZW5lcnMsIGFzIG9wcG9zZWQgdG8gdGFraW5nIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cyB0byBwYXNzIG9uLlxuICAgICAqIEFzIHdpdGggZW1pdEV2ZW50LCB5b3UgY2FuIHBhc3MgYSByZWdleCBpbiBwbGFjZSBvZiB0aGUgZXZlbnQgbmFtZSB0byBlbWl0IHRvIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXZ0IE5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQgYW5kIGV4ZWN1dGUgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLip9IE9wdGlvbmFsIGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byBlYWNoIGxpc3RlbmVyLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLmVtaXRFdmVudChldnQsIGFyZ3MpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZiBhXG4gICAgICogbGlzdGVuZXJzIHJldHVybiB2YWx1ZSBtYXRjaGVzIHRoZSBvbmUgc2V0IGhlcmUgdGhlbiBpdCB3aWxsIGJlIHJlbW92ZWRcbiAgICAgKiBhZnRlciBleGVjdXRpb24uIFRoaXMgdmFsdWUgZGVmYXVsdHMgdG8gdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBjaGVjayBmb3Igd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLnNldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIHNldE9uY2VSZXR1cm5WYWx1ZSh2YWx1ZSkge1xuICAgICAgICB0aGlzLl9vbmNlUmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgdGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgYWdhaW5zdCB3aGVuIGV4ZWN1dGluZyBsaXN0ZW5lcnMuIElmXG4gICAgICogdGhlIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGlzIG9uZSB0aGVuIGl0IHNob3VsZCBiZSByZW1vdmVkXG4gICAgICogYXV0b21hdGljYWxseS4gSXQgd2lsbCByZXR1cm4gdHJ1ZSBieSBkZWZhdWx0LlxuICAgICAqXG4gICAgICogQHJldHVybiB7KnxCb29sZWFufSBUaGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBmb3Igb3IgdGhlIGRlZmF1bHQsIHRydWUuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldE9uY2VSZXR1cm5WYWx1ZSA9IGZ1bmN0aW9uIF9nZXRPbmNlUmV0dXJuVmFsdWUoKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCdfb25jZVJldHVyblZhbHVlJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmNlUmV0dXJuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBldmVudHMgb2JqZWN0IGFuZCBjcmVhdGVzIG9uZSBpZiByZXF1aXJlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIGV2ZW50cyBzdG9yYWdlIG9iamVjdC5cbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBwcm90by5fZ2V0RXZlbnRzID0gZnVuY3Rpb24gX2dldEV2ZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2V2ZW50cyB8fCAodGhpcy5fZXZlbnRzID0ge30pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBnbG9iYWwge0BsaW5rIEV2ZW50RW1pdHRlcn0gdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoaXMgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBOb24gY29uZmxpY3RpbmcgRXZlbnRFbWl0dGVyIGNsYXNzLlxuICAgICAqL1xuICAgIEV2ZW50RW1pdHRlci5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBvcmlnaW5hbEdsb2JhbFZhbHVlO1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH07XG5cbiAgICAvLyBFeHBvc2UgdGhlIGNsYXNzIGVpdGhlciB2aWEgQU1ELCBDb21tb25KUyBvciB0aGUgZ2xvYmFsIG9iamVjdFxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBFdmVudEVtaXR0ZXI7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyl7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZXhwb3J0cy5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG4gICAgfVxufSh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHRoaXMgfHwge30pKTtcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgICBcImF1dGhvclwiOiBcIk9wZW5WaWR1XCIsIFxuICAgIFwiZGVwZW5kZW5jaWVzXCI6IHtcbiAgICAgICAgXCJmcmVlaWNlXCI6IFwiMi4yLjJcIiwgXG4gICAgICAgIFwiaGFya1wiOiBcIjEuMi4zXCIsIFxuICAgICAgICBcImpzbmxvZ1wiOiBcIjIuMzAuMFwiLCBcbiAgICAgICAgXCJtaW1lXCI6IFwiMy4wLjBcIiwgXG4gICAgICAgIFwicGxhdGZvcm1cIjogXCIxLjMuNlwiLCBcbiAgICAgICAgXCJzZW12ZXJcIjogXCI3LjMuNVwiLCBcbiAgICAgICAgXCJ1dWlkXCI6IFwiOC4zLjJcIiwgXG4gICAgICAgIFwid29sZnk4Ny1ldmVudGVtaXR0ZXJcIjogXCI1LjIuOVwiLCBcbiAgICAgICAgXCJldmVudHNcIjogXCIzLjMuMFwiLCBcbiAgICAgICAgXCJpbmhlcml0c1wiOiBcIjIuMC40XCJcbiAgICB9LCBcbiAgICBcImRlc2NyaXB0aW9uXCI6IFwiT3BlblZpZHUgQnJvd3NlclwiLCBcbiAgICBcImRldkRlcGVuZGVuY2llc1wiOiB7XG4gICAgICAgIFwiQHR5cGVzL25vZGVcIjogXCIxNy4wLjhcIiwgXG4gICAgICAgIFwiQHR5cGVzL3BsYXRmb3JtXCI6IFwiMS4zLjRcIiwgXG4gICAgICAgIFwiYnJvd3NlcmlmeVwiOiBcIjE3LjAuMFwiLCBcbiAgICAgICAgXCJncnVudFwiOiBcIjEuNC4xXCIsIFxuICAgICAgICBcImdydW50LWNsaVwiOiBcIjEuNC4zXCIsIFxuICAgICAgICBcImdydW50LWNvbnRyaWItY29weVwiOiBcIjEuMC4wXCIsIFxuICAgICAgICBcImdydW50LWNvbnRyaWItc2Fzc1wiOiBcIjIuMC4wXCIsIFxuICAgICAgICBcImdydW50LWNvbnRyaWItdWdsaWZ5XCI6IFwiNS4wLjFcIiwgXG4gICAgICAgIFwiZ3J1bnQtY29udHJpYi13YXRjaFwiOiBcIjEuMS4wXCIsIFxuICAgICAgICBcImdydW50LXBvc3Rjc3NcIjogXCIwLjkuMFwiLCBcbiAgICAgICAgXCJncnVudC1zdHJpbmctcmVwbGFjZVwiOiBcIjEuMy4xXCIsIFxuICAgICAgICBcImdydW50LXRzXCI6IFwiNi4wLjAtYmV0YS4yMlwiLCBcbiAgICAgICAgXCJ0ZXJzZXJcIjogXCI1LjEwLjBcIiwgXG4gICAgICAgIFwidHNpZnlcIjogXCI1LjAuNFwiLCBcbiAgICAgICAgXCJ0c2xpbnRcIjogXCI2LjEuM1wiLCBcbiAgICAgICAgXCJ0eXBlZG9jXCI6IFwiMC4yMi4xMFwiLCBcbiAgICAgICAgXCJ0eXBlc2NyaXB0XCI6IFwiNC41LjRcIlxuICAgIH0sIFxuICAgIFwibGljZW5zZVwiOiBcIkFwYWNoZS0yLjBcIiwgXG4gICAgXCJtYWluXCI6IFwibGliL2luZGV4LmpzXCIsIFxuICAgIFwibmFtZVwiOiBcIm9wZW52aWR1LWJyb3dzZXJcIiwgXG4gICAgXCJyZXBvc2l0b3J5XCI6IHtcbiAgICAgICAgXCJ0eXBlXCI6IFwiZ2l0XCIsIFxuICAgICAgICBcInVybFwiOiBcImdpdDovL2dpdGh1Yi5jb20vT3BlblZpZHUvb3BlbnZpZHVcIlxuICAgIH0sIFxuICAgIFwic2NyaXB0c1wiOiB7XG4gICAgICAgIFwiYnJvd3NlcmlmeVwiOiBcIlZFUlNJT049JHtWRVJTSU9OOi1kZXZ9OyBta2RpciAtcCBzdGF0aWMvanMvICYmIGNkIHNyYyAmJiAuLi9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9iaW4vY21kLmpzIE1haW4udHMgLXAgWyB0c2lmeSBdIC0tZXhjbHVkZSBrdXJlbnRvLWJyb3dzZXItZXh0ZW5zaW9ucyAtLWRlYnVnIC1vIC4uL3N0YXRpYy9qcy9vcGVudmlkdS1icm93c2VyLSRWRVJTSU9OLmpzIC12XCIsIFxuICAgICAgICBcImJyb3dzZXJpZnktcHJvZFwiOiBcIlZFUlNJT049JHtWRVJTSU9OOi1kZXZ9OyBta2RpciAtcCBzdGF0aWMvanMvICYmIGNkIHNyYyAmJiAuLi9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9iaW4vY21kLmpzIC0tZGVidWcgTWFpbi50cyAtcCBbIHRzaWZ5IF0gLS1leGNsdWRlIGt1cmVudG8tYnJvd3Nlci1leHRlbnNpb25zIHwgLi4vbm9kZV9tb2R1bGVzL3RlcnNlci9iaW4vdGVyc2VyIC0tc291cmNlLW1hcCBjb250ZW50PWlubGluZSAtLW91dHB1dCAuLi9zdGF0aWMvanMvb3BlbnZpZHUtYnJvd3Nlci0kVkVSU0lPTi5taW4uanNcIiwgXG4gICAgICAgIFwiYnVpbGRcIjogXCJjZCBzcmMvT3BlblZpZHUgJiYgLi8uLi8uLi9ub2RlX21vZHVsZXMvdHlwZXNjcmlwdC9iaW4vdHNjICYmIGNkIC4uLy4uICYmIC4vbm9kZV9tb2R1bGVzL3R5cGVzY3JpcHQvYmluL3RzYyAtLWRlY2xhcmF0aW9uIHNyYy9pbmRleC50cyAtLW91dERpciAuL2xpYiAtLXNvdXJjZU1hcCAtLXRhcmdldCBlczUgLS1saWIgZG9tLGVzNSxlczIwMTUucHJvbWlzZSxzY3JpcHRob3N0ICYmIHJtIC1yZiAuL3RzNC40ICYmIG1rZGlyIC1wIC4vdHM0LjQvbGliICYmIGNwIC1yIC4vbGliIC4vdHM0LjQgJiYgZmluZCAuL3RzNC40L2xpYiAtdHlwZSBmICEgLWluYW1lICcqLmQudHMnIC1kZWxldGUgJiYgLi9jb25maWcvcmVwbGFjZV9mb3JfdHM0NC5zaFwiLCBcbiAgICAgICAgXCJkb2NzXCI6IFwiLi9nZW5lcmF0ZS1kb2NzLnNoXCJcbiAgICB9LCBcbiAgICBcInR5cGVzXCI6IFwibGliL2luZGV4LmQudHNcIiwgXG4gICAgXCJ0eXBlc1ZlcnNpb25zXCI6IHtcbiAgICAgICAgXCI8NC40XCI6IHtcbiAgICAgICAgICAgIFwiKlwiOiBbXG4gICAgICAgICAgICAgICAgXCJ0czQuNC8qXCJcbiAgICAgICAgICAgIF1cbiAgICAgICAgfVxuICAgIH0sIFxuICAgIFwidmVyc2lvblwiOiBcIjIuMjIuMFwiXG59IiwiaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1L09wZW5WaWR1JztcbmltcG9ydCB7IEpMIH0gZnJvbSAnanNubG9nJztcblxuaWYgKHdpbmRvdykge1xuICAgIHdpbmRvd1snT3BlblZpZHUnXSA9IE9wZW5WaWR1O1xufVxuXG4vLyBEaXNhYmxlIGpzbmxvZyB3aGVuIGxpYnJhcnkgaXMgbG9hZGVkXG5KTC5zZXRPcHRpb25zKHsgZW5hYmxlZDogZmFsc2UgfSlcbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi9TZXNzaW9uJztcbmltcG9ydCB7IFN0cmVhbSB9IGZyb20gJy4vU3RyZWFtJztcbmltcG9ydCB7IExvY2FsQ29ubmVjdGlvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9Mb2NhbENvbm5lY3Rpb25PcHRpb25zJztcbmltcG9ydCB7IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvUmVtb3RlQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBTdHJlYW1PcHRpb25zU2VydmVyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvU3RyZWFtT3B0aW9uc1NlcnZlcic7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IEV4Y2VwdGlvbkV2ZW50LCBFeGNlcHRpb25FdmVudE5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FeGNlcHRpb25FdmVudCc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuXG4vKipcbiAqIFJlcHJlc2VudHMgZWFjaCBvbmUgb2YgdGhlIHVzZXIncyBjb25uZWN0aW9uIHRvIHRoZSBzZXNzaW9uICh0aGUgbG9jYWwgb25lIGFuZCBvdGhlciB1c2VyJ3MgY29ubmVjdGlvbnMpLlxuICogVGhlcmVmb3JlIGVhY2ggW1tTZXNzaW9uXV0gYW5kIFtbU3RyZWFtXV0gb2JqZWN0IGhhcyBhbiBhdHRyaWJ1dGUgb2YgdHlwZSBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY29ubmVjdGlvbklkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaW1lIHdoZW4gdGhpcyBjb25uZWN0aW9uIHdhcyBjcmVhdGVkIGluIE9wZW5WaWR1IFNlcnZlciAoVVRDIG1pbGxpc2Vjb25kcylcbiAgICAgKi9cbiAgICBjcmVhdGlvblRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIERhdGEgYXNzb2NpYXRlZCB0byB0aGlzIGNvbm5lY3Rpb24gKGFuZCB0aGVyZWZvcmUgdG8gY2VydGFpbiB1c2VyKS4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgZmllbGQ6XG4gICAgICogaXQgYWxsb3dzIHlvdSB0byBicm9hZGNhc3QgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3Ugd2FudCBmb3IgZWFjaCB1c2VyIChhIHVzZXJuYW1lLCBmb3IgZXhhbXBsZSlcbiAgICAgKi9cbiAgICBkYXRhOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBSb2xlIG9mIHRoZSBjb25uZWN0aW9uLlxuICAgICAqIC0gYFNVQlNDUklCRVJgOiBjYW4gc3Vic2NyaWJlIHRvIHB1Ymxpc2hlZCBTdHJlYW1zIG9mIG90aGVyIHVzZXJzIGJ5IGNhbGxpbmcgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICogLSBgUFVCTElTSEVSYDogU1VCU0NSSUJFUiBwZXJtaXNzaW9ucyArIGNhbiBwdWJsaXNoIHRoZWlyIG93biBTdHJlYW1zIGJ5IGNhbGxpbmcgW1tTZXNzaW9uLnB1Ymxpc2hdXVxuICAgICAqIC0gYE1PREVSQVRPUmA6IFNVQlNDUklCRVIgKyBQVUJMSVNIRVIgcGVybWlzc2lvbnMgKyBjYW4gZm9yY2UgdGhlIHVucHVibGlzaGluZyBvciBkaXNjb25uZWN0aW9uIG92ZXIgYSB0aGlyZC1wYXJ0eSBTdHJlYW0gb3IgQ29ubmVjdGlvbiBieSBjYWxsIFtbU2Vzc2lvbi5mb3JjZVVucHVibGlzaF1dIGFuZCBbW1Nlc3Npb24uZm9yY2VEaXNjb25uZWN0XV1cbiAgICAgKlxuICAgICAqICoqT25seSBkZWZpbmVkIGZvciB0aGUgbG9jYWwgY29ubmVjdGlvbi4gSW4gcmVtb3RlIGNvbm5lY3Rpb25zIHdpbGwgYmUgYHVuZGVmaW5lZGAqKlxuICAgICAqL1xuICAgIHJvbGU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbXMgcHVibGlzaGVkIGJ5IHRoaXMgQ29ubmVjdGlvbiB3aWxsIGJlIHJlY29yZGVkIG9yIG5vdC4gVGhpcyBvbmx5IGFmZmVjdHMgW0lORElWSURVQUwgcmVjb3JkaW5nXSgvZW4vc3RhYmxlL2FkdmFuY2VkLWZlYXR1cmVzL3JlY29yZGluZy8jaW5kaXZpZHVhbC1yZWNvcmRpbmctc2VsZWN0aW9uKSA8YSBocmVmPVwiaHR0cHM6Ly9kb2NzLm9wZW52aWR1LmlvL2VuL3N0YWJsZS9vcGVudmlkdS1wcm8vXCIgc3R5bGU9XCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGJhY2tncm91bmQtY29sb3I6IHJnYigwLCAxMzYsIDE3MCk7IGNvbG9yOiB3aGl0ZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHBhZGRpbmc6IDBweCA1cHg7IG1hcmdpbi1yaWdodDogNXB4OyBib3JkZXItcmFkaXVzOiAzcHg7IGZvbnQtc2l6ZTogMTNweDsgbGluZS1oZWlnaHQ6MjFweDsgZm9udC1mYW1pbHk6IE1vbnRzZXJyYXQsIHNhbnMtc2VyaWZcIj5QUk88L2E+XG4gICAgICpcbiAgICAgKiAqKk9ubHkgZGVmaW5lZCBmb3IgdGhlIGxvY2FsIGNvbm5lY3Rpb24uIEluIHJlbW90ZSBjb25uZWN0aW9ucyB3aWxsIGJlIGB1bmRlZmluZWRgKipcbiAgICAgKi9cbiAgICByZWNvcmQ6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtPzogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxvY2FsT3B0aW9uczogTG9jYWxDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVPcHRpb25zOiBSZW1vdGVDb25uZWN0aW9uT3B0aW9ucyB8IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJwY1Nlc3Npb25JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbiwgY29ubmVjdGlvbk9wdGlvbnM6IExvY2FsQ29ubmVjdGlvbk9wdGlvbnMgfCBSZW1vdGVDb25uZWN0aW9uT3B0aW9ucykge1xuICAgICAgICBsZXQgbXNnID0gXCInQ29ubmVjdGlvbicgY3JlYXRlZCBcIjtcbiAgICAgICAgaWYgKCEhKDxMb2NhbENvbm5lY3Rpb25PcHRpb25zPmNvbm5lY3Rpb25PcHRpb25zKS5yb2xlKSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIGxvY2FsXG4gICAgICAgICAgICB0aGlzLmxvY2FsT3B0aW9ucyA9IDxMb2NhbENvbm5lY3Rpb25PcHRpb25zPmNvbm5lY3Rpb25PcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSB0aGlzLmxvY2FsT3B0aW9ucy5pZDtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gdGhpcy5sb2NhbE9wdGlvbnMuY3JlYXRlZEF0O1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gdGhpcy5sb2NhbE9wdGlvbnMubWV0YWRhdGE7XG4gICAgICAgICAgICB0aGlzLnJwY1Nlc3Npb25JZCA9IHRoaXMubG9jYWxPcHRpb25zLnNlc3Npb25JZDtcbiAgICAgICAgICAgIHRoaXMucm9sZSA9IHRoaXMubG9jYWxPcHRpb25zLnJvbGU7XG4gICAgICAgICAgICB0aGlzLnJlY29yZCA9IHRoaXMubG9jYWxPcHRpb25zLnJlY29yZDtcbiAgICAgICAgICAgIG1zZyArPSAnKGxvY2FsKSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBDb25uZWN0aW9uIGlzIHJlbW90ZVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVPcHRpb25zID0gPFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zPmNvbm5lY3Rpb25PcHRpb25zO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uSWQgPSB0aGlzLnJlbW90ZU9wdGlvbnMuaWQ7XG4gICAgICAgICAgICB0aGlzLmNyZWF0aW9uVGltZSA9IHRoaXMucmVtb3RlT3B0aW9ucy5jcmVhdGVkQXQ7XG4gICAgICAgICAgICBpZiAodGhpcy5yZW1vdGVPcHRpb25zLm1ldGFkYXRhKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhID0gdGhpcy5yZW1vdGVPcHRpb25zLm1ldGFkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucmVtb3RlT3B0aW9ucy5zdHJlYW1zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0UmVtb3RlU3RyZWFtcyh0aGlzLnJlbW90ZU9wdGlvbnMuc3RyZWFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtc2cgKz0gXCIocmVtb3RlKSB3aXRoICdjb25uZWN0aW9uSWQnIFtcIiArIHRoaXMucmVtb3RlT3B0aW9ucy5pZCArICddJztcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuaW5mbyhtc2cpO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogdm9pZCB7XG5cbiAgICAgICAgbG9nZ2VyLmRlYnVnKCghIXRoaXMuc3RyZWFtIS5vdXRib3VuZFN0cmVhbU9wdHMgPyAnTG9jYWwnIDogJ1JlbW90ZScpICsgJ2NhbmRpZGF0ZSBmb3InICtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbklkLCBjYW5kaWRhdGUpO1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdCgnb25JY2VDYW5kaWRhdGUnLCB7XG4gICAgICAgICAgICBlbmRwb2ludE5hbWU6IHRoaXMuY29ubmVjdGlvbklkLFxuICAgICAgICAgICAgY2FuZGlkYXRlOiBjYW5kaWRhdGUuY2FuZGlkYXRlLFxuICAgICAgICAgICAgc2RwTWlkOiBjYW5kaWRhdGUuc2RwTWlkLFxuICAgICAgICAgICAgc2RwTUxpbmVJbmRleDogY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXhcbiAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBzZW5kaW5nIElDRSBjYW5kaWRhdGU6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ2V4Y2VwdGlvbicsIFtuZXcgRXhjZXB0aW9uRXZlbnQodGhpcy5zZXNzaW9uLCBFeGNlcHRpb25FdmVudE5hbWUuSUNFX0NBTkRJREFURV9FUlJPUiwgdGhpcy5zZXNzaW9uLCBcIlRoZXJlIHdhcyBhbiB1bmV4cGVjdGVkIGVycm9yIG9uIHRoZSBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIGFuIElDRSBjYW5kaWRhdGUgZ2VuZXJhdGVkIGFuZCBzZW50IGJ5IHRoZSBjbGllbnQtc2lkZVwiLCBlcnJvcildKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRSZW1vdGVTdHJlYW1zKG9wdGlvbnM6IFN0cmVhbU9wdGlvbnNTZXJ2ZXJbXSk6IHZvaWQge1xuXG4gICAgICAgIC8vIFRoaXMgaXMgcmVhZHkgZm9yIHN1cHBvcnRpbmcgbXVsdGlwbGUgc3RyZWFtcyBwZXIgQ29ubmVjdGlvbiBvYmplY3QuIFJpZ2h0IG5vdyB0aGUgbG9vcCB3aWxsIGFsd2F5cyBydW4ganVzdCBvbmNlXG4gICAgICAgIC8vIHRoaXMuc3RyZWFtIHNob3VsZCBhbHNvIGJlIHJlcGxhY2VkIGJ5IGEgY29sbGVjdGlvbiBvZiBzdHJlYW1zIHRvIHN1cHBvcnQgbXVsdGlwbGUgc3RyZWFtcyBwZXIgQ29ubmVjdGlvblxuICAgICAgICBvcHRpb25zLmZvckVhY2gob3B0cyA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1PcHRpb25zOiBJbmJvdW5kU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBpZDogb3B0cy5pZCxcbiAgICAgICAgICAgICAgICBjcmVhdGVkQXQ6IG9wdHMuY3JlYXRlZEF0LFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IHRoaXMsXG4gICAgICAgICAgICAgICAgaGFzQXVkaW86IG9wdHMuaGFzQXVkaW8sXG4gICAgICAgICAgICAgICAgaGFzVmlkZW86IG9wdHMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgYXVkaW9BY3RpdmU6IG9wdHMuYXVkaW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IG9wdHMudmlkZW9BY3RpdmUsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IG9wdHMudHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgZnJhbWVSYXRlOiBvcHRzLmZyYW1lUmF0ZSxcbiAgICAgICAgICAgICAgICB2aWRlb0RpbWVuc2lvbnM6ICEhb3B0cy52aWRlb0RpbWVuc2lvbnMgPyBKU09OLnBhcnNlKG9wdHMudmlkZW9EaW1lbnNpb25zKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBmaWx0ZXI6ICEhb3B0cy5maWx0ZXIgPyBvcHRzLmZpbHRlciA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0odGhpcy5zZXNzaW9uLCBzdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgdGhpcy5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbG9nZ2VyLmluZm8oXCJSZW1vdGUgJ0Nvbm5lY3Rpb24nIHdpdGggJ2Nvbm5lY3Rpb25JZCcgW1wiICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnXSBpcyBub3cgY29uZmlndXJlZCBmb3IgcmVjZWl2aW5nIFN0cmVhbXMgd2l0aCBvcHRpb25zOiAnLCB0aGlzLnN0cmVhbSEuaW5ib3VuZFN0cmVhbU9wdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhZGRTdHJlYW0oc3RyZWFtOiBTdHJlYW0pOiB2b2lkIHtcbiAgICAgICAgc3RyZWFtLmNvbm5lY3Rpb24gPSB0aGlzO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3RyZWFtKHN0cmVhbUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSkge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IGFzIEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnQnO1xuaW1wb3J0IHsgRXZlbnRNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudE1hcC9FdmVudE1hcCc7XG5cbmltcG9ydCBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdXNlckhhbmRsZXJBcnJvd0hhbmRsZXI6IFdlYWtNYXA8KGV2ZW50OiBFdmVudCkgPT4gdm9pZCwgKGV2ZW50OiBFdmVudCkgPT4gdm9pZD4gPSBuZXcgV2Vha01hcCgpO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgZnVuY3Rpb24gYGhhbmRsZXJgIHRvIGhhbmRsZSBldmVudCBgdHlwZWBcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBFdmVudERpc3BhdGNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYWJzdHJhY3Qgb248SyBleHRlbmRzIGtleW9mIChFdmVudE1hcCk+KHR5cGU6IEssIGhhbmRsZXI6IChldmVudDogKEV2ZW50TWFwKVtLXSkgPT4gdm9pZCk6IHRoaXM7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGZ1bmN0aW9uIGBoYW5kbGVyYCB0byBoYW5kbGUgZXZlbnQgYHR5cGVgIGp1c3Qgb25jZS4gVGhlIGhhbmRsZXIgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHJlbW92ZWQgYWZ0ZXIgZmlyc3QgZXhlY3V0aW9uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgb2JqZWN0IHRoYXQgZGlzcGF0Y2hlZCB0aGUgZXZlbnRcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBvbmNlPEsgZXh0ZW5kcyBrZXlvZiAoRXZlbnRNYXApPih0eXBlOiBLLCBoYW5kbGVyOiAoZXZlbnQ6IChFdmVudE1hcClbS10pID0+IHZvaWQpOiB0aGlzO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGBoYW5kbGVyYCBmcm9tIGV2ZW50IGB0eXBlYC4gSWYgbm8gaGFuZGxlciBpcyBwcm92aWRlZCwgYWxsIGhhbmRsZXJzIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgYWJzdHJhY3Qgb2ZmPEsgZXh0ZW5kcyBrZXlvZiAoRXZlbnRNYXApPih0eXBlOiBLLCBoYW5kbGVyPzogKGV2ZW50OiAoRXZlbnRNYXApW0tdKSA9PiB2b2lkKTogdGhpcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkF1eCh0eXBlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKG1lc3NhZ2UsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8obWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy51c2VySGFuZGxlckFycm93SGFuZGxlci5zZXQoaGFuZGxlciwgYXJyb3dIYW5kbGVyKTtcbiAgICAgICAgdGhpcy5lZS5vbih0eXBlLCBhcnJvd0hhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25jZUF1eCh0eXBlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgaGFuZGxlcjogKGV2ZW50OiBFdmVudCkgPT4gdm9pZCk6IEV2ZW50RGlzcGF0Y2hlciB7XG4gICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IGV2ZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKG1lc3NhZ2UsIGV2ZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8obWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoYW5kbGVyKGV2ZW50KTtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBoYW5kbGVyIGZyb20gbWFwIGFmdGVyIGZpcnN0IGFuZCBvbmx5IGV4ZWN1dGlvblxuICAgICAgICAgICAgdGhpcy51c2VySGFuZGxlckFycm93SGFuZGxlci5kZWxldGUoaGFuZGxlcik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuc2V0KGhhbmRsZXIsIGFycm93SGFuZGxlcik7XG4gICAgICAgIHRoaXMuZWUub25jZSh0eXBlLCBhcnJvd0hhbmRsZXIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb2ZmQXV4KHR5cGU6IHN0cmluZywgaGFuZGxlcj86IChldmVudDogRXZlbnQpID0+IHZvaWQpOiBFdmVudERpc3BhdGNoZXIge1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZWUucmVtb3ZlQWxsTGlzdGVuZXJzKHR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTXVzdCByZW1vdmUgaW50ZXJuYWwgYXJyb3cgZnVuY3Rpb24gaGFuZGxlciBwYWlyZWQgd2l0aCB1c2VyIGhhbmRsZXJcbiAgICAgICAgICAgIGNvbnN0IGFycm93SGFuZGxlciA9IHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuZ2V0KGhhbmRsZXIpO1xuICAgICAgICAgICAgaWYgKCEhYXJyb3dIYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5vZmYodHlwZSwgYXJyb3dIYW5kbGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudXNlckhhbmRsZXJBcnJvd0hhbmRsZXIuZGVsZXRlKGhhbmRsZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBGaWx0ZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0ZpbHRlckV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuLyoqXG4gKiAqKldBUk5JTkcqKjogZXhwZXJpbWVudGFsIG9wdGlvbi4gVGhpcyBpbnRlcmZhY2UgbWF5IGNoYW5nZSBpbiB0aGUgbmVhciBmdXR1cmVcbiAqXG4gKiBWaWRlby9hdWRpbyBmaWx0ZXIgYXBwbGllZCB0byBhIFN0cmVhbS4gU2VlIFtbU3RyZWFtLmFwcGx5RmlsdGVyXV1cbiAqL1xuZXhwb3J0IGNsYXNzIEZpbHRlciB7XG5cbiAgICAvKipcbiAgICAgKiBUeXBlIG9mIGZpbHRlciBhcHBsaWVkLiBUaGlzIGlzIHRoZSBuYW1lIG9mIHRoZSByZW1vdGUgY2xhc3MgaWRlbnRpZnlpbmcgdGhlIGZpbHRlciB0byBhcHBseSBpbiBLdXJlbnRvIE1lZGlhIFNlcnZlci5cbiAgICAgKiBGb3IgZXhhbXBsZTogYFwiRmFjZU92ZXJsYXlGaWx0ZXJcImAsIGBcIkdTdHJlYW1lckZpbHRlclwiYC5cbiAgICAgKlxuICAgICAqIFlvdSBjYW4gZ2V0IHRoaXMgcHJvcGVydHkgaW4gYCoua21kLmpzb25gIGZpbGVzIGRlZmluaW5nIHRoZSBLdXJlbnRvIGZpbHRlcnMuIEZvciBleGFtcGxlLCBmb3IgR1N0cmVhbWVyRmlsdGVyIHRoYXQnc1xuICAgICAqIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vS3VyZW50by9rbXMtZmlsdGVycy9ibG9iLzUzYTQ1MmZhYzcxZDYxNzk1OTUyZTNkMjIwMjE1NmM2YjAwZjZkNjUvc3JjL3NlcnZlci9pbnRlcmZhY2UvZmlsdGVycy5HU3RyZWFtZXJGaWx0ZXIua21kLmpzb24jTDQpXG4gICAgICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogUGFyYW1ldGVycyB1c2VkIHRvIGluaXRpYWxpemUgdGhlIGZpbHRlci5cbiAgICAgKiBUaGVzZSBjb3JyZXNwb25kIHRvIHRoZSBjb25zdHJ1Y3RvciBwYXJhbWV0ZXJzIHVzZWQgaW4gdGhlIGZpbHRlciBpbiBLdXJlbnRvIE1lZGlhIFNlcnZlciAoZXhjZXB0IGZvciBgbWVkaWFQaXBlbGluZWAgcGFyYW1ldGVyLCB3aGljaCBpcyBuZXZlciBuZWVkZWQpLlxuICAgICAqXG4gICAgICogRm9yIGV4YW1wbGU6IGZvciBgZmlsdGVyLnR5cGUgPSBcIkdTdHJlYW1lckZpbHRlclwiYCBjb3VsZCBiZSBgZmlsdGVyLm9wdGlvbnMgPSB7XCJjb21tYW5kXCI6IFwidmlkZW9iYWxhbmNlIHNhdHVyYXRpb249MC4wXCJ9YFxuICAgICAqXG4gICAgICogWW91IGNhbiBnZXQgdGhpcyBwcm9wZXJ0eSBpbiBgKi5rbWQuanNvbmAgZmlsZXMgZGVmaW5pbmcgdGhlIEt1cmVudG8gZmlsdGVycy4gRm9yIGV4YW1wbGUsIGZvciBHU3RyZWFtZXJGaWx0ZXIgdGhhdCdzXG4gICAgICogW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9LdXJlbnRvL2ttcy1maWx0ZXJzL2Jsb2IvNTNhNDUyZmFjNzFkNjE3OTU5NTJlM2QyMjAyMTU2YzZiMDBmNmQ2NS9zcmMvc2VydmVyL2ludGVyZmFjZS9maWx0ZXJzLkdTdHJlYW1lckZpbHRlci5rbWQuanNvbiNMMTMtTDMxKVxuICAgICAqL1xuICAgIG9wdGlvbnM6IE9iamVjdDtcblxuICAgIC8qKlxuICAgICAqIFZhbHVlIHBhc3NlZCB0aGUgbGFzdCB0aW1lIFtbRmlsdGVyLmV4ZWNNZXRob2RdXSB3YXMgY2FsbGVkLiBJZiBgdW5kZWZpbmVkYCB0aGlzIG1ldGhvZCBoYXMgbm90IGJlZW4gY2FsbGVkIHlldC5cbiAgICAgKlxuICAgICAqIFlvdSBjYW4gdXNlIHRoaXMgdmFsdWUgdG8ga25vdyB0aGUgY3VycmVudCBzdGF0dXMgb2YgYW55IGFwcGxpZWQgZmlsdGVyXG4gICAgICovXG4gICAgbGFzdEV4ZWNNZXRob2Q/OiB7XG4gICAgICAgIG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IE9iamVjdFxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFuZGxlcnM6IE1hcDxzdHJpbmcsIChldmVudDogRmlsdGVyRXZlbnQpID0+IHZvaWQ+ID0gbmV3IE1hcCgpO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuICAgIHByaXZhdGUgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlcjtcblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHR5cGU6IHN0cmluZywgb3B0aW9uczogT2JqZWN0KSB7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyBhIGZpbHRlciBtZXRob2QuIEF2YWlsYWJsZSBtZXRob2RzIGFyZSBzcGVjaWZpYyBmb3IgZWFjaCBmaWx0ZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSBtZXRob2QgTmFtZSBvZiB0aGUgbWV0aG9kXG4gICAgICogQHBhcmFtIHBhcmFtcyBQYXJhbWV0ZXJzIG9mIHRoZSBtZXRob2RcbiAgICAgKi9cbiAgICBleGVjTWV0aG9kKG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IE9iamVjdCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBsb2dnZXIuaW5mbygnRXhlY3V0aW5nIGZpbHRlciBtZXRob2QgdG8gc3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG5cbiAgICAgICAgICAgIGxldCBmaW5hbFBhcmFtcztcblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc0V4ZWNNZXRob2QgPSB0cmlnZ2VyRXZlbnQgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdGaWx0ZXIgbWV0aG9kIHN1Y2Nlc3NmdWxseSBleGVjdXRlZCBvbiBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9ICg8YW55Pk9iamVjdCkuYXNzaWduKHt9LCB0aGlzLnN0cmVhbS5maWx0ZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmZpbHRlciEubGFzdEV4ZWNNZXRob2QgPSB7IG1ldGhvZCwgcGFyYW1zOiBmaW5hbFBhcmFtcyB9O1xuICAgICAgICAgICAgICAgIGlmICh0cmlnZ2VyRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zdHJlYW0uc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICdmaWx0ZXInLCB0aGlzLnN0cmVhbS5maWx0ZXIhLCBvbGRWYWx1ZSwgJ2V4ZWNGaWx0ZXJNZXRob2QnKV0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLCB0aGlzLnN0cmVhbSwgJ2ZpbHRlcicsIHRoaXMuc3RyZWFtLmZpbHRlciEsIG9sZFZhbHVlLCAnZXhlY0ZpbHRlck1ldGhvZCcpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnR5cGUuc3RhcnRzV2l0aCgnVkI6JykpIHtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcGFyYW1zID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zID0gSlNPTi5wYXJzZShwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5WSVJUVUFMX0JBQ0tHUk9VTkRfRVJST1IsICdXcm9uZyBwYXJhbXMgc3ludGF4OiAnICsgZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZpbmFsUGFyYW1zID0gcGFyYW1zO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZCA9PT0gJ3VwZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS52aXJ0dWFsQmFja2dyb3VuZFNpbmtFbGVtZW50cz8uVkIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuVklSVFVBTF9CQUNLR1JPVU5EX0VSUk9SLCAnVGhlcmUgaXMgbm8gVmlydHVhbCBCYWNrZ3JvdW5kIGZpbHRlciBhcHBsaWVkJykpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlydHVhbEJhY2tncm91bmRTaW5rRWxlbWVudHMuVkIudXBkYXRlVmFsdWVzKHBhcmFtcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBzdWNjZXNzRXhlY01ldGhvZChmYWxzZSkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLm5hbWUgPT09IE9wZW5WaWR1RXJyb3JOYW1lLlZJUlRVQUxfQkFDS0dST1VORF9FUlJPUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvci5uYW1lLCBlcnJvci5tZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlZJUlRVQUxfQkFDS0dST1VORF9FUlJPUiwgJ0Vycm9yIHVwZGF0aW5nIHZhbHVlcyBvbiBWaXJ0dWFsIEJhY2tncm91bmQgZmlsdGVyOiAnICsgZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5WSVJUVUFMX0JBQ0tHUk9VTkRfRVJST1IsIGBVbmtub3duIFZpcnR1YWwgQmFja2dyb3VuZCBtZXRob2QgXCIke21ldGhvZH1cImApKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgbGV0IHN0cmluZ1BhcmFtcztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBhcmFtcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ1BhcmFtcyA9IEpTT04uc3RyaW5naWZ5KHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1zZyA9IFwiJ3BhcmFtcycgcHJvcGVydHkgbXVzdCBiZSBhIEpTT04gZm9ybWF0dGVkIG9iamVjdFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGVycm9yTXNnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3JNc2cpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3RyaW5nUGFyYW1zID0gPHN0cmluZz5wYXJhbXM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZmluYWxQYXJhbXMgPSBzdHJpbmdQYXJhbXM7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICAnZXhlY0ZpbHRlck1ldGhvZCcsXG4gICAgICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBtZXRob2QsIHBhcmFtczogc3RyaW5nUGFyYW1zIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgZXhlY3V0aW5nIGZpbHRlciBtZXRob2QgZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZXhlY3V0ZSBhIGZpbHRlciBtZXRob2RcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN1Y2Nlc3NFeGVjTWV0aG9kKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmUgdG8gY2VydGFpbiBmaWx0ZXIgZXZlbnQuIEF2YWlsYWJsZSBldmVudHMgYXJlIHNwZWNpZmljIGZvciBlYWNoIGZpbHRlclxuICAgICAqXG4gICAgICogQHBhcmFtIGV2ZW50VHlwZSBFdmVudCB0byB3aGljaCBzdWJzY3JpYmUgdG8uXG4gICAgICogQHBhcmFtIGhhbmRsZXIgRnVuY3Rpb24gdG8gZXhlY3V0ZSB1cG9uIGV2ZW50IGRpc3BhdGNoZWQuIEl0IHJlY2VpdmVzIGFzIHBhcmFtZXRlciBhIFtbRmlsdGVyRXZlbnRdXSBvYmplY3RcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgZXZlbnQgbGlzdGVuZXIgd2FzIHN1Y2Nlc3NmdWxseSBhdHRhY2hlZCB0byB0aGUgZmlsdGVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBhZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZTogc3RyaW5nLCBoYW5kbGVyOiAoZXZlbnQ6IEZpbHRlckV2ZW50KSA9PiB2b2lkKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbygnQWRkaW5nIGZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJyB0byBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2FkZEZpbHRlckV2ZW50TGlzdGVuZXInLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBldmVudFR5cGUgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBhZGRpbmcgZmlsdGVyIGV2ZW50IGxpc3RlbmVyIHRvIGV2ZW50ICcgKyBldmVudFR5cGUgKyAnZm9yIFN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGFkZCBhIGZpbHRlciBldmVudCBsaXN0ZW5lclwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVycy5zZXQoZXZlbnRUeXBlLCBoYW5kbGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdGaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICcgc3VjY2Vzc2Z1bGx5IGFwcGxpZWQgb24gU3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGNlcnRhaW4gZmlsdGVyIGV2ZW50IGxpc3RlbmVyIHByZXZpb3VzbHkgc2V0LlxuICAgICAqXG4gICAgICogQHBhcmFtIGV2ZW50VHlwZSBFdmVudCB0byB1bnN1YnNjcmliZSBmcm9tLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBldmVudCBsaXN0ZW5lciB3YXMgc3VjY2Vzc2Z1bGx5IHJlbW92ZWQgZnJvbSB0aGUgZmlsdGVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpbiBvdGhlciBjYXNlXG4gICAgICovXG4gICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFR5cGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1JlbW92aW5nIGZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJyB0byBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ3JlbW92ZUZpbHRlckV2ZW50TGlzdGVuZXInLFxuICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtLnN0cmVhbUlkLCBldmVudFR5cGUgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciByZW1vdmluZyBmaWx0ZXIgZXZlbnQgbGlzdGVuZXIgdG8gZXZlbnQgJyArIGV2ZW50VHlwZSArICdmb3IgU3RyZWFtICcgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gYWRkIGEgZmlsdGVyIGV2ZW50IGxpc3RlbmVyXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZXJzLmRlbGV0ZShldmVudFR5cGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZpbHRlciBldmVudCBsaXN0ZW5lciB0byBldmVudCAnICsgZXZlbnRUeXBlICsgJyBzdWNjZXNzZnVsbHkgcmVtb3ZlZCBvbiBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgTG9jYWxSZWNvcmRlclN0YXRlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9Mb2NhbFJlY29yZGVyU3RhdGUnO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9VdGlscy9QbGF0Zm9ybSc7XG5pbXBvcnQgTWltZSA9IHJlcXVpcmUoJ21pbWUvbGl0ZScpO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5sZXQgcGxhdGZvcm06IFBsYXRmb3JtVXRpbHM7XG5cblxuLyoqXG4gKiBFYXN5IHJlY29yZGluZyBvZiBbW1N0cmVhbV1dIG9iamVjdHMgc3RyYWlnaHRhd2F5IGZyb20gdGhlIGJyb3dzZXIuIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0TG9jYWxSZWNvcmRlcl1dIG1ldGhvZFxuICovXG5leHBvcnQgY2xhc3MgTG9jYWxSZWNvcmRlciB7XG5cbiAgICBzdGF0ZTogTG9jYWxSZWNvcmRlclN0YXRlO1xuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uSWQ6IHN0cmluZztcbiAgICBwcml2YXRlIG1lZGlhUmVjb3JkZXI6IE1lZGlhUmVjb3JkZXI7XG4gICAgcHJpdmF0ZSBjaHVua3M6IGFueVtdID0gW107XG4gICAgcHJpdmF0ZSBibG9iPzogQmxvYjtcbiAgICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWRlb1ByZXZpZXdTcmM6IHN0cmluZztcbiAgICBwcml2YXRlIHZpZGVvUHJldmlldzogSFRNTFZpZGVvRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0cmVhbTogU3RyZWFtKSB7XG4gICAgICAgIHBsYXRmb3JtID0gUGxhdGZvcm1VdGlscy5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25JZCA9ICghIXRoaXMuc3RyZWFtLmNvbm5lY3Rpb24pID8gdGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgOiAnZGVmYXVsdC1jb25uZWN0aW9uJztcbiAgICAgICAgdGhpcy5pZCA9IHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJ18nICsgdGhpcy5jb25uZWN0aW9uSWQgKyAnX2xvY2FscmVjb3JkJztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUFEWWAuIEFmdGVyIG1ldGhvZCBzdWNjZWVkcyBpcyBzZXQgdG8gYFJFQ09SRElOR2BcbiAgICAgKlxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBbTWVkaWFSZWNvcmRlci5vcHRpb25zXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTWVkaWFSZWNvcmRlci9NZWRpYVJlY29yZGVyI3BhcmFtZXRlcnMpIHRvIGJlIHVzZWQgdG8gcmVjb3JkIHRoaXMgU3RyZWFtLlxuICAgICAqIEZvciBleGFtcGxlOiBcbiAgICAgKiBcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogdmFyIE9WID0gbmV3IE9wZW5WaWR1KCk7XG4gICAgICogdmFyIHB1Ymxpc2hlciA9IGF3YWl0IE9WLmluaXRQdWJsaXNoZXJBc3luYygpO1xuICAgICAqIHZhciBsb2NhbFJlY29yZGVyID0gT1YuaW5pdExvY2FsUmVjb3JkZXIocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICogdmFyIG9wdGlvbnMgPSB7XG4gICAgICogICAgICBtaW1lVHlwZTogJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCcsXG4gICAgICogICAgICBhdWRpb0JpdHNQZXJTZWNvbmQ6MTI4MDAwLFxuICAgICAqICAgICAgdmlkZW9CaXRzUGVyU2Vjb25kOjI1MDAwMDBcbiAgICAgKiB9O1xuICAgICAqIGxvY2FsUmVjb3JkZXIucmVjb3JkKG9wdGlvbnMpO1xuICAgICAqIGBgYFxuICAgICAqIFxuICAgICAqIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBkZWZhdWx0IG9wdGlvbnMgcHJlZmVycmVkIGJ5IHRoZSBwbGF0Zm9ybSB3aWxsIGJlIHVzZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgcmVjb3JkKG9wdGlvbnM/OiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJyB8fCBvcHRpb25zIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoYFdoZW4gY2FsbGluZyBMb2NhbFJlY29yZGVyLnJlY29yZChvcHRpb25zKSBwYXJhbWV0ZXIgJ29wdGlvbnMnIGNhbm5vdCBiZSBhIHN0cmluZy4gTXVzdCBiZSBhbiBvYmplY3QgbGlrZSB7IG1pbWVUeXBlOiBcIiR7b3B0aW9uc31cIiB9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFSZWNvcmRlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdNZWRpYVJlY29yZGVyIG5vdCBzdXBwb3J0ZWQgb24geW91ciBkZXZpY2UuIFNlZSBjb21wYXRpYmlsaXR5IGluIGh0dHBzOi8vY2FuaXVzZS5jb20vI3NlYXJjaD1NZWRpYVJlY29yZGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignTWVkaWFSZWNvcmRlciBub3Qgc3VwcG9ydGVkIG9uIHlvdXIgZGV2aWNlLiBTZWUgY29tcGF0aWJpbGl0eSBpbiBodHRwczovL2Nhbml1c2UuY29tLyNzZWFyY2g9TWVkaWFSZWNvcmRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnJlY29yZCgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ1JFQURZXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuY2xlYW4oKVxcJyBvciBpbml0IGEgbmV3IExvY2FsUmVjb3JkZXIgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nKFwiU3RhcnRpbmcgbG9jYWwgcmVjb3JkaW5nIG9mIHN0cmVhbSAnXCIgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZCArIFwiJyBvZiBjb25uZWN0aW9uICdcIiArIHRoaXMuY29ubmVjdGlvbklkICsgXCInXCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7IG1pbWVUeXBlOiAndmlkZW8vd2VibScgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFvcHRpb25zLm1pbWVUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubWltZVR5cGUgPSAndmlkZW8vd2VibSc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIodGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KCk7XG5cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZGF0YWF2YWlsYWJsZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGUuZGF0YS5zaXplID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUuZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uZXJyb3IgPSAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignTWVkaWFSZWNvcmRlciBlcnJvcjogJywgZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdGFydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdNZWRpYVJlY29yZGVyIHN0YXJ0ZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnBhdXNlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ01lZGlhUmVjb3JkZXIgcGF1c2VkIChzdGF0ZT0nICsgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICsgJyknKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbnJlc3VtZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdNZWRpYVJlY29yZGVyIHJlc3VtZWQgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkc7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRW5kcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBSRUNPUkRJTkdgIG9yIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBGSU5JU0hFRGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHJlY29yZGluZyBzdWNjZXNzZnVsbHkgc3RvcHBlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaWYgbm90XG4gICAgICovXG4gICAgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUFEWSB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKEVycm9yKCdcXCdMb2NhbFJlY29yZC5zdG9wKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUkVDT1JESU5HXFwnIG9yIFxcJ1BBVVNFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0YXJ0KClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU3RvcERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgdGhlIHJlY29yZGluZyBvZiB0aGUgU3RyZWFtLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgUkVDT1JESU5HYC4gQWZ0ZXIgbWV0aG9kIHN1Y2NlZWRzIGlzIHNldCB0byBgUEFVU0VEYFxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgcmVjb3JkaW5nIHdhcyBzdWNjZXNzZnVsbHkgcGF1c2VkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwYXVzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5SRUNPUkRJTkcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQucGF1c2UoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdSRUNPUkRJTkdcXCcgKGN1cnJlbnQgdmFsdWU6IFxcJycgKyB0aGlzLnN0YXRlICsgJ1xcJykuIENhbGwgXFwnTG9jYWxSZWNvcmRlci5zdGFydCgpXFwnIG9yIFxcJ0xvY2FsUmVjb3JkZXIucmVzdW1lKClcXCcgYmVmb3JlJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlBBVVNFRDtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyB0aGUgcmVjb3JkaW5nIG9mIHRoZSBTdHJlYW0uIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBQQVVTRURgLiBBZnRlciBtZXRob2Qgc3VjY2VlZHMgaXMgc2V0IHRvIGBSRUNPUkRJTkdgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvcmRpbmcgd2FzIHN1Y2Nlc3NmdWxseSByZXN1bWVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICByZXN1bWUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucmVzdW1lKClcXCcgbmVlZHMgXFwnTG9jYWxSZWNvcmQuc3RhdGVcXCcgdG8gYmUgXFwnUEFVU0VEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIucGF1c2UoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORztcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQcmV2aWV3cyB0aGUgcmVjb3JkaW5nLCBhcHBlbmRpbmcgYSBuZXcgSFRNTFZpZGVvRWxlbWVudCB0byBlbGVtZW50IHdpdGggaWQgYHBhcmVudElkYC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYFxuICAgICAqL1xuICAgIHByZXZpZXcocGFyZW50RWxlbWVudCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQucHJldmlldygpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlldy5pZCA9IHRoaXMuaWQ7XG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgICAgICBpZiAocGxhdGZvcm0uaXNTYWZhcmlCcm93c2VyKCkpIHtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNldEF0dHJpYnV0ZSgncGxheXNpbmxpbmUnLCAndHJ1ZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJlbnRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50RWxlbWVudERvbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHBhcmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnREb20pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUHJldmlldyA9IHBhcmVudEVsZW1lbnREb20uYXBwZW5kQ2hpbGQodGhpcy52aWRlb1ByZXZpZXcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52aWRlb1ByZXZpZXcgPSBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudmlkZW9QcmV2aWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudmlkZW9QcmV2aWV3LnNyYyA9IHRoaXMudmlkZW9QcmV2aWV3U3JjO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnZpZGVvUHJldmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEdyYWNlZnVsbHkgc3RvcHMgYW5kIGNsZWFucyB0aGUgY3VycmVudCByZWNvcmRpbmcgKFdBUk5JTkc6IGl0IGlzIGNvbXBsZXRlbHkgZGlzbWlzc2VkKS4gU2V0cyBbW3N0YXRlXV0gdG8gYFJFQURZYCBzbyB0aGUgcmVjb3JkaW5nIGNhbiBzdGFydCBhZ2FpblxuICAgICAqL1xuICAgIGNsZWFuKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYmxvYjtcbiAgICAgICAgICAgIHRoaXMuY2h1bmtzID0gW107XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQURZO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSA9PT0gTG9jYWxSZWNvcmRlclN0YXRlLlJFQ09SRElORyB8fCB0aGlzLnN0YXRlID09PSBMb2NhbFJlY29yZGVyU3RhdGUuUEFVU0VEKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3AoKS50aGVuKCgpID0+IGYoKSkuY2F0Y2goKCkgPT4gZigpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGYoKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyB0aHJvdWdoIHRoZSBicm93c2VyLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgXG4gICAgICovXG4gICAgZG93bmxvYWQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBMb2NhbFJlY29yZGVyU3RhdGUuRklOSVNIRUQpIHtcbiAgICAgICAgICAgIHRocm93IChFcnJvcignXFwnTG9jYWxSZWNvcmQuZG93bmxvYWQoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBhOiBIVE1MQW5jaG9yRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgICAgICAgIGEuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKDxhbnk+dGhpcy5ibG9iKTtcbiAgICAgICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLmlkICsgJy4nICsgTWltZS5nZXRFeHRlbnNpb24odGhpcy5ibG9iIS50eXBlKTtcbiAgICAgICAgICAgIGEuY2xpY2soKTtcbiAgICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSByYXcgQmxvYiBmaWxlLiBNZXRob2RzIHByZXZpZXcsIGRvd25sb2FkLCB1cGxvYWRBc0JpbmFyeSBhbmQgdXBsb2FkQXNNdWx0aXBhcnRmaWxlIHVzZSB0aGlzIHNhbWUgZmlsZSB0byBwZXJmb3JtIHRoZWlyIHNwZWNpZmljIGFjdGlvbnMuIFtbc3RhdGVdXSBwcm9wZXJ0eSBtdXN0IGJlIGBGSU5JU0hFRGBcbiAgICAgKi9cbiAgICBnZXRCbG9iKCk6IEJsb2Ige1xuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICB0aHJvdyAoRXJyb3IoJ0NhbGwgXFwnTG9jYWxSZWNvcmQuc3RvcCgpXFwnIGJlZm9yZSBnZXR0aW5nIEJsb2IgZmlsZScpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJsb2IhO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGxvYWRzIHRoZSByZWNvcmRlZCB2aWRlbyBhcyBhIGJpbmFyeSBmaWxlIHBlcmZvcm1pbmcgYW4gSFRUUC9QT1NUIG9wZXJhdGlvbiB0byBVUkwgYGVuZHBvaW50YC4gW1tzdGF0ZV1dIHByb3BlcnR5IG11c3QgYmUgYEZJTklTSEVEYC4gT3B0aW9uYWwgSFRUUCBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgYXMgc2Vjb25kIHBhcmFtZXRlci4gRm9yIGV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogdmFyIGhlYWRlcnMgPSB7XG4gICAgICogIFwiQ29va2llXCI6IFwiJFZlcnNpb249MTsgU2tpbj1uZXc7XCIsXG4gICAgICogIFwiQXV0aG9yaXphdGlvblwiOlwiQmFzaWMgUVd4aFpHcGJqcHVJSE5sY3RaUT09XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHdpdGggdGhlIGBodHRwLnJlc3BvbnNlVGV4dGAgZnJvbSBzZXJ2ZXIgaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCBhbmQgcmVqZWN0ZWQgd2l0aCB0aGUgZmFpbGVkIGBodHRwLnN0YXR1c2AgaWYgbm90XG4gICAgICovXG4gICAgdXBsb2FkQXNCaW5hcnkoZW5kcG9pbnQ6IHN0cmluZywgaGVhZGVycz86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gTG9jYWxSZWNvcmRlclN0YXRlLkZJTklTSEVEKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChFcnJvcignXFwnTG9jYWxSZWNvcmQudXBsb2FkQXNCaW5hcnkoKVxcJyBuZWVkcyBcXCdMb2NhbFJlY29yZC5zdGF0ZVxcJyB0byBiZSBcXCdGSU5JU0hFRFxcJyAoY3VycmVudCB2YWx1ZTogXFwnJyArIHRoaXMuc3RhdGUgKyAnXFwnKS4gQ2FsbCBcXCdMb2NhbFJlY29yZGVyLnN0b3AoKVxcJyBiZWZvcmUnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICBodHRwLm9wZW4oJ1BPU1QnLCBlbmRwb2ludCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGhlYWRlcnMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBodHRwLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaHR0cC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChodHRwLnN0YXR1cy50b1N0cmluZygpLmNoYXJBdCgwKSA9PT0gJzInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3VjY2VzcyByZXNwb25zZSBmcm9tIHNlcnZlciAoSFRUUCBzdGF0dXMgc3RhbmRhcmQ6IDJYWCBpcyBzdWNjZXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGh0dHAucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChodHRwLnN0YXR1cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGh0dHAuc2VuZCh0aGlzLmJsb2IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZHMgdGhlIHJlY29yZGVkIHZpZGVvIGFzIGEgbXVsdGlwYXJ0IGZpbGUgcGVyZm9ybWluZyBhbiBIVFRQL1BPU1Qgb3BlcmF0aW9uIHRvIFVSTCBgZW5kcG9pbnRgLiBbW3N0YXRlXV0gcHJvcGVydHkgbXVzdCBiZSBgRklOSVNIRURgLiBPcHRpb25hbCBIVFRQIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCBhcyBzZWNvbmQgcGFyYW1ldGVyLiBGb3IgZXhhbXBsZTpcbiAgICAgKiBgYGBcbiAgICAgKiB2YXIgaGVhZGVycyA9IHtcbiAgICAgKiAgXCJDb29raWVcIjogXCIkVmVyc2lvbj0xOyBTa2luPW5ldztcIixcbiAgICAgKiAgXCJBdXRob3JpemF0aW9uXCI6XCJCYXNpYyBRV3hoWkdwYmpwdUlITmxjdFpRPT1cIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgd2l0aCB0aGUgYGh0dHAucmVzcG9uc2VUZXh0YCBmcm9tIHNlcnZlciBpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIHRoZSBmYWlsZWQgYGh0dHAuc3RhdHVzYCBpZiBub3Q6XG4gICAgICovXG4gICAgdXBsb2FkQXNNdWx0aXBhcnRmaWxlKGVuZHBvaW50OiBzdHJpbmcsIGhlYWRlcnM/OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUgIT09IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoRXJyb3IoJ1xcJ0xvY2FsUmVjb3JkLnVwbG9hZEFzTXVsdGlwYXJ0ZmlsZSgpXFwnIG5lZWRzIFxcJ0xvY2FsUmVjb3JkLnN0YXRlXFwnIHRvIGJlIFxcJ0ZJTklTSEVEXFwnIChjdXJyZW50IHZhbHVlOiBcXCcnICsgdGhpcy5zdGF0ZSArICdcXCcpLiBDYWxsIFxcJ0xvY2FsUmVjb3JkZXIuc3RvcCgpXFwnIGJlZm9yZScpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaHR0cCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIGh0dHAub3BlbignUE9TVCcsIGVuZHBvaW50LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoaGVhZGVycykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0dHAuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kYWJsZSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICAgIHNlbmRhYmxlLmFwcGVuZCgnZmlsZScsIHRoaXMuYmxvYiEsIHRoaXMuaWQgKyAnLicgKyBNaW1lLmdldEV4dGVuc2lvbih0aGlzLmJsb2IhLnR5cGUpKTtcblxuICAgICAgICAgICAgICAgIGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaHR0cC5zdGF0dXMudG9TdHJpbmcoKS5jaGFyQXQoMCkgPT09ICcyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1Y2Nlc3MgcmVzcG9uc2UgZnJvbSBzZXJ2ZXIgKEhUVFAgc3RhdHVzIHN0YW5kYXJkOiAyWFggaXMgc3VjY2VzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShodHRwLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoaHR0cC5zdGF0dXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGh0dHAuc2VuZChzZW5kYWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgICBwcml2YXRlIG9uU3RvcERlZmF1bHQoKTogdm9pZCB7XG4gICAgICAgIGxvZ2dlci5sb2coJ01lZGlhUmVjb3JkZXIgc3RvcHBlZCAgKHN0YXRlPScgKyB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhdGUgKyAnKScpO1xuXG4gICAgICAgIHRoaXMuYmxvYiA9IG5ldyBCbG9iKHRoaXMuY2h1bmtzLCB7IHR5cGU6IHRoaXMubWVkaWFSZWNvcmRlci5taW1lVHlwZSB9KTtcbiAgICAgICAgdGhpcy5jaHVua3MgPSBbXTtcblxuICAgICAgICB0aGlzLnZpZGVvUHJldmlld1NyYyA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHRoaXMuYmxvYik7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IExvY2FsUmVjb3JkZXJTdGF0ZS5GSU5JU0hFRDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBMb2NhbFJlY29yZGVyIH0gZnJvbSAnLi9Mb2NhbFJlY29yZGVyJztcbmltcG9ydCB7IFB1Ymxpc2hlciB9IGZyb20gJy4vUHVibGlzaGVyJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgRGV2aWNlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9EZXZpY2UnO1xuaW1wb3J0IHsgT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uJztcbmltcG9ydCB7IFB1Ymxpc2hlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1B1Ymxpc2hlclByb3BlcnRpZXMnO1xuaW1wb3J0IHsgQ3VzdG9tTWVkaWFTdHJlYW1Db25zdHJhaW50cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0N1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMnO1xuaW1wb3J0IHsgT3BlblZpZHVFcnJvciwgT3BlblZpZHVFcnJvck5hbWUgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL09wZW5WaWR1RXJyb3InO1xuaW1wb3J0IHsgVmlkZW9JbnNlcnRNb2RlIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9WaWRlb0luc2VydE1vZGUnO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9VdGlscy9QbGF0Zm9ybSc7XG5cbmltcG9ydCAqIGFzIHNjcmVlblNoYXJpbmdBdXRvIGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvU2NyZWVuU2hhcmluZy9TY3JlZW4tQ2FwdHVyaW5nLUF1dG8nO1xuaW1wb3J0ICogYXMgc2NyZWVuU2hhcmluZyBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1NjcmVlblNoYXJpbmcvU2NyZWVuLUNhcHR1cmluZyc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlckNvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uXCI7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuaW1wb3J0IEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ3dvbGZ5ODctZXZlbnRlbWl0dGVyJyk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuaW1wb3J0IFJwY0J1aWxkZXIgPSByZXF1aXJlKCcuLi9PcGVuVmlkdUludGVybmFsL0t1cmVudG9VdGlscy9rdXJlbnRvLWpzb25ycGMnKTtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IHBhY2thZ2VKc29uID0gcmVxdWlyZSgnLi4vLi4vcGFja2FnZS5qc29uJyk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuZGVjbGFyZSB2YXIgY29yZG92YTogYW55O1xuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG4vKipcbiAqIEVudHJ5cG9pbnQgb2YgT3BlblZpZHUgQnJvd3NlciBsaWJyYXJ5LlxuICogVXNlIGl0IHRvIGluaXRpYWxpemUgb2JqZWN0cyBvZiB0eXBlIFtbU2Vzc2lvbl1dLCBbW1B1Ymxpc2hlcl1dIGFuZCBbW0xvY2FsUmVjb3JkZXJdXVxuICovXG5leHBvcnQgY2xhc3MgT3BlblZpZHUge1xuXG4gIHByaXZhdGUganNvblJwY0NsaWVudDogYW55O1xuICBwcml2YXRlIG1hc3Rlck5vZGVIYXNDcmFzaGVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlc3Npb246IFNlc3Npb247XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBwdWJsaXNoZXJzOiBQdWJsaXNoZXJbXSA9IFtdO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgd3NVcmk6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGh0dHBVcmk6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlY3JldCA9ICcnO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcmVjb3JkZXIgPSBmYWxzZTtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGljZVNlcnZlcnM6IFJUQ0ljZVNlcnZlcltdO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcm9sZTogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZmluYWxVc2VySWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIG1lZGlhU2VydmVyOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICB2aWRlb1NpbXVsY2FzdDogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGxpZmU6IG51bWJlciA9IC0xO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgYWR2YW5jZWRDb25maWd1cmF0aW9uOiBPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IHt9O1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgd2VicnRjU3RhdHNJbnRlcnZhbDogbnVtYmVyID0gLTE7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzZW5kQnJvd3NlckxvZ3M6IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbiA9IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbi5kaXNhYmxlZDtcbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGlzQXRMZWFzdFBybzogYm9vbGVhbiA9IGZhbHNlO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgaXNFbnRlcnByaXNlOiBib29sZWFuID0gZmFsc2U7XG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBsaWJyYXJ5VmVyc2lvbjogc3RyaW5nO1xuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZWUgPSBuZXcgRXZlbnRFbWl0dGVyKClcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwbGF0Zm9ybSA9IFBsYXRmb3JtVXRpbHMuZ2V0SW5zdGFuY2UoKTtcbiAgICB0aGlzLmxpYnJhcnlWZXJzaW9uID0gcGFja2FnZUpzb24udmVyc2lvbjtcbiAgICBsb2dnZXIuaW5mbyhcIk9wZW5WaWR1IGluaXRpYWxpemVkXCIpO1xuICAgIGxvZ2dlci5pbmZvKCdQbGF0Zm9ybSBkZXRlY3RlZDogJyArIHBsYXRmb3JtLmdldERlc2NyaXB0aW9uKCkpO1xuICAgIGxvZ2dlci5pbmZvKCdvcGVudmlkdS1icm93c2VyIHZlcnNpb246ICcgKyB0aGlzLmxpYnJhcnlWZXJzaW9uKTtcblxuICAgIGlmIChwbGF0Zm9ybS5pc01vYmlsZURldmljZSgpIHx8IHBsYXRmb3JtLmlzUmVhY3ROYXRpdmUoKSkge1xuICAgICAgLy8gTGlzdGVuIHRvIG9yaWVudGF0aW9uY2hhbmdlIG9ubHkgb24gbW9iaWxlIGRldmljZXNcbiAgICAgIHRoaXMub25PcmllbnRhdGlvbkNoYW5nZWQoKCkgPT4ge1xuICAgICAgICB0aGlzLnB1Ymxpc2hlcnMuZm9yRWFjaChwdWJsaXNoZXIgPT4ge1xuICAgICAgICAgIGlmIChwdWJsaXNoZXIuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgJiYgISFwdWJsaXNoZXIuc3RyZWFtICYmICEhcHVibGlzaGVyLnN0cmVhbS5oYXNWaWRlbykge1xuICAgICAgICAgICAgdGhpcy5zZW5kTmV3VmlkZW9EaW1lbnNpb25zSWZSZXF1aXJlZChwdWJsaXNoZXIsICdkZXZpY2VSb3RhdGVkJywgNzUsIDEwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgbmV3IHNlc3Npb25cbiAgICovXG4gIGluaXRTZXNzaW9uKCk6IFNlc3Npb24ge1xuICAgIHRoaXMuc2Vzc2lvbiA9IG5ldyBTZXNzaW9uKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnNlc3Npb247XG4gIH1cblxuXG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQdWJsaXNoZXI7XG4gIGluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogUHVibGlzaGVyO1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlcjogKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IFB1Ymxpc2hlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIG5ldyBwdWJsaXNoZXJcbiAgICpcbiAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgKlxuICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhbiBgYWNjZXNzRGlhbG9nT3BlbmVkYCBldmVudCwgb25seSBpZiB0aGUgcG9wLXVwIHNob3duIGJ5IHRoZSBicm93c2VyIHRvIHJlcXVlc3QgcGVybWlzc2lvbnMgZm9yIHRoZSBjYW1lcmEgaXMgb3BlbmVkLiBZb3UgY2FuIHVzZSB0aGlzIGV2ZW50IHRvIGFsZXJ0IHRoZSB1c2VyIGFib3V0IGdyYW50aW5nIHBlcm1pc3Npb25zXG4gICAqIGZvciB5b3VyIHdlYnNpdGUuIEFuIGBhY2Nlc3NEaWFsb2dDbG9zZWRgIGV2ZW50IHdpbGwgYWxzbyBiZSBkaXNwYXRjaGVkIGFmdGVyIHVzZXIgY2xpY2tzIG9uIFwiQWxsb3dcIiBvciBcIkJsb2NrXCIgaW4gdGhlIHBvcC11cC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGBhY2Nlc3NEZW5pZWRgIGV2ZW50IG9uY2UgaXQgaGFzIGJlZW4gZ3JhbnRlZCBhY2Nlc3MgdG8gdGhlIHJlcXVlc3RlZCBpbnB1dCBkZXZpY2VzIG9yIG5vdC5cbiAgICpcbiAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSBhIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00gKG9ubHkgaWYgeW91XG4gICAqIFtsZXQgT3BlblZpZHUgdGFrZSBjYXJlIG9mIHRoZSB2aWRlbyBwbGF5ZXJzXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIGxvY2FsIHN0cmVhbXMgc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50ICBIVE1MIERPTSBlbGVtZW50IChvciBpdHMgYGlkYCBhdHRyaWJ1dGUpIGluIHdoaWNoIHRoZSB2aWRlbyBlbGVtZW50IG9mIHRoZSBQdWJsaXNoZXIgd2lsbCBiZSBpbnNlcnRlZCAoc2VlIFtbUHVibGlzaGVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgUHVibGlzaGVyLlxuICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1B1Ymxpc2hlci5hZGRWaWRlb0VsZW1lbnRdXSBvciBbW1B1Ymxpc2hlci5jcmVhdGVWaWRlb0VsZW1lbnRdXSB0byBtYW5hZ2UgdGhlIHZpZGVvIGVsZW1lbnRzIG9uIHlvdXIgb3duIChzZWUgW01hbmFnZSB2aWRlbyBwbGF5ZXJzXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcykgc2VjdGlvbilcbiAgICogQHBhcmFtIGNvbXBsZXRpb25IYW5kbGVyIGBlcnJvcmAgcGFyYW1ldGVyIGlzIG51bGwgaWYgYGluaXRQdWJsaXNoZXJgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgIGBjb21wbGV0aW9uSGFuZGxlcmAgZnVuY3Rpb24gaXMgY2FsbGVkIGJlZm9yZSB0aGUgUHVibGlzaGVyIGRpc3BhdGNoZXMgYW4gYGFjY2Vzc0FsbG93ZWRgIG9yIGFuIGBhY2Nlc3NEZW5pZWRgIGV2ZW50XG4gICAqL1xuICBpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTI/LCBwYXJhbTM/KTogUHVibGlzaGVyIHtcblxuICAgIGxldCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yICE9PSAnZnVuY3Rpb24nKSkge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBwcm9wZXJ0aWVzLCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSAoPFB1Ymxpc2hlclByb3BlcnRpZXM+cGFyYW0yKTtcblxuICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgYXVkaW9Tb3VyY2U6ICh0eXBlb2YgcHJvcGVydGllcy5hdWRpb1NvdXJjZSAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5hdWRpb1NvdXJjZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZnJhbWVSYXRlOiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSA/IHVuZGVmaW5lZCA6ICgodHlwZW9mIHByb3BlcnRpZXMuZnJhbWVSYXRlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLmZyYW1lUmF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgIGluc2VydE1vZGU6ICh0eXBlb2YgcHJvcGVydGllcy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwcm9wZXJ0aWVzLmluc2VydE1vZGUgPT09ICdzdHJpbmcnKSA/IFZpZGVvSW5zZXJ0TW9kZVtwcm9wZXJ0aWVzLmluc2VydE1vZGVdIDogcHJvcGVydGllcy5pbnNlcnRNb2RlKSA6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogKHR5cGVvZiBwcm9wZXJ0aWVzLm1pcnJvciAhPT0gJ3VuZGVmaW5lZCcpID8gcHJvcGVydGllcy5taXJyb3IgOiB0cnVlLFxuICAgICAgICBwdWJsaXNoQXVkaW86ICh0eXBlb2YgcHJvcGVydGllcy5wdWJsaXNoQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHByb3BlcnRpZXMucHVibGlzaEF1ZGlvIDogdHJ1ZSxcbiAgICAgICAgcHVibGlzaFZpZGVvOiAodHlwZW9mIHByb3BlcnRpZXMucHVibGlzaFZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbyA6IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgcHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spID8gdW5kZWZpbmVkIDogKCh0eXBlb2YgcHJvcGVydGllcy5yZXNvbHV0aW9uICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnJlc29sdXRpb24gOiAnNjQweDQ4MCcpLFxuICAgICAgICB2aWRlb1NvdXJjZTogKHR5cGVvZiBwcm9wZXJ0aWVzLnZpZGVvU291cmNlICE9PSAndW5kZWZpbmVkJykgPyBwcm9wZXJ0aWVzLnZpZGVvU291cmNlIDogdW5kZWZpbmVkLFxuICAgICAgICB2aWRlb1NpbXVsY2FzdDogcHJvcGVydGllcy52aWRlb1NpbXVsY2FzdCxcbiAgICAgICAgZmlsdGVyOiBwcm9wZXJ0aWVzLmZpbHRlclxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuXG4gICAgICAvLyBNYXRjaGVzICdpbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQpJyBvciAnaW5pdFB1Ymxpc2hlcih0YXJnZXRFbGVtZW50LCBjb21wbGV0aW9uSGFuZGxlciknXG5cbiAgICAgIHByb3BlcnRpZXMgPSB7XG4gICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgIG1pcnJvcjogdHJ1ZSxcbiAgICAgICAgcHVibGlzaEF1ZGlvOiB0cnVlLFxuICAgICAgICBwdWJsaXNoVmlkZW86IHRydWUsXG4gICAgICAgIHJlc29sdXRpb246ICc2NDB4NDgwJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJsaXNoZXI6IFB1Ymxpc2hlciA9IG5ldyBQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgdGhpcyk7XG5cbiAgICBsZXQgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQ7XG4gICAgaWYgKCEhcGFyYW0yICYmICh0eXBlb2YgcGFyYW0yID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTI7XG4gICAgfSBlbHNlIGlmICghIXBhcmFtMykge1xuICAgICAgY29tcGxldGlvbkhhbmRsZXIgPSBwYXJhbTM7XG4gICAgfVxuXG4gICAgcHVibGlzaGVyLmluaXRpYWxpemUoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBwdWJsaXNoZXIuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbZXJyb3JdKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5wdWJsaXNoZXJzLnB1c2gocHVibGlzaGVyKTtcbiAgICByZXR1cm4gcHVibGlzaGVyO1xuICB9XG5cblxuICAvKipcbiAgICogUHJvbWlzaWZpZWQgdmVyc2lvbiBvZiBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXVxuICAgKlxuICAgKiA+IFdBUk5JTkc6IGV2ZW50cyBgYWNjZXNzRGlhbG9nT3BlbmVkYCBhbmQgYGFjY2Vzc0RpYWxvZ0Nsb3NlZGAgd2lsbCBub3QgYmUgZGlzcGF0Y2hlZCBpZiB1c2luZyB0aGlzIG1ldGhvZCBpbnN0ZWFkIG9mIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dXG4gICAqL1xuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQpOiBQcm9taXNlPFB1Ymxpc2hlcj47XG4gIGluaXRQdWJsaXNoZXJBc3luYyh0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcyk6IFByb21pc2U8UHVibGlzaGVyPjtcblxuICBpbml0UHVibGlzaGVyQXN5bmModGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM/OiBQdWJsaXNoZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxQdWJsaXNoZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8UHVibGlzaGVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGxldCBwdWJsaXNoZXI6IFB1Ymxpc2hlcjtcblxuICAgICAgY29uc3QgY2FsbGJhY2sgPSAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmUocHVibGlzaGVyKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgaWYgKCEhcHJvcGVydGllcykge1xuICAgICAgICBwdWJsaXNoZXIgPSB0aGlzLmluaXRQdWJsaXNoZXIodGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHVibGlzaGVyID0gdGhpcy5pbml0UHVibGlzaGVyKHRhcmdldEVsZW1lbnQsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgbG9jYWwgcmVjb3JkZXIgZm9yIHJlY29yZGluZyBzdHJlYW1zIHN0cmFpZ2h0IGF3YXkgZnJvbSB0aGUgYnJvd3NlclxuICAgKiBAcGFyYW0gc3RyZWFtICBTdHJlYW0gdG8gcmVjb3JkXG4gICAqL1xuICBpbml0TG9jYWxSZWNvcmRlcihzdHJlYW06IFN0cmVhbSk6IExvY2FsUmVjb3JkZXIge1xuICAgIHJldHVybiBuZXcgTG9jYWxSZWNvcmRlcihzdHJlYW0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIE9wZW5WaWR1XG4gICAqIEByZXR1cm5zIDEgaWYgdGhlIGJyb3dzZXIgc3VwcG9ydHMgT3BlblZpZHUsIDAgb3RoZXJ3aXNlXG4gICAqL1xuICBjaGVja1N5c3RlbVJlcXVpcmVtZW50cygpOiBudW1iZXIge1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzSVBob25lT3JJUGFkKCkpIHtcbiAgICAgIGlmIChwbGF0Zm9ybS5pc0lPU1dpdGhTYWZhcmkoKSB8fCBwbGF0Zm9ybS5pc0lvbmljSW9zKCkgfHxcbiAgICAgICAgcGxhdGZvcm0uaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzT3BlcmFNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8gQWNjZXB0OiBDaHJvbWUgKGRlc2t0b3AgYW5kIEFuZHJvaWQpLCBGaXJlZm94IChkZXNrdG9wIGFuZCBBbmRyb2lkKSwgT3BlcmEgKGRlc2t0b3AgYW5kIEFuZHJvaWQpLFxuICAgIC8vIFNhZmFyaSAoT1NYIGFuZCBpT1MpLCBFZGdlIENocm9taXVtICg+PSA4MCksIElvbmljIChBbmRyb2lkIGFuZCBpT1MpLCBTYW1zdW5nIEludGVybmV0IEJyb3dzZXIgKEFuZHJvaWQpXG4gICAgaWYgKHBsYXRmb3JtLmlzQ2hyb21lQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzQ2hyb21lTW9iaWxlQnJvd3NlcigpIHx8XG4gICAgICBwbGF0Zm9ybS5pc0ZpcmVmb3hCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzT3BlcmFCcm93c2VyKCkgfHxcbiAgICAgIHBsYXRmb3JtLmlzT3BlcmFNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWRnZU1vYmlsZUJyb3dzZXIoKSB8fFxuICAgICAgcGxhdGZvcm0uaXNTYWZhcmlCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNBbmRyb2lkQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWxlY3Ryb24oKSB8fCBwbGF0Zm9ybS5pc1NhbXN1bmdCcm93c2VyKClcbiAgICApIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICAvLyBSZWplY3QgaVBob25lcyBhbmQgaVBhZHMgaWYgbm90IFNhZmFyaSAoJ1NhZmFyaScgYWxzbyBjb3ZlcnMgSW9uaWMgZm9yIGlPUylcbiAgICAvLyBSZWplY3Qgb3RoZXJzIGJyb3dzZXJzIG5vdCBtZW50aW9uZWQgYWJvdmVcbiAgICByZXR1cm4gMDtcblxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBzY3JlZW4tc2hhcmluZy4gRGVza3RvcCBDaHJvbWUsIEZpcmVmb3ggYW5kIE9wZXJhIHN1cHBvcnQgc2NyZWVuLXNoYXJpbmdcbiAgICogQHJldHVybnMgMSBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBzY3JlZW4tc2hhcmluZywgMCBvdGhlcndpc2VcbiAgICovXG4gIGNoZWNrU2NyZWVuU2hhcmluZ0NhcGFiaWxpdGllcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gcGxhdGZvcm0uY2FuU2NyZWVuU2hhcmUoKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWRpYSBpbnB1dCBkZXZpY2VzIGF2YWlsYWJsZSBvbiB0aGUgc3lzdGVtLiBZb3UgY2FuIHBhc3MgcHJvcGVydHkgYGRldmljZUlkYCBvZiBhIFtbRGV2aWNlXV0gb2JqZWN0IGFzIHZhbHVlIG9mIGBhdWRpb1NvdXJjZWAgb3IgYHZpZGVvU291cmNlYCBwcm9wZXJ0aWVzIGluIFtbaW5pdFB1Ymxpc2hlcl1dIG1ldGhvZFxuICAgKi9cbiAgZ2V0RGV2aWNlcygpOiBQcm9taXNlPERldmljZVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPERldmljZVtdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKS50aGVuKChkZXZpY2VJbmZvcykgPT4ge1xuICAgICAgICBjb25zdCBkZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuXG4gICAgICAgIC8vIElvbmljIEFuZHJvaWQgIGRldmljZXNcbiAgICAgICAgaWYgKHBsYXRmb3JtLmlzSW9uaWNBbmRyb2lkKCkgJiYgdHlwZW9mIGNvcmRvdmEgIT0gXCJ1bmRlZmluZWRcIiAmJiBjb3Jkb3ZhPy5wbHVnaW5zPy5FbnVtZXJhdGVEZXZpY2VzUGx1Z2luKSB7XG4gICAgICAgICAgY29yZG92YS5wbHVnaW5zLkVudW1lcmF0ZURldmljZXNQbHVnaW4uZ2V0RW51bWVyYXRlRGV2aWNlcygpLnRoZW4oKHBsdWdpbkRldmljZXM6IERldmljZVtdKSA9PiB7XG4gICAgICAgICAgICBsZXQgcGx1Z2luQXVkaW9EZXZpY2VzOiBEZXZpY2VbXSA9IFtdO1xuICAgICAgICAgICAgbGV0IHZpZGVvRGV2aWNlczogRGV2aWNlW10gPSBbXTtcbiAgICAgICAgICAgIGxldCBhdWRpb0RldmljZXM6IERldmljZVtdID0gW107XG4gICAgICAgICAgICBwbHVnaW5BdWRpb0RldmljZXMgPSBwbHVnaW5EZXZpY2VzLmZpbHRlcigoZGV2aWNlOiBEZXZpY2UpID0+IGRldmljZS5raW5kID09PSAnYXVkaW9pbnB1dCcpO1xuICAgICAgICAgICAgdmlkZW9EZXZpY2VzID0gZGV2aWNlSW5mb3MuZmlsdGVyKChkZXZpY2U6IERldmljZSkgPT4gZGV2aWNlLmtpbmQgPT09ICd2aWRlb2lucHV0Jyk7XG4gICAgICAgICAgICBhdWRpb0RldmljZXMgPSBkZXZpY2VJbmZvcy5maWx0ZXIoKGRldmljZTogRGV2aWNlKSA9PiBkZXZpY2Uua2luZCA9PT0gJ2F1ZGlvaW5wdXQnKTtcbiAgICAgICAgICAgIHZpZGVvRGV2aWNlcy5mb3JFYWNoKChkZXZpY2VJbmZvLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIWRldmljZUluZm8ubGFiZWwpIHtcbiAgICAgICAgICAgICAgICBsZXQgbGFiZWwgPSBcIlwiO1xuICAgICAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgbGFiZWwgPSBcIkZyb250IENhbWVyYVwiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5kZXggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgIGxhYmVsID0gXCJCYWNrIENhbWVyYVwiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBsYWJlbCA9IFwiVW5rbm93biBDYW1lcmFcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgICAgbGFiZWw6IGxhYmVsXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgICAgICBsYWJlbDogZGV2aWNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGF1ZGlvRGV2aWNlcy5mb3JFYWNoKChkZXZpY2VJbmZvLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoIWRldmljZUluZm8ubGFiZWwpIHtcbiAgICAgICAgICAgICAgICBsZXQgbGFiZWwgPSBcIlwiO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgMDogLy8gRGVmYXVsdCBNaWNyb3Bob25lXG4gICAgICAgICAgICAgICAgICAgIGxhYmVsID0gJ0RlZmF1bHQnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgMTogLy8gTWljcm9waG9uZSArIFNwZWFrZXJwaG9uZVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZhdWx0TWF0Y2ggPSBwbHVnaW5BdWRpb0RldmljZXMuZmlsdGVyKChkKSA9PiBkLmxhYmVsLmluY2x1ZGVzKCdCdWlsdCcpKVswXTtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBkZWZhdWx0TWF0Y2ggPyBkZWZhdWx0TWF0Y2gubGFiZWwgOiAnQnVpbHQtaW4gTWljcm9waG9uZSc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSAyOiAvLyBIZWFkc2V0IE1pY3JvcGhvbmVcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lyZWRNYXRjaCA9IHBsdWdpbkF1ZGlvRGV2aWNlcy5maWx0ZXIoKGQpID0+IGQubGFiZWwuaW5jbHVkZXMoJ1dpcmVkJykpWzBdO1xuICAgICAgICAgICAgICAgICAgICBpZiAod2lyZWRNYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gd2lyZWRNYXRjaC5sYWJlbDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICdIZWFkc2V0IGVhcnBpZWNlJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lyZWxlc3NNYXRjaCA9IHBsdWdpbkF1ZGlvRGV2aWNlcy5maWx0ZXIoKGQpID0+IGQubGFiZWwuaW5jbHVkZXMoJ0JsdWV0b290aCcpKVswXTtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSB3aXJlbGVzc01hdGNoID8gd2lyZWxlc3NNYXRjaC5sYWJlbCA6ICdXaXJlbGVzcyc7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBcIlVua25vd24gTWljcm9waG9uZVwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGV2aWNlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgIGtpbmQ6IGRldmljZUluZm8ua2luZCxcbiAgICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgICAgbGFiZWw6IGxhYmVsXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgICAgZGV2aWNlSWQ6IGRldmljZUluZm8uZGV2aWNlSWQsXG4gICAgICAgICAgICAgICAgICBsYWJlbDogZGV2aWNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGRldmljZXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgLy8gUmVzdCBvZiBwbGF0Zm9ybXNcbiAgICAgICAgICBkZXZpY2VJbmZvcy5mb3JFYWNoKGRldmljZUluZm8gPT4ge1xuICAgICAgICAgICAgaWYgKGRldmljZUluZm8ua2luZCA9PT0gJ2F1ZGlvaW5wdXQnIHx8IGRldmljZUluZm8ua2luZCA9PT0gJ3ZpZGVvaW5wdXQnKSB7XG4gICAgICAgICAgICAgIGRldmljZXMucHVzaCh7XG4gICAgICAgICAgICAgICAga2luZDogZGV2aWNlSW5mby5raW5kLFxuICAgICAgICAgICAgICAgIGRldmljZUlkOiBkZXZpY2VJbmZvLmRldmljZUlkLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2VJbmZvLmxhYmVsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiByZXNvbHZlKGRldmljZXMpO1xuICAgICAgICB9XG4gICAgICB9KS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBnZXR0aW5nIGRldmljZXMnLCBlcnJvcik7XG4gICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG5cbiAgLyoqXG4gICAqIEdldCBhIE1lZGlhU3RyZWFtIG9iamVjdCB0aGF0IHlvdSBjYW4gY3VzdG9taXplIGJlZm9yZSBjYWxsaW5nIFtbaW5pdFB1Ymxpc2hlcl1dIChwYXNzIF9NZWRpYVN0cmVhbVRyYWNrXyBwcm9wZXJ0eSBvZiB0aGUgX01lZGlhU3RyZWFtXyB2YWx1ZSByZXNvbHZlZCBieSB0aGUgUHJvbWlzZSBhcyBgYXVkaW9Tb3VyY2VgIG9yIGB2aWRlb1NvdXJjZWAgcHJvcGVydGllcyBpbiBbW2luaXRQdWJsaXNoZXJdXSlcbiAgICpcbiAgICogUGFyYW1ldGVyIGBvcHRpb25zYCBpcyB0aGUgc2FtZSBhcyBpbiBbW2luaXRQdWJsaXNoZXJdXSBzZWNvbmQgcGFyYW1ldGVyIChvZiB0eXBlIFtbUHVibGlzaGVyUHJvcGVydGllc11dKSwgYnV0IG9ubHkgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIHdpbGwgYmUgYXBwbGllZDogYGF1ZGlvU291cmNlYCwgYHZpZGVvU291cmNlYCwgYGZyYW1lUmF0ZWAsIGByZXNvbHV0aW9uYFxuICAgKlxuICAgKiBUbyBjdXN0b21pemUgdGhlIFB1Ymxpc2hlcidzIHZpZGVvLCB0aGUgQVBJIGZvciBIVE1MQ2FudmFzRWxlbWVudCBpcyB2ZXJ5IHVzZWZ1bC4gRm9yIGV4YW1wbGUsIHRvIGdldCBhIGJsYWNrLWFuZC13aGl0ZSB2aWRlbyBhdCAxMCBmcHMgYW5kIEhEIHJlc29sdXRpb24gd2l0aCBubyBzb3VuZDpcbiAgICogYGBgXG4gICAqIHZhciBPViA9IG5ldyBPcGVuVmlkdSgpO1xuICAgKiB2YXIgRlJBTUVfUkFURSA9IDEwO1xuICAgKlxuICAgKiBPVi5nZXRVc2VyTWVkaWEoe1xuICAgKiAgICBhdWRpb1NvdXJjZTogZmFsc2UsXG4gICAqICAgIHZpZGVvU291cmNlOiB1bmRlZmluZWQsXG4gICAqICAgIHJlc29sdXRpb246ICcxMjgweDcyMCcsXG4gICAqICAgIGZyYW1lUmF0ZTogRlJBTUVfUkFURVxuICAgKiB9KVxuICAgKiAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAqXG4gICAqICAgIHZhciB2aWRlb1RyYWNrID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICogICAgdmFyIHZpZGVvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICogICAgdmlkZW8uc3JjT2JqZWN0ID0gbmV3IE1lZGlhU3RyZWFtKFt2aWRlb1RyYWNrXSk7XG4gICAqXG4gICAqICAgIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICogICAgdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgKiAgICBjdHguZmlsdGVyID0gJ2dyYXlzY2FsZSgxMDAlKSc7XG4gICAqXG4gICAqICAgIHZpZGVvLmFkZEV2ZW50TGlzdGVuZXIoJ3BsYXknLCAoKSA9PiB7XG4gICAqICAgICAgdmFyIGxvb3AgPSAoKSA9PiB7XG4gICAqICAgICAgICBpZiAoIXZpZGVvLnBhdXNlZCAmJiAhdmlkZW8uZW5kZWQpIHtcbiAgICogICAgICAgICAgY3R4LmRyYXdJbWFnZSh2aWRlbywgMCwgMCwgMzAwLCAxNzApO1xuICAgKiAgICAgICAgICBzZXRUaW1lb3V0KGxvb3AsIDEwMDAvIEZSQU1FX1JBVEUpOyAvLyBEcmF3aW5nIGF0IDEwIGZwc1xuICAgKiAgICAgICAgfVxuICAgKiAgICAgIH07XG4gICAqICAgICAgbG9vcCgpO1xuICAgKiAgICB9KTtcbiAgICogICAgdmlkZW8ucGxheSgpO1xuICAgKlxuICAgKiAgICB2YXIgZ3JheVZpZGVvVHJhY2sgPSBjYW52YXMuY2FwdHVyZVN0cmVhbShGUkFNRV9SQVRFKS5nZXRWaWRlb1RyYWNrcygpWzBdO1xuICAgKiAgICB2YXIgcHVibGlzaGVyID0gdGhpcy5PVi5pbml0UHVibGlzaGVyKFxuICAgKiAgICAgIG15SHRtbFRhcmdldCxcbiAgICogICAgICB7XG4gICAqICAgICAgICBhdWRpb1NvdXJjZTogZmFsc2UsXG4gICAqICAgICAgICB2aWRlb1NvdXJjZTogZ3JheVZpZGVvVHJhY2tcbiAgICogICAgICB9KTtcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0VXNlck1lZGlhKG9wdGlvbnM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPE1lZGlhU3RyZWFtPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPE1lZGlhU3RyZWFtPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgIGNvbnN0IGFza0ZvckF1ZGlvU3RyZWFtT25seSA9IChwcmV2aW91c01lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSwgY29uc3RyYWludHM6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMpID0+IHtcbiAgICAgICAgY29uc3QgZGVmaW5lZEF1ZGlvQ29uc3RyYWludCA9ICgoY29uc3RyYWludHMuYXVkaW8gPT09IHVuZGVmaW5lZCkgPyB0cnVlIDogY29uc3RyYWludHMuYXVkaW8pO1xuICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eDogTWVkaWFTdHJlYW1Db25zdHJhaW50cyA9IHsgYXVkaW86IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQsIHZpZGVvOiBmYWxzZSB9O1xuICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAudGhlbihhdWRpb09ubHlTdHJlYW0gPT4ge1xuICAgICAgICAgICAgcHJldmlvdXNNZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShwcmV2aW91c01lZGlhU3RyZWFtKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICBwcmV2aW91c01lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcmV2aW91c01lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KHRoaXMuZ2VuZXJhdGVBdWRpb0RldmljZUVycm9yKGVycm9yLCBjb25zdHJhaW50c0F1eCkpO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyhvcHRpb25zKS50aGVuKG15Q29uc3RyYWludHMgPT4ge1xuXG4gICAgICAgIGlmICghIW15Q29uc3RyYWludHMudmlkZW9UcmFjayAmJiAhIW15Q29uc3RyYWludHMuYXVkaW9UcmFjayB8fFxuICAgICAgICAgICEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LnZpZGVvID09PSBmYWxzZSB8fFxuICAgICAgICAgICEhbXlDb25zdHJhaW50cy52aWRlb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LmF1ZGlvID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgLy8gTm8gbmVlZCB0byBjYWxsIGdldFVzZXJNZWRpYSBhdCBhbGwuIEJvdGggdHJhY2tzIHByb3ZpZGVkLCBvciBvbmx5IEFVRElPIHRyYWNrIHByb3ZpZGVkIG9yIG9ubHkgVklERU8gdHJhY2sgcHJvdmlkZWRcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh0aGlzLmFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzLCBuZXcgTWVkaWFTdHJlYW0oKSkpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gZ2V0VXNlck1lZGlhIG11c3QgYmUgY2FsbGVkLiBBVURJTyBvciBWSURFTyBhcmUgcmVxdWVzdGluZyBhIG5ldyB0cmFja1xuXG4gICAgICAgICAgLy8gRGVsZXRlIGFscmVhZHkgcHJvdmlkZWQgY29uc3RyYWludHMgZm9yIGF1ZGlvIG9yIHZpZGVvXG4gICAgICAgICAgaWYgKCEhbXlDb25zdHJhaW50cy52aWRlb1RyYWNrKSB7XG4gICAgICAgICAgICBkZWxldGUgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW87XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghIW15Q29uc3RyYWludHMuYXVkaW9UcmFjaykge1xuICAgICAgICAgICAgZGVsZXRlIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLmF1ZGlvO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxldCBtdXN0QXNrRm9yQXVkaW9UcmFja0xhdGVyID0gZmFsc2U7XG4gICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnZpZGVvU291cmNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gVmlkZW8gaXMgZGV2aWNlSWQgb3Igc2NyZWVuIHNoYXJpbmdcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnZpZGVvU291cmNlID09PSAnc2NyZWVuJyB8fFxuICAgICAgICAgICAgICBvcHRpb25zLnZpZGVvU291cmNlID09PSAnd2luZG93JyB8fFxuICAgICAgICAgICAgICAocGxhdGZvcm0uaXNFbGVjdHJvbigpICYmIG9wdGlvbnMudmlkZW9Tb3VyY2Uuc3RhcnRzV2l0aCgnc2NyZWVuOicpKSkge1xuICAgICAgICAgICAgICAvLyBWaWRlbyBpcyBzY3JlZW4gc2hhcmluZ1xuICAgICAgICAgICAgICBtdXN0QXNrRm9yQXVkaW9UcmFja0xhdGVyID0gIW15Q29uc3RyYWludHMuYXVkaW9UcmFjayAmJiAob3B0aW9ucy5hdWRpb1NvdXJjZSAhPT0gbnVsbCAmJiBvcHRpb25zLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgICAgICAgICAgIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzWydnZXREaXNwbGF5TWVkaWEnXSAmJiAhcGxhdGZvcm0uaXNFbGVjdHJvbigpKSB7XG4gICAgICAgICAgICAgICAgLy8gZ2V0RGlzcGxheU1lZGlhIHN1cHBvcnRlZFxuICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddKHsgdmlkZW86IHRydWUgfSlcbiAgICAgICAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRBbHJlYWR5UHJvdmlkZWRUcmFja3MobXlDb25zdHJhaW50cywgbWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAobXVzdEFza0ZvckF1ZGlvVHJhY2tMYXRlcikge1xuICAgICAgICAgICAgICAgICAgICAgIGFza0ZvckF1ZGlvU3RyZWFtT25seShtZWRpYVN0cmVhbSwgPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0NBUFRVUkVfREVOSUVEO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZ2V0RGlzcGxheU1lZGlhIE5PVCBzdXBwb3J0ZWQuIENhbiBwZXJmb3JtIGdldFVzZXJNZWRpYSBiZWxvdyB3aXRoIGFscmVhZHkgY2FsY3VsYXRlZCBjb25zdHJhaW50c1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBWaWRlbyBpcyBkZXZpY2VJZC4gQ2FuIHBlcmZvcm0gZ2V0VXNlck1lZGlhIGJlbG93IHdpdGggYWxyZWFkeSBjYWxjdWxhdGVkIGNvbnN0cmFpbnRzXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIFVzZSBhbHJlYWR5IGNhbGN1bGF0ZWQgY29uc3RyYWludHNcbiAgICAgICAgICBjb25zdCBjb25zdHJhaW50c0F1eCA9IG11c3RBc2tGb3JBdWRpb1RyYWNrTGF0ZXIgPyB7IHZpZGVvOiBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyB9IDogbXlDb25zdHJhaW50cy5jb25zdHJhaW50cztcbiAgICAgICAgICBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50c0F1eClcbiAgICAgICAgICAgIC50aGVuKG1lZGlhU3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5hZGRBbHJlYWR5UHJvdmlkZWRUcmFja3MobXlDb25zdHJhaW50cywgbWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgICBpZiAobXVzdEFza0ZvckF1ZGlvVHJhY2tMYXRlcikge1xuICAgICAgICAgICAgICAgIGFza0ZvckF1ZGlvU3RyZWFtT25seShtZWRpYVN0cmVhbSwgPE1lZGlhU3RyZWFtQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgIGxldCBlcnJvck5hbWU6IE9wZW5WaWR1RXJyb3JOYW1lO1xuICAgICAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICBpZiAoIShvcHRpb25zLnZpZGVvU291cmNlID09PSAnc2NyZWVuJykpIHtcbiAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQ7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIC8qIHRzbGludDpkaXNhYmxlOm5vLWVtcHR5ICovXG4gIC8qKlxuICAgKiBEaXNhYmxlIGFsbCBsb2dnaW5nIGV4Y2VwdCBlcnJvciBsZXZlbFxuICAgKi9cbiAgZW5hYmxlUHJvZE1vZGUoKTogdm9pZCB7XG4gICAgbG9nZ2VyLmVuYWJsZVByb2RNb2RlKCk7XG4gIH1cbiAgLyogdHNsaW50OmVuYWJsZTpuby1lbXB0eSAqL1xuXG5cbiAgLyoqXG4gICAqIFNldCBPcGVuVmlkdSBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbnMuIGBjb25maWd1cmF0aW9uYCBpcyBhbiBvYmplY3Qgb2YgdHlwZSBbW09wZW5WaWR1QWR2YW5jZWRDb25maWd1cmF0aW9uXV0uIENhbGwgdGhpcyBtZXRob2QgdG8gb3ZlcnJpZGUgcHJldmlvdXMgdmFsdWVzIGF0IGFueSBtb21lbnQuXG4gICAqL1xuICBzZXRBZHZhbmNlZENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFkdmFuY2VkQ29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb247XG4gIH1cblxuXG4gIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIG9uT3JpZW50YXRpb25DaGFuZ2VkKGhhbmRsZXIpOiB2b2lkIHtcbiAgICAoPGFueT53aW5kb3cpLmFkZEV2ZW50TGlzdGVuZXIoJ29yaWVudGF0aW9uY2hhbmdlJywgaGFuZGxlcik7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgc2VuZE5ld1ZpZGVvRGltZW5zaW9uc0lmUmVxdWlyZWQocHVibGlzaGVyOiBQdWJsaXNoZXIsIHJlYXNvbjogc3RyaW5nLCBXQUlUX0lOVEVSVkFMOiBudW1iZXIsIE1BWF9BVFRFTVBUUzogbnVtYmVyKSB7XG4gICAgbGV0IGF0dGVtcHRzID0gMDtcbiAgICBjb25zdCBvbGRXaWR0aCA9IHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLndpZHRoO1xuICAgIGNvbnN0IG9sZEhlaWdodCA9IHB1Ymxpc2hlci5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodDtcblxuICAgIGNvbnN0IHJlcGVhdFVudGlsQ2hhbmdlT3JNYXhBdHRlbXB0czogTm9kZUpTLlRpbWVvdXQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBhdHRlbXB0cysrO1xuICAgICAgaWYgKGF0dGVtcHRzID4gTUFYX0FUVEVNUFRTKSB7XG4gICAgICAgIGNsZWFyVGltZW91dChyZXBlYXRVbnRpbENoYW5nZU9yTWF4QXR0ZW1wdHMpO1xuICAgICAgfVxuICAgICAgcHVibGlzaGVyLmdldFZpZGVvRGltZW5zaW9ucygpLnRoZW4obmV3RGltZW5zaW9ucyA9PiB7XG4gICAgICAgIGlmIChuZXdEaW1lbnNpb25zLndpZHRoICE9PSBvbGRXaWR0aCB8fCBuZXdEaW1lbnNpb25zLmhlaWdodCAhPT0gb2xkSGVpZ2h0KSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHJlcGVhdFVudGlsQ2hhbmdlT3JNYXhBdHRlbXB0cyk7XG4gICAgICAgICAgdGhpcy5zZW5kVmlkZW9EaW1lbnNpb25zQ2hhbmdlZEV2ZW50KHB1Ymxpc2hlciwgcmVhc29uLCBvbGRXaWR0aCwgb2xkSGVpZ2h0LCBuZXdEaW1lbnNpb25zLndpZHRoLCBuZXdEaW1lbnNpb25zLmhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sIFdBSVRfSU5URVJWQUwpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRWaWRlb0RpbWVuc2lvbnNDaGFuZ2VkRXZlbnQocHVibGlzaGVyOiBQdWJsaXNoZXIsIHJlYXNvbjogc3RyaW5nLCBvbGRXaWR0aDogbnVtYmVyLCBvbGRIZWlnaHQ6IG51bWJlciwgbmV3V2lkdGg6IG51bWJlciwgbmV3SGVpZ2h0OiBudW1iZXIpIHtcbiAgICBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IHtcbiAgICAgIHdpZHRoOiBuZXdXaWR0aCB8fCAwLFxuICAgICAgaGVpZ2h0OiBuZXdIZWlnaHQgfHwgMFxuICAgIH07XG4gICAgdGhpcy5zZW5kUmVxdWVzdChcbiAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAge1xuICAgICAgICBzdHJlYW1JZDogcHVibGlzaGVyLnN0cmVhbS5zdHJlYW1JZCxcbiAgICAgICAgcHJvcGVydHk6ICd2aWRlb0RpbWVuc2lvbnMnLFxuICAgICAgICBuZXdWYWx1ZTogSlNPTi5zdHJpbmdpZnkocHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMpLFxuICAgICAgICByZWFzb25cbiAgICAgIH0sXG4gICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHNlbmRpbmcgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIiwgZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcy5zZXNzaW9uLCBwdWJsaXNoZXIuc3RyZWFtLCAndmlkZW9EaW1lbnNpb25zJywgcHVibGlzaGVyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMsIHsgd2lkdGg6IG9sZFdpZHRoLCBoZWlnaHQ6IG9sZEhlaWdodCB9LCByZWFzb24pXSk7XG4gICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChwdWJsaXNoZXIsIHB1Ymxpc2hlci5zdHJlYW0sICd2aWRlb0RpbWVuc2lvbnMnLCBwdWJsaXNoZXIuc3RyZWFtLnZpZGVvRGltZW5zaW9ucywgeyB3aWR0aDogb2xkV2lkdGgsIGhlaWdodDogb2xkSGVpZ2h0IH0sIHJlYXNvbildKTtcbiAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YShwdWJsaXNoZXIpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2VuZXJhdGVNZWRpYUNvbnN0cmFpbnRzKHB1Ymxpc2hlclByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMpOiBQcm9taXNlPEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHM+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8Q3VzdG9tTWVkaWFTdHJlYW1Db25zdHJhaW50cz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICBjb25zdCBteUNvbnN0cmFpbnRzOiBDdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpb1RyYWNrOiB1bmRlZmluZWQsXG4gICAgICAgIHZpZGVvVHJhY2s6IHVuZGVmaW5lZCxcbiAgICAgICAgY29uc3RyYWludHM6IHtcbiAgICAgICAgICBhdWRpbzogdW5kZWZpbmVkLFxuICAgICAgICAgIHZpZGVvOiB1bmRlZmluZWRcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgYXVkaW9Tb3VyY2UgPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlO1xuICAgICAgY29uc3QgdmlkZW9Tb3VyY2UgPSBwdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlO1xuXG4gICAgICAvLyBDQVNFIDE6IG51bGwvZmFsc2VcbiAgICAgIGlmIChhdWRpb1NvdXJjZSA9PT0gbnVsbCB8fCBhdWRpb1NvdXJjZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgLy8gTm8gYXVkaW8gdHJhY2tcbiAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEuYXVkaW8gPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICh2aWRlb1NvdXJjZSA9PT0gbnVsbCB8fCB2aWRlb1NvdXJjZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgLy8gTm8gdmlkZW8gdHJhY2tcbiAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS5hdWRpbyA9PT0gZmFsc2UgJiYgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIEVSUk9SISBhdWRpb1NvdXJjZSBhbmQgdmlkZW9Tb3VyY2UgY2Fubm90IGJlIGJvdGggZmFsc2UgYXQgdGhlIHNhbWUgdGltZVxuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk5PX0lOUFVUX1NPVVJDRV9TRVQsXG4gICAgICAgICAgXCJQcm9wZXJ0aWVzICdhdWRpb1NvdXJjZScgYW5kICd2aWRlb1NvdXJjZScgY2Fubm90IGJlIHNldCB0byBmYWxzZSBvciBudWxsIGF0IHRoZSBzYW1lIHRpbWVcIikpO1xuICAgICAgfVxuXG4gICAgICAvLyBDQVNFIDI6IE1lZGlhU3RyZWFtVHJhY2tzXG4gICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIGF1ZGlvU291cmNlIGluc3RhbmNlb2YgTWVkaWFTdHJlYW1UcmFjaykge1xuICAgICAgICAvLyBBbHJlYWR5IHByb3ZpZGVkIGF1ZGlvIHRyYWNrXG4gICAgICAgIG15Q29uc3RyYWludHMuYXVkaW9UcmFjayA9IGF1ZGlvU291cmNlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiBNZWRpYVN0cmVhbVRyYWNrICE9PSAndW5kZWZpbmVkJyAmJiB2aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgLy8gQWxyZWFkeSBwcm92aWRlZCB2aWRlbyB0cmFja1xuICAgICAgICBteUNvbnN0cmFpbnRzLnZpZGVvVHJhY2sgPSB2aWRlb1NvdXJjZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ0FTRSAzOiBEZWZhdWx0IHRyYWNrc1xuICAgICAgaWYgKGF1ZGlvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEuYXVkaW8gPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHZpZGVvU291cmNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSB7XG4gICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIGlkZWFsOiA2NDBcbiAgICAgICAgICB9LFxuICAgICAgICAgIGhlaWdodDoge1xuICAgICAgICAgICAgaWRlYWw6IDQ4MFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gQ0FTRSAzLjU6IGdpdmUgdmFsdWVzIHRvIHJlc29sdXRpb24gYW5kIGZyYW1lUmF0ZSBpZiB2aWRlbyBub3QgbnVsbC9mYWxzZVxuICAgICAgaWYgKHZpZGVvU291cmNlICE9PSBudWxsICYmIHZpZGVvU291cmNlICE9PSBmYWxzZSkge1xuICAgICAgICBpZiAoISFwdWJsaXNoZXJQcm9wZXJ0aWVzLnJlc29sdXRpb24pIHtcbiAgICAgICAgICBjb25zdCB3aWR0aEFuZEhlaWdodCA9IHB1Ymxpc2hlclByb3BlcnRpZXMucmVzb2x1dGlvbi50b0xvd2VyQ2FzZSgpLnNwbGl0KCd4Jyk7XG4gICAgICAgICAgY29uc3QgaWRlYWxXaWR0aCA9IE51bWJlcih3aWR0aEFuZEhlaWdodFswXSk7XG4gICAgICAgICAgY29uc3QgaWRlYWxIZWlnaHQgPSBOdW1iZXIod2lkdGhBbmRIZWlnaHRbMV0pO1xuICAgICAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLnZpZGVvID0ge1xuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgaWRlYWw6IGlkZWFsV2lkdGhcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoZWlnaHQ6IHtcbiAgICAgICAgICAgICAgaWRlYWw6IGlkZWFsSGVpZ2h0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghIXB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlKSB7XG4gICAgICAgICAgKDxNZWRpYVRyYWNrQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8pLmZyYW1lUmF0ZSA9IHsgaWRlYWw6IHB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlIH07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ0FTRSA0OiBkZXZpY2VJZCBvciBzY3JlZW4gc2hhcmluZ1xuICAgICAgdGhpcy5jb25maWd1cmVEZXZpY2VJZE9yU2NyZWVuc2hhcmluZyhteUNvbnN0cmFpbnRzLCBwdWJsaXNoZXJQcm9wZXJ0aWVzLCByZXNvbHZlLCByZWplY3QpO1xuXG4gICAgICByZXR1cm4gcmVzb2x2ZShteUNvbnN0cmFpbnRzKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBzdGFydFdzKG9uQ29ubmVjdFN1Y2NlczogKGVycm9yOiBFcnJvcikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGhlYXJ0YmVhdDogNTAwMCxcbiAgICAgIHdzOiB7XG4gICAgICAgIHVyaTogdGhpcy53c1VyaSArICc/c2Vzc2lvbklkPScgKyB0aGlzLnNlc3Npb24uc2Vzc2lvbklkLFxuICAgICAgICBvbmNvbm5lY3RlZDogb25Db25uZWN0U3VjY2VzLFxuICAgICAgICBvbmRpc2Nvbm5lY3Q6IHRoaXMuZGlzY29ubmVjdENhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0aW5nOiB0aGlzLnJlY29ubmVjdGluZ0NhbGxiYWNrLmJpbmQodGhpcyksXG4gICAgICAgIG9ucmVjb25uZWN0ZWQ6IHRoaXMucmVjb25uZWN0ZWRDYWxsYmFjay5iaW5kKHRoaXMpLFxuICAgICAgICBpc21hc3Rlcm5vZGVjcmFzaGVkOiB0aGlzLmlzTWFzdGVyTm9kZUNyYXNoZWQuYmluZCh0aGlzKVxuICAgICAgfSxcbiAgICAgIHJwYzoge1xuICAgICAgICByZXF1ZXN0VGltZW91dDogMTAwMDAsXG4gICAgICAgIGhlYXJ0YmVhdFJlcXVlc3RUaW1lb3V0OiA1MDAwLFxuICAgICAgICBwYXJ0aWNpcGFudEpvaW5lZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRKb2luZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFB1Ymxpc2hlZDogdGhpcy5zZXNzaW9uLm9uUGFydGljaXBhbnRQdWJsaXNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudFVucHVibGlzaGVkOiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudFVucHVibGlzaGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgcGFydGljaXBhbnRMZWZ0OiB0aGlzLnNlc3Npb24ub25QYXJ0aWNpcGFudExlZnQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBwYXJ0aWNpcGFudEV2aWN0ZWQ6IHRoaXMuc2Vzc2lvbi5vblBhcnRpY2lwYW50RXZpY3RlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIHJlY29yZGluZ1N0YXJ0ZWQ6IHRoaXMuc2Vzc2lvbi5vblJlY29yZGluZ1N0YXJ0ZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICByZWNvcmRpbmdTdG9wcGVkOiB0aGlzLnNlc3Npb24ub25SZWNvcmRpbmdTdG9wcGVkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgc2VuZE1lc3NhZ2U6IHRoaXMuc2Vzc2lvbi5vbk5ld01lc3NhZ2UuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vblN0cmVhbVByb3BlcnR5Q2hhbmdlZC5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIGNvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWQ6IHRoaXMuc2Vzc2lvbi5vbkNvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBuZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZDogdGhpcy5zZXNzaW9uLm9uTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRDaGFuZ2VkLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgZmlsdGVyRXZlbnREaXNwYXRjaGVkOiB0aGlzLnNlc3Npb24ub25GaWx0ZXJFdmVudERpc3BhdGNoZWQuYmluZCh0aGlzLnNlc3Npb24pLFxuICAgICAgICBpY2VDYW5kaWRhdGU6IHRoaXMuc2Vzc2lvbi5yZWN2SWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5zZXNzaW9uKSxcbiAgICAgICAgbWVkaWFFcnJvcjogdGhpcy5zZXNzaW9uLm9uTWVkaWFFcnJvci5iaW5kKHRoaXMuc2Vzc2lvbiksXG4gICAgICAgIG1hc3Rlck5vZGVDcmFzaGVkTm90aWZpY2F0aW9uOiB0aGlzLm9uTWFzdGVyTm9kZUNyYXNoZWROb3RpZmljYXRpb24uYmluZCh0aGlzKSxcbiAgICAgICAgZm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyOiB0aGlzLnNlc3Npb24ub25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXIuYmluZCh0aGlzLnNlc3Npb24pXG4gICAgICB9XG4gICAgfTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQgPSBuZXcgUnBjQnVpbGRlci5jbGllbnRzLkpzb25ScGNDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAaGlkZGVuXG4gICAqL1xuICBvbk1hc3Rlck5vZGVDcmFzaGVkTm90aWZpY2F0aW9uKHJlc3BvbnNlKTogdm9pZCB7XG4gICAgY29uc29sZS5lcnJvcignTWFzdGVyIE5vZGUgaGFzIGNyYXNoZWQnKTtcbiAgICB0aGlzLm1hc3Rlck5vZGVIYXNDcmFzaGVkID0gdHJ1ZTtcbiAgICB0aGlzLnNlc3Npb24ub25Mb3N0Q29ubmVjdGlvbihcIm5vZGVDcmFzaGVkXCIpO1xuICAgIHRoaXMuanNvblJwY0NsaWVudC5jbG9zZSg0MTAzLCBcIk1hc3RlciBOb2RlIGhhcyBjcmFzaGVkXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzUmVhZHlTdGF0ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmpzb25ScGNDbGllbnQuZ2V0UmVhZHlTdGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGNsb3NlV3MoKTogdm9pZCB7XG4gICAgdGhpcy5qc29uUnBjQ2xpZW50LmNsb3NlKDQxMDIsIFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgY2xpZW50XCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHNlbmRSZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCBwYXJhbXM6IGFueSwgY2FsbGJhY2s/KTogdm9pZCB7XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICBwYXJhbXMgPSB7fTtcbiAgICB9XG4gICAgbG9nZ2VyLmRlYnVnKCdTZW5kaW5nIHJlcXVlc3Q6IHttZXRob2Q6XCInICsgbWV0aG9kICsgJ1wiLCBwYXJhbXM6ICcgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgJ30nKTtcbiAgICB0aGlzLmpzb25ScGNDbGllbnQuc2VuZChtZXRob2QsIHBhcmFtcywgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFdzVXJpKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMud3NVcmk7XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgZ2V0U2VjcmV0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VjcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdldFJlY29yZGVyKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlY29yZGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGdlbmVyYXRlQXVkaW9EZXZpY2VFcnJvcihlcnJvciwgY29uc3RyYWludHM6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMpOiBPcGVuVmlkdUVycm9yIHtcbiAgICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Vycm9yJykge1xuICAgICAgLy8gU2FmYXJpIE92ZXJDb25zdHJhaW5lZEVycm9yIGhhcyBhcyBuYW1lIHByb3BlcnR5ICdFcnJvcicgaW5zdGVhZCBvZiAnT3ZlckNvbnN0cmFpbmVkRXJyb3InXG4gICAgICBlcnJvci5uYW1lID0gZXJyb3IuY29uc3RydWN0b3IubmFtZTtcbiAgICB9XG4gICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlOiBzdHJpbmc7XG4gICAgc3dpdGNoIChlcnJvci5uYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICByZXR1cm4gbmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpO1xuICAgICAgY2FzZSAnbm90YWxsb3dlZGVycm9yJzpcbiAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuREVWSUNFX0FDQ0VTU19ERU5JRUQ7XG4gICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHJldHVybiBuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSk7XG4gICAgICBjYXNlICdvdmVyY29uc3RyYWluZWRlcnJvcic6XG4gICAgICAgIGlmIChlcnJvci5jb25zdHJhaW50LnRvTG93ZXJDYXNlKCkgPT09ICdkZXZpY2VpZCcpIHtcbiAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgIGVycm9yTWVzc2FnZSA9IFwiQXVkaW8gaW5wdXQgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ1wiICsgKDxDb25zdHJhaW5ET01TdHJpbmdQYXJhbWV0ZXJzPig8TWVkaWFUcmFja0NvbnN0cmFpbnRzPmNvbnN0cmFpbnRzLmF1ZGlvKS5kZXZpY2VJZCEhKS5leGFjdCArIFwiJyBub3QgZm91bmRcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5QVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUjtcbiAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKTtcbiAgICAgIGNhc2UgJ25vdHJlYWRhYmxlZXJyb3InOlxuICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUxSRUFEWV9JTl9VU0U7XG4gICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHJldHVybiAobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfR0VORVJJQ19FUlJPUiwgZXJyb3IudG9TdHJpbmcoKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIGFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzOiBDdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0sIHN0cmVhbT86IFN0cmVhbSkge1xuICAgIGlmICghIW15Q29uc3RyYWludHMudmlkZW9UcmFjaykge1xuICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2sobXlDb25zdHJhaW50cy52aWRlb1RyYWNrKTtcbiAgICAgIGlmICghIXN0cmVhbSkge1xuICAgICAgICBpZiAoISFteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzLnZpZGVvKSB7XG4gICAgICAgICAgc3RyZWFtLmxhc3RWaWRlb1RyYWNrQ29uc3RyYWludHMgPSBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzLnZpZGVvO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0cmVhbS5sYXN0VmlkZW9UcmFja0NvbnN0cmFpbnRzID0gbXlDb25zdHJhaW50cy52aWRlb1RyYWNrLmdldENvbnN0cmFpbnRzKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrKSB7XG4gICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhteUNvbnN0cmFpbnRzLmF1ZGlvVHJhY2spO1xuICAgIH1cbiAgICByZXR1cm4gbWVkaWFTdHJlYW07XG4gIH1cblxuICAvKipcbiAgICogQGhpZGRlblxuICAgKi9cbiAgcHJvdGVjdGVkIGNvbmZpZ3VyZURldmljZUlkT3JTY3JlZW5zaGFyaW5nKG15Q29uc3RyYWludHM6IEN1c3RvbU1lZGlhU3RyZWFtQ29uc3RyYWludHMsIHB1Ymxpc2hlclByb3BlcnRpZXM6IFB1Ymxpc2hlclByb3BlcnRpZXMsIHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbnN0IGF1ZGlvU291cmNlID0gcHVibGlzaGVyUHJvcGVydGllcy5hdWRpb1NvdXJjZTtcbiAgICBjb25zdCB2aWRlb1NvdXJjZSA9IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2U7XG4gICAgaWYgKHR5cGVvZiBhdWRpb1NvdXJjZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG15Q29uc3RyYWludHMuY29uc3RyYWludHMhLmF1ZGlvID0geyBkZXZpY2VJZDogeyBleGFjdDogYXVkaW9Tb3VyY2UgfSB9O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdmlkZW9Tb3VyY2UgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgIGlmICghdGhpcy5pc1NjcmVlblNoYXJlKHZpZGVvU291cmNlKSkge1xuICAgICAgICB0aGlzLnNldFZpZGVvU291cmNlKG15Q29uc3RyYWludHMsIHZpZGVvU291cmNlKTtcblxuICAgICAgfSBlbHNlIHtcblxuICAgICAgICAvLyBTY3JlZW4gc2hhcmluZ1xuXG4gICAgICAgIGlmICghdGhpcy5jaGVja1NjcmVlblNoYXJpbmdDYXBhYmlsaXRpZXMoKSkge1xuICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCwgJ1lvdSBjYW4gb25seSBzY3JlZW4gc2hhcmUgaW4gZGVza3RvcCBDaHJvbWUsIEZpcmVmb3gsIE9wZXJhLCBTYWZhcmkgKD49MTMuMCksIEVkZ2UgKD49IDgwKSBvciBFbGVjdHJvbi4gRGV0ZWN0ZWQgY2xpZW50OiAnICsgcGxhdGZvcm0uZ2V0TmFtZSgpICsgJyAnICsgcGxhdGZvcm0uZ2V0VmVyc2lvbigpKTtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgaWYgKHBsYXRmb3JtLmlzRWxlY3Ryb24oKSkge1xuICAgICAgICAgICAgY29uc3QgcHJlZml4ID0gXCJzY3JlZW46XCI7XG4gICAgICAgICAgICBjb25zdCB2aWRlb1NvdXJjZVN0cmluZzogc3RyaW5nID0gdmlkZW9Tb3VyY2U7XG4gICAgICAgICAgICBjb25zdCBlbGVjdHJvblNjcmVlbklkID0gdmlkZW9Tb3VyY2VTdHJpbmcuc3Vic3RyKHZpZGVvU291cmNlU3RyaW5nLmluZGV4T2YocHJlZml4KSArIHByZWZpeC5sZW5ndGgpO1xuICAgICAgICAgICAgKDxhbnk+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8pID0ge1xuICAgICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlSWQ6IGVsZWN0cm9uU2NyZWVuSWRcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG15Q29uc3RyYWludHMpO1xuXG4gICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gJiYgIShwbGF0Zm9ybS5pc0ZpcmVmb3hCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpKSAmJiAhbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10pIHtcblxuICAgICAgICAgICAgICAvLyBDdXN0b20gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGZvciBDaHJvbWUgKGFuZCBPcGVyYSkgYW5kIG5vIHN1cHBvcnQgZm9yIE1lZGlhRGV2aWNlcy5nZXREaXNwbGF5TWVkaWEoKVxuXG4gICAgICAgICAgICAgIHNjcmVlblNoYXJpbmcuZ2V0U2NyZWVuQ29uc3RyYWludHMoKGVycm9yLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yIHx8ICEhc2NyZWVuQ29uc3RyYWludHMubWFuZGF0b3J5ICYmIHNjcmVlbkNvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZSA9PT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICAgIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJyB8fCBlcnJvciA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQsICdZb3UgbXVzdCBhbGxvdyBhY2Nlc3MgdG8gb25lIHdpbmRvdyBvZiB5b3VyIGRlc2t0b3AnKTtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25JZCA9IHRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uIS5zcGxpdCgnLycpLnBvcCgpISEudHJpbSgpO1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyhleHRlbnNpb25JZCwgc3RhdHVzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSAnaW5zdGFsbGVkLWRpc2FibGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX0RJU0FCTEVELCAnWW91IG11c3QgZW5hYmxlIHRoZSBzY3JlZW4gZXh0ZW5zaW9uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT09ICdub3QtaW5zdGFsbGVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQsICg8c3RyaW5nPnRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbyA9IHNjcmVlbkNvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobXlDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlc1snZ2V0RGlzcGxheU1lZGlhJ10pIHtcbiAgICAgICAgICAgICAgICAvLyBnZXREaXNwbGF5TWVkaWEgc3VwcG9ydCAoQ2hyb21lID49IDcyLCBGaXJlZm94ID49IDY2LCBTYWZhcmkgPj0gMTMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobXlDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24gZm9yIENocm9tZS9PcGVyYSwgb3IgaXMgRmlyZWZveCA8IDY2XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyZWZveFN0cmluZyA9IChwbGF0Zm9ybS5pc0ZpcmVmb3hCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpKSA/IHB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBzY3JlZW5TaGFyaW5nQXV0by5nZXRTY3JlZW5JZChmaXJlZm94U3RyaW5nLCAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5Db25zdHJhaW50cykgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yID09PSAnbm90LWluc3RhbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25VcmwgPSAhIXRoaXMuYWR2YW5jZWRDb25maWd1cmF0aW9uLnNjcmVlblNoYXJlQ2hyb21lRXh0ZW5zaW9uID8gdGhpcy5hZHZhbmNlZENvbmZpZ3VyYXRpb24uc2NyZWVuU2hhcmVDaHJvbWVFeHRlbnNpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgJ2h0dHBzOi8vY2hyb21lLmdvb2dsZS5jb20vd2Vic3RvcmUvZGV0YWlsL29wZW52aWR1LXNjcmVlbnNoYXJpbmcvbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnO1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9FWFRFTlNJT05fTk9UX0lOU1RBTExFRCwgZXh0ZW5zaW9uVXJsKTtcbiAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgPT09ICdpbnN0YWxsZWQtZGlzYWJsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyID0gbmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCwgJ1lvdSBtdXN0IGVuYWJsZSB0aGUgc2NyZWVuIGV4dGVuc2lvbicpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlcnJvciA9PT0gJ3Blcm1pc3Npb24tZGVuaWVkJykge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlNDUkVFTl9DQVBUVVJFX0RFTklFRCwgJ1lvdSBtdXN0IGFsbG93IGFjY2VzcyB0byBvbmUgd2luZG93IG9mIHlvdXIgZGVza3RvcCcpO1xuICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCAnVW5rbm93biBlcnJvciB3aGVuIGFjY2Vzc2luZyBzY3JlZW4gc2hhcmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSBzY3JlZW5Db25zdHJhaW50cy52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobXlDb25zdHJhaW50cyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBoaWRkZW5cbiAgICovXG4gIHByb3RlY3RlZCBzZXRWaWRlb1NvdXJjZShteUNvbnN0cmFpbnRzOiBDdXN0b21NZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCB2aWRlb1NvdXJjZTogc3RyaW5nKSB7XG4gICAgaWYgKCFteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzIS52aWRlbykge1xuICAgICAgbXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8gPSB7fTtcbiAgICB9XG4gICAgKDxNZWRpYVRyYWNrQ29uc3RyYWludHM+bXlDb25zdHJhaW50cy5jb25zdHJhaW50cyEudmlkZW8pWydkZXZpY2VJZCddID0geyBleGFjdDogdmlkZW9Tb3VyY2UgfTtcbiAgfVxuXG5cbiAgLyogUHJpdmF0ZSBtZXRob2RzICovXG5cbiAgcHJpdmF0ZSBkaXNjb25uZWN0Q2FsbGJhY2soKTogdm9pZCB7XG4gICAgbG9nZ2VyLndhcm4oJ1dlYnNvY2tldCBjb25uZWN0aW9uIGxvc3QnKTtcbiAgICBpZiAodGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLm9uTG9zdENvbm5lY3Rpb24oJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFsZXJ0KCdDb25uZWN0aW9uIGVycm9yLiBQbGVhc2UgcmVsb2FkIHBhZ2UuJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWNvbm5lY3RpbmdDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBsb2dnZXIud2FybignV2Vic29ja2V0IGNvbm5lY3Rpb24gbG9zdCAocmVjb25uZWN0aW5nKScpO1xuICAgIGlmICghdGhpcy5pc1Jvb21BdmFpbGFibGUoKSkge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncmVjb25uZWN0aW5nJywgW10pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0V2Vic29ja2V0VGhyb3VnaFJwY0Nvbm5lY3RNZXRob2QocnBjU2Vzc2lvbklkKSB7XG4gICAgLy8gVGhpcyBSUEMgbWV0aG9kIGFsbG93cyBjaGVja2luZzpcbiAgICAvLyBTaW5nbGUgTWFzdGVyOiBpZiBzdWNjZXNzLCBjb25uZWN0aW9uIHJlY292ZXJlZFxuICAgIC8vICAgICAgICAgICAgICAgIGlmIGVycm9yLCBubyBNYXN0ZXIgTm9kZSBjcmFzaGVkIGFuZCBsaWZlIHdpbGwgYmUgLTEuIG9uTG9zdENvbm5lY3Rpb24gd2l0aCByZWFzb24gbmV0d29ya0Rpc2Nvbm5lY3Qgd2lsbCBiZSB0cmlnZ2VyZWRcbiAgICAvLyBNdWx0aSBNYXN0ZXI6IGlmIHN1Y2Nlc3MsIGNvbm5lY3Rpb24gcmVjb3ZlcmVkXG4gICAgLy8gICAgICAgICAgICAgICBpZiBlcnJvciBhbmQgTWFzdGVyIE5vZGUgY3Jhc2hlZCBub3RpZmljYXRpb24gd2FzIGFscmVhZHkgcmVjZWl2ZWQsIG5vdGhpbmcgbXVzdCBiZSBkb25lXG4gICAgLy8gICAgICAgICAgICAgICBpZiBlcnJvciBhbmQgTWFzdGVyIE5vZGUgTk9UIGNyYXNoZWQsIHNlc3Npb25TdGF0dXMgbWV0aG9kIG11c3QgYmUgc2VudDpcbiAgICAvLyAgICAgICAgICAgICAgICAgaWYgbGlmZSBpcyBlcXVhbCwgbmV0d29ya0Rpc2Nvbm5lY3RcbiAgICAvLyAgICAgICAgICAgICAgICAgaWYgbGlmZSBpcyBncmVhdGVyLCBub2RlQ3Jhc2hlZFxuICAgIHRoaXMuc2VuZFJlcXVlc3QoJ2Nvbm5lY3QnLCB7IHNlc3Npb25JZDogcnBjU2Vzc2lvbklkLCByZWNvbm5lY3Q6IHRydWUgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgaWYgKCEhZXJyb3IpIHtcblxuICAgICAgICBpZiAodGhpcy5pc01hc3Rlck5vZGVDcmFzaGVkKCkpIHtcblxuICAgICAgICAgIGxvZ2dlci53YXJuKCdNYXN0ZXIgTm9kZSBoYXMgY3Jhc2hlZCEnKTtcblxuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgbG9nZ2VyLmVycm9yKGVycm9yKTtcblxuICAgICAgICAgIGNvbnN0IG5vdGlmeUxvc3RDb25uZWN0aW9uID0gKHJlYXNvbiwgZXJyb3JNc2cpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGVycm9yTXNnKTtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vbkxvc3RDb25uZWN0aW9uKHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmpzb25ScGNDbGllbnQuY2xvc2UoNDEwMSwgXCJSZWNvbm5lY3Rpb24gZmF1bHQ6IFwiICsgZXJyb3JNc2cpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJwY1Nlc3Npb25TdGF0dXMgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5saWZlID09PSAtMSkge1xuICAgICAgICAgICAgICAvLyBTaW5nbGUgTWFzdGVyXG4gICAgICAgICAgICAgIG5vdGlmeUxvc3RDb25uZWN0aW9uKCduZXR3b3JrRGlzY29ubmVjdCcsICdXUyBzdWNjZXNzZnVsbHkgcmVjb25uZWN0ZWQgYnV0IHRoZSB1c2VyIHdhcyBhbHJlYWR5IGV2aWN0ZWQgZHVlIHRvIHRpbWVvdXQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIE11bHRpIE1hc3RlclxuICAgICAgICAgICAgICAvLyBUaGlzIFJQQyBtZXRob2QgaXMgb25seSByZXF1aXJlZCB0byBmaW5kIG91dCB0aGUgcmVhc29uIG9mIHRoZSBkaXNjb25uZWN0aW9uOlxuICAgICAgICAgICAgICAvLyB3aGV0aGVyIHRoZSBjbGllbnQgbG9zdCBpdHMgbmV0d29yayBjb25uZWN0aW9uIG9yIGEgTWFzdGVyIE5vZGUgY3Jhc2hlZFxuICAgICAgICAgICAgICB0aGlzLnNlbmRSZXF1ZXN0KCdzZXNzaW9uU3RhdHVzJywgeyBzZXNzaW9uSWQ6IHRoaXMuc2Vzc2lvbi5zZXNzaW9uSWQgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBjaGVja2luZyBzZXNzaW9uIHN0YXR1cycsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubGlmZSA9PT0gcmVzcG9uc2UubGlmZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlmZSBzdG9yZWQgaW4gdGhlIGNsaWVudCBtYXRjaGVzIHRoZSBsaWZlIHN0b3JlZCBpbiB0aGUgc2VydmVyLCBpdCBtZWFucyB0aGF0IHRoZSBjbGllbnQgbG9zdCBpdHMgbmV0d29yayBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIG5vdGlmeUxvc3RDb25uZWN0aW9uKCduZXR3b3JrRGlzY29ubmVjdCcsICdXUyBzdWNjZXNzZnVsbHkgcmVjb25uZWN0ZWQgYnV0IHRoZSB1c2VyIHdhcyBhbHJlYWR5IGV2aWN0ZWQgZHVlIHRvIHRpbWVvdXQnKTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsaWZlIHN0b3JlZCBpbiB0aGUgY2xpZW50IGlzIGJlbG93IHRoZSBsaWZlIHN0b3JlZCBpbiB0aGUgc2VydmVyLCBpdCBtZWFucyB0aGF0IHRoZSBNYXN0ZXIgTm9kZSBoYXMgY3Jhc2hlZFxuICAgICAgICAgICAgICAgICAgICBub3RpZnlMb3N0Q29ubmVjdGlvbignbm9kZUNyYXNoZWQnLCAnV1Mgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdGVkIHRvIE9wZW5WaWR1IFNlcnZlciBidXQgeW91ciBNYXN0ZXIgTm9kZSBjcmFzaGVkJyk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMDA3ICYmIGVycm9yLm1lc3NhZ2UgPT09ICdyZWNvbm5lY3Rpb24gZXJyb3InKSB7XG4gICAgICAgICAgICAvLyBLdXJlbnRvIGVycm9yOiBpbnZhbGlkIFJQQyBzZXNzaW9uSWQuIFRoaXMgbWVhbnMgdGhhdCB0aGUga3VyZW50by1qc29ucnBjLXNlcnZlciBvZiBvcGVudmlkdS1zZXJ2ZXIgd2hlcmUga3VyZW50by1qc29ucnBjLWNsaWVudFxuICAgICAgICAgICAgLy8gaXMgdHJ5aW5nIHRvIHJlY29ubmVjdCBkb2VzIG5vdCBrbm93IGFib3V0IHRoaXMgc2Vzc2lvbklkLiBUaGlzIGNhbiBtZWFuIHR3byB0aGluZ3M6IFxuICAgICAgICAgICAgLy8gMSkgb3BlbnZpZHUtYnJvd3NlciBtYW5hZ2VkIHRvIHJlY29ubmVjdCBhZnRlciBhIHdoaWxlLCBidXQgb3BlbnZpZHUtc2VydmVyIGFscmVhZHkgZXZpY3RlZCB0aGUgdXNlciBmb3Igbm90IHJlY2VpdmluZyBwaW5nLlxuICAgICAgICAgICAgLy8gMikgb3BlbnZpZHUtc2VydmVyIHByb2Nlc3MgaXMgYSBkaWZmZXJlbnQgb25lIGJlY2F1c2Ugb2YgYSBub2RlIGNyYXNoLlxuICAgICAgICAgICAgLy8gU2VuZCBhIFwic2Vzc2lvblN0YXR1c1wiIG1ldGhvZCB0byBjaGVjayB0aGUgcmVhc29uXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdJbnZhbGlkIFJQQyBzZXNzaW9uSWQuIENsaWVudCBuZXR3b3JrIGRpc2Nvbm5lY3Rpb24gb3IgTWFzdGVyIE5vZGUgY3Jhc2gnKTtcbiAgICAgICAgICAgIHJwY1Nlc3Npb25TdGF0dXMoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcnBjU2Vzc2lvblN0YXR1cygpO1xuICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmpzb25ScGNDbGllbnQucmVzZXRQaW5nKCk7XG4gICAgICAgIHRoaXMuc2Vzc2lvbi5vblJlY292ZXJlZENvbm5lY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgcmVjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBsb2dnZXIud2FybignV2Vic29ja2V0IHJlY29ubmVjdGVkJyk7XG4gICAgaWYgKHRoaXMuaXNSb29tQXZhaWxhYmxlKCkpIHtcbiAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi5jb25uZWN0aW9uKSB7XG4gICAgICAgIHRoaXMucmVjb25uZWN0V2Vic29ja2V0VGhyb3VnaFJwY0Nvbm5lY3RNZXRob2QodGhpcy5zZXNzaW9uLmNvbm5lY3Rpb24ucnBjU2Vzc2lvbklkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdUaGVyZSB3YXMgbm8gcHJldmlvdXMgY29ubmVjdGlvbiB3aGVuIHJ1bm5pbmcgcmVjb25uZWN0aW9uIGNhbGxiYWNrJyk7XG4gICAgICAgIC8vIE1ha2UgU2Vzc2lvbiBvYmplY3QgZGlzcGF0Y2ggJ3Nlc3Npb25EaXNjb25uZWN0ZWQnIGV2ZW50XG4gICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgJ25ldHdvcmtEaXNjb25uZWN0Jyk7XG4gICAgICAgIHRoaXMuc2Vzc2lvbi5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICBzZXNzaW9uRGlzY29ubmVjdEV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYWxlcnQoJ0Nvbm5lY3Rpb24gZXJyb3IuIFBsZWFzZSByZWxvYWQgcGFnZS4nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzTWFzdGVyTm9kZUNyYXNoZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMubWFzdGVyTm9kZUhhc0NyYXNoZWQ7XG4gIH1cblxuICBwcml2YXRlIGlzUm9vbUF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5zZXNzaW9uICE9PSB1bmRlZmluZWQgJiYgdGhpcy5zZXNzaW9uIGluc3RhbmNlb2YgU2Vzc2lvbikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci53YXJuKCdTZXNzaW9uIGluc3RhbmNlIG5vdCBmb3VuZCcpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNTY3JlZW5TaGFyZSh2aWRlb1NvdXJjZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHZpZGVvU291cmNlID09PSAnc2NyZWVuJyB8fFxuICAgICAgdmlkZW9Tb3VyY2UgPT09ICd3aW5kb3cnIHx8XG4gICAgICAocGxhdGZvcm0uaXNFbGVjdHJvbigpICYmIHZpZGVvU291cmNlLnN0YXJ0c1dpdGgoJ3NjcmVlbjonKSlcbiAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgT3BlblZpZHUgfSBmcm9tICcuL09wZW5WaWR1JztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuL1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBQdWJsaXNoZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9QdWJsaXNoZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IFB1Ymxpc2hlckV2ZW50TWFwIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRXZlbnRNYXAvUHVibGlzaGVyRXZlbnRNYXAnO1xuaW1wb3J0IHsgU3RyZWFtRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TdHJlYW1FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlscyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0nO1xuaW1wb3J0IHsgVHlwZU9mVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0VudW1zL1R5cGVPZlZpZGVvJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG4vKipcbiAqIFBhY2tzIGxvY2FsIG1lZGlhIHN0cmVhbXMuIFBhcnRpY2lwYW50cyBjYW4gcHVibGlzaCBpdCB0byBhIHNlc3Npb24uIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kLlxuICpcbiAqIFNlZSBhdmFpbGFibGUgZXZlbnQgbGlzdGVuZXJzIGF0IFtbUHVibGlzaGVyRXZlbnRNYXBdXS5cbiAqL1xuZXhwb3J0IGNsYXNzIFB1Ymxpc2hlciBleHRlbmRzIFN0cmVhbU1hbmFnZXIge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIGdyYW50ZWQgYWNjZXNzIHRvIHRoZSByZXF1ZXN0ZWQgaW5wdXQgZGV2aWNlcyBvciBub3RcbiAgICAgKi9cbiAgICBhY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHlvdSBoYXZlIGNhbGxlZCBbW1B1Ymxpc2hlci5zdWJzY3JpYmVUb1JlbW90ZV1dIHdpdGggdmFsdWUgYHRydWVgIG9yIGBmYWxzZWAgKCpmYWxzZSogYnkgZGVmYXVsdClcbiAgICAgKi9cbiAgICBpc1N1YnNjcmliZWRUb1JlbW90ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIHRvIHdoaWNoIHRoZSBQdWJsaXNoZXIgYmVsb25nc1xuICAgICAqL1xuICAgIHNlc3Npb246IFNlc3Npb247IC8vIEluaXRpYWxpemVkIGJ5IFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpXG5cbiAgICBwcml2YXRlIGFjY2Vzc0RlbmllZCA9IGZhbHNlO1xuICAgIHByb3RlY3RlZCBwcm9wZXJ0aWVzOiBQdWJsaXNoZXJQcm9wZXJ0aWVzO1xuICAgIHByaXZhdGUgcGVybWlzc2lvbkRpYWxvZ1RpbWVvdXQ6IE5vZGVKUy5UaW1lcjtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHZpZGVvUmVmZXJlbmNlOiBIVE1MVmlkZW9FbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsOiBOb2RlSlMuVGltZXI7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogUHVibGlzaGVyUHJvcGVydGllcywgb3BlbnZpZHU6IE9wZW5WaWR1KSB7XG4gICAgICAgIHN1cGVyKG5ldyBTdHJlYW0oKCEhb3BlbnZpZHUuc2Vzc2lvbikgPyBvcGVudmlkdS5zZXNzaW9uIDogbmV3IFNlc3Npb24ob3BlbnZpZHUpLCB7IHB1Ymxpc2hlclByb3BlcnRpZXM6IHByb3BlcnRpZXMsIG1lZGlhQ29uc3RyYWludHM6IHt9IH0pLCB0YXJnRWwpO1xuICAgICAgICBwbGF0Zm9ybSA9IFBsYXRmb3JtVXRpbHMuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICAgICAgdGhpcy5vcGVudmlkdSA9IG9wZW52aWR1O1xuXG4gICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgKHJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBzdHJlYW1FdmVudCA9IG5ldyBTdHJlYW1FdmVudCh0cnVlLCB0aGlzLCAnc3RyZWFtRGVzdHJveWVkJywgdGhpcy5zdHJlYW0sIHJlYXNvbik7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUHVibGlzaCBvciB1bnB1Ymxpc2ggdGhlIGF1ZGlvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgYGVuYWJsZWRgIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqID4gX09ubHkgaWYgYFNlc3Npb24ucHVibGlzaChQdWJsaXNoZXIpYCBoYXMgYmVlbiBjYWxsZWQgZm9yIHRoaXMgUHVibGlzaGVyX1xuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcImF1ZGlvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaEF1ZGlvXCJgXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCBldmVudCB3aXRoIGBjaGFuZ2VkUHJvcGVydHlgIHNldCB0byBgXCJhdWRpb0FjdGl2ZVwiYCBhbmQgYHJlYXNvbmAgc2V0IHRvIGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIFRoZSByZXNwZWN0aXZlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCByZWNlaXZpbmcgdGhpcyBQdWJsaXNoZXIncyBzdHJlYW0gd2lsbCBhbHNvIGRpc3BhdGNoIHRoZSBleGFjdCBzYW1lIGV2ZW50XG4gICAgICpcbiAgICAgKiBTZWUgW1tTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW5hYmxlZCBgdHJ1ZWAgdG8gcHVibGlzaCB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVucHVibGlzaCBpdFxuICAgICAqL1xuICAgIHB1Ymxpc2hBdWRpbyhlbmFibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gZW5hYmxlZCkge1xuICAgICAgICAgICAgY29uc3QgYWZmZWN0ZWRNZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0gPSB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSA/IHRoaXMuc3RyZWFtLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlISA6IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICBhZmZlY3RlZE1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gZW5hYmxlZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uICYmICEhdGhpcy5zdHJlYW0uc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZDogdGhpcy5zdHJlYW0uc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ2F1ZGlvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiBlbmFibGVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAncHVibGlzaEF1ZGlvJ1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMuc3RyZWFtLCAnYXVkaW9BY3RpdmUnLCBlbmFibGVkLCAhZW5hYmxlZCwgJ3B1Ymxpc2hBdWRpbycpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICdhdWRpb0FjdGl2ZScsIGVuYWJsZWQsICFlbmFibGVkLCAncHVibGlzaEF1ZGlvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YSh0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA9IGVuYWJsZWQ7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArIChlbmFibGVkID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIGF1ZGlvIHN0cmVhbScpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIG9yIHVucHVibGlzaCB0aGUgdmlkZW8gc3RyZWFtIChpZiBhdmFpbGFibGUpLiBDYWxsaW5nIHRoaXMgbWV0aG9kIHR3aWNlIGluIGEgcm93IHBhc3Npbmcgc2FtZSBgZW5hYmxlZGAgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogPiBfT25seSBpZiBgU2Vzc2lvbi5wdWJsaXNoKFB1Ymxpc2hlcilgIGhhcyBiZWVuIGNhbGxlZCBmb3IgdGhpcyBQdWJsaXNoZXJfXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVByb3BlcnR5Q2hhbmdlZGAgZXZlbnQgd2l0aCBgY2hhbmdlZFByb3BlcnR5YCBzZXQgdG8gYFwidmlkZW9BY3RpdmVcImAgYW5kIGByZWFzb25gIHNldCB0byBgXCJwdWJsaXNoVmlkZW9cImBcbiAgICAgKiBUaGUgW1tQdWJsaXNoZXJdXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCB0aGUgZXhhY3Qgc2FtZSBldmVudFxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1Qcm9wZXJ0eUNoYW5nZWRgIGV2ZW50IHdpdGggYGNoYW5nZWRQcm9wZXJ0eWAgc2V0IHRvIGBcInZpZGVvQWN0aXZlXCJgIGFuZCBgcmVhc29uYCBzZXQgdG8gYFwicHVibGlzaFZpZGVvXCJgXG4gICAgICogVGhlIHJlc3BlY3RpdmUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IHJlY2VpdmluZyB0aGlzIFB1Ymxpc2hlcidzIHN0cmVhbSB3aWxsIGFsc28gZGlzcGF0Y2ggdGhlIGV4YWN0IHNhbWUgZXZlbnRcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbmFibGVkIGB0cnVlYCB0byBwdWJsaXNoIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5wdWJsaXNoIGl0XG4gICAgICogQHBhcmFtIHJlc291cmNlXG4gICAgICogLSBJZiBwYXJhbWV0ZXIgKipgZW5hYmxlZGAqKiBpcyBgZmFsc2VgLCB0aGlzIG9wdGlvbmFsIHBhcmFtZXRlciBpcyBvZiB0eXBlIGJvb2xlYW4uIEl0IGNhbiBiZSBzZXQgdG8gYHRydWVgIHRvIGZvcmNpYmx5IGZyZWUgdGhlIGhhcmR3YXJlIHJlc291cmNlIGFzc29jaWF0ZWQgdG8gdGhlIHZpZGVvIHRyYWNrLCBvciBjYW4gYmUgc2V0IHRvIGBmYWxzZWAgdG8ga2VlcCB0aGUgYWNjZXNzIHRvIHRoZSBoYXJkd2FyZSByZXNvdXJjZS5cbiAgICAgKiBOb3QgZnJlZWluZyB0aGUgcmVzb3VyY2UgbWFrZXMgdGhlIG9wZXJhdGlvbiBtdWNoIG1vcmUgZWZmaWNpZW50LCBidXQgZGVwZW5kaW5nIG9uIHRoZSBwbGF0Zm9ybSB0d28gc2lkZS1lZmZlY3RzIGNhbiBiZSBpbnRyb2R1Y2VkOiB0aGUgdmlkZW8gZGV2aWNlIG1heSBub3QgYmUgYWNjZXNzaWJsZSBieSBvdGhlciBhcHBsaWNhdGlvbnMgYW5kIHRoZSBhY2Nlc3MgbGlnaHQgb2ZcbiAgICAgKiB3ZWJjYW1zIG1heSByZW1haW4gb24uIFRoaXMgaXMgcGxhdGZvcm0tZGVwZW5kZW50OiBzb21lIGJyb3dzZXJzIHdpbGwgbm90IHByZXNlbnQgdGhlIHNpZGUtZWZmZWN0cyBldmVuIHdoZW4gbm90IGZyZWVpbmcgdGhlIHJlc291cmNlLjwvbGk+XG4gICAgICogLSBJZiBwYXJhbWV0ZXIgKipgZW5hYmxlZGAqKiBpcyBgdHJ1ZWAsIHRoaXMgb3B0aW9uYWwgcGFyYW1ldGVyIGlzIG9mIHR5cGUgW01lZGlhU3RyZWFtVHJhY2tdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9NZWRpYVN0cmVhbVRyYWNrKS4gSXQgY2FuIGJlIHNldCB0byBmb3JjZSB0aGUgcmVzdG9yYXRpb24gb2YgdGhlIHZpZGVvIHRyYWNrIHdpdGggYSBjdXN0b20gdHJhY2suIFRoaXMgbWF5IGJlXG4gICAgICogdXNlZnVsIGlmIHRoZSBQdWJsaXNoZXIgd2FzIHVucHVibGlzaGVkIGZyZWVpbmcgdGhlIGhhcmR3YXJlIHJlc291cmNlLCBhbmQgb3BlbnZpZHUtYnJvd3NlciBpcyBub3QgYWJsZSB0byBzdWNjZXNzZnVsbHkgcmUtY3JlYXRlIHRoZSB2aWRlbyB0cmFjayBhcyBpdCB3YXMgYmVmb3JlIHVucHVibGlzaGluZy4gSW4gdGhpcyB3YXkgcHJldmlvdXMgdHJhY2sgc2V0dGluZ3Mgd2lsbCBiZSBpZ25vcmVkIGFuZCB0aGlzIE1lZGlhU3RyZWFtVHJhY2tcbiAgICAgKiB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cbiAgICAgKi9cbiAgICBwdWJsaXNoVmlkZW88VCBleHRlbmRzIGJvb2xlYW4+KGVuYWJsZWQ6IFQsIHJlc291cmNlPzogVCBleHRlbmRzIGZhbHNlID8gYm9vbGVhbiA6IE1lZGlhU3RyZWFtVHJhY2spOiBQcm9taXNlPHZvaWQ+IHtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0udmlkZW9BY3RpdmUgIT09IGVuYWJsZWQpIHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGFmZmVjdGVkTWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtID0gdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgPyB0aGlzLnN0cmVhbS5sb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZSEgOiB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgIGxldCBtdXN0UmVzdGFydE1lZGlhU3RyZWFtID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYWZmZWN0ZWRNZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWVuYWJsZWQgJiYgcmVzb3VyY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlbmFibGVkICYmIHRyYWNrLnJlYWR5U3RhdGUgPT09ICdlbmRlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlc291cmNlIHdhcyBmcmVlZFxuICAgICAgICAgICAgICAgICAgICAgICAgbXVzdFJlc3RhcnRNZWRpYVN0cmVhbSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIGEgVmlydHVhbCBCYWNrZ3JvdW5kIGZpbHRlciBhcHBsaWVkIHRoYXQgbXVzdCBiZSByZW1vdmVkIGluIGNhc2UgdGhlIGhhcmR3YXJlIG11c3QgYmUgZnJlZWQgXG4gICAgICAgICAgICAgICAgaWYgKCFlbmFibGVkICYmIHJlc291cmNlID09PSB0cnVlICYmICEhdGhpcy5zdHJlYW0uZmlsdGVyICYmIHRoaXMuc3RyZWFtLmZpbHRlci50eXBlLnN0YXJ0c1dpdGgoJ1ZCOicpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmxhc3RWQkZpbHRlciA9IHRoaXMuc3RyZWFtLmZpbHRlcjsgLy8gU2F2ZSB0aGUgZmlsdGVyIHRvIGJlIHJlLWFwcGxpZWQgaW4gY2FzZSBvZiB1bm11dGVcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdHJlYW0ucmVtb3ZlRmlsdGVyQXV4KHRydWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChtdXN0UmVzdGFydE1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZFZpZGVvVHJhY2sgPSBhZmZlY3RlZE1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgICAgICAgICAgICAgICAgIGFmZmVjdGVkTWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sob2xkVmlkZW9UcmFjayk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVwbGFjZVZpZGVvVHJhY2sgPSBhc3luYyAodHI6IE1lZGlhU3RyZWFtVHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFmZmVjdGVkTWVkaWFTdHJlYW0uYWRkVHJhY2sodHIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlcGxhY2VUcmFja0luUnRjUnRwU2VuZGVyKHRyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMuc3RyZWFtLmxhc3RWQkZpbHRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucyA9IHRoaXMuc3RyZWFtLmxhc3RWQkZpbHRlciEub3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFzdEV4ZWNNZXRob2QgPSB0aGlzLnN0cmVhbS5sYXN0VkJGaWx0ZXIhLmxhc3RFeGVjTWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFsYXN0RXhlY01ldGhvZCAmJiBsYXN0RXhlY01ldGhvZC5tZXRob2QgPT09ICd1cGRhdGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgb3B0aW9ucywgbGFzdEV4ZWNNZXRob2QucGFyYW1zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnN0cmVhbS5hcHBseUZpbHRlcih0aGlzLnN0cmVhbS5sYXN0VkJGaWx0ZXIhLnR5cGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW0ubGFzdFZCRmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVzb3VyY2UgJiYgcmVzb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCByZXBsYWNlVmlkZW9UcmFjayhyZXNvdXJjZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lZGlhU3RyZWFtID0gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoeyBhdWRpbzogZmFsc2UsIHZpZGVvOiB0aGlzLnN0cmVhbS5sYXN0VmlkZW9UcmFja0NvbnN0cmFpbnRzIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHJlcGxhY2VWaWRlb1RyYWNrKG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbiAmJiAhIXRoaXMuc3RyZWFtLnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAgICAgICAgICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkOiB0aGlzLnN0cmVhbS5zdHJlYW1JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eTogJ3ZpZGVvQWN0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogZW5hYmxlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFzb246ICdwdWJsaXNoVmlkZW8nXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBzZW5kaW5nICdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc2Vzc2lvbiwgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIGVuYWJsZWQsICFlbmFibGVkLCAncHVibGlzaFZpZGVvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQodGhpcywgdGhpcy5zdHJlYW0sICd2aWRlb0FjdGl2ZScsIGVuYWJsZWQsICFlbmFibGVkLCAncHVibGlzaFZpZGVvJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLnNlbmRWaWRlb0RhdGEodGhpcy5zdHJlYW0uc3RyZWFtTWFuYWdlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvQWN0aXZlID0gZW5hYmxlZDtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIidQdWJsaXNoZXInIGhhcyBcIiArIChlbmFibGVkID8gJ3B1Ymxpc2hlZCcgOiAndW5wdWJsaXNoZWQnKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGlzIG1ldGhvZCBiZWZvcmUgW1tTZXNzaW9uLnB1Ymxpc2hdXSBpZiB5b3UgcHJlZmVyIHRvIHN1YnNjcmliZSB0byB5b3VyIFB1Ymxpc2hlcidzIHJlbW90ZSBzdHJlYW0gaW5zdGVhZCBvZiB1c2luZyB0aGUgbG9jYWwgc3RyZWFtLCBhcyBhbnkgb3RoZXIgdXNlciB3b3VsZCBkby5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb1JlbW90ZSh2YWx1ZT86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdmFsdWUgPSAodmFsdWUgIT09IHVuZGVmaW5lZCkgPyB2YWx1ZSA6IHRydWU7XG4gICAgICAgIHRoaXMuaXNTdWJzY3JpYmVkVG9SZW1vdGUgPSB2YWx1ZTtcbiAgICAgICAgdGhpcy5zdHJlYW0uc3Vic2NyaWJlVG9NeVJlbW90ZSh2YWx1ZSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uPEsgZXh0ZW5kcyBrZXlvZiBQdWJsaXNoZXJFdmVudE1hcD4odHlwZTogSywgaGFuZGxlcjogKGV2ZW50OiBQdWJsaXNoZXJFdmVudE1hcFtLXSkgPT4gdm9pZCk6IHRoaXMge1xuXG4gICAgICAgIHN1cGVyLm9uKDxhbnk+dHlwZSwgaGFuZGxlcik7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1DcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVB1Ymxpc2hlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLm9uKCdzdHJlYW0tY3JlYXRlZC1ieS1wdWJsaXNoZXInLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdzdHJlYW1DcmVhdGVkJywgW25ldyBTdHJlYW1FdmVudChmYWxzZSwgdGhpcywgJ3N0cmVhbUNyZWF0ZWQnLCB0aGlzLnN0cmVhbSwgJycpXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhY2Nlc3NBbGxvd2VkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NBbGxvd2VkJywgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzRGVuaWVkJykge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWNjZXNzRGVuaWVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ2FjY2Vzc0RlbmllZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbmNlXV1cbiAgICAgKi9cbiAgICBvbmNlPEsgZXh0ZW5kcyBrZXlvZiBQdWJsaXNoZXJFdmVudE1hcD4odHlwZTogSywgaGFuZGxlcjogKGV2ZW50OiBQdWJsaXNoZXJFdmVudE1hcFtLXSkgPT4gdm9pZCk6IHRoaXMge1xuXG4gICAgICAgIHN1cGVyLm9uY2UoPGFueT50eXBlLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUNyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0RXZlbnQoJ3N0cmVhbUNyZWF0ZWQnLCBbbmV3IFN0cmVhbUV2ZW50KGZhbHNlLCB0aGlzLCAnc3RyZWFtQ3JlYXRlZCcsIHRoaXMuc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUub25jZSgnc3RyZWFtLWNyZWF0ZWQtYnktcHVibGlzaGVyJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgdGhpcy5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSAnYWNjZXNzQWxsb3dlZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0FsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzQWxsb3dlZCcsIFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FjY2Vzc0RlbmllZCcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmFjY2Vzc0RlbmllZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEV2ZW50KCdhY2Nlc3NEZW5pZWQnLCBbXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmY8SyBleHRlbmRzIGtleW9mIFB1Ymxpc2hlckV2ZW50TWFwPih0eXBlOiBLLCBoYW5kbGVyPzogKGV2ZW50OiBQdWJsaXNoZXJFdmVudE1hcFtLXSkgPT4gdm9pZCk6IHRoaXMge1xuICAgICAgICBzdXBlci5vZmYoPGFueT50eXBlLCBoYW5kbGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgY3VycmVudCB2aWRlbyBvciBhdWRpbyB0cmFjayB3aXRoIGEgZGlmZmVyZW50IG9uZS4gVGhpcyBhbGxvd3MgeW91IHRvIHJlcGxhY2UgYW4gb25nb2luZyB0cmFjayB3aXRoIGEgZGlmZmVyZW50IG9uZVxuICAgICAqIHdpdGhvdXQgaGF2aW5nIHRvIHJlbmVnb3RpYXRlIHRoZSB3aG9sZSBXZWJSVEMgY29ubmVjdGlvbiAodGhhdCBpcywgaW5pdGlhbGl6aW5nIGEgbmV3IFB1Ymxpc2hlciwgdW5wdWJsaXNoaW5nIHRoZSBwcmV2aW91cyBvbmVcbiAgICAgKiBhbmQgcHVibGlzaGluZyB0aGUgbmV3IG9uZSkuXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIGdldCB0aGlzIG5ldyBNZWRpYVN0cmVhbVRyYWNrIGJ5IHVzaW5nIHRoZSBuYXRpdmUgV2ViIEFQSSBvciBzaW1wbHkgd2l0aCBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dIG1ldGhvZC5cbiAgICAgKlxuICAgICAqICoqV0FSTklORzogdGhpcyBtZXRob2QgaGFzIGJlZW4gcHJvdmVuIHRvIHdvcmsgaW4gdGhlIG1ham9yaXR5IG9mIGNhc2VzLCBidXQgdGhlcmUgbWF5IGJlIHNvbWUgY29tYmluYXRpb25zIG9mIHB1Ymxpc2hlZC9yZXBsYWNlZCB0cmFja3MgdGhhdCBtYXkgYmUgaW5jb21wYXRpYmxlXG4gICAgICogYmV0d2VlbiB0aGVtIGFuZCBicmVhayB0aGUgY29ubmVjdGlvbiBpbiBPcGVuVmlkdSBTZXJ2ZXIuIEEgY29tcGxldGUgcmVuZWdvdGlhdGlvbiBtYXkgYmUgdGhlIG9ubHkgc29sdXRpb24gaW4gdGhpcyBjYXNlLlxuICAgICAqIFZpc2l0IFtSVENSdHBTZW5kZXIucmVwbGFjZVRyYWNrXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUlRDUnRwU2VuZGVyL3JlcGxhY2VUcmFjaykgZG9jdW1lbnRhdGlvbiBmb3IgZnVydGhlciBkZXRhaWxzLioqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdHJhY2sgVGhlIFtNZWRpYVN0cmVhbVRyYWNrXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTWVkaWFTdHJlYW1UcmFjaykgb2JqZWN0IHRvIHJlcGxhY2UgdGhlIGN1cnJlbnQgb25lLlxuICAgICAqIElmIGl0IGlzIGFuIGF1ZGlvIHRyYWNrLCB0aGUgY3VycmVudCBhdWRpbyB0cmFjayB3aWxsIGJlIHRoZSByZXBsYWNlZCBvbmUuIElmIGl0IGlzIGEgdmlkZW8gdHJhY2ssIHRoZSBjdXJyZW50IHZpZGVvIHRyYWNrIHdpbGwgYmUgdGhlIHJlcGxhY2VkIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBpZiB0aGUgdHJhY2sgd2FzIHN1Y2Nlc3NmdWxseSByZXBsYWNlZCBhbmQgcmVqZWN0ZWQgd2l0aCBhbiBFcnJvciBvYmplY3QgaW4gb3RoZXIgY2FzZVxuICAgICAqL1xuICAgIGFzeW5jIHJlcGxhY2VUcmFjayh0cmFjazogTWVkaWFTdHJlYW1UcmFjayk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXBsYWNlVHJhY2tBdXgodHJhY2ssIHRydWUpO1xuICAgIH1cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgbGV0IGNvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge307XG4gICAgICAgICAgICBsZXQgY29uc3RyYWludHNBdXg6IE1lZGlhU3RyZWFtQ29uc3RyYWludHMgPSB7fTtcbiAgICAgICAgICAgIGNvbnN0IHRpbWVGb3JEaWFsb2dFdmVudCA9IDIwMDA7XG4gICAgICAgICAgICBsZXQgc3RhcnRUaW1lO1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckNhbGxiYWNrID0gKG9wZW5WaWR1RXJyb3I6IE9wZW5WaWR1RXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0RlbmllZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hY2Nlc3NBbGxvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBQdWJsaXNoZXIgaW5pdGlhbGl6YXRpb24gZmFpbGVkLiAke29wZW5WaWR1RXJyb3IubmFtZX06ICR7b3BlblZpZHVFcnJvci5tZXNzYWdlfWApXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDYWxsYmFjayA9IChtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmFjY2Vzc0FsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYWNjZXNzRGVuaWVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy5hdWRpb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMuYXVkaW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMucHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2sobWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZFRyYWNrKCg8TWVkaWFTdHJlYW1UcmFjaz50aGlzLnByb3BlcnRpZXMudmlkZW9Tb3VyY2UpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBBcHBseSBQdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hBdWRpbyBhbmQgUHVibGlzaGVyUHJvcGVydGllcy5wdWJsaXNoVmlkZW9cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS5hdWRpb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISFtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZWQgPSAodGhpcy5zdHJlYW0udmlkZW9BY3RpdmUgIT09IHVuZGVmaW5lZCAmJiB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSAhPT0gbnVsbCkgPyB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA6ICEhdGhpcy5zdHJlYW0ub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaFZpZGVvO1xuICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFNldCBDb250ZW50IEhpbnQgb24gYWxsIE1lZGlhU3RyZWFtVHJhY2tzXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0cmFjayBvZiBtZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdHJhY2suY29udGVudEhpbnQ/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29udGVudEhpbnQgZm9yIGF1ZGlvOiBcIlwiLCBcInNwZWVjaFwiLCBcInNwZWVjaC1yZWNvZ25pdGlvblwiLCBcIm11c2ljXCIuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBodHRwczovL3czYy5naXRodWIuaW8vbXN0LWNvbnRlbnQtaGludC8jYXVkaW8tY29udGVudC1oaW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suY29udGVudEhpbnQgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBBdWRpbyB0cmFjayBDb250ZW50IEhpbnQgc2V0OiAnJHt0cmFjay5jb250ZW50SGludH0nYCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCB0cmFjayBvZiBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdHJhY2suY29udGVudEhpbnQ/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29udGVudEhpbnQgZm9yIHZpZGVvOiBcIlwiLCBcIm1vdGlvblwiLCBcImRldGFpbFwiLCBcInRleHRcIi5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vdzNjLmdpdGh1Yi5pby9tc3QtY29udGVudC1oaW50LyN2aWRlby1jb250ZW50LWhpbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc3RyZWFtLnR5cGVPZlZpZGVvKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBUeXBlT2ZWaWRlby5TQ1JFRU46XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLmNvbnRlbnRIaW50ID0gXCJkZXRhaWxcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBUeXBlT2ZWaWRlby5DVVNUT006XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiQ1VTVE9NIHR5cGUgdmlkZW8gdHJhY2sgd2FzIHByb3ZpZGVkIHdpdGhvdXQgQ29udGVudCBIaW50IVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suY29udGVudEhpbnQgPSBcIm1vdGlvblwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFR5cGVPZlZpZGVvLkNBTUVSQTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFR5cGVPZlZpZGVvLklQQ0FNOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLmNvbnRlbnRIaW50ID0gXCJtb3Rpb25cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgVmlkZW8gdHJhY2sgQ29udGVudCBIaW50IHNldDogJyR7dHJhY2suY29udGVudEhpbnR9J2ApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9SZWZlcmVuY2UobWVkaWFTdHJlYW0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBzdWJzY3JpYmVkIHRvIG91ciByZW1vdGUgd2UgZG9uJ3Qgc3RpbGwgc2V0IHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaW4gdGhlIHZpZGVvIGVsZW1lbnRzIHRvXG4gICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkIGVhcmx5ICdzdHJlYW1QbGF5aW5nJyBldmVudFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS51cGRhdGVNZWRpYVN0cmVhbUluVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpcnN0VmlkZW9FbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFZpZGVvKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFzIHZpZGVvIHRyYWNrXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0VmlkZW9EaW1lbnNpb25zKCkudGhlbihkaW1lbnNpb25zID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogZGltZW5zaW9ucy53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGRpbWVuc2lvbnMuaGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgaW50ZXJ2YWwgdG8gbGlzdGVuIGZvciBzY3JlZW4gcmVzaXplIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyZWVuU2hhcmVSZXNpemVJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2V0dGluZ3M6IE1lZGlhVHJhY2tTZXR0aW5ncyA9IG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3V2lkdGggPSBzZXR0aW5ncy53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3SGVpZ2h0ID0gc2V0dGluZ3MuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aENoYW5nZWQgPSBuZXdXaWR0aCAhPSBudWxsICYmIG5ld1dpZHRoICE9PSB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodENoYW5nZWQgPSBuZXdIZWlnaHQgIT0gbnVsbCAmJiBuZXdIZWlnaHQgIT09IHRoaXMuc3RyZWFtLnZpZGVvRGltZW5zaW9ucy5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkICYmICh3aWR0aENoYW5nZWQgfHwgaGVpZ2h0Q2hhbmdlZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFZpZGVvRGltZW5zaW9uc0NoYW5nZWRFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzY3JlZW5SZXNpemVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0RpbWVuc2lvbnMud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0udmlkZW9EaW1lbnNpb25zLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdXaWR0aCB8fCAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0hlaWdodCB8fCAwXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgNjUwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVlLmVtaXRFdmVudCgnc3RyZWFtLXJlYWR5LXRvLXB1Ymxpc2gnLCBbXSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgYXVkaW8gdHJhY2sgKG5vIHZpZGVvRGltZW5zaW9ucylcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVhZHktdG8tcHVibGlzaCcsIFtdKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgZ2V0TWVkaWFTdWNjZXNzID0gKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSwgZGVmaW5lZEF1ZGlvQ29uc3RyYWludCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc1NlbmRTY3JlZW4oKSAmJiB0aGlzLnN0cmVhbS5pc1NlbmRBdWRpbygpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gZ2V0dGluZyBkZXNrdG9wIGFzIHVzZXIgbWVkaWEgYXVkaW8gY29uc3RyYWludCBtdXN0IGJlIGZhbHNlLiBOb3cgd2UgY2FuIGFzayBmb3IgaXQgaWYgcmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHNBdXguYXVkaW8gPSBkZWZpbmVkQXVkaW9Db25zdHJhaW50O1xuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c0F1eC52aWRlbyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFBlcm1pc3Npb25EaWFsb2dUaW1lcih0aW1lRm9yRGlhbG9nRXZlbnQpO1xuXG4gICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzQXV4KVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oYXVkaW9Pbmx5U3RyZWFtID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyUGVybWlzc2lvbkRpYWxvZ1RpbWVyKHN0YXJ0VGltZSwgdGltZUZvckRpYWxvZ0V2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5hZGRUcmFjayhhdWRpb09ubHlTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sodGhpcy5vcGVudmlkdS5nZW5lcmF0ZUF1ZGlvRGV2aWNlRXJyb3IoZXJyb3IsIGNvbnN0cmFpbnRzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBnZXRNZWRpYUVycm9yID0gZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgZ2V0TWVkaWFFcnJvcjogJHtlcnJvci50b1N0cmluZygpfWApO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJQZXJtaXNzaW9uRGlhbG9nVGltZXIoc3RhcnRUaW1lLCB0aW1lRm9yRGlhbG9nRXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvci5uYW1lID09PSAnRXJyb3InKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSBPdmVyQ29uc3RyYWluZWRFcnJvciBoYXMgYXMgbmFtZSBwcm9wZXJ0eSAnRXJyb3InIGluc3RlYWQgb2YgJ092ZXJDb25zdHJhaW5lZEVycm9yJ1xuICAgICAgICAgICAgICAgICAgICBlcnJvci5uYW1lID0gZXJyb3IuY29uc3RydWN0b3IubmFtZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZXJyb3IubmFtZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ25vdGZvdW5kZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLklOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2sobmV3IE9wZW5WaWR1RXJyb3IoZXJyb3JOYW1lLCBlcnJvck1lc3NhZ2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RhbGxvd2VkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBPcGVuVmlkdUVycm9yTmFtZS5TQ1JFRU5fQ0FQVFVSRV9ERU5JRUQgOiBPcGVuVmlkdUVycm9yTmFtZS5ERVZJQ0VfQUNDRVNTX0RFTklFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnb3ZlcmNvbnN0cmFpbmVkZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWRlbzogY29uc3RyYWludHMudmlkZW9cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29uc3RyYWludC50b0xvd2VyQ2FzZSgpID09PSAnZGV2aWNlaWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJBdWRpbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMuYXVkaW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIkF1ZGlvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IuY29uc3RyYWludC50b0xvd2VyQ2FzZSgpID09PSAnZGV2aWNlaWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck5hbWUgPSBPcGVuVmlkdUVycm9yTmFtZS5JTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gXCJWaWRlbyBpbnB1dCBkZXZpY2Ugd2l0aCBkZXZpY2VJZCAnXCIgKyAoPENvbnN0cmFpbkRPTVN0cmluZ1BhcmFtZXRlcnM+KDxNZWRpYVRyYWNrQ29uc3RyYWludHM+Y29uc3RyYWludHMudmlkZW8pLmRldmljZUlkISEpLmV4YWN0ICsgXCInIG5vdCBmb3VuZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lID0gT3BlblZpZHVFcnJvck5hbWUuUFVCTElTSEVSX1BST1BFUlRJRVNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBcIlZpZGVvIGlucHV0IGRldmljZSBkb2Vzbid0IHN1cHBvcnQgdGhlIHZhbHVlIHBhc3NlZCBmb3IgY29uc3RyYWludCAnXCIgKyBlcnJvci5jb25zdHJhaW50ICsgXCInXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2Fib3J0ZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdub3RyZWFkYWJsZWVycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkRFVklDRV9BTFJFQURZX0lOX1VTRTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZSA9IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKG5ldyBPcGVuVmlkdUVycm9yKGVycm9yTmFtZSwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yTmFtZSA9IE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1I7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2UgPSBlcnJvci50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDYWxsYmFjayhuZXcgT3BlblZpZHVFcnJvcihlcnJvck5hbWUsIGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmdlbmVyYXRlTWVkaWFDb25zdHJhaW50cyh0aGlzLnByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgLnRoZW4obXlDb25zdHJhaW50cyA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhbXlDb25zdHJhaW50cy52aWRlb1RyYWNrICYmICEhbXlDb25zdHJhaW50cy5hdWRpb1RyYWNrIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAhIW15Q29uc3RyYWludHMuYXVkaW9UcmFjayAmJiBteUNvbnN0cmFpbnRzLmNvbnN0cmFpbnRzPy52aWRlbyA9PT0gZmFsc2UgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICEhbXlDb25zdHJhaW50cy52aWRlb1RyYWNrICYmIG15Q29uc3RyYWludHMuY29uc3RyYWludHM/LmF1ZGlvID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm8gbmVlZCB0byBjYWxsIGdldFVzZXJNZWRpYSBhdCBhbGwuIE1lZGlhU3RyZWFtVHJhY2tzIGFscmVhZHkgcHJvdmlkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayh0aGlzLm9wZW52aWR1LmFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzLCBuZXcgTWVkaWFTdHJlYW0oKSwgdGhpcy5zdHJlYW0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJldHVybiBhcyB3ZSBkbyBub3QgbmVlZCB0byBwcm9jZXNzIGZ1cnRoZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzID0gbXlDb25zdHJhaW50cy5jb25zdHJhaW50cztcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRib3VuZFN0cmVhbU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiBjb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlclByb3BlcnRpZXM6IHRoaXMucHJvcGVydGllc1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5zZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbmVkQXVkaW9Db25zdHJhaW50ID0gKChjb25zdHJhaW50cy5hdWRpbyA9PT0gdW5kZWZpbmVkKSA/IHRydWUgOiBjb25zdHJhaW50cy5hdWRpbyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LmF1ZGlvID0gdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkgPyBmYWxzZSA6IGRlZmluZWRBdWRpb0NvbnN0cmFpbnQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzQXV4LnZpZGVvID0gY29uc3RyYWludHMudmlkZW87XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UGVybWlzc2lvbkRpYWxvZ1RpbWVyKHRpbWVGb3JEaWFsb2dFdmVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmlzU2VuZFNjcmVlbigpICYmIG5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddICYmICFwbGF0Zm9ybS5pc0VsZWN0cm9uKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXNbJ2dldERpc3BsYXlNZWRpYSddKHsgdmlkZW86IHRydWUgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbihtZWRpYVN0cmVhbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuYWRkQWxyZWFkeVByb3ZpZGVkVHJhY2tzKG15Q29uc3RyYWludHMsIG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWVkaWFTdWNjZXNzKG1lZGlhU3RyZWFtLCBkZWZpbmVkQXVkaW9Db25zdHJhaW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldE1lZGlhRXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0ubGFzdFZpZGVvVHJhY2tDb25zdHJhaW50cyA9IGNvbnN0cmFpbnRzQXV4LnZpZGVvO1xuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoY29uc3RyYWludHNBdXgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4obWVkaWFTdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmFkZEFscmVhZHlQcm92aWRlZFRyYWNrcyhteUNvbnN0cmFpbnRzLCBtZWRpYVN0cmVhbSwgdGhpcy5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRNZWRpYVN1Y2Nlc3MobWVkaWFTdHJlYW0sIGRlZmluZWRBdWRpb0NvbnN0cmFpbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TWVkaWFFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcjogT3BlblZpZHVFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFzeW5jIHJlcGxhY2VUcmFja0F1eCh0cmFjazogTWVkaWFTdHJlYW1UcmFjaywgdXBkYXRlTGFzdENvbnN0cmFpbnRzOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIC8vIFNldCBmaWVsZCBcImVuYWJsZWRcIiBvZiB0aGUgbmV3IHRyYWNrIHRvIHRoZSBwcmV2aW91cyB2YWx1ZVxuICAgICAgICBjb25zdCB0cmFja09yaWdpbmFsRW5hYmxlZFZhbHVlOiBib29sZWFuID0gdHJhY2suZW5hYmxlZDtcbiAgICAgICAgaWYgKHRyYWNrLmtpbmQgPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmFjay5raW5kID09PSAnYXVkaW8nKSB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSBpZiB0aGUgUHVibGlzaGVyIGhhcyBiZWVuIHB1Ymxpc2hlZCBpcyBuZWNlc3NhcnkgdG8gY2FsbCBuYXRpdmUgV2ViIEFQSSBSVENSdHBTZW5kZXIucmVwbGFjZVRyYWNrXG4gICAgICAgICAgICAgICAgLy8gSWYgaXQgaGFzIG5vdCBiZWVuIHB1Ymxpc2hlZCB5ZXQsIHJlcGxhY2luZyBpdCBvbiB0aGUgTWVkaWFTdHJlYW0gb2JqZWN0IGlzIGVub3VnaFxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmVwbGFjZVRyYWNrSW5NZWRpYVN0cmVhbSh0cmFjaywgdXBkYXRlTGFzdENvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5yZXBsYWNlVHJhY2tJblJ0Y1J0cFNlbmRlcih0cmFjayk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFB1Ymxpc2hlciBub3QgcHVibGlzaGVkLiBTaW1wbHkgcmVwbGFjZSB0aGUgdHJhY2sgb24gdGhlIGxvY2FsIE1lZGlhU3RyZWFtXG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucmVwbGFjZVRyYWNrSW5NZWRpYVN0cmVhbSh0cmFjaywgdXBkYXRlTGFzdENvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRyYWNrLmVuYWJsZWQgPSB0cmFja09yaWdpbmFsRW5hYmxlZFZhbHVlO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICpcbiAgICAgKiBUbyBvYnRhaW4gdGhlIHZpZGVvRGltZW5zaW9ucyB3ZSB3YWl0IGZvciB0aGUgdmlkZW8gcmVmZXJlbmNlIHRvIGhhdmUgZW5vdWdoIG1ldGFkYXRhXG4gICAgICogYW5kIHRoZW4gdHJ5IHRvIHVzZSBNZWRpYVN0cmVhbVRyYWNrLmdldFNldHRpbmdzTWV0aG9kKCkuIElmIG5vdCBhdmFpbGFibGUsIHRoZW4gd2VcbiAgICAgKiB1c2UgdGhlIEhUTUxWaWRlb0VsZW1lbnQgcHJvcGVydGllcyB2aWRlb1dpZHRoIGFuZCB2aWRlb0hlaWdodFxuICAgICAqL1xuICAgIGdldFZpZGVvRGltZW5zaW9ucygpOiBQcm9taXNlPHsgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIgfT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICAvLyBJb25pYyBpT1MgYW5kIFNhZmFyaSBpT1Mgc3VwcG9zZWRseSByZXF1aXJlIHRoZSB2aWRlbyBlbGVtZW50IHRvIGFjdHVhbGx5IGV4aXN0IGluc2lkZSB0aGUgRE9NXG4gICAgICAgICAgICBjb25zdCByZXF1aXJlc0RvbUluc2VydGlvbjogYm9vbGVhbiA9IHBsYXRmb3JtLmlzSW9uaWNJb3MoKSB8fCBwbGF0Zm9ybS5pc0lPU1dpdGhTYWZhcmkoKTtcblxuICAgICAgICAgICAgbGV0IGxvYWRlZG1ldGFkYXRhTGlzdGVuZXI7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlRGltZW5zaW9ucyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgd2lkdGg6IG51bWJlcjtcbiAgICAgICAgICAgICAgICBsZXQgaGVpZ2h0OiBudW1iZXI7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpLmdldFZpZGVvVHJhY2tzKClbMF0uZ2V0U2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGggPSBzZXR0aW5ncy53aWR0aCB8fCB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHNldHRpbmdzLmhlaWdodCB8fCB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvSGVpZ2h0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdNZWRpYVN0cmVhbVRyYWNrIGRvZXMgbm90IGhhdmUgZ2V0U2V0dGluZ3MgbWV0aG9kIG9uICcgKyBwbGF0Zm9ybS5nZXREZXNjcmlwdGlvbigpKTtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGggPSB0aGlzLnZpZGVvUmVmZXJlbmNlLnZpZGVvV2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IHRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9IZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGxvYWRlZG1ldGFkYXRhTGlzdGVuZXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJywgbG9hZGVkbWV0YWRhdGFMaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZXF1aXJlc0RvbUluc2VydGlvbikge1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHRoaXMudmlkZW9SZWZlcmVuY2UpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9SZWZlcmVuY2UucmVhZHlTdGF0ZSA+PSAxKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHZpZGVvIGFscmVhZHkgaGFzIG1ldGFkYXRhIGF2YWlsYWJsZVxuICAgICAgICAgICAgICAgIC8vIE5vIG5lZWQgb2YgbG9hZGVkbWV0YWRhdGEgZXZlbnRcbiAgICAgICAgICAgICAgICByZXNvbHZlRGltZW5zaW9ucygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgdmlkZW8gZG9lcyBub3QgaGF2ZSBtZXRhZGF0YSBhdmFpbGFibGUgeWV0XG4gICAgICAgICAgICAgICAgLy8gTXVzdCBsaXN0ZW4gdG8gbG9hZGVkbWV0YWRhdGEgZXZlbnRcbiAgICAgICAgICAgICAgICBsb2FkZWRtZXRhZGF0YUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9XaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMudmlkZW9SZWZlcmVuY2UudmlkZW9XaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZURpbWVuc2lvbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCA0MCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlRGltZW5zaW9ucygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWRlZG1ldGFkYXRhJywgbG9hZGVkbWV0YWRhdGFMaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgaWYgKHJlcXVpcmVzRG9tSW5zZXJ0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGhpcy52aWRlb1JlZmVyZW5jZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKSB7XG4gICAgICAgIGlmICh0aGlzLmVlLmdldExpc3RlbmVycygnc3RyZWFtUGxheWluZycpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVZpZGVvUmVmZXJlbmNlKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zZXRBdHRyaWJ1dGUoJ211dGVkJywgJ3RydWUnKTtcbiAgICAgICAgdGhpcy52aWRlb1JlZmVyZW5jZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICBpZiAocGxhdGZvcm0uaXNTYWZhcmlCcm93c2VyKCkgfHwgKHBsYXRmb3JtLmlzSVBob25lT3JJUGFkKCkgJiYgKHBsYXRmb3JtLmlzQ2hyb21lTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWRnZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc09wZXJhTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRmlyZWZveE1vYmlsZUJyb3dzZXIoKSkpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLnNldEF0dHJpYnV0ZSgncGxheXNpbmxpbmUnLCAndHJ1ZScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RyZWFtLnNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgaWYgKCEhdGhpcy5maXJzdFZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5maXJzdFZpZGVvRWxlbWVudC50YXJnZXRFbGVtZW50LCA8VmlkZW9JbnNlcnRNb2RlPnRoaXMucHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZpZGVvUmVmZXJlbmNlLnNyY09iamVjdCA9IG1lZGlhU3RyZWFtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhc3luYyByZXBsYWNlVHJhY2tJbk1lZGlhU3RyZWFtKHRyYWNrOiBNZWRpYVN0cmVhbVRyYWNrLCB1cGRhdGVMYXN0Q29uc3RyYWludHM6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgbWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtID0gdGhpcy5zdHJlYW0uZGlzcGxheU15UmVtb3RlKCkgPyB0aGlzLnN0cmVhbS5sb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZSEgOiB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpO1xuICAgICAgICBsZXQgcmVtb3ZlZFRyYWNrOiBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICBpZiAodHJhY2sua2luZCA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgcmVtb3ZlZFRyYWNrID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICAgICAgICAgIGlmICh1cGRhdGVMYXN0Q29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5sYXN0VmlkZW9UcmFja0NvbnN0cmFpbnRzID0gdHJhY2suZ2V0Q29uc3RyYWludHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbW92ZWRUcmFjayA9IG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF07XG4gICAgICAgIH1cbiAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2socmVtb3ZlZFRyYWNrKTtcbiAgICAgICAgcmVtb3ZlZFRyYWNrLnN0b3AoKTtcbiAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2sodHJhY2spO1xuICAgICAgICBpZiAodHJhY2sua2luZCA9PT0gJ3ZpZGVvJyAmJiB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkICYmIHVwZGF0ZUxhc3RDb25zdHJhaW50cykge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kTmV3VmlkZW9EaW1lbnNpb25zSWZSZXF1aXJlZCh0aGlzLCAndHJhY2tSZXBsYWNlZCcsIDUwLCAzMCk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb24uc2VuZFZpZGVvRGF0YSh0aGlzLnN0cmVhbS5zdHJlYW1NYW5hZ2VyLCA1LCB0cnVlLCA1KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRQZXJtaXNzaW9uRGlhbG9nVGltZXIod2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25EaWFsb2dUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nT3BlbmVkJywgW10pO1xuICAgICAgICB9LCB3YWl0VGltZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjbGVhclBlcm1pc3Npb25EaWFsb2dUaW1lcihzdGFydFRpbWU6IG51bWJlciwgd2FpdFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZXJtaXNzaW9uRGlhbG9nVGltZW91dCk7XG4gICAgICAgIGlmICgoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgPiB3YWl0VGltZSkge1xuICAgICAgICAgICAgLy8gUGVybWlzc2lvbiBkaWFsb2cgd2FzIHNob3duIGFuZCBub3cgaXMgY2xvc2VkXG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCgnYWNjZXNzRGlhbG9nQ2xvc2VkJywgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXBsYWNlVHJhY2tJblJ0Y1J0cFNlbmRlcih0cmFjazogTWVkaWFTdHJlYW1UcmFjayk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBzZW5kZXJzOiBSVENSdHBTZW5kZXJbXSA9IHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuZ2V0U2VuZGVycygpO1xuICAgICAgICBsZXQgc2VuZGVyOiBSVENSdHBTZW5kZXIgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0cmFjay5raW5kID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICBzZW5kZXIgPSBzZW5kZXJzLmZpbmQocyA9PiAhIXMudHJhY2sgJiYgcy50cmFjay5raW5kID09PSAndmlkZW8nKTtcbiAgICAgICAgICAgIGlmICghc2VuZGVyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGVyZVxcJ3Mgbm8gcmVwbGFjZWFibGUgdHJhY2sgZm9yIHRoYXQga2luZCBvZiBNZWRpYVN0cmVhbVRyYWNrIGluIHRoaXMgUHVibGlzaGVyIG9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRyYWNrLmtpbmQgPT09ICdhdWRpbycpIHtcbiAgICAgICAgICAgIHNlbmRlciA9IHNlbmRlcnMuZmluZChzID0+ICEhcy50cmFjayAmJiBzLnRyYWNrLmtpbmQgPT09ICdhdWRpbycpO1xuICAgICAgICAgICAgaWYgKCFzZW5kZXIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlXFwncyBubyByZXBsYWNlYWJsZSB0cmFjayBmb3IgdGhhdCBraW5kIG9mIE1lZGlhU3RyZWFtVHJhY2sgaW4gdGhpcyBQdWJsaXNoZXIgb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gdHJhY2sga2luZCAnICsgdHJhY2sua2luZCk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgKHNlbmRlciBhcyBSVENSdHBTZW5kZXIpLnJlcGxhY2VUcmFjayh0cmFjayk7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4vQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuL0ZpbHRlcic7XG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gJy4vT3BlblZpZHUnO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4vU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgeyBTdWJzY3JpYmVyIH0gZnJvbSAnLi9TdWJzY3JpYmVyJztcbmltcG9ydCB7IENhcGFiaWxpdGllcyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9QdWJsaWMvQ2FwYWJpbGl0aWVzJztcbmltcG9ydCB7IEV2ZW50RGlzcGF0Y2hlciB9IGZyb20gJy4vRXZlbnREaXNwYXRjaGVyJztcbmltcG9ydCB7IFNpZ25hbE9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1NpZ25hbE9wdGlvbnMnO1xuaW1wb3J0IHsgU3Vic2NyaWJlclByb3BlcnRpZXMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N1YnNjcmliZXJQcm9wZXJ0aWVzJztcbmltcG9ydCB7IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1ByaXZhdGUvUmVtb3RlQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgTG9jYWxDb25uZWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvSW50ZXJmYWNlcy9Qcml2YXRlL0xvY2FsQ29ubmVjdGlvbk9wdGlvbnMnO1xuaW1wb3J0IHsgU2Vzc2lvbk9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9TZXNzaW9uT3B0aW9ucyc7XG5pbXBvcnQgeyBTZXNzaW9uRXZlbnRNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudE1hcC9TZXNzaW9uRXZlbnRNYXAnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbkV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvbkV2ZW50JztcbmltcG9ydCB7IEZpbHRlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvRmlsdGVyRXZlbnQnO1xuaW1wb3J0IHsgUmVjb3JkaW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9SZWNvcmRpbmdFdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TZXNzaW9uRGlzY29ubmVjdGVkRXZlbnQnO1xuaW1wb3J0IHsgU2lnbmFsRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9TaWduYWxFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1FdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbUV2ZW50JztcbmltcG9ydCB7IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvQ29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9OZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlscyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0nO1xuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmltcG9ydCBzZW12ZXJNYWpvciA9IHJlcXVpcmUoJ3NlbXZlci9mdW5jdGlvbnMvbWFqb3InKTtcbi8qKlxuICogQGhpZGRlblxuICovXG5pbXBvcnQgc2VtdmVyTWlub3IgPSByZXF1aXJlKCdzZW12ZXIvZnVuY3Rpb25zL21pbm9yJyk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmxldCBwbGF0Zm9ybTogUGxhdGZvcm1VdGlscztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgdmlkZW8gY2FsbC4gSXQgY2FuIGFsc28gYmUgc2VlbiBhcyBhIHZpZGVvY29uZmVyZW5jZSByb29tIHdoZXJlIG11bHRpcGxlIHVzZXJzIGNhbiBjb25uZWN0LlxuICogUGFydGljaXBhbnRzIHdobyBwdWJsaXNoIHRoZWlyIHZpZGVvcyB0byBhIHNlc3Npb24gY2FuIGJlIHNlZW4gYnkgdGhlIHJlc3Qgb2YgdXNlcnMgY29ubmVjdGVkIHRvIHRoYXQgc3BlY2lmaWMgc2Vzc2lvbi5cbiAqIEluaXRpYWxpemVkIHdpdGggW1tPcGVuVmlkdS5pbml0U2Vzc2lvbl1dIG1ldGhvZC5cbiAqXG4gKiBTZWUgYXZhaWxhYmxlIGV2ZW50IGxpc3RlbmVycyBhdCBbW1Nlc3Npb25FdmVudE1hcF1dLlxuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvbiBleHRlbmRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBMb2NhbCBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIG9iamVjdCBpcyBkZWZpbmVkIG9ubHkgYWZ0ZXIgW1tTZXNzaW9uLmNvbm5lY3RdXSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZXhlY3V0ZWQsIGFuZCBjYW4gYmUgcmV0cmlldmVkIHN1YnNjcmliaW5nIHRvIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIFNlc3Npb25cbiAgICAgKi9cbiAgICBzZXNzaW9uSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgYWxsIFN0cmVhbU1hbmFnZXJzIG9mIHRoaXMgU2Vzc2lvbiAoW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0pXG4gICAgICovXG4gICAgc3RyZWFtTWFuYWdlcnM6IFN0cmVhbU1hbmFnZXJbXSA9IFtdO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGRlZmluaW5nIHRoZSBtZXRob2RzIHRoYXQgdGhlIGNsaWVudCBpcyBhYmxlIHRvIGNhbGwuIFRoZXNlIGFyZSBkZWZpbmVkIGJ5IHRoZSBbW0Nvbm5lY3Rpb24ucm9sZV1dLlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIG9ubHkgZGVmaW5lZCBhZnRlciBbW1Nlc3Npb24uY29ubmVjdF1dIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZXNvbHZlZFxuICAgICAqL1xuICAgIGNhcGFiaWxpdGllczogQ2FwYWJpbGl0aWVzO1xuXG4gICAgLy8gVGhpcyBtYXAgaXMgb25seSB1c2VkIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uIGJldHdlZW4gJ2pvaW5Sb29tJyByZXNwb25zZSBhbmQgJ29uUGFydGljaXBhbnRQdWJsaXNoZWQnIG5vdGlmaWNhdGlvblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdGVTdHJlYW1zQ3JlYXRlZDogTWFwPHN0cmluZywgYm9vbGVhbj4gPSBuZXcgTWFwKCk7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3RlQ29ubmVjdGlvbnM6IE1hcDxzdHJpbmcsIENvbm5lY3Rpb24+ID0gbmV3IE1hcCgpO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvcGVudmlkdTogT3BlblZpZHU7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9wdGlvbnM6IFNlc3Npb25PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICB0b2tlbjogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIHZpZGVvRGF0YUludGVydmFsOiBOb2RlSlMuVGltZW91dDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJpdmF0ZSB2aWRlb0RhdGFUaW1lb3V0OiBOb2RlSlMuVGltZW91dDtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcGVudmlkdTogT3BlblZpZHUpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMub3BlbnZpZHUgPSBvcGVudmlkdTtcbiAgICB9XG5cbiAgICBjb25uZWN0KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPGFueT47XG4gICAgY29ubmVjdCh0b2tlbjogc3RyaW5nLCBtZXRhZGF0YTogYW55KTogUHJvbWlzZTxhbnk+O1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdHMgdG8gdGhlIHNlc3Npb24gdXNpbmcgYHRva2VuYC4gUGFyYW1ldGVyIGBtZXRhZGF0YWAgYWxsb3dzIHlvdSB0byBwYXNzIGV4dHJhIGRhdGEgdG8gc2hhcmUgd2l0aCBvdGhlciB1c2VycyB3aGVuXG4gICAgICogdGhleSByZWNlaXZlIGBzdHJlYW1DcmVhdGVkYCBldmVudC4gVGhlIHN0cnVjdHVyZSBvZiBgbWV0YWRhdGFgIHN0cmluZyBpcyB1cCB0byB5b3UgKG1heWJlIHNvbWUgc3RhbmRhcmRpemVkIGZvcm1hdFxuICAgICAqIGFzIEpTT04gb3IgWE1MIGlzIGEgZ29vZCBpZGVhKS5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0YWRhdGEgaXMgbm90IGNvbnNpZGVyZWQgc2VjdXJlLCBhcyBpdCBpcyBnZW5lcmF0ZWQgaW4gdGhlIGNsaWVudCBzaWRlLiBUbyBwYXNzIHNlY3VyZSBkYXRhLCBhZGQgaXQgYXMgYSBwYXJhbWV0ZXIgaW4gdGhlXG4gICAgICogdG9rZW4gZ2VuZXJhdGlvbiBvcGVyYXRpb24gKHRocm91Z2ggdGhlIEFQSSBSRVNULCBvcGVudmlkdS1qYXZhLWNsaWVudCBvciBvcGVudmlkdS1ub2RlLWNsaWVudCkuXG4gICAgICpcbiAgICAgKiBPbmx5IGFmdGVyIHRoZSByZXR1cm5lZCBQcm9taXNlIGlzIHN1Y2Nlc3NmdWxseSByZXNvbHZlZCBbW1Nlc3Npb24uY29ubmVjdGlvbl1dIG9iamVjdCB3aWxsIGJlIGF2YWlsYWJsZSBhbmQgcHJvcGVybHkgZGVmaW5lZC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgdGhlIGxvY2FsIHBhcnRpY2lwYW50IHdpbGwgZmlyc3QgZGlzcGF0Y2ggb25lIG9yIG1vcmUgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudHMgdXBvbiBzdWNjZXNzZnVsIHRlcm1pbmF0aW9uIG9mIHRoaXMgbWV0aG9kOlxuICAgICAqIC0gRmlyc3Qgb25lIGZvciB5b3VyIG93biBsb2NhbCBDb25uZWN0aW9uIG9iamVjdCwgc28geW91IGNhbiByZXRyaWV2ZSBbW1Nlc3Npb24uY29ubmVjdGlvbl1dIHByb3BlcnR5LlxuICAgICAqIC0gVGhlbiBvbmUgZm9yIGVhY2ggcmVtb3RlIENvbm5lY3Rpb24gcHJldmlvdXNseSBjb25uZWN0ZWQgdG8gdGhlIFNlc3Npb24sIGlmIGFueS4gQW55IG90aGVyIHJlbW90ZSB1c2VyIGNvbm5lY3RpbmcgdG8gdGhlIFNlc3Npb24gYWZ0ZXIgeW91IGhhdmVcbiAgICAgKiBzdWNjZXNzZnVsbHkgY29ubmVjdGVkIHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnQgd2hlbiB0aGV5IGRvIHNvLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBhbHNvIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IGZvciBlYWNoIHJlbW90ZSBhY3RpdmUgW1tQdWJsaXNoZXJdXSB0aGF0IHdhcyBhbHJlYWR5IHN0cmVhbWluZ1xuICAgICAqIHdoZW4gY29ubmVjdGluZywganVzdCBhZnRlciBkaXNwYXRjaGluZyBhbGwgcmVtb3RlIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnRzLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBjb25uZWN0aW9uQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTdHJlYW1FdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgdG8gd2hpY2ggeW91IG11c3Qgc3Vic2NyaWJlIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKlxuICAgICAqL1xuICAgIGNvbm5lY3QodG9rZW46IHN0cmluZywgbWV0YWRhdGE/OiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzVG9rZW4odG9rZW4pO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcGVudmlkdS5jaGVja1N5c3RlbVJlcXVpcmVtZW50cygpKSB7XG4gICAgICAgICAgICAgICAgLy8gRWFybHkgY29uZmlndXJhdGlvbiB0byBkZWFjdGl2YXRlIGF1dG9tYXRpYyBzdWJzY3JpcHRpb24gdG8gc3RyZWFtc1xuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRJZDogdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhOiAhIW1ldGFkYXRhID8gdGhpcy5zdHJpbmdDbGllbnRNZXRhZGF0YShtZXRhZGF0YSkgOiAnJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0QXV4KHRva2VuKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKCkpXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5CUk9XU0VSX05PVF9TVVBQT1JURUQsICdCcm93c2VyICcgKyBwbGF0Zm9ybS5nZXROYW1lKCkgKyAnICh2ZXJzaW9uICcgKyBwbGF0Zm9ybS5nZXRWZXJzaW9uKCkgKyAnKSBmb3IgJyArIHBsYXRmb3JtLmdldEZhbWlseSgpICsgJyBpcyBub3Qgc3VwcG9ydGVkIGluIE9wZW5WaWR1JykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMZWF2ZXMgdGhlIHNlc3Npb24sIGRlc3Ryb3lpbmcgYWxsIHN0cmVhbXMgYW5kIGRlbGV0aW5nIHRoZSB1c2VyIGFzIGEgcGFydGljaXBhbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHNlc3Npb25EaXNjb25uZWN0ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBsZWF2aW5nIHBhcnRpY2lwYW50IGZyb20gZXZlcnkgU3Vic2NyaWJlciBvYmplY3Qgb2YgdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpXG4gICAgICogYW5kIGFsc28gZGVsZXRlcyBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gZWFjaCBTdWJzY3JpYmVyIChvbmx5IHRob3NlIFtjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXJdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zLyNsZXQtb3BlbnZpZHUtdGFrZS1jYXJlLW9mLXRoZS12aWRlby1wbGF5ZXJzKSkuXG4gICAgICogRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIGVhY2ggU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHNlc3Npb25EaXNjb25uZWN0ZWRgIHRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYW5kIHRha2UgY2FyZSBvZiBkaXNwb3NpbmcgYW5kIGNsZWFuaW5nIGFsbCB0aGUgU3Vic2NyaWJlciBvYmplY3RzIHlvdXJzZWxmLlxuICAgICAqIFNlZSBbW1Nlc3Npb25EaXNjb25uZWN0ZWRFdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBsb2NhbCBwYXJ0aWNpcGFudCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQgaWYgdGhlcmUgaXMgYSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBwdWJsaXNoaW5nIHRvIHRoZSBzZXNzaW9uLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24gKHRvIGRvIHNvIGl0IGlzIGEgbWFuZGF0b3J5IHJlcXVpcmVtZW50IHRvIGNhbGwgYFNlc3Npb24udW5wdWJsaXNoKClgXG4gICAgICogb3IvYW5kIGBTZXNzaW9uLmRpc2Nvbm5lY3QoKWAgaW4gdGhlIHByZXZpb3VzIHNlc3Npb24pLiBTZWUgW1tTdHJlYW1FdmVudF1dIGFuZCBbW1ZpZGVvRWxlbWVudEV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgb3RoZXIgcGFydGljaXBhbnQgY29ubmVjdGVkIHRvIHRoZSBzZXNzaW9uIHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZGlzY29ubmVjdGVkIHBhcnRpY2lwYW50IHdhcyBwdWJsaXNoaW5nLlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHRoZSBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgU3Vic2NyaWJlciBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIENhbGwgYGV2ZW50LnByZXZlbnREZWZhdWx0KClgIHVwb24gZXZlbnQgYHN0cmVhbURlc3Ryb3llZGAgdG8gYXZvaWQgdGhpcyBkZWZhdWx0IGJlaGF2aW9yIGFuZCB0YWtlIGNhcmUgb2YgZGlzcG9zaW5nIGFuZCBjbGVhbmluZyB0aGUgU3Vic2NyaWJlciBvYmplY3QgeW91cnNlbGYuXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYGNvbm5lY3Rpb25EZXN0cm95ZWRgIGV2ZW50IGluIGFueSBjYXNlLiBTZWUgW1tDb25uZWN0aW9uRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqL1xuICAgIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGVhdmUoZmFsc2UsICdkaXNjb25uZWN0Jyk7XG4gICAgfVxuXG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCk6IFN1YnNjcmliZXI7XG4gICAgc3Vic2NyaWJlKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpOiBTdWJzY3JpYmVyO1xuICAgIHN1YnNjcmliZShzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGNvbXBsZXRpb25IYW5kbGVyOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkKSA9PiB2b2lkKTogU3Vic2NyaWJlcjtcbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcywgY29tcGxldGlvbkhhbmRsZXI6IChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpOiBTdWJzY3JpYmVyO1xuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlcyB0byBhIGBzdHJlYW1gLCBhZGRpbmcgYSBuZXcgSFRNTCB2aWRlbyBlbGVtZW50IHRvIERPTSB3aXRoIGBzdWJzY3JpYmVyUHJvcGVydGllc2Agc2V0dGluZ3MuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGluIHRoZSBjYWxsYmFjayBvZiBgc3RyZWFtQ3JlYXRlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgW1tTdWJzY3JpYmVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50Q3JlYXRlZGAgZXZlbnQgb25jZSB0aGUgSFRNTCB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGFkZGVkIHRvIERPTSAob25seSBpZiB5b3VcbiAgICAgKiBbbGV0IE9wZW5WaWR1IHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVyc10oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS4gU2VlIFtbVmlkZW9FbGVtZW50RXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU3Vic2NyaWJlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IG9uY2UgdGhlIHJlbW90ZSBzdHJlYW0gc3RhcnRzIHBsYXlpbmcuIFNlZSBbW1N0cmVhbU1hbmFnZXJFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RyZWFtIFN0cmVhbSBvYmplY3QgdG8gc3Vic2NyaWJlIHRvXG4gICAgICogQHBhcmFtIHRhcmdldEVsZW1lbnQgSFRNTCBET00gZWxlbWVudCAob3IgaXRzIGBpZGAgYXR0cmlidXRlKSBpbiB3aGljaCB0aGUgdmlkZW8gZWxlbWVudCBvZiB0aGUgU3Vic2NyaWJlciB3aWxsIGJlIGluc2VydGVkIChzZWUgW1tTdWJzY3JpYmVyUHJvcGVydGllcy5pbnNlcnRNb2RlXV0pLiBJZiAqbnVsbCogb3IgKnVuZGVmaW5lZCogbm8gZGVmYXVsdCB2aWRlbyB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgU3Vic2NyaWJlci5cbiAgICAgKiBZb3UgY2FuIGFsd2F5cyBjYWxsIG1ldGhvZCBbW1N1YnNjcmliZXIuYWRkVmlkZW9FbGVtZW50XV0gb3IgW1tTdWJzY3JpYmVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dIHRvIG1hbmFnZSB0aGUgdmlkZW8gZWxlbWVudHMgb24geW91ciBvd24gKHNlZSBbTWFuYWdlIHZpZGVvIHBsYXllcnNdKC9lbi9zdGFibGUvY2hlYXRzaGVldC9tYW5hZ2UtdmlkZW9zKSBzZWN0aW9uKVxuICAgICAqIEBwYXJhbSBjb21wbGV0aW9uSGFuZGxlciBgZXJyb3JgIHBhcmFtZXRlciBpcyBudWxsIGlmIGBzdWJzY3JpYmVgIHN1Y2NlZWRzLCBhbmQgaXMgZGVmaW5lZCBpZiBpdCBmYWlscy5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LCBwYXJhbTM/OiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCBTdWJzY3JpYmVyUHJvcGVydGllcywgcGFyYW00PzogKChlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQpID0+IHZvaWQpKTogU3Vic2NyaWJlciB7XG4gICAgICAgIGxldCBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcyA9IHt9O1xuICAgICAgICBpZiAoISFwYXJhbTMgJiYgdHlwZW9mIHBhcmFtMyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgICAgICBpbnNlcnRNb2RlOiAodHlwZW9mIHBhcmFtMy5pbnNlcnRNb2RlICE9PSAndW5kZWZpbmVkJykgPyAoKHR5cGVvZiBwYXJhbTMuaW5zZXJ0TW9kZSA9PT0gJ3N0cmluZycpID8gVmlkZW9JbnNlcnRNb2RlW3BhcmFtMy5pbnNlcnRNb2RlXSA6IHByb3BlcnRpZXMuaW5zZXJ0TW9kZSkgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5ELFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZVRvQXVkaW86ICh0eXBlb2YgcGFyYW0zLnN1YnNjcmliZVRvQXVkaW8gIT09ICd1bmRlZmluZWQnKSA/IHBhcmFtMy5zdWJzY3JpYmVUb0F1ZGlvIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiAodHlwZW9mIHBhcmFtMy5zdWJzY3JpYmVUb1ZpZGVvICE9PSAndW5kZWZpbmVkJykgPyBwYXJhbTMuc3Vic2NyaWJlVG9WaWRlbyA6IHRydWVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGluc2VydE1vZGU6IFZpZGVvSW5zZXJ0TW9kZS5BUFBFTkQsXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlVG9BdWRpbzogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVUb1ZpZGVvOiB0cnVlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNvbXBsZXRpb25IYW5kbGVyOiAoKGVycm9yOiBFcnJvciB8IHVuZGVmaW5lZCkgPT4gdm9pZCkgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmICghIXBhcmFtMyAmJiAodHlwZW9mIHBhcmFtMyA9PT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgICAgIGNvbXBsZXRpb25IYW5kbGVyID0gcGFyYW0zO1xuICAgICAgICB9IGVsc2UgaWYgKCEhcGFyYW00KSB7XG4gICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlciA9IHBhcmFtNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgIGlmIChjb21wbGV0aW9uSGFuZGxlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvZ2dlci5pbmZvKCdTdWJzY3JpYmluZyB0byAnICsgc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcblxuICAgICAgICBzdHJlYW0uc3Vic2NyaWJlKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnU3Vic2NyaWJlZCBjb3JyZWN0bHkgdG8gJyArIHN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRpb25IYW5kbGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbkhhbmRsZXIodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGlvbkhhbmRsZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uSGFuZGxlcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1YnNjcmliZXIgPSBuZXcgU3Vic2NyaWJlcihzdHJlYW0sIHRhcmdldEVsZW1lbnQsIHByb3BlcnRpZXMpO1xuICAgICAgICBpZiAoISFzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudChzdWJzY3JpYmVyLnRhcmdldEVsZW1lbnQsIDxWaWRlb0luc2VydE1vZGU+cHJvcGVydGllcy5pbnNlcnRNb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3Vic2NyaWJlcjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFByb21pc2lmaWVkIHZlcnNpb24gb2YgW1tTZXNzaW9uLnN1YnNjcmliZV1dXG4gICAgICovXG4gICAgc3Vic2NyaWJlQXN5bmMoc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ6IHN0cmluZyB8IEhUTUxFbGVtZW50KTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcbiAgICBzdWJzY3JpYmVBc3luYyhzdHJlYW06IFN0cmVhbSwgdGFyZ2V0RWxlbWVudDogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIHByb3BlcnRpZXM6IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPjtcblxuICAgIHN1YnNjcmliZUFzeW5jKHN0cmVhbTogU3RyZWFtLCB0YXJnZXRFbGVtZW50OiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllcz86IFN1YnNjcmliZXJQcm9wZXJ0aWVzKTogUHJvbWlzZTxTdWJzY3JpYmVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTdWJzY3JpYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBzdWJzY3JpYmVyOiBTdWJzY3JpYmVyO1xuXG4gICAgICAgICAgICBjb25zdCBjYWxsYmFjayA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShzdWJzY3JpYmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoISFwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlciA9IHRoaXMuc3Vic2NyaWJlKHN0cmVhbSwgdGFyZ2V0RWxlbWVudCwgcHJvcGVydGllcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyID0gdGhpcy5zdWJzY3JpYmUoc3RyZWFtLCB0YXJnZXRFbGVtZW50LCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgZnJvbSBgc3Vic2NyaWJlcmAsIGF1dG9tYXRpY2FsbHkgcmVtb3ZpbmcgaXRzIGFzc29jaWF0ZWQgSFRNTCB2aWRlbyBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1N1YnNjcmliZXJdXSBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50IGZvciBlYWNoIHZpZGVvIGFzc29jaWF0ZWQgdG8gaXQgdGhhdCB3YXMgcmVtb3ZlZCBmcm9tIERPTS5cbiAgICAgKiBPbmx5IHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpIHdpbGwgYmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAgICpcbiAgICAgKiBTZWUgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmVcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShzdWJzY3JpYmVyOiBTdWJzY3JpYmVyKTogUHJvbWlzZTx2b2lkPiB7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlc3Npb25Db25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbklkID0gc3Vic2NyaWJlci5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQ7XG5cbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnVW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdChcbiAgICAgICAgICAgICAgICAgICAgJ3Vuc3Vic2NyaWJlRnJvbVZpZGVvJyxcbiAgICAgICAgICAgICAgICAgICAgeyBzZW5kZXI6IHN1YnNjcmliZXIuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgdW5zdWJzY3JpYmluZyBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnVW5zdWJzY3JpYmVkIGNvcnJlY3RseSBmcm9tICcgKyBjb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlci5zdHJlYW0uZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLnN0cmVhbS5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgdG8gdGhlIFNlc3Npb24gdGhlIFB1Ymxpc2hlciBvYmplY3RcbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBsb2NhbCBbW1B1Ymxpc2hlcl1dIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbUNyZWF0ZWRgIGV2ZW50IHVwb24gc3VjY2Vzc2Z1bCB0ZXJtaW5hdGlvbiBvZiB0aGlzIG1ldGhvZC4gU2VlIFtbU3RyZWFtRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIGxvY2FsIFtbUHVibGlzaGVyXV0gb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtUGxheWluZ2Agb25jZSB0aGUgbWVkaWEgc3RyZWFtIHN0YXJ0cyBwbGF5aW5nLiBTZWUgW1tTdHJlYW1NYW5hZ2VyRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBvdGhlciBwYXJ0aWNpcGFudCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1DcmVhdGVkYCBldmVudCBzbyB0aGV5IGNhbiBzdWJzY3JpYmUgdG8gaXQuIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSBwdWJsaXNoZXIgd2FzIHN1Y2Nlc3NmdWxseSBwdWJsaXNoZWQgYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIHB1Ymxpc2gocHVibGlzaGVyOiBQdWJsaXNoZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlc3Npb25Db25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QodGhpcy5ub3RDb25uZWN0ZWRFcnJvcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHVibGlzaGVyLnNlc3Npb24gPSB0aGlzO1xuICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5zZXNzaW9uID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKCFwdWJsaXNoZXIuc3RyZWFtLnB1Ymxpc2hlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyAnU2Vzc2lvbi51bnB1Ymxpc2goUHVibGlzaGVyKScgaGFzIE5PVCBiZWVuIGNhbGxlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgcHVibGlzaGVyLnN0cmVhbS5wdWJsaXNoKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kVmlkZW9EYXRhKHB1Ymxpc2hlciwgOCwgdHJ1ZSwgNSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICdTZXNzaW9uLnVucHVibGlzaChQdWJsaXNoZXIpJyBoYXMgYmVlbiBjYWxsZWQuIE11c3QgaW5pdGlhbGl6ZSBhZ2FpbiBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICBwdWJsaXNoZXIuaW5pdGlhbGl6ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRTdHJlYW0ocHVibGlzaGVyLnN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdWJsaXNoZXIucmVlc3RhYmxpc2hTdHJlYW1QbGF5aW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1Ymxpc2hlci5zdHJlYW0ucHVibGlzaCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbmRWaWRlb0RhdGEocHVibGlzaGVyLCA4LCB0cnVlLCA1KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVW5wdWJsaXNoZXMgZnJvbSB0aGUgU2Vzc2lvbiB0aGUgUHVibGlzaGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBbW1B1Ymxpc2hlcl1dIG9iamVjdCBvZiB0aGUgbG9jYWwgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHN0b3AgYWxsIG1lZGlhIHRyYWNrcyBhbmQgZGVsZXRlIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byB0aGlzIFB1Ymxpc2hlclxuICAgICAqIChvbmx5IHRob3NlIHZpZGVvcyBbY3JlYXRlZCBieSBPcGVuVmlkdSBCcm93c2VyXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLlxuICAgICAqIEZvciBldmVyeSB2aWRlbyByZW1vdmVkLCB0aGUgUHVibGlzaGVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudERlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogQ2FsbCBgZXZlbnQucHJldmVudERlZmF1bHQoKWAgdXBvbiBldmVudCBgc3RyZWFtRGVzdHJveWVkYCBpZiB5b3Ugd2FudCB0byBjbGVhbiB0aGUgUHVibGlzaGVyIG9iamVjdCBvbiB5b3VyIG93biBvciByZS1wdWJsaXNoIGl0IGluIGEgZGlmZmVyZW50IFNlc3Npb24uXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IG90aGVyIHBhcnRpY2lwYW50IGNvbm5lY3RlZCB0byB0aGUgc2Vzc2lvbiB3aWxsIGRpc3BhdGNoIGEgYHN0cmVhbURlc3Ryb3llZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgdGhlIFN1YnNjcmliZXIgb2JqZWN0IGZyb20gdGhlIHNlc3Npb24gKHRoaXMgaW5jbHVkZXMgY2xvc2luZyB0aGUgUlRDUGVlckNvbm5lY3Rpb24gYW5kIGRpc3Bvc2luZyBhbGwgTWVkaWFTdHJlYW1UcmFja3MpIGFuZFxuICAgICAqIGRlbGV0ZSBhbnkgSFRNTCB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gaXQgKG9ubHkgdGhvc2UgW2NyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3Nlcl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI2xldC1vcGVudmlkdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKiBDYWxsIGBldmVudC5wcmV2ZW50RGVmYXVsdCgpYCB1cG9uIGV2ZW50IGBzdHJlYW1EZXN0cm95ZWRgIHRvIGF2b2lkIHRoaXMgZGVmYXVsdCBiZWhhdmlvciBhbmQgdGFrZSBjYXJlIG9mIGRpc3Bvc2luZyBhbmQgY2xlYW5pbmcgdGhlIFN1YnNjcmliZXIgb2JqZWN0IG9uIHlvdXIgb3duLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSBhbmQgW1tWaWRlb0VsZW1lbnRFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICovXG4gICAgdW5wdWJsaXNoKHB1Ymxpc2hlcjogUHVibGlzaGVyKTogUHJvbWlzZTx2b2lkPiB7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlc3Npb25Db25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgICAgIHRocm93IHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBwdWJsaXNoZXIuc3RyZWFtO1xuXG4gICAgICAgICAgICBpZiAoIXN0cmVhbS5jb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoJ1RoZSBhc3NvY2lhdGVkIENvbm5lY3Rpb24gb2JqZWN0IG9mIHRoaXMgUHVibGlzaGVyIGlzIG51bGwnKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0cmVhbS5jb25uZWN0aW9uICE9PSB0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignVGhlIGFzc29jaWF0ZWQgQ29ubmVjdGlvbiBvYmplY3Qgb2YgdGhpcyBQdWJsaXNoZXIgaXMgbm90IHlvdXIgbG9jYWwgQ29ubmVjdGlvbi4nICtcbiAgICAgICAgICAgICAgICAgICAgXCJPbmx5IG1vZGVyYXRvcnMgY2FuIGZvcmNlIHVucHVibGlzaCBvbiByZW1vdGUgU3RyZWFtcyB2aWEgJ2ZvcmNlVW5wdWJsaXNoJyBtZXRob2RcIikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdVbnB1Ymxpc2hpbmcgbG9jYWwgbWVkaWEgKCcgKyBzdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQgKyAnKScpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5zZW5kUmVxdWVzdCgndW5wdWJsaXNoVmlkZW8nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnTWVkaWEgdW5wdWJsaXNoZWQgY29ycmVjdGx5Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5kaXNwb3NlV2ViUnRjUGVlcigpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZWFtLmNvbm5lY3Rpb24uc3RyZWFtID09IHN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBDb25uZWN0aW9uLnN0cmVhbSBtYXkgaGF2ZSBjaGFuZ2VkIGlmIFNlc3Npb24ucHVibGlzaCB3YXMgY2FsbGVkIHdpdGggb3RoZXIgUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHN0cmVhbS5jb25uZWN0aW9uLnN0cmVhbTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtRXZlbnQgPSBuZXcgU3RyZWFtRXZlbnQodHJ1ZSwgcHVibGlzaGVyLCAnc3RyZWFtRGVzdHJveWVkJywgcHVibGlzaGVyLnN0cmVhbSwgJ3VucHVibGlzaCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVibGlzaGVyLmVtaXRFdmVudCgnc3RyZWFtRGVzdHJveWVkJywgW3N0cmVhbUV2ZW50XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1FdmVudC5jYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBGb3JjZXMgc29tZSB1c2VyIHRvIGxlYXZlIHRoZSBzZXNzaW9uXG4gICAgICpcbiAgICAgKiAjIyMjIEV2ZW50cyBkaXNwYXRjaGVkXG4gICAgICpcbiAgICAgKiBUaGUgYmVoYXZpb3IgaXMgdGhlIHNhbWUgYXMgd2hlbiBzb21lIHVzZXIgY2FsbHMgW1tTZXNzaW9uLmRpc2Nvbm5lY3RdXSwgYnV0IGByZWFzb25gIHByb3BlcnR5IGluIGFsbCBldmVudHMgd2lsbCBiZSBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICpcbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIGV2ZXJ5IHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCBpZiB0aGUgZXZpY3RlZCB1c2VyIHdhcyBwdWJsaXNoaW5nIGEgc3RyZWFtLCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImAuXG4gICAgICogVGhlIFtbU2Vzc2lvbl1dIG9iamVjdCBvZiBldmVyeSBwYXJ0aWNpcGFudCBleGNlcHQgdGhlIGV2aWN0ZWQgb25lIHdpbGwgZGlzcGF0Y2ggYSBgY29ubmVjdGlvbkRlc3Ryb3llZGAgZXZlbnQgZm9yIHRoZSBldmljdGVkIHVzZXIsIHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKlxuICAgICAqIElmIGFueSwgdGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYC5cbiAgICAgKiBUaGUgW1tTZXNzaW9uXV0gb2JqZWN0IG9mIHRoZSBldmljdGVkIHBhcnRpY2lwYW50IHdpbGwgZGlzcGF0Y2ggYSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGAgZXZlbnQgd2l0aCBwcm9wZXJ0eSBgcmVhc29uYCBzZXQgdG8gYFwiZm9yY2VEaXNjb25uZWN0QnlVc2VyXCJgLlxuICAgICAqXG4gICAgICogU2VlIFtbU3RyZWFtRXZlbnRdXSwgW1tDb25uZWN0aW9uRXZlbnRdXSBhbmQgW1tTZXNzaW9uRGlzY29ubmVjdGVkRXZlbnRdXSB0byBsZWFybiBtb3JlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIG9ubHkgYWZ0ZXIgdGhlIHBhcnRpY2lwYW50IGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBldmljdGVkIGZyb20gdGhlIHNlc3Npb24gYW5kIHJlamVjdGVkIHdpdGggYW4gRXJyb3Igb2JqZWN0IGlmIG5vdFxuICAgICAqL1xuICAgIGZvcmNlRGlzY29ubmVjdChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KHRoaXMubm90Q29ubmVjdGVkRXJyb3IoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdGb3JjaW5nIGRpc2Nvbm5lY3QgZm9yIGNvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlRGlzY29ubmVjdCcsXG4gICAgICAgICAgICAgICAgeyBjb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb24uY29ubmVjdGlvbklkIH0sXG4gICAgICAgICAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgZm9yY2luZyBkaXNjb25uZWN0IGZvciBDb25uZWN0aW9uICcgKyBjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gZm9yY2UgYSBkaXNjb25uZWN0aW9uXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRm9yY2luZyBkaXNjb25uZWN0IGNvcnJlY3RseSBmb3IgQ29ubmVjdGlvbiAnICsgY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRm9yY2VzIHNvbWUgdXNlciB0byB1bnB1Ymxpc2ggYSBTdHJlYW1cbiAgICAgKlxuICAgICAqICMjIyMgRXZlbnRzIGRpc3BhdGNoZWRcbiAgICAgKlxuICAgICAqIFRoZSBiZWhhdmlvciBpcyB0aGUgc2FtZSBhcyB3aGVuIHNvbWUgdXNlciBjYWxscyBbW1Nlc3Npb24udW5wdWJsaXNoXV0sIGJ1dCBgcmVhc29uYCBwcm9wZXJ0eSBpbiBhbGwgZXZlbnRzIHdpbGwgYmUgYFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFRoZSBbW1Nlc3Npb25dXSBvYmplY3Qgb2YgZXZlcnkgcGFydGljaXBhbnQgd2lsbCBkaXNwYXRjaCBhIGBzdHJlYW1EZXN0cm95ZWRgIGV2ZW50IHdpdGggcHJvcGVydHkgYHJlYXNvbmAgc2V0IHRvIGBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiYFxuICAgICAqXG4gICAgICogVGhlIFtbUHVibGlzaGVyXV0gb2JqZWN0IG9mIHRoZSBhZmZlY3RlZCBwYXJ0aWNpcGFudCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgc3RyZWFtRGVzdHJveWVkYCBldmVudCB3aXRoIHByb3BlcnR5IGByZWFzb25gIHNldCB0byBgXCJmb3JjZURpc2Nvbm5lY3RCeVVzZXJcImBcbiAgICAgKlxuICAgICAqIFNlZSBbW1N0cmVhbUV2ZW50XV0gdG8gbGVhcm4gbW9yZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSAodG8gd2hpY2ggeW91IGNhbiBvcHRpb25hbGx5IHN1YnNjcmliZSB0bykgdGhhdCBpcyByZXNvbHZlZCBvbmx5IGFmdGVyIHRoZSByZW1vdGUgU3RyZWFtIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSB1bnB1Ymxpc2hlZCBmcm9tIHRoZSBzZXNzaW9uIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBmb3JjZVVucHVibGlzaChzdHJlYW06IFN0cmVhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbkNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdCh0aGlzLm5vdENvbm5lY3RlZEVycm9yKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsb2dnZXIuaW5mbygnRm9yY2luZyB1bnB1Ymxpc2ggZm9yIHN0cmVhbSAnICsgc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgJ2ZvcmNlVW5wdWJsaXNoJyxcbiAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiBzdHJlYW0uc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBmb3JjaW5nIHVucHVibGlzaCBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX1BFUk1JU1NJT05fREVOSUVELCBcIllvdSBkb24ndCBoYXZlIHBlcm1pc3Npb25zIHRvIGZvcmNlIGFuIHVucHVibGlzaGluZ1wiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0ZvcmNpbmcgdW5wdWJsaXNoIGNvcnJlY3RseSBmb3IgU3RyZWFtICcgKyBzdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgb25lIHNpZ25hbC4gYHNpZ25hbGAgb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogYGBganNvblxuICAgICAqIHtkYXRhOnN0cmluZywgdG86Q29ubmVjdGlvbltdLCB0eXBlOnN0cmluZ31cbiAgICAgKiBgYGBcbiAgICAgKiBBbGwgdXNlcnMgc3Vic2NyaWJlZCB0byB0aGF0IHNpZ25hbCAoYHNlc3Npb24ub24oJ3NpZ25hbDp0eXBlJywgLi4uKWAgb3IgYHNlc3Npb24ub24oJ3NpZ25hbCcsIC4uLilgIGZvciBhbGwgc2lnbmFscykgYW5kIHdob3NlIENvbm5lY3Rpb24gb2JqZWN0cyBhcmUgaW4gYHRvYCBhcnJheSB3aWxsIHJlY2VpdmUgaXQuIFRoZWlyIGxvY2FsXG4gICAgICogU2Vzc2lvbiBvYmplY3RzIHdpbGwgZGlzcGF0Y2ggYSBgc2lnbmFsYCBvciBgc2lnbmFsOnR5cGVgIGV2ZW50LiBTZWUgW1tTaWduYWxFdmVudF1dIHRvIGxlYXJuIG1vcmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgKHRvIHdoaWNoIHlvdSBjYW4gb3B0aW9uYWxseSBzdWJzY3JpYmUgdG8pIHRoYXQgaXMgcmVzb2x2ZWQgaWYgdGhlIG1lc3NhZ2Ugc3VjY2Vzc2Z1bGx5IHJlYWNoZWQgb3BlbnZpZHUtc2VydmVyIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3QuIF9UaGlzIGRvZXNuJ3RcbiAgICAgKiBtZWFuIHRoYXQgb3BlbnZpZHUtc2VydmVyIGNvdWxkIHJlc2VuZCB0aGUgbWVzc2FnZSB0byBhbGwgdGhlIGxpc3RlZCByZWNlaXZlcnMuX1xuICAgICAqL1xuICAgIC8qIHRzbGludDpkaXNhYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG4gICAgc2lnbmFsKHNpZ25hbDogU2lnbmFsT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbkNvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdCh0aGlzLm5vdENvbm5lY3RlZEVycm9yKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzaWduYWxNZXNzYWdlID0ge307XG5cbiAgICAgICAgICAgIGlmIChzaWduYWwudG8gJiYgc2lnbmFsLnRvLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICAgICAgICAgIHNpZ25hbC50by5mb3JFYWNoKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbklkcy5wdXNoKGNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ3RvJ10gPSBjb25uZWN0aW9uSWRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0byddID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNpZ25hbE1lc3NhZ2VbJ2RhdGEnXSA9IHNpZ25hbC5kYXRhID8gc2lnbmFsLmRhdGEgOiAnJztcblxuICAgICAgICAgICAgbGV0IHR5cGVBdXg6IHN0cmluZyA9IHNpZ25hbC50eXBlID8gc2lnbmFsLnR5cGUgOiAnc2lnbmFsJztcbiAgICAgICAgICAgIGlmICghIXR5cGVBdXgpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZUF1eC5zdWJzdHJpbmcoMCwgNykgIT09ICdzaWduYWw6Jykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlQXV4ID0gJ3NpZ25hbDonICsgdHlwZUF1eDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWduYWxNZXNzYWdlWyd0eXBlJ10gPSB0eXBlQXV4O1xuXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdzZW5kTWVzc2FnZScsIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBKU09OLnN0cmluZ2lmeShzaWduYWxNZXNzYWdlKVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKiB0c2xpbnQ6ZW5hYmxlOm5vLXN0cmluZy1saXRlcmFsICovXG5cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vbl1dXG4gICAgICovXG4gICAgb248SyBleHRlbmRzIGtleW9mIFNlc3Npb25FdmVudE1hcD4odHlwZTogSywgaGFuZGxlcjogKGV2ZW50OiBTZXNzaW9uRXZlbnRNYXBbS10pID0+IHZvaWQpOiB0aGlzIHtcblxuICAgICAgICBzdXBlci5vbkF1eCh0eXBlLCBcIkV2ZW50ICdcIiArIHR5cGUgKyBcIicgdHJpZ2dlcmVkIGJ5ICdTZXNzaW9uJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMgd2l0aCBhdWRpbywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBpbiBhbGwgb2YgdGhlbVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIXJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5lbmFibGVIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uPy5zdHJlYW0/Lmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uIGFuZCBwdWJsaXNoaW5nIHdpdGggYXVkaW8sIGFsc28gZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCBmb3IgdGhlIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcyB3aXRoIGF1ZGlvLCBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgaW4gYWxsIG9mIHRoZW1cbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24/LnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBjb25uZWN0ZWQgdG8gdGhlIFNlc3Npb24gYW5kIHB1Ymxpc2hpbmcgd2l0aCBhdWRpbywgYWxzbyBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgZm9yIHRoZSBQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZTxLIGV4dGVuZHMga2V5b2YgU2Vzc2lvbkV2ZW50TWFwPih0eXBlOiBLLCBoYW5kbGVyOiAoZXZlbnQ6IFNlc3Npb25FdmVudE1hcFtLXSkgPT4gdm9pZCk6IHRoaXMge1xuXG4gICAgICAgIHN1cGVyLm9uY2VBdXgodHlwZSwgXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlIGJ5ICdTZXNzaW9uJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWxyZWFkeSBhdmFpbGFibGUgcmVtb3RlIHN0cmVhbXMgd2l0aCBhdWRpbywgZW5hYmxlIGhhcmsgJ3NwZWFraW5nJyBldmVudCAob25jZSkgaW4gYWxsIG9mIHRoZW0gb25jZVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIXJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5lbmFibGVPbmNlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbj8uc3RyZWFtPy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIC8vIElmIGNvbm5lY3RlZCB0byB0aGUgU2Vzc2lvbiBhbmQgcHVibGlzaGluZyB3aXRoIGF1ZGlvLCBhbHNvIGVuYWJsZSBoYXJrICdzcGVha2luZycgZXZlbnQgKG9uY2UpIGZvciB0aGUgUHVibGlzaGVyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnN0cmVhbS5lbmFibGVPbmNlSGFya1NwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSBhbHJlYWR5IGF2YWlsYWJsZSByZW1vdGUgc3RyZWFtcyB3aXRoIGF1ZGlvLCBlbmFibGUgaGFyayAnc3RvcHBlZF9zcGVha2luZycgZXZlbnQgKG9uY2UpIGluIGFsbCBvZiB0aGVtIG9uY2VcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uPy5zdHJlYW0/Lmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgY29ubmVjdGVkIHRvIHRoZSBTZXNzaW9uIGFuZCBwdWJsaXNoaW5nIHdpdGggYXVkaW8sIGFsc28gZW5hYmxlIGhhcmsgJ3N0b3BwZWRfc3BlYWtpbmcnIGV2ZW50IChvbmNlKSBmb3IgdGhlIFB1Ymxpc2hlclxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub2ZmXV1cbiAgICAgKi9cbiAgICBvZmY8SyBleHRlbmRzIGtleW9mIFNlc3Npb25FdmVudE1hcD4odHlwZTogSywgaGFuZGxlcj86IChldmVudDogU2Vzc2lvbkV2ZW50TWFwW0tdKSA9PiB2b2lkKTogdGhpcyB7XG5cbiAgICAgICAgc3VwZXIub2ZmQXV4KHR5cGUsIGhhbmRsZXIpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAncHVibGlzaGVyU3RhcnRTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIFNlc3Npb24gb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZm9yRWFjaChyZW1vdGVDb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0/LnN0cmVhbU1hbmFnZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFN1YnNjcmliZXIgb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlLCByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1NYW5hZ2VyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtLmRpc2FibGVIYXJrU3BlYWtpbmdFdmVudChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24/LnN0cmVhbT8uc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBQdWJsaXNoZXIgb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmFueVNwZWVjaEV2ZW50TGlzdGVuZXJFbmFibGVkKCdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgZmFsc2UsIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZGlzYWJsZUhhcmtTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIFNlc3Npb24gb2JqZWN0IHN0aWxsIGhhcyBzb21lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5mb3JFYWNoKHJlbW90ZUNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbT8uc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgU3Vic2NyaWJlciBvYmplY3Qgc3RpbGwgaGFzIHNvbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmFueVNwZWVjaEV2ZW50TGlzdGVuZXJFbmFibGVkKCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBmYWxzZSwgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5kaXNhYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuY29ubmVjdGlvbj8uc3RyZWFtPy5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFB1Ymxpc2hlciBvYmplY3Qgc3RpbGwgaGFzIHNvbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYW55U3BlZWNoRXZlbnRMaXN0ZW5lckVuYWJsZWQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIGZhbHNlLCB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbU1hbmFnZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc2FibGVIYXJrU3RvcHBlZFNwZWFraW5nRXZlbnQoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLyogSGlkZGVuIG1ldGhvZHMgKi9cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50Sm9pbmVkKGV2ZW50OiBSZW1vdGVDb25uZWN0aW9uT3B0aW9ucyk6IHZvaWQge1xuICAgICAgICAvLyBDb25uZWN0aW9uIHNob3VsZG4ndCBleGlzdFxuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24oZXZlbnQuaWQsICcnKVxuICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ0Nvbm5lY3Rpb24gJyArIGNvbm5lY3Rpb24uY29ubmVjdGlvbklkICsgJyBhbHJlYWR5IGV4aXN0cyBpbiBjb25uZWN0aW9ucyBsaXN0Jyk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKG9wZW5WaWR1RXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCBldmVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5zZXQoZXZlbnQuaWQsIGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdjb25uZWN0aW9uQ3JlYXRlZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkNyZWF0ZWQnLCBjb25uZWN0aW9uLCAnJyldKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50TGVmdChldmVudDogeyBjb25uZWN0aW9uSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnb25QYXJ0aWNpcGFudExlZnQnKS50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBzdHJlYW0sIGV2ZW50LnJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbURlc3Ryb3llZCcsIFtzdHJlYW1FdmVudF0pO1xuICAgICAgICAgICAgICAgIHN0cmVhbUV2ZW50LmNhbGxEZWZhdWx0QmVoYXZpb3IoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWQuZGVsZXRlKHN0cmVhbS5zdHJlYW1JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zLmRlbGV0ZShjb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkRlc3Ryb3llZCcsIFtuZXcgQ29ubmVjdGlvbkV2ZW50KGZhbHNlLCB0aGlzLCAnY29ubmVjdGlvbkRlc3Ryb3llZCcsIGNvbm5lY3Rpb24sIGV2ZW50LnJlYXNvbildKTtcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25QYXJ0aWNpcGFudFB1Ymxpc2hlZChldmVudDogUmVtb3RlQ29ubmVjdGlvbk9wdGlvbnMpOiB2b2lkIHtcblxuICAgICAgICBjb25zdCBhZnRlckNvbm5lY3Rpb25Gb3VuZCA9IChjb25uZWN0aW9uKSA9PiB7XG5cbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuc2V0KGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBjb25uZWN0aW9uKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLmdldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCkpIHtcbiAgICAgICAgICAgICAgICAvLyBBdm9pZCByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHN0cmVhbS5zdWJzY3JpYmUoKSBpbiBcIm9uUGFydGljaXBhbnRQdWJsaXNoZWRcIiBhbmQgaW4gXCJqb2luUm9vbVwiIHJwYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29uZGl0aW9uIGlzIGZhbHNlIGlmIG9wZW52aWR1LXNlcnZlciBzZW5kcyBcInBhcnRpY2lwYW50UHVibGlzaGVkXCIgZXZlbnQgdG8gYSBzdWJzY3JpYmVyIHBhcnRpY2lwYW50IHRoYXQgaGFzXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBzdWJzY3JpYmVkIHRvIGNlcnRhaW4gc3RyZWFtIGluIHRoZSBjYWxsYmFjayBvZiBcImpvaW5Sb29tXCIgbWV0aG9kXG5cbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgY29ubmVjdGlvbi5zdHJlYW0sICcnKV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLnNldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCwgdHJ1ZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0IHRoZSBleGlzdGluZyBDb25uZWN0aW9uIGNyZWF0ZWQgb24gJ29uUGFydGljaXBhbnRKb2luZWQnIGZvclxuICAgICAgICAvLyBleGlzdGluZyBwYXJ0aWNpcGFudHMgb3IgY3JlYXRlIGEgbmV3IG9uZSBmb3IgbmV3IHBhcnRpY2lwYW50c1xuICAgICAgICBsZXQgY29ubmVjdGlvbjogQ29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKGV2ZW50LmlkLCAnb25QYXJ0aWNpcGFudFB1Ymxpc2hlZCcpXG5cbiAgICAgICAgICAgIC50aGVuKGNvbiA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIGV4aXN0aW5nIENvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uID0gY29uO1xuICAgICAgICAgICAgICAgIGV2ZW50Lm1ldGFkYXRhID0gY29uLmRhdGE7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdGVPcHRpb25zID0gZXZlbnQ7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5pbml0UmVtb3RlU3RyZWFtcyhldmVudC5zdHJlYW1zKTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBDb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICBhZnRlckNvbm5lY3Rpb25Gb3VuZChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50VW5wdWJsaXNoZWQoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91ciBzdHJlYW0gaGFzIGJlZW4gZm9yY2VkbHkgdW5wdWJsaXNoZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKGV2ZW50LnJlYXNvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbW90ZUNvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnb25QYXJ0aWNpcGFudFVucHVibGlzaGVkJylcblxuICAgICAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUV2ZW50ID0gbmV3IFN0cmVhbUV2ZW50KHRydWUsIHRoaXMsICdzdHJlYW1EZXN0cm95ZWQnLCBjb25uZWN0aW9uLnN0cmVhbSEsIGV2ZW50LnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1EZXN0cm95ZWQnLCBbc3RyZWFtRXZlbnRdKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtRXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0aW5nIHRoZSByZW1vdGUgc3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbUlkOiBzdHJpbmcgPSBjb25uZWN0aW9uLnN0cmVhbSEuc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc0NyZWF0ZWQuZGVsZXRlKHN0cmVhbUlkKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uLnJlbW92ZVN0cmVhbShzdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblBhcnRpY2lwYW50RXZpY3RlZChldmVudDogeyBjb25uZWN0aW9uSWQ6IHN0cmluZywgcmVhc29uOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAvLyBZb3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgc2Vzc2lvblxuICAgICAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uSWQgJiYgIXRoaXMuY29ubmVjdGlvbi5kaXNwb3NlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGVhdmUodHJ1ZSwgZXZlbnQucmVhc29uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk5ld01lc3NhZ2UoZXZlbnQ6IHsgdHlwZT86IHN0cmluZywgZGF0YT86IHN0cmluZywgZnJvbT86IHN0cmluZyB9KTogdm9pZCB7XG5cbiAgICAgICAgbG9nZ2VyLmluZm8oJ05ldyBzaWduYWw6ICcgKyBKU09OLnN0cmluZ2lmeShldmVudCkpO1xuXG4gICAgICAgIGNvbnN0IHN0cmlwcGVkVHlwZSA9ICEhZXZlbnQudHlwZSA/IGV2ZW50LnR5cGUucmVwbGFjZSgvXihzaWduYWw6KS8sICcnKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAoISFldmVudC5mcm9tKSB7XG4gICAgICAgICAgICAvLyBTaWduYWwgc2VudCBieSBvdGhlciBjbGllbnRcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29ubmVjdGlvbihldmVudC5mcm9tLCBcIkNvbm5lY3Rpb24gJ1wiICsgZXZlbnQuZnJvbSArIFwiJyB1bmtub3duIHdoZW4gJ29uTmV3TWVzc2FnZScuIEV4aXN0aW5nIHJlbW90ZSBjb25uZWN0aW9uczogXCJcbiAgICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KHRoaXMucmVtb3RlQ29ubmVjdGlvbnMua2V5cygpKSArICcuIEV4aXN0aW5nIGxvY2FsIGNvbm5lY3Rpb246ICcgKyB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKVxuXG4gICAgICAgICAgICAgICAgLnRoZW4oY29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzaWduYWwnLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIHN0cmlwcGVkVHlwZSwgZXZlbnQuZGF0YSwgY29ubmVjdGlvbildKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXZlbnQudHlwZSAmJiBldmVudC50eXBlICE9PSAnc2lnbmFsJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoZXZlbnQudHlwZSwgW25ldyBTaWduYWxFdmVudCh0aGlzLCBzdHJpcHBlZFR5cGUsIGV2ZW50LmRhdGEsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gU2lnbmFsIHNlbnQgYnkgc2VydmVyXG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc2lnbmFsJywgW25ldyBTaWduYWxFdmVudCh0aGlzLCBzdHJpcHBlZFR5cGUsIGV2ZW50LmRhdGEsIHVuZGVmaW5lZCldKTtcbiAgICAgICAgICAgIGlmICghIWV2ZW50LnR5cGUgJiYgZXZlbnQudHlwZSAhPT0gJ3NpZ25hbCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudChldmVudC50eXBlLCBbbmV3IFNpZ25hbEV2ZW50KHRoaXMsIHN0cmlwcGVkVHlwZSwgZXZlbnQuZGF0YSwgdW5kZWZpbmVkKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uU3RyZWFtUHJvcGVydHlDaGFuZ2VkKGV2ZW50OiB7IGNvbm5lY3Rpb25JZDogc3RyaW5nLCBzdHJlYW1JZDogc3RyaW5nLCBwcm9wZXJ0eTogc3RyaW5nLCBuZXdWYWx1ZTogYW55LCByZWFzb246IHN0cmluZyB9KTogdm9pZCB7XG5cbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPSAoY29ubmVjdGlvbjogQ29ubmVjdGlvbikgPT4ge1xuICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0gJiYgY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQgPT09IGV2ZW50LnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW07XG4gICAgICAgICAgICAgICAgbGV0IG9sZFZhbHVlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQucHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnYXVkaW9BY3RpdmUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBzdHJlYW0uYXVkaW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IGV2ZW50Lm5ld1ZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uYXVkaW9BY3RpdmUgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd2aWRlb0FjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0FjdGl2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50Lm5ld1ZhbHVlID0gZXZlbnQubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS52aWRlb0FjdGl2ZSA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3ZpZGVvRGltZW5zaW9ucyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS52aWRlb0RpbWVuc2lvbnM7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IEpTT04ucGFyc2UoSlNPTi5wYXJzZShldmVudC5uZXdWYWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnZpZGVvRGltZW5zaW9ucyA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2ZpbHRlcic6XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHN0cmVhbS5maWx0ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5uZXdWYWx1ZSA9IChPYmplY3Qua2V5cyhldmVudC5uZXdWYWx1ZSkubGVuZ3RoID4gMCkgPyBldmVudC5uZXdWYWx1ZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5uZXdWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlciA9IG5ldyBGaWx0ZXIoZXZlbnQubmV3VmFsdWUudHlwZSwgZXZlbnQubmV3VmFsdWUub3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLmZpbHRlci5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50Lm5ld1ZhbHVlLmxhc3RFeGVjTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5maWx0ZXIubGFzdEV4ZWNNZXRob2QgPSBldmVudC5uZXdWYWx1ZS5sYXN0RXhlY01ldGhvZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0uZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQubmV3VmFsdWUgPSBzdHJlYW0uZmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHN0cmVhbSwgZXZlbnQucHJvcGVydHksIGV2ZW50Lm5ld1ZhbHVlLCBvbGRWYWx1ZSwgZXZlbnQucmVhc29uKV0pO1xuICAgICAgICAgICAgICAgIGlmICghIXN0cmVhbS5zdHJlYW1NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbS5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudChzdHJlYW0uc3RyZWFtTWFuYWdlciwgc3RyZWFtLCBldmVudC5wcm9wZXJ0eSwgZXZlbnQubmV3VmFsdWUsIG9sZFZhbHVlLCBldmVudC5yZWFzb24pXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJObyBzdHJlYW0gd2l0aCBzdHJlYW1JZCAnXCIgKyBldmVudC5zdHJlYW1JZCArIFwiJyBmb3VuZCBmb3IgY29ubmVjdGlvbiAnXCIgKyBldmVudC5jb25uZWN0aW9uSWQgKyBcIicgb24gJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcgZXZlbnRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGV2ZW50LmNvbm5lY3Rpb25JZCA9PT0gdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCkge1xuICAgICAgICAgICAgLy8gWW91ciBzdHJlYW0gaGFzIGJlZW4gZm9yY2VkbHkgY2hhbmdlZCAoZmlsdGVyIGZlYXR1cmUpXG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKGV2ZW50LmNvbm5lY3Rpb25JZCwgJ29uU3RyZWFtUHJvcGVydHlDaGFuZ2VkJylcbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkNvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWQoZXZlbnQ6IHsgcHJvcGVydHk6IHN0cmluZywgbmV3VmFsdWU6IGFueSB9KTogdm9pZCB7XG4gICAgICAgIGxldCBvbGRWYWx1ZTtcbiAgICAgICAgc3dpdGNoIChldmVudC5wcm9wZXJ0eSkge1xuICAgICAgICAgICAgY2FzZSAncm9sZSc6XG4gICAgICAgICAgICAgICAgb2xkVmFsdWUgPSB0aGlzLmNvbm5lY3Rpb24ucm9sZS5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5yb2xlID0gZXZlbnQubmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmxvY2FsT3B0aW9ucyEucm9sZSA9IGV2ZW50Lm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncmVjb3JkJzpcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZSA9IHRoaXMuY29ubmVjdGlvbi5yZWNvcmQ7XG4gICAgICAgICAgICAgICAgZXZlbnQubmV3VmFsdWUgPSBldmVudC5uZXdWYWx1ZSA9PT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5yZWNvcmQgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24ubG9jYWxPcHRpb25zIS5yZWNvcmQgPSBldmVudC5uZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZCcsIFtuZXcgQ29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMsIHRoaXMuY29ubmVjdGlvbiwgZXZlbnQucHJvcGVydHksIGV2ZW50Lm5ld1ZhbHVlLCBvbGRWYWx1ZSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25OZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZENoYW5nZWQoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIG5ld1ZhbHVlOiBudW1iZXIsIG9sZFZhbHVlOiBudW1iZXIgfSk6IHZvaWQge1xuICAgICAgICBpZiAoZXZlbnQuY29ubmVjdGlvbklkID09PSB0aGlzLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnbmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWQnLCBbbmV3IE5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQodGhpcywgZXZlbnQubmV3VmFsdWUsIGV2ZW50Lm9sZFZhbHVlLCB0aGlzLmNvbm5lY3Rpb24pXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24oZXZlbnQuY29ubmVjdGlvbklkLCAnQ29ubmVjdGlvbiBub3QgZm91bmQgZm9yIGNvbm5lY3Rpb25JZCAnICsgZXZlbnQuY29ubmVjdGlvbklkKVxuICAgICAgICAgICAgICAgIC50aGVuKChjb25uZWN0aW9uOiBDb25uZWN0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCduZXR3b3JrUXVhbGl0eUxldmVsQ2hhbmdlZCcsIFtuZXcgTmV0d29ya1F1YWxpdHlMZXZlbENoYW5nZWRFdmVudCh0aGlzLCBldmVudC5uZXdWYWx1ZSwgZXZlbnQub2xkVmFsdWUsIGNvbm5lY3Rpb24pXSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gob3BlblZpZHVFcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihvcGVuVmlkdUVycm9yKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWN2SWNlQ2FuZGlkYXRlKGV2ZW50OiB7IHNlbmRlckNvbm5lY3Rpb25JZDogc3RyaW5nLCBlbmRwb2ludE5hbWU6IHN0cmluZywgc2RwTUxpbmVJbmRleDogbnVtYmVyLCBzZHBNaWQ6IHN0cmluZywgY2FuZGlkYXRlOiBzdHJpbmcgfSk6IHZvaWQge1xuICAgICAgICAvLyBUaGUgZXZlbnQgY29udGFpbnMgZmllbGRzIHRoYXQgY2FuIGJlIHVzZWQgdG8gb2J0YWluIGEgcHJvcGVyIGNhbmRpZGF0ZSxcbiAgICAgICAgLy8gdXNpbmcgdGhlIFJUQ0ljZUNhbmRpZGF0ZSBjb25zdHJ1Y3RvcjpcbiAgICAgICAgLy8gaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jZG9tLXJ0Y2ljZWNhbmRpZGF0ZS1jb25zdHJ1Y3RvclxuICAgICAgICBjb25zdCBjYW5kaWRhdGVJbml0OiBSVENJY2VDYW5kaWRhdGVJbml0ID0ge1xuICAgICAgICAgICAgY2FuZGlkYXRlOiBldmVudC5jYW5kaWRhdGUsXG4gICAgICAgICAgICBzZHBNTGluZUluZGV4OiBldmVudC5zZHBNTGluZUluZGV4LFxuICAgICAgICAgICAgc2RwTWlkOiBldmVudC5zZHBNaWQsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGljZUNhbmRpZGF0ZSA9IG5ldyBSVENJY2VDYW5kaWRhdGUoY2FuZGlkYXRlSW5pdCk7XG5cbiAgICAgICAgdGhpcy5nZXRDb25uZWN0aW9uKGV2ZW50LnNlbmRlckNvbm5lY3Rpb25JZCwgJ0Nvbm5lY3Rpb24gbm90IGZvdW5kIGZvciBjb25uZWN0aW9uSWQgJyArIGV2ZW50LnNlbmRlckNvbm5lY3Rpb25JZCArICcgb3duaW5nIGVuZHBvaW50ICcgKyBldmVudC5lbmRwb2ludE5hbWUgKyAnLiBJY2UgY2FuZGlkYXRlIHdpbGwgYmUgaWdub3JlZDogJyArIGljZUNhbmRpZGF0ZSlcbiAgICAgICAgICAgIC50aGVuKGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbTogU3RyZWFtID0gY29ubmVjdGlvbi5zdHJlYW0hO1xuICAgICAgICAgICAgICAgIHN0cmVhbS5nZXRXZWJSdGNQZWVyKCkuYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGFkZGluZyBjYW5kaWRhdGUgZm9yICcgKyBzdHJlYW0hLnN0cmVhbUlkXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgc3RyZWFtIG9mIGVuZHBvaW50ICcgKyBldmVudC5lbmRwb2ludE5hbWUgKyAnOiAnICsgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3Iob3BlblZpZHVFcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25TZXNzaW9uQ2xvc2VkKG1zZyk6IHZvaWQge1xuICAgICAgICBsb2dnZXIuaW5mbygnU2Vzc2lvbiBjbG9zZWQ6ICcgKyBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgY29uc3QgcyA9IG1zZy5zZXNzaW9uSWQ7XG4gICAgICAgIGlmIChzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzZXNzaW9uLWNsb3NlZCcsIFt7XG4gICAgICAgICAgICAgICAgc2Vzc2lvbjogc1xuICAgICAgICAgICAgfV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1Nlc3Npb24gdW5kZWZpbmVkIG9uIHNlc3Npb24gY2xvc2VkJywgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbkxvc3RDb25uZWN0aW9uKHJlYXNvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdMb3N0IGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICBpZiAoISF0aGlzLnNlc3Npb25JZCAmJiAhIXRoaXMuY29ubmVjdGlvbiAmJiAhdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICB0aGlzLmxlYXZlKHRydWUsIHJlYXNvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25SZWNvdmVyZWRDb25uZWN0aW9uKCk6IHZvaWQge1xuICAgICAgICBsb2dnZXIuaW5mbygnUmVjb3ZlcmVkIGNvbm5lY3Rpb24gaW4gU2Vzc2lvbiAnICsgdGhpcy5zZXNzaW9uSWQpO1xuICAgICAgICB0aGlzLnJlY29ubmVjdEJyb2tlblN0cmVhbXMoKTtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29ubmVjdGVkJywgW10pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvbk1lZGlhRXJyb3IoZXZlbnQ6IHsgZXJyb3I6IHN0cmluZyB9KTogdm9pZCB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignTWVkaWEgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShldmVudCkpO1xuICAgICAgICBjb25zdCBlcnIgPSBldmVudC5lcnJvcjtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Vycm9yLW1lZGlhJywgW3tcbiAgICAgICAgICAgICAgICBlcnJvcjogZXJyXG4gICAgICAgICAgICB9XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybignUmVjZWl2ZWQgdW5kZWZpbmVkIG1lZGlhIGVycm9yOicsIGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBvblJlY29yZGluZ1N0YXJ0ZWQoZXZlbnQ6IHsgaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0YXJ0ZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdGFydGVkJywgZXZlbnQuaWQsIGV2ZW50Lm5hbWUpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG9uUmVjb3JkaW5nU3RvcHBlZChldmVudDogeyBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHJlYXNvbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3JlY29yZGluZ1N0b3BwZWQnLCBbbmV3IFJlY29yZGluZ0V2ZW50KHRoaXMsICdyZWNvcmRpbmdTdG9wcGVkJywgZXZlbnQuaWQsIGV2ZW50Lm5hbWUsIGV2ZW50LnJlYXNvbildKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25GaWx0ZXJFdmVudERpc3BhdGNoZWQoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIHN0cmVhbUlkOiBzdHJpbmcsIGZpbHRlclR5cGU6IHN0cmluZywgZXZlbnRUeXBlOiBzdHJpbmcsIGRhdGE6IHN0cmluZyB9KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25JZDogc3RyaW5nID0gZXZlbnQuY29ubmVjdGlvbklkO1xuICAgICAgICB0aGlzLmdldENvbm5lY3Rpb24oY29ubmVjdGlvbklkLCAnTm8gY29ubmVjdGlvbiBmb3VuZCBmb3IgY29ubmVjdGlvbklkICcgKyBjb25uZWN0aW9uSWQpXG4gICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgRmlsdGVyIGV2ZW50IG9mIHR5cGUgXCIke2V2ZW50LmV2ZW50VHlwZX1cIiBkaXNwYXRjaGVkYCk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtOiBTdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbSE7XG4gICAgICAgICAgICAgICAgaWYgKCFzdHJlYW0gfHwgIXN0cmVhbS5maWx0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxvZ2dlci5lcnJvcihgRmlsdGVyIGV2ZW50IG9mIHR5cGUgXCIke2V2ZW50LmV2ZW50VHlwZX1cIiBkaXNwYXRjaGVkIGZvciBzdHJlYW0gJHtzdHJlYW0uc3RyZWFtSWR9IGJ1dCB0aGVyZSBpcyBubyAkeyFzdHJlYW0gPyAnc3RyZWFtJyA6ICdmaWx0ZXInfSBkZWZpbmVkYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50SGFuZGxlciA9IHN0cmVhbS5maWx0ZXIuaGFuZGxlcnMuZ2V0KGV2ZW50LmV2ZW50VHlwZSk7XG4gICAgICAgICAgICAgICAgaWYgKCFldmVudEhhbmRsZXIgfHwgdHlwZW9mIGV2ZW50SGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3R1YWxIYW5kbGVyczogc3RyaW5nW10gPSBBcnJheS5mcm9tKHN0cmVhbS5maWx0ZXIuaGFuZGxlcnMua2V5cygpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxvZ2dlci5lcnJvcihgRmlsdGVyIGV2ZW50IG9mIHR5cGUgXCIke2V2ZW50LmV2ZW50VHlwZX1cIiBub3QgaGFuZGxlZCBvciBub3QgYSBmdW5jdGlvbiEgQWN0aXZlIGZpbHRlciBldmVudHM6ICR7YWN0dWFsSGFuZGxlcnMuam9pbignLCcpfWApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50SGFuZGxlci5jYWxsKHRoaXMsIG5ldyBGaWx0ZXJFdmVudChzdHJlYW0uZmlsdGVyLCBldmVudC5ldmVudFR5cGUsIGV2ZW50LmRhdGEpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXIoZXZlbnQ6IHsgY29ubmVjdGlvbklkOiBzdHJpbmcsIHN0cmVhbUlkOiBzdHJpbmcsIHNkcE9mZmVyOiBzdHJpbmcgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5nZXRSZW1vdGVDb25uZWN0aW9uKGV2ZW50LmNvbm5lY3Rpb25JZCwgJ29uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyJylcbiAgICAgICAgICAgICAgICAudGhlbihjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhY29ubmVjdGlvbi5zdHJlYW0gJiYgY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQgPT09IGV2ZW50LnN0cmVhbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBjb25uZWN0aW9uLnN0cmVhbTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmVhbS5zZXR1cFJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcihyZXNvbHZlLCByZWplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25nb2luZyByZWNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXYWl0IGZvciB0aGUgZXZlbnQgZW1pdHRlciB0byBiZSBmcmVlICh3aXRoIHN1Y2Nlc3Mgb3IgZXJyb3IpIGFuZCBjYWxsIHRoZSBtZXRob2QgYWdhaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZWFtLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciFbJ29uRm9yY2libHlSZWNvbm5lY3RTdWJzY3JpYmVyTGFzdEV2ZW50J10gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUd28gb3IgbW9yZSBvbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlciBldmVudHMgd2VyZSByZWNlaXZlZCB3aGlsZSBhIHJlY29ubmVjdGlvbiBwcm9jZXNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHRoZSBzdWJzY3JpYmVyIHdhcyBhbHJlYWR5IHRha2luZyBwbGFjZS4gQWx3YXlzIHVzZSB0aGUgbGFzdCBvbmUgdG8gcmV0cnkgdGhlIHJlLXN1YnNjcmlwdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9jZXNzLCBhcyB0aGF0IFNEUCBvZmZlciB3aWxsIGJlIHRoZSBvbmx5IG9uZSBhdmFpbGFibGUgYXQgdGhlIHNlcnZlciBzaWRlLiBJZ25vcmUgcHJldmlvdXMgb25lc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIVsnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXJMYXN0RXZlbnQnXSA9IGV2ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KCdPbmdvaW5nIGZvcmNlZCBzdWJzY3JpYmVyIHJlY29ubmVjdGlvbicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSBvbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlciBldmVuIGhhcyBiZWVuIHJlY2VpdmVkIHdoaWxlIGEgcmVjb25uZWN0aW9uIHByb2Nlc3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhlIHN1YnNjcmliZXIgd2FzIGFscmVhZHkgdGFraW5nIHBsYWNlLiBTZXQgdXAgYSBsaXN0ZW5lciB0byB3YWl0IGZvciBpdCB0byByZXRyeSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yY2VkIHJlY29ubmVjdGlvbiBwcm9jZXNzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXIhWydvbkZvcmNpYmx5UmVjb25uZWN0U3Vic2NyaWJlckxhc3RFdmVudCddID0gZXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRBdXggPSBzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIVsnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXJMYXN0RXZlbnQnXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzdHJlYW0ucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyIVsnb25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXJMYXN0RXZlbnQnXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25Gb3JjaWJseVJlY29ubmVjdFN1YnNjcmliZXIoZXZlbnRBdXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXIhLm9uY2UoJ3N1Y2Nlc3MnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciEub25jZSgnZXJyb3InLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW0uY29tcGxldGVXZWJSdGNQZWVyUmVjZWl2ZSh0cnVlLCB0cnVlLCBldmVudC5zZHBPZmZlcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBzdHJlYW0uZmluYWxSZXNvbHZlRm9yU3Vic2NyaXB0aW9uKHRydWUsIHJlc29sdmUpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiBzdHJlYW0uZmluYWxSZWplY3RGb3JTdWJzY3JpcHRpb24odHJ1ZSwgYEVycm9yIHdoaWxlIGZvcmNpYmx5IHJlY29ubmVjdGluZyByZW1vdGUgc3RyZWFtICR7ZXZlbnQuc3RyZWFtSWR9OiAke2Vycm9yLnRvU3RyaW5nKCl9YCwgcmVqZWN0KSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJNc2cgPSBcIk5vIHN0cmVhbSB3aXRoIHN0cmVhbUlkICdcIiArIGV2ZW50LnN0cmVhbUlkICsgXCInIGZvdW5kIGZvciBjb25uZWN0aW9uICdcIiArIGV2ZW50LmNvbm5lY3Rpb25JZCArIFwiJyBvbiAnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJyBldmVudFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGVyck1zZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVyck1zZyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChvcGVuVmlkdUVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG9wZW5WaWR1RXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVjb25uZWN0QnJva2VuU3RyZWFtcygpOiB2b2lkIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ1JlLWVzdGFibGlzaGluZyBtZWRpYSBjb25uZWN0aW9ucy4uLicpO1xuICAgICAgICBsZXQgc29tZVJlY29ubmVjdGlvbiA9IGZhbHNlO1xuICAgICAgICAvLyBSZS1lc3RhYmxpc2ggUHVibGlzaGVyIHN0cmVhbVxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24uc3RyZWFtICYmIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWNlQ29ubmVjdGlvblN0YXRlQnJva2VuKCkpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdSZS1lc3RhYmxpc2hpbmcgUHVibGlzaGVyICcgKyB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLnN0cmVhbUlkKTtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uaW5pdFdlYlJ0Y1BlZXJTZW5kKHRydWUpO1xuICAgICAgICAgICAgc29tZVJlY29ubmVjdGlvbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmUtZXN0YWJsaXNoIFN1YnNjcmliZXIgc3RyZWFtc1xuICAgICAgICB0aGlzLnJlbW90ZUNvbm5lY3Rpb25zLmZvckVhY2gocmVtb3RlQ29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICBpZiAoISFyZW1vdGVDb25uZWN0aW9uLnN0cmVhbSAmJiByZW1vdGVDb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JY2VDb25uZWN0aW9uU3RhdGVCcm9rZW4oKSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdSZS1lc3RhYmxpc2hpbmcgU3Vic2NyaWJlciAnICsgcmVtb3RlQ29ubmVjdGlvbi5zdHJlYW0uc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIHJlbW90ZUNvbm5lY3Rpb24uc3RyZWFtLmluaXRXZWJSdGNQZWVyUmVjZWl2ZSh0cnVlKTtcbiAgICAgICAgICAgICAgICBzb21lUmVjb25uZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghc29tZVJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1RoZXJlIHdlcmUgbm8gbWVkaWEgc3RyZWFtcyBpbiBuZWVkIG9mIGEgcmVjb25uZWN0aW9uJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW1pdEV2ZW50KHR5cGU6IHN0cmluZywgZXZlbnRBcnJheTogYW55W10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQodHlwZSwgZXZlbnRBcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxlYXZlKGZvcmNlZDogYm9vbGVhbiwgcmVhc29uOiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBmb3JjZWQgPSAhIWZvcmNlZDtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ0xlYXZpbmcgU2Vzc2lvbiAoZm9yY2VkPScgKyBmb3JjZWQgKyAnKScpO1xuICAgICAgICB0aGlzLnN0b3BWaWRlb0RhdGFJbnRlcnZhbHMoKTtcblxuICAgICAgICBpZiAoISF0aGlzLmNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkICYmICFmb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdsZWF2ZVJvb20nLCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBsZWF2ZVJvb20gZXJyb3I6ICR7SlNPTi5zdHJpbmdpZnkoZXJyb3IpfWApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuY2xvc2VXcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmNsb3NlV3MoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zdG9wUHVibGlzaGVyU3RyZWFtKHJlYXNvbik7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25uZWN0aW9uLmRpc3Bvc2VkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBTZXNzaW9uIG9iamVjdCBkaXNwYXRjaCAnc2Vzc2lvbkRpc2Nvbm5lY3RlZCcgZXZlbnQgKGlmIGl0IGlzIG5vdCBhbHJlYWR5IGRpc3Bvc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25EaXNjb25uZWN0RXZlbnQgPSBuZXcgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50KHRoaXMsIHJlYXNvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3Nlc3Npb25EaXNjb25uZWN0ZWQnLCBbc2Vzc2lvbkRpc2Nvbm5lY3RFdmVudF0pO1xuICAgICAgICAgICAgICAgIHNlc3Npb25EaXNjb25uZWN0RXZlbnQuY2FsbERlZmF1bHRCZWhhdmlvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1lvdSB3ZXJlIG5vdCBjb25uZWN0ZWQgdG8gdGhlIHNlc3Npb24gJyArIHRoaXMuc2Vzc2lvbklkKTtcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuZmx1c2goKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZVBhcmFtcyh0b2tlbjogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IGpvaW5QYXJhbXMgPSB7XG4gICAgICAgICAgICB0b2tlbjogKCEhdG9rZW4pID8gdG9rZW4gOiAnJyxcbiAgICAgICAgICAgIHNlc3Npb246IHRoaXMuc2Vzc2lvbklkLFxuICAgICAgICAgICAgcGxhdGZvcm06ICEhcGxhdGZvcm0uZ2V0RGVzY3JpcHRpb24oKSA/IHBsYXRmb3JtLmdldERlc2NyaXB0aW9uKCkgOiAndW5rbm93bicsXG4gICAgICAgICAgICBzZGtWZXJzaW9uOiB0aGlzLm9wZW52aWR1LmxpYnJhcnlWZXJzaW9uLFxuICAgICAgICAgICAgbWV0YWRhdGE6ICEhdGhpcy5vcHRpb25zLm1ldGFkYXRhID8gdGhpcy5vcHRpb25zLm1ldGFkYXRhIDogJycsXG4gICAgICAgICAgICBzZWNyZXQ6IHRoaXMub3BlbnZpZHUuZ2V0U2VjcmV0KCksXG4gICAgICAgICAgICByZWNvcmRlcjogdGhpcy5vcGVudmlkdS5nZXRSZWNvcmRlcigpXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBqb2luUGFyYW1zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZW5kVmlkZW9EYXRhKHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXIsIGludGVydmFsU2Vjb25kczogbnVtYmVyID0gMSwgZG9JbnRlcnZhbDogYm9vbGVhbiA9IGZhbHNlLCBtYXhMb29wczogbnVtYmVyID0gMSkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBwbGF0Zm9ybS5pc0Nocm9tZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0Nocm9tZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc09wZXJhQnJvd3NlcigpIHx8XG4gICAgICAgICAgICBwbGF0Zm9ybS5pc09wZXJhTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWRnZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0VkZ2VNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFbGVjdHJvbigpIHx8XG4gICAgICAgICAgICAocGxhdGZvcm0uaXNTYWZhcmlCcm93c2VyKCkgJiYgIXBsYXRmb3JtLmlzSW9uaWNJb3MoKSkgfHwgcGxhdGZvcm0uaXNBbmRyb2lkQnJvd3NlcigpIHx8XG4gICAgICAgICAgICBwbGF0Zm9ybS5pc1NhbXN1bmdCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNJb25pY0FuZHJvaWQoKSB8fCBwbGF0Zm9ybS5pc0lPU1dpdGhTYWZhcmkoKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IG9idGFpbkFuZFNlbmRWaWRlbyA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYyA9IHN0cmVhbU1hbmFnZXIuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKHBjLmNvbm5lY3Rpb25TdGF0ZSA9PT0gJ2Nvbm5lY3RlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhdHNNYXAgPSBhd2FpdCBwYy5nZXRTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhcnI6IGFueVtdID0gW107XG4gICAgICAgICAgICAgICAgICAgIHN0YXRzTWFwLmZvckVhY2goc3RhdHMgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChcImZyYW1lV2lkdGhcIiBpbiBzdGF0cykgJiYgKFwiZnJhbWVIZWlnaHRcIiBpbiBzdGF0cykgJiYgKGFyci5sZW5ndGggPT09IDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyLnB1c2goc3RhdHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFyci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd2aWRlb0RhdGEnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBhcnJbMF0uZnJhbWVIZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGFyclswXS5mcmFtZVdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiBzdHJlYW1NYW5hZ2VyLnN0cmVhbS52aWRlb0FjdGl2ZSAhPSBudWxsID8gc3RyZWFtTWFuYWdlci5zdHJlYW0udmlkZW9BY3RpdmUgOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogc3RyZWFtTWFuYWdlci5zdHJlYW0uYXVkaW9BY3RpdmUgIT0gbnVsbCA/IHN0cmVhbU1hbmFnZXIuc3RyZWFtLmF1ZGlvQWN0aXZlIDogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRXJyb3Igc2VuZGluZyAndmlkZW9EYXRhJyBldmVudFwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZG9JbnRlcnZhbCkge1xuICAgICAgICAgICAgICAgIGxldCBsb29wcyA9IDE7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RhdGFJbnRlcnZhbCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvb3BzIDwgbWF4TG9vcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnRhaW5BbmRTZW5kVmlkZW8oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy52aWRlb0RhdGFJbnRlcnZhbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LCBpbnRlcnZhbFNlY29uZHMgKiAxMDAwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0RhdGFUaW1lb3V0ID0gc2V0VGltZW91dChvYnRhaW5BbmRTZW5kVmlkZW8sIGludGVydmFsU2Vjb25kcyAqIDEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHBsYXRmb3JtLmlzRmlyZWZveEJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc0ZpcmVmb3hNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNJb25pY0lvcygpIHx8IHBsYXRmb3JtLmlzUmVhY3ROYXRpdmUoKSkge1xuICAgICAgICAgICAgLy8gQmFzaWMgdmVyc2lvbiBmb3IgRmlyZWZveCBhbmQgSW9uaWMgaU9TLiBUaGV5IGRvIG5vdCBzdXBwb3J0IHN0YXRzXG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCd2aWRlb0RhdGEnLCB7XG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBzdHJlYW1NYW5hZ2VyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnM/LmhlaWdodCB8fCAwLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBzdHJlYW1NYW5hZ2VyLnN0cmVhbS52aWRlb0RpbWVuc2lvbnM/LndpZHRoIHx8IDAsXG4gICAgICAgICAgICAgICAgdmlkZW9BY3RpdmU6IHN0cmVhbU1hbmFnZXIuc3RyZWFtLnZpZGVvQWN0aXZlICE9IG51bGwgPyBzdHJlYW1NYW5hZ2VyLnN0cmVhbS52aWRlb0FjdGl2ZSA6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGF1ZGlvQWN0aXZlOiBzdHJlYW1NYW5hZ2VyLnN0cmVhbS5hdWRpb0FjdGl2ZSAhPSBudWxsID8gc3RyZWFtTWFuYWdlci5zdHJlYW0uYXVkaW9BY3RpdmUgOiBmYWxzZVxuICAgICAgICAgICAgfSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBzZW5kaW5nICd2aWRlb0RhdGEnIGV2ZW50XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignQnJvd3NlciAnICsgcGxhdGZvcm0uZ2V0TmFtZSgpICsgJyAodmVyc2lvbiAnICsgcGxhdGZvcm0uZ2V0VmVyc2lvbigpICsgJykgZm9yICcgKyBwbGF0Zm9ybS5nZXRGYW1pbHkoKSArICcgaXMgbm90IHN1cHBvcnRlZCBpbiBPcGVuVmlkdSBmb3IgTmV0d29yayBRdWFsaXR5Jyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc2Vzc2lvbkNvbm5lY3RlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbiAhPSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBub3RDb25uZWN0ZWRFcnJvcigpOiBPcGVuVmlkdUVycm9yIHtcbiAgICAgICAgcmV0dXJuIG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLk9QRU5WSURVX05PVF9DT05ORUNURUQsIFwiVGhlcmUgaXMgbm8gY29ubmVjdGlvbiB0byB0aGUgc2Vzc2lvbi4gTWV0aG9kICdTZXNzaW9uLmNvbm5lY3QnIG11c3QgYmUgc3VjY2Vzc2Z1bGx5IGNvbXBsZXRlZCBmaXJzdFwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYW55U3BlZWNoRXZlbnRMaXN0ZW5lckVuYWJsZWQoZXZlbnQ6IHN0cmluZywgb25seU9uY2U6IGJvb2xlYW4sIHN0cmVhbU1hbmFnZXI/OiBTdHJlYW1NYW5hZ2VyKTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBoYW5kbGVyc0luU2Vzc2lvbiA9IHRoaXMuZWUuZ2V0TGlzdGVuZXJzKGV2ZW50KTtcbiAgICAgICAgaWYgKG9ubHlPbmNlKSB7XG4gICAgICAgICAgICBoYW5kbGVyc0luU2Vzc2lvbiA9IGhhbmRsZXJzSW5TZXNzaW9uLmZpbHRlcihoID0+IChoIGFzIGFueSkub25jZSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGxpc3RlbmVyc0luU2Vzc2lvbiA9IGhhbmRsZXJzSW5TZXNzaW9uLmxlbmd0aDtcbiAgICAgICAgaWYgKGxpc3RlbmVyc0luU2Vzc2lvbiA+IDApIHJldHVybiB0cnVlO1xuICAgICAgICBsZXQgbGlzdGVuZXJzSW5TdHJlYW1NYW5hZ2VyID0gMDtcbiAgICAgICAgaWYgKCEhc3RyZWFtTWFuYWdlcikge1xuICAgICAgICAgICAgbGV0IGhhbmRsZXJzSW5TdHJlYW1NYW5hZ2VyID0gc3RyZWFtTWFuYWdlci5lZS5nZXRMaXN0ZW5lcnMoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKG9ubHlPbmNlKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlcnNJblN0cmVhbU1hbmFnZXIgPSBoYW5kbGVyc0luU3RyZWFtTWFuYWdlci5maWx0ZXIoaCA9PiAoaCBhcyBhbnkpLm9uY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGlzdGVuZXJzSW5TdHJlYW1NYW5hZ2VyID0gaGFuZGxlcnNJblN0cmVhbU1hbmFnZXIubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaXN0ZW5lcnNJblN0cmVhbU1hbmFnZXIgPiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRUb2tlblBhcmFtcyh0b2tlbjogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gdG9rZW4ubWF0Y2goL14od3NzP1xcOilcXC9cXC8oKFteOlxcLz8jXSopKD86XFw6KFswLTldKykpPykoW1xcL117MCwxfVtePyNdKikoXFw/W14jXSp8KSgjLip8KSQvKTtcbiAgICAgICAgaWYgKCEhbWF0Y2gpIHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHtcbiAgICAgICAgICAgICAgICBwcm90b2NvbDogbWF0Y2hbMV0sXG4gICAgICAgICAgICAgICAgaG9zdDogbWF0Y2hbMl0sXG4gICAgICAgICAgICAgICAgaG9zdG5hbWU6IG1hdGNoWzNdLFxuICAgICAgICAgICAgICAgIHBvcnQ6IG1hdGNoWzRdLFxuICAgICAgICAgICAgICAgIHBhdGhuYW1lOiBtYXRjaFs1XSxcbiAgICAgICAgICAgICAgICBzZWFyY2g6IG1hdGNoWzZdLFxuICAgICAgICAgICAgICAgIGhhc2g6IG1hdGNoWzddXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB0b2tlbi5zcGxpdCgnPycpO1xuICAgICAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSBkZWNvZGVVUkkocGFyYW1zWzFdKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnJicpXG4gICAgICAgICAgICAgICAgLm1hcChwYXJhbSA9PiBwYXJhbS5zcGxpdCgnPScpKVxuICAgICAgICAgICAgICAgIC5yZWR1Y2UoKHZhbHVlcywgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlc1trZXldID0gdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlc1xuICAgICAgICAgICAgICAgIH0sIHt9KTtcblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IHF1ZXJ5UGFyYW1zWydzZXNzaW9uSWQnXSxcbiAgICAgICAgICAgICAgICBzZWNyZXQ6IHF1ZXJ5UGFyYW1zWydzZWNyZXQnXSxcbiAgICAgICAgICAgICAgICByZWNvcmRlcjogcXVlcnlQYXJhbXNbJ3JlY29yZGVyJ10sXG4gICAgICAgICAgICAgICAgd2VicnRjU3RhdHNJbnRlcnZhbDogcXVlcnlQYXJhbXNbJ3dlYnJ0Y1N0YXRzSW50ZXJ2YWwnXSxcbiAgICAgICAgICAgICAgICBzZW5kQnJvd3NlckxvZ3M6IHF1ZXJ5UGFyYW1zWydzZW5kQnJvd3NlckxvZ3MnXSxcbiAgICAgICAgICAgICAgICBlZGl0aW9uOiBxdWVyeVBhcmFtc1snZWRpdGlvbiddLFxuICAgICAgICAgICAgICAgIHdzVXJpOiAnd3NzOi8vJyArIHVybC5ob3N0ICsgJy9vcGVudmlkdScsXG4gICAgICAgICAgICAgICAgaHR0cFVyaTogJ2h0dHBzOi8vJyArIHVybC5ob3N0XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRva2VuIG5vdCB2YWxpZDogXCIke3Rva2VufVwiYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByaXZhdGUgY29ubmVjdEF1eCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnN0YXJ0V3MoKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBqb2luUGFyYW1zID0gdGhpcy5pbml0aWFsaXplUGFyYW1zKHRva2VuKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlbmRSZXF1ZXN0KCdqb2luUm9vbScsIGpvaW5QYXJhbXMsIChlcnJvciwgcmVzcG9uc2U6IExvY2FsQ29ubmVjdGlvbk9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJvY2VzcyBqb2luIHJvb20gcmVzcG9uc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NKb2luUm9vbVJlc3BvbnNlKHJlc3BvbnNlLCB0b2tlbik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIGxvY2FsIENvbm5lY3Rpb24gb2JqZWN0IHdpdGggdmFsdWVzIHJldHVybmVkIGJ5IG9wZW52aWR1LXNlcnZlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBDb25uZWN0aW9uKHRoaXMsIHJlc3BvbnNlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgcmVtb3RlIENvbm5lY3Rpb25zIHdpdGggdmFsdWUgcmV0dXJuZWQgYnkgb3BlbnZpZHUtc2VydmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW9uczogbmV3IEFycmF5PENvbm5lY3Rpb24+KCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbXM6IG5ldyBBcnJheTxTdHJlYW0+KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nUGFydGljaXBhbnRzOiBSZW1vdGVDb25uZWN0aW9uT3B0aW9uc1tdID0gcmVzcG9uc2UudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudHMuZm9yRWFjaCgocmVtb3RlQ29ubmVjdGlvbk9wdGlvbnM6IFJlbW90ZUNvbm5lY3Rpb25PcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBuZXcgQ29ubmVjdGlvbih0aGlzLCByZW1vdGVDb25uZWN0aW9uT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuc2V0KGNvbm5lY3Rpb24uY29ubmVjdGlvbklkLCBjb25uZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24uc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVN0cmVhbXNDcmVhdGVkLnNldChjb25uZWN0aW9uLnN0cmVhbS5zdHJlYW1JZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuc3RyZWFtcy5wdXNoKGNvbm5lY3Rpb24uc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3duICdjb25uZWN0aW9uQ3JlYXRlZCcgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnY29ubmVjdGlvbkNyZWF0ZWQnLCBbbmV3IENvbm5lY3Rpb25FdmVudChmYWxzZSwgdGhpcywgJ2Nvbm5lY3Rpb25DcmVhdGVkJywgdGhpcy5jb25uZWN0aW9uLCAnJyldKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9uZSAnY29ubmVjdGlvbkNyZWF0ZWQnIGV2ZW50IGZvciBlYWNoIGV4aXN0aW5nIGNvbm5lY3Rpb24gaW4gdGhlIHNlc3Npb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuY29ubmVjdGlvbnMuZm9yRWFjaChjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ2Nvbm5lY3Rpb25DcmVhdGVkJywgW25ldyBDb25uZWN0aW9uRXZlbnQoZmFsc2UsIHRoaXMsICdjb25uZWN0aW9uQ3JlYXRlZCcsIGNvbm5lY3Rpb24sICcnKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25lICdzdHJlYW1DcmVhdGVkJyBldmVudCBmb3IgZWFjaCBhY3RpdmUgc3RyZWFtIGluIHRoZSBzZXNzaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnN0cmVhbXMuZm9yRWFjaChzdHJlYW0gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtQ3JlYXRlZCcsIFtuZXcgU3RyZWFtRXZlbnQoZmFsc2UsIHRoaXMsICdzdHJlYW1DcmVhdGVkJywgc3RyZWFtLCAnJyldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BQdWJsaXNoZXJTdHJlYW0ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25uZWN0aW9uLnN0cmVhbSkge1xuICAgICAgICAgICAgLy8gRGlzcG9zZSBQdWJsaXNoZXIncyAgbG9jYWwgc3RyZWFtXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLnN0cmVhbS5pc0xvY2FsU3RyZWFtUHVibGlzaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gTWFrZSBQdWJsaXNoZXIgb2JqZWN0IGRpc3BhdGNoICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50IGlmIHRoZSBTdHJlYW0gd2FzIHB1Ymxpc2hlZFxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zdHJlYW0uZWUuZW1pdEV2ZW50KCdsb2NhbC1zdHJlYW0tZGVzdHJveWVkJywgW3JlYXNvbl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdG9wVmlkZW9EYXRhSW50ZXJ2YWxzKCk6IHZvaWQge1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMudmlkZW9EYXRhSW50ZXJ2YWwpO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy52aWRlb0RhdGFUaW1lb3V0KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0cmluZ0NsaWVudE1ldGFkYXRhKG1ldGFkYXRhOiBhbnkpOiBzdHJpbmcge1xuICAgICAgICBpZiAodHlwZW9mIG1ldGFkYXRhICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG1ldGFkYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnZXRDb25uZWN0aW9uKGNvbm5lY3Rpb25JZDogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8Q29ubmVjdGlvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICBpZiAoISFjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSByZW1vdGUgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCA9PT0gY29ubmVjdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgbG9jYWwgY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh0aGlzLmNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3Rpb24gbm90IGZvdW5kLiBSZWplY3Qgd2l0aCBPcGVuVmlkdUVycm9yXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuR0VORVJJQ19FUlJPUiwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFJlbW90ZUNvbm5lY3Rpb24oY29ubmVjdGlvbklkOiBzdHJpbmcsIG9wZXJhdGlvbjogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxDb25uZWN0aW9uPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5yZW1vdGVDb25uZWN0aW9ucy5nZXQoY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIGlmICghIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHJlbW90ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoY29ubmVjdGlvbik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlbW90ZSBjb25uZWN0aW9uIG5vdCBmb3VuZC4gUmVqZWN0IHdpdGggT3BlblZpZHVFcnJvclxuICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9ICdSZW1vdGUgY29ubmVjdGlvbiAnICsgY29ubmVjdGlvbklkICsgXCIgdW5rbm93biB3aGVuICdcIiArIG9wZXJhdGlvbiArIFwiJy4gXCIgK1xuICAgICAgICAgICAgICAgICAgICAnRXhpc3RpbmcgcmVtb3RlIGNvbm5lY3Rpb25zOiAnICsgSlNPTi5zdHJpbmdpZnkodGhpcy5yZW1vdGVDb25uZWN0aW9ucy5rZXlzKCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuR0VORVJJQ19FUlJPUiwgZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc1Rva2VuKHRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdG9rZW5QYXJhbXMgPSB0aGlzLmdldFRva2VuUGFyYW1zKHRva2VuKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSB0b2tlblBhcmFtcy5zZXNzaW9uSWQ7XG5cbiAgICAgICAgaWYgKCEhdG9rZW5QYXJhbXMuc2VjcmV0KSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LnNlY3JldCA9IHRva2VuUGFyYW1zLnNlY3JldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISF0b2tlblBhcmFtcy5yZWNvcmRlcikge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS5yZWNvcmRlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdG9rZW5QYXJhbXMud2VicnRjU3RhdHNJbnRlcnZhbCkge1xuICAgICAgICAgICAgdGhpcy5vcGVudmlkdS53ZWJydGNTdGF0c0ludGVydmFsID0gdG9rZW5QYXJhbXMud2VicnRjU3RhdHNJbnRlcnZhbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoISF0b2tlblBhcmFtcy5zZW5kQnJvd3NlckxvZ3MpIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuc2VuZEJyb3dzZXJMb2dzID0gdG9rZW5QYXJhbXMuc2VuZEJyb3dzZXJMb2dzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbnZpZHUuaXNBdExlYXN0UHJvID0gdG9rZW5QYXJhbXMuZWRpdGlvbiA9PT0gJ3BybycgfHwgdG9rZW5QYXJhbXMuZWRpdGlvbiA9PT0gJ2VudGVycHJpc2UnO1xuICAgICAgICB0aGlzLm9wZW52aWR1LmlzRW50ZXJwcmlzZSA9IHRva2VuUGFyYW1zLmVkaXRpb24gPT09ICdlbnRlcnByaXNlJztcblxuICAgICAgICB0aGlzLm9wZW52aWR1LndzVXJpID0gdG9rZW5QYXJhbXMud3NVcmk7XG4gICAgICAgIHRoaXMub3BlbnZpZHUuaHR0cFVyaSA9IHRva2VuUGFyYW1zLmh0dHBVcmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcm9jZXNzSm9pblJvb21SZXNwb25zZShvcHRzOiBMb2NhbENvbm5lY3Rpb25PcHRpb25zLCB0b2tlbjogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbklkID0gb3B0cy5zZXNzaW9uO1xuICAgICAgICBpZiAob3B0cy5jdXN0b21JY2VTZXJ2ZXJzICE9IG51bGwgJiYgb3B0cy5jdXN0b21JY2VTZXJ2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBpY2VTZXJ2ZXIgb2Ygb3B0cy5jdXN0b21JY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICAgICAgbGV0IHJ0Y0ljZVNlcnZlcjogUlRDSWNlU2VydmVyID0ge1xuICAgICAgICAgICAgICAgICAgICB1cmxzOiBbaWNlU2VydmVyLnVybF1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIlNUVU4vVFVSTiBzZXJ2ZXIgSVA6IFwiICsgaWNlU2VydmVyLnVybCk7XG4gICAgICAgICAgICAgICAgaWYgKGljZVNlcnZlci51c2VybmFtZSAhPSBudWxsICYmIGljZVNlcnZlci5jcmVkZW50aWFsICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcnRjSWNlU2VydmVyLnVzZXJuYW1lID0gaWNlU2VydmVyLnVzZXJuYW1lO1xuICAgICAgICAgICAgICAgICAgICBydGNJY2VTZXJ2ZXIuY3JlZGVudGlhbCA9IGljZVNlcnZlci5jcmVkZW50aWFsO1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdUVVJOIGNyZWRlbnRpYWxzIFsnICsgaWNlU2VydmVyLnVzZXJuYW1lICsgJzonICsgaWNlU2VydmVyLmNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLm9wZW52aWR1LmljZVNlcnZlcnMucHVzaChydGNJY2VTZXJ2ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG9wdHMuY290dXJuSXAgIT0gbnVsbCAmJiBvcHRzLmNvdHVyblBvcnQgIT0gbnVsbCAmJiBvcHRzLnR1cm5Vc2VybmFtZSAhPSBudWxsICYmIG9wdHMudHVybkNyZWRlbnRpYWwgIT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc3QgdHVyblVybDEgPSAndHVybjonICsgb3B0cy5jb3R1cm5JcCArICc6JyArIG9wdHMuY290dXJuUG9ydDtcbiAgICAgICAgICAgIHRoaXMub3BlbnZpZHUuaWNlU2VydmVycyA9IFtcbiAgICAgICAgICAgICAgICB7IHVybHM6IFt0dXJuVXJsMV0sIHVzZXJuYW1lOiBvcHRzLnR1cm5Vc2VybmFtZSwgY3JlZGVudGlhbDogb3B0cy50dXJuQ3JlZGVudGlhbCB9XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIlNUVU4vVFVSTiBzZXJ2ZXIgSVA6IFwiICsgb3B0cy5jb3R1cm5JcCk7XG4gICAgICAgICAgICBsb2dnZXIubG9nKCdUVVJOIHRlbXAgY3JlZGVudGlhbHMgWycgKyBvcHRzLnR1cm5Vc2VybmFtZSArICc6JyArIG9wdHMudHVybkNyZWRlbnRpYWwgKyAnXScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbnZpZHUucm9sZSA9IG9wdHMucm9sZTtcbiAgICAgICAgdGhpcy5vcGVudmlkdS5maW5hbFVzZXJJZCA9IG9wdHMuZmluYWxVc2VySWQ7XG4gICAgICAgIHRoaXMub3BlbnZpZHUubWVkaWFTZXJ2ZXIgPSBvcHRzLm1lZGlhU2VydmVyO1xuICAgICAgICB0aGlzLm9wZW52aWR1LnZpZGVvU2ltdWxjYXN0ID0gb3B0cy52aWRlb1NpbXVsY2FzdDtcbiAgICAgICAgdGhpcy5jYXBhYmlsaXRpZXMgPSB7XG4gICAgICAgICAgICBzdWJzY3JpYmU6IHRydWUsXG4gICAgICAgICAgICBwdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgIT09ICdTVUJTQ1JJQkVSJyxcbiAgICAgICAgICAgIGZvcmNlVW5wdWJsaXNoOiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InLFxuICAgICAgICAgICAgZm9yY2VEaXNjb25uZWN0OiB0aGlzLm9wZW52aWR1LnJvbGUgPT09ICdNT0RFUkFUT1InXG4gICAgICAgIH07XG4gICAgICAgIGxvZ2dlci5pbmZvKFwib3BlbnZpZHUtc2VydmVyIHZlcnNpb246IFwiICsgb3B0cy52ZXJzaW9uKTtcbiAgICAgICAgaWYgKG9wdHMubGlmZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW52aWR1LmxpZmUgPSBvcHRzLmxpZmU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbWlub3JEaWZmZXJlbmNlOiBudW1iZXIgPSBzZW12ZXJNaW5vcihvcHRzLnZlcnNpb24pIC0gc2VtdmVyTWlub3IodGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbik7XG4gICAgICAgIGlmICgoc2VtdmVyTWFqb3Iob3B0cy52ZXJzaW9uKSAhPT0gc2VtdmVyTWFqb3IodGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbikpIHx8ICEobWlub3JEaWZmZXJlbmNlID09IDAgfHwgbWlub3JEaWZmZXJlbmNlID09IDEpKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoYG9wZW52aWR1LWJyb3dzZXIgKCR7dGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbn0pIGFuZCBvcGVudmlkdS1zZXJ2ZXIgKCR7b3B0cy52ZXJzaW9ufSkgdmVyc2lvbnMgYXJlIGluY29tcGF0aWJsZS4gYFxuICAgICAgICAgICAgICAgICsgJ0Vycm9ycyBhcmUgbGlrZWx5IHRvIG9jY3VyLiBvcGVudmlkdS1icm93c2VyIFNESyBpcyBvbmx5IGNvbXBhdGlibGUgd2l0aCB0aGUgc2FtZSB2ZXJzaW9uIG9yIHRoZSBpbW1lZGlhdGVseSBmb2xsb3dpbmcgbWlub3IgdmVyc2lvbiBvZiBhbiBPcGVuVmlkdSBkZXBsb3ltZW50Jyk7XG4gICAgICAgIH0gZWxzZSBpZiAobWlub3JEaWZmZXJlbmNlID09IDEpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGBvcGVudmlkdS1icm93c2VyIHZlcnNpb24gJHt0aGlzLm9wZW52aWR1LmxpYnJhcnlWZXJzaW9ufSBkb2VzIG5vdCBtYXRjaCBvcGVudmlkdS1zZXJ2ZXIgdmVyc2lvbiAke29wdHMudmVyc2lvbn0uIGBcbiAgICAgICAgICAgICAgICArIGBUaGVzZSB2ZXJzaW9ucyBhcmUgc3RpbGwgY29tcGF0aWJsZSB3aXRoIGVhY2ggb3RoZXIsIGJ1dCBvcGVudmlkdS1icm93c2VyIHZlcnNpb24gbXVzdCBiZSB1cGRhdGVkIGFzIHNvb24gYXMgcG9zc2libGUgdG8gJHtzZW12ZXJNYWpvcihvcHRzLnZlcnNpb24pfS4ke3NlbXZlck1pbm9yKG9wdHMudmVyc2lvbil9LnguIGBcbiAgICAgICAgICAgICAgICArIGBUaGlzIGNsaWVudCB1c2luZyBvcGVudmlkdS1icm93c2VyICR7dGhpcy5vcGVudmlkdS5saWJyYXJ5VmVyc2lvbn0gd2lsbCBiZWNvbWUgaW5jb21wYXRpYmxlIHdpdGggdGhlIG5leHQgcmVsZWFzZSBvZiBvcGVudmlkdS1zZXJ2ZXJgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbmZpZ3VyZSBKU05Mb2dzXG4gICAgICAgIE9wZW5WaWR1TG9nZ2VyLmNvbmZpZ3VyZUpTTkxvZyh0aGlzLm9wZW52aWR1LCB0b2tlbik7XG5cbiAgICAgICAgLy8gU3RvcmUgdG9rZW5cbiAgICAgICAgdGhpcy50b2tlbiA9IHRva2VuO1xuICAgIH1cblxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuL0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgRmlsdGVyIH0gZnJvbSAnLi9GaWx0ZXInO1xuaW1wb3J0IHsgUHVibGlzaGVyIH0gZnJvbSAnLi9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4vU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuL1N1YnNjcmliZXInO1xuaW1wb3J0IHsgSW5ib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9JbmJvdW5kU3RyZWFtT3B0aW9ucyc7XG5pbXBvcnQgeyBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHJpdmF0ZS9PdXRib3VuZFN0cmVhbU9wdGlvbnMnO1xuaW1wb3J0IHsgV2ViUnRjUGVlciwgV2ViUnRjUGVlclNlbmRvbmx5LCBXZWJSdGNQZWVyUmVjdm9ubHksIFdlYlJ0Y1BlZXJTZW5kcmVjdiwgV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1dlYlJ0Y1BlZXIvV2ViUnRjUGVlcic7XG5pbXBvcnQgeyBXZWJSdGNTdGF0cyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvV2ViUnRjU3RhdHMvV2ViUnRjU3RhdHMnO1xuaW1wb3J0IHsgRXhjZXB0aW9uRXZlbnQsIEV4Y2VwdGlvbkV2ZW50TmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V4Y2VwdGlvbkV2ZW50JztcbmltcG9ydCB7IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9QdWJsaXNoZXJTcGVha2luZ0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXJFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbU1hbmFnZXJFdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL1N0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50JztcbmltcG9ydCB7IE9wZW5WaWR1RXJyb3IsIE9wZW5WaWR1RXJyb3JOYW1lIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9PcGVuVmlkdUVycm9yJztcbmltcG9ydCB7IFR5cGVPZlZpZGVvIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FbnVtcy9UeXBlT2ZWaWRlbyc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IFBsYXRmb3JtVXRpbHMgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL1V0aWxzL1BsYXRmb3JtJztcblxuaW1wb3J0IHsgdjQgYXMgdXVpZHY0IH0gZnJvbSAndXVpZCc7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5pbXBvcnQgaGFyayA9IHJlcXVpcmUoJ2hhcmsnKTtcbi8qKlxuICogQGhpZGRlblxuICovXG5pbXBvcnQgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnd29sZnk4Ny1ldmVudGVtaXR0ZXInKTtcbi8qKlxuICogQGhpZGRlblxuICovXG5jb25zdCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmxldCBwbGF0Zm9ybTogUGxhdGZvcm1VdGlscztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGVhY2ggb25lIG9mIHRoZSBtZWRpYSBzdHJlYW1zIGF2YWlsYWJsZSBpbiBPcGVuVmlkdSBTZXJ2ZXIgZm9yIGNlcnRhaW4gc2Vzc2lvbi5cbiAqIEVhY2ggW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gaGFzIGFuIGF0dHJpYnV0ZSBvZiB0eXBlIFN0cmVhbSwgYXMgdGhleSBnaXZlIGFjY2Vzc1xuICogdG8gb25lIG9mIHRoZW0gKHNlbmRpbmcgYW5kIHJlY2VpdmluZyBpdCwgcmVzcGVjdGl2ZWx5KVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBDb25uZWN0aW9uIG9iamVjdCB0aGF0IGlzIHB1Ymxpc2hpbmcgdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZSByYXRlIG9mIHRoZSB2aWRlbyBpbiBmcmFtZXMgcGVyIHNlY29uZC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWYgdGhlIFtbUHVibGlzaGVyXV0gb2ZcbiAgICAgKiB0aGUgc3RyZWFtIHdhcyBpbml0aWFsaXplZCBwYXNzaW5nIGEgX2ZyYW1lUmF0ZV8gcHJvcGVydHkgb24gW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gbWV0aG9kXG4gICAgICovXG4gICAgZnJhbWVSYXRlPzogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhIHZpZGVvIHRyYWNrIG9yIG5vdFxuICAgICAqL1xuICAgIGhhc1ZpZGVvOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgc3RyZWFtIGhhcyBhbiBhdWRpbyB0cmFjayBvciBub3RcbiAgICAgKi9cbiAgICBoYXNBdWRpbzogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIHN0cmVhbSBoYXMgdGhlIHZpZGVvIHRyYWNrIG11dGVkIG9yIHVubXV0ZWQuIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaFZpZGVvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgdmlkZW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaGFzIHRoZSBhdWRpbyB0cmFjayBtdXRlZCBvciB1bm11dGVkLiBJZiBbW2hhc0F1ZGlvXV0gaXMgZmFsc2UsIHRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiBUaGlzIHByb3BlcnR5IG1heSBjaGFuZ2UgaWYgdGhlIFB1Ymxpc2hlciBwdWJsaXNoaW5nIHRoZSBzdHJlYW0gY2FsbHMgW1tQdWJsaXNoZXIucHVibGlzaEF1ZGlvXV0uIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWRcbiAgICAgKiBieSB0aGUgU2Vzc2lvbiBvYmplY3QgYXMgd2VsbCBhcyBieSB0aGUgYWZmZWN0ZWQgU3Vic2NyaWJlci9QdWJsaXNoZXIgb2JqZWN0XG4gICAgICovXG4gICAgYXVkaW9BY3RpdmU6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBVbmlxdWUgaWRlbnRpZmllciBvZiB0aGUgc3RyZWFtLiBJZiB0aGUgc3RyZWFtIGJlbG9uZ3MgdG8gYS4uLlxuICAgICAqIC0gU3Vic2NyaWJlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBzdHJlYW1JZGAgaXMgb25seSBkZWZpbmVkIGFmdGVyIHN1Y2Nlc3NmdWwgZXhlY3V0aW9uIG9mIFtbU2Vzc2lvbi5wdWJsaXNoXV1cbiAgICAgKi9cbiAgICBzdHJlYW1JZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGltZSB3aGVuIHRoaXMgc3RyZWFtIHdhcyBjcmVhdGVkIGluIE9wZW5WaWR1IFNlcnZlciAoVVRDIG1pbGxpc2Vjb25kcykuIERlcGVuZGluZyBvbiB0aGUgb3duZXIgb2YgdGhpcyBzdHJlYW06XG4gICAgICogLSBTdWJzY3JpYmVyIG9iamVjdDogcHJvcGVydHkgYGNyZWF0aW9uVGltZWAgaXMgYWx3YXlzIGRlZmluZWRcbiAgICAgKiAtIFB1Ymxpc2hlciBvYmplY3Q6IHByb3BlcnR5IGBjcmVhdGlvblRpbWVgIGlzIG9ubHkgZGVmaW5lZCBhZnRlciBzdWNjZXNzZnVsIGV4ZWN1dGlvbiBvZiBbW1Nlc3Npb24ucHVibGlzaF1dXG4gICAgICovXG4gICAgY3JlYXRpb25UaW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDYW4gYmU6XG4gICAgICogLSBgXCJDQU1FUkFcImA6IHdoZW4gdGhlIHZpZGVvIHNvdXJjZSBjb21lcyBmcm9tIGEgd2ViY2FtLlxuICAgICAqIC0gYFwiU0NSRUVOXCJgOiB3aGVuIHRoZSB2aWRlbyBzb3VyY2UgY29tZXMgZnJvbSBzY3JlZW4tc2hhcmluZy5cbiAgICAgKiAtIGBcIkNVU1RPTVwiYDogd2hlbiBbW1B1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2VdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBpbiB0aGUgUHVibGlzaGVyIHNpZGUgd2l0aCBhIGN1c3RvbSBNZWRpYVN0cmVhbVRyYWNrIHdoZW4gY2FsbGluZyBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSkuXG4gICAgICogLSBgXCJJUENBTVwiYDogd2hlbiB0aGUgdmlkZW8gc291cmNlIGNvbWVzIGZyb20gYW4gSVAgY2FtZXJhIHBhcnRpY2lwYW50IGluc3RlYWQgb2YgYSByZWd1bGFyIHBhcnRpY2lwYW50IChzZWUgW0lQIGNhbWVyYXNdKC9lbi9zdGFibGUvYWR2YW5jZWQtZmVhdHVyZXMvaXAtY2FtZXJhcy8pKS5cbiAgICAgKlxuICAgICAqIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB0eXBlT2ZWaWRlbz86IGtleW9mIHR5cGVvZiBUeXBlT2ZWaWRlbzsgLy8gVE9ETzogQ2hhbmdlIHRoaXMgdHlwZSB0byBlbnVtIFR5cGVPZlZpZGVvIG9uIHRoZSBuZXh0IGJyZWFraW5nLWNoYW5nZSByZWxlYXNlXG5cbiAgICAvKipcbiAgICAgKiBTdHJlYW1NYW5hZ2VyIG9iamVjdCAoW1tQdWJsaXNoZXJdXSBvciBbW1N1YnNjcmliZXJdXSkgaW4gY2hhcmdlIG9mIGRpc3BsYXlpbmcgdGhpcyBzdHJlYW0gaW4gdGhlIERPTVxuICAgICAqL1xuICAgIHN0cmVhbU1hbmFnZXI6IFN0cmVhbU1hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBXaWR0aCBhbmQgaGVpZ2h0IGluIHBpeGVscyBvZiB0aGUgZW5jb2RlZCB2aWRlbyBzdHJlYW0uIElmIFtbaGFzVmlkZW9dXSBpcyBmYWxzZSwgdGhpcyBwcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIFRoaXMgcHJvcGVydHkgbWF5IGNoYW5nZSBpZiB0aGUgUHVibGlzaGVyIHRoYXQgaXMgcHVibGlzaGluZzpcbiAgICAgKiAtIElmIGl0IGlzIGEgbW9iaWxlIGRldmljZSwgd2hlbmV2ZXIgdGhlIHVzZXIgcm90YXRlcyB0aGUgZGV2aWNlLlxuICAgICAqIC0gSWYgaXQgaXMgc2NyZWVuLXNoYXJpbmcsIHdoZW5ldmVyIHRoZSB1c2VyIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIGNhcHR1cmVkIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIFdoZW5ldmVyIHRoaXMgaGFwcGVucyBhIFtbU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnRdXSB3aWxsIGJlIGRpc3BhdGNoZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0IGFzIHdlbGwgYXMgYnkgdGhlIGFmZmVjdGVkIFN1YnNjcmliZXIvUHVibGlzaGVyIG9iamVjdFxuICAgICAqL1xuICAgIHZpZGVvRGltZW5zaW9uczogeyB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciB9O1xuXG4gICAgLyoqXG4gICAgICogKipXQVJOSU5HKio6IGV4cGVyaW1lbnRhbCBvcHRpb24uIFRoaXMgaW50ZXJmYWNlIG1heSBjaGFuZ2UgaW4gdGhlIG5lYXIgZnV0dXJlXG4gICAgICpcbiAgICAgKiBGaWx0ZXIgYXBwbGllZCB0byB0aGUgU3RyZWFtLiBZb3UgY2FuIGFwcGx5IGZpbHRlcnMgYnkgY2FsbGluZyBbW1N0cmVhbS5hcHBseUZpbHRlcl1dLCBleGVjdXRlIG1ldGhvZHMgb2YgdGhlIGFwcGxpZWQgZmlsdGVyIHdpdGhcbiAgICAgKiBbW0ZpbHRlci5leGVjTWV0aG9kXV0gYW5kIHJlbW92ZSBpdCB3aXRoIFtbU3RyZWFtLnJlbW92ZUZpbHRlcl1dLiBCZSBhd2FyZSB0aGF0IHRoZSBjbGllbnQgY2FsbGluZyB0aGlzIG1ldGhvZHMgbXVzdCBoYXZlIHRoZVxuICAgICAqIG5lY2Vzc2FyeSBwZXJtaXNzaW9uczogdGhlIHRva2VuIG93bmVkIGJ5IHRoZSBjbGllbnQgbXVzdCBoYXZlIGJlZW4gaW5pdGlhbGl6ZWQgd2l0aCB0aGUgYXBwcm9wcmlhdGVkIGBhbGxvd2VkRmlsdGVyc2AgYXJyYXkuXG4gICAgICovXG4gICAgZmlsdGVyPzogRmlsdGVyO1xuXG4gICAgcHJvdGVjdGVkIHdlYlJ0Y1BlZXI6IFdlYlJ0Y1BlZXI7XG4gICAgcHJvdGVjdGVkIG1lZGlhU3RyZWFtPzogTWVkaWFTdHJlYW07XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0czogV2ViUnRjU3RhdHM7XG5cbiAgICBwcml2YXRlIGlzU3Vic2NyaWJlVG9SZW1vdGUgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgdmlydHVhbEJhY2tncm91bmRTb3VyY2VFbGVtZW50cz86IHsgdmlkZW9DbG9uZTogSFRNTFZpZGVvRWxlbWVudCwgbWVkaWFTdHJlYW1DbG9uZTogTWVkaWFTdHJlYW0gfTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdmlydHVhbEJhY2tncm91bmRTaW5rRWxlbWVudHM/OiB7IFZCOiBhbnksIHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50IH07XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHVibGlzaGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXNzaW9uOiBTZXNzaW9uO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbmJvdW5kU3RyZWFtT3B0czogSW5ib3VuZFN0cmVhbU9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIG91dGJvdW5kU3RyZWFtT3B0czogT3V0Ym91bmRTdHJlYW1PcHRpb25zO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzcGVlY2hFdmVudDogYW55O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrU3BlYWtpbmdFbmFibGVkID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhcmtTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkT25jZSA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrVm9sdW1lQ2hhbmdlRW5hYmxlZCA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBoYXJrVm9sdW1lQ2hhbmdlRW5hYmxlZE9uY2UgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFya09wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlPzogTWVkaWFTdHJlYW07XG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI6IEV2ZW50RW1pdHRlciB8IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGFzdFZpZGVvVHJhY2tDb25zdHJhaW50czogTWVkaWFUcmFja0NvbnN0cmFpbnRzIHwgYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgbGFzdFZCRmlsdGVyPzogRmlsdGVyO1xuXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2Vzc2lvbjogU2Vzc2lvbiwgb3B0aW9uczogSW5ib3VuZFN0cmVhbU9wdGlvbnMgfCBPdXRib3VuZFN0cmVhbU9wdGlvbnMgfCB7fSkge1xuXG4gICAgICAgIHBsYXRmb3JtID0gUGxhdGZvcm1VdGlscy5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLnNlc3Npb24gPSBzZXNzaW9uO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCdpZCcpKSB7XG4gICAgICAgICAgICAvLyBJbmJvdW5kU3RyZWFtT3B0aW9uczogc3RyZWFtIGJlbG9uZ3MgdG8gYSBTdWJzY3JpYmVyXG4gICAgICAgICAgICB0aGlzLmluYm91bmRTdHJlYW1PcHRzID0gPEluYm91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5pZDtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5jcmVhdGVkQXQ7XG4gICAgICAgICAgICB0aGlzLmhhc0F1ZGlvID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5oYXNBdWRpbztcbiAgICAgICAgICAgIHRoaXMuaGFzVmlkZW8gPSB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmhhc1ZpZGVvO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzQXVkaW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQWN0aXZlID0gdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5hdWRpb0FjdGl2ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmhhc1ZpZGVvKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0FjdGl2ZSA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9BY3RpdmU7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9ICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy50eXBlT2ZWaWRlbykgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLnR5cGVPZlZpZGVvO1xuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVSYXRlID0gKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZnJhbWVSYXRlID09PSAtMSkgPyB1bmRlZmluZWQgOiB0aGlzLmluYm91bmRTdHJlYW1PcHRzLmZyYW1lUmF0ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRGltZW5zaW9ucyA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMudmlkZW9EaW1lbnNpb25zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdGhpcy5pbmJvdW5kU3RyZWFtT3B0cy5maWx0ZXIgJiYgKE9iamVjdC5rZXlzKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZmlsdGVyKS5sZW5ndGggPiAwKSkge1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZmlsdGVyLmxhc3RFeGVjTWV0aG9kICYmIE9iamVjdC5rZXlzKHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZmlsdGVyLmxhc3RFeGVjTWV0aG9kKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZmlsdGVyLmxhc3RFeGVjTWV0aG9kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmZpbHRlciA9IHRoaXMuaW5ib3VuZFN0cmVhbU9wdHMuZmlsdGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3V0Ym91bmRTdHJlYW1PcHRpb25zOiBzdHJlYW0gYmVsb25ncyB0byBhIFB1Ymxpc2hlclxuICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSA8T3V0Ym91bmRTdHJlYW1PcHRpb25zPm9wdGlvbnM7XG5cbiAgICAgICAgICAgIHRoaXMuaGFzQXVkaW8gPSB0aGlzLmlzU2VuZEF1ZGlvKCk7XG4gICAgICAgICAgICB0aGlzLmhhc1ZpZGVvID0gdGhpcy5pc1NlbmRWaWRlbygpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBdWRpbykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9BY3RpdmUgPSAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMucHVibGlzaEF1ZGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFzVmlkZW8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvQWN0aXZlID0gISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnB1Ymxpc2hWaWRlbztcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZnJhbWVSYXRlO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTWVkaWFTdHJlYW1UcmFjayAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSBpbnN0YW5jZW9mIE1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50eXBlT2ZWaWRlbyA9IFR5cGVPZlZpZGVvLkNVU1RPTTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGVPZlZpZGVvID0gdGhpcy5pc1NlbmRTY3JlZW4oKSA/IFR5cGVPZlZpZGVvLlNDUkVFTiA6IFR5cGVPZlZpZGVvLkNBTUVSQTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmZpbHRlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5maWx0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVlLm9uKCdtZWRpYXN0cmVhbS11cGRhdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnVwZGF0ZU1lZGlhU3RyZWFtKHRoaXMubWVkaWFTdHJlYW0hKTtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnVmlkZW8gc3JjT2JqZWN0IFsnICsgdGhpcy5tZWRpYVN0cmVhbT8uaWQgKyAnXSB1cGRhdGVkIGluIHN0cmVhbSBbJyArIHRoaXMuc3RyZWFtSWQgKyAnXScpO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFJlY3JlYXRlcyB0aGUgbWVkaWEgY29ubmVjdGlvbiB3aXRoIHRoZSBzZXJ2ZXIuIFRoaXMgZW50YWlscyB0aGUgZGlzcG9zYWwgb2YgdGhlIHByZXZpb3VzIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCB0aGUgcmUtbmVnb3RpYXRpb25cbiAgICAgKiBvZiBhIG5ldyBvbmUsIHRoYXQgd2lsbCBhcHBseSB0aGUgc2FtZSBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgY2FuIGJlIHVzZWZ1bCBpbiB0aG9zZSBzaXR1YXRpb25zIHdlcmUgdGhlcmUgdGhlIG1lZGlhIGNvbm5lY3Rpb24gYnJlYWtzIGFuZCBPcGVuVmlkdSBpcyBub3QgYWJsZSB0byByZWNvdmVyIG9uIGl0cyBvd25cbiAgICAgKiBmb3IgYW55IGtpbmQgb2YgdW5hbnRpY2lwYXRlZCByZWFzb24gKHNlZSBbQXV0b21hdGljIHJlY29ubmVjdGlvbl0oL2VuL3N0YWJsZS9hZHZhbmNlZC1mZWF0dXJlcy9hdXRvbWF0aWMtcmVjb25uZWN0aW9uLykpLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSByZWNvbm5lY3Rpb24gb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVjb25uZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWNvbm5lY3RTdHJlYW0oJ0FQSScpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgYW4gYXVkaW8vdmlkZW8gZmlsdGVyIHRvIHRoZSBzdHJlYW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdHlwZSBUeXBlIG9mIGZpbHRlciBhcHBsaWVkLiBTZWUgW1tGaWx0ZXIudHlwZV1dXG4gICAgICogQHBhcmFtIG9wdGlvbnMgUGFyYW1ldGVycyB1c2VkIHRvIGluaXRpYWxpemUgdGhlIGZpbHRlci4gU2VlIFtbRmlsdGVyLm9wdGlvbnNdXVxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIHRvIHRoZSBhcHBsaWVkIGZpbHRlciBpZiBzdWNjZXNzIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpZiBub3RcbiAgICAgKi9cbiAgICBhcHBseUZpbHRlcih0eXBlOiBzdHJpbmcsIG9wdGlvbnM6IE9iamVjdCk6IFByb21pc2U8RmlsdGVyPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGlmICghIXRoaXMuZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5HRU5FUklDX0VSUk9SLCAnVGhlcmUgaXMgYWxyZWFkeSBhIGZpbHRlciBhcHBsaWVkIHRvIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXNvbHZlQXBwbHlGaWx0ZXIgPSAoZXJyb3IsIHRyaWdnZXJFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGFwcGx5aW5nIGZpbHRlciBmb3IgU3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuT1BFTlZJRFVfUEVSTUlTU0lPTl9ERU5JRUQsIFwiWW91IGRvbid0IGhhdmUgcGVybWlzc2lvbnMgdG8gYXBwbHkgYSBmaWx0ZXJcIikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRmlsdGVyIHN1Y2Nlc3NmdWxseSBhcHBsaWVkIG9uIFN0cmVhbSAnICsgdGhpcy5zdHJlYW1JZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlOiBGaWx0ZXIgPSB0aGlzLmZpbHRlciE7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyID0gbmV3IEZpbHRlcih0eXBlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXIuc3RyZWFtID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWdnZXJFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciwgb2xkVmFsdWUsICdhcHBseUZpbHRlcicpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdzdHJlYW1Qcm9wZXJ0eUNoYW5nZWQnLCBbbmV3IFN0cmVhbVByb3BlcnR5Q2hhbmdlZEV2ZW50KHRoaXMuc3RyZWFtTWFuYWdlciwgdGhpcywgJ2ZpbHRlcicsIHRoaXMuZmlsdGVyLCBvbGRWYWx1ZSwgJ2FwcGx5RmlsdGVyJyldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh0aGlzLmZpbHRlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZS5zdGFydHNXaXRoKCdWQjonKSkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ2xpZW50IGZpbHRlcnNcblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5oYXNWaWRlbykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlZJUlRVQUxfQkFDS0dST1VORF9FUlJPUiwgJ1RoZSBWaXJ0dWFsIEJhY2tncm91bmQgZmlsdGVyIHJlcXVpcmVzIGEgdmlkZW8gdHJhY2sgdG8gYmUgYXBwbGllZCcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm1lZGlhU3RyZWFtIHx8IHRoaXMuc3RyZWFtTWFuYWdlci52aWRlb3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IE9wZW5WaWR1RXJyb3IoT3BlblZpZHVFcnJvck5hbWUuVklSVFVBTF9CQUNLR1JPVU5EX0VSUk9SLCAnVGhlIFN0cmVhbU1hbmFnZXIgcmVxdWlyZXMgc29tZSB2aWRlbyBlbGVtZW50IHRvIGJlIGF0dGFjaGVkIHRvIGl0IGluIG9yZGVyIHRvIGFwcGx5IGEgVmlydHVhbCBCYWNrZ3JvdW5kIGZpbHRlcicpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgb3BlbnZpZHVUb2tlbjogc3RyaW5nO1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMuc2Vzc2lvbi50b2tlbikge1xuICAgICAgICAgICAgICAgICAgICBvcGVudmlkdVRva2VuID0gdGhpcy5zZXNzaW9uLnRva2VuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9wZW52aWR1VG9rZW4gPSBvcHRpb25zWyd0b2tlbiddO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW9wZW52aWR1VG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5WSVJUVUFMX0JBQ0tHUk9VTkRfRVJST1IsICdWaXJ0dWFsIEJhY2tncm91bmQgcmVxdWlyZXMgdGhlIGNsaWVudCB0byBiZSBjb25uZWN0ZWQgdG8gYSBTZXNzaW9uIG9yIHRvIGhhdmUgYSBcInRva2VuXCIgcHJvcGVydHkgYXZhaWxhYmxlIGluIFwib3B0aW9uc1wiIHBhcmFtZXRlciB3aXRoIGEgdmFsaWQgT3BlblZpZHUgdG9rZW4nKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgdG9rZW5QYXJhbXMgPSB0aGlzLnNlc3Npb24uZ2V0VG9rZW5QYXJhbXMob3BlbnZpZHVUb2tlbik7XG4gICAgICAgICAgICAgICAgaWYgKHRva2VuUGFyYW1zLmVkaXRpb24gIT09ICdwcm8nICYmIHRva2VuUGFyYW1zLmVkaXRpb24gIT09ICdlbnRlcnByaXNlJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLlZJUlRVQUxfQkFDS0dST1VORF9FUlJPUiwgJ09wZW5WaWR1IFZpcnR1YWwgQmFja2dyb3VuZCBBUEkgaXMgYXZhaWxhYmxlIGZyb20gT3BlblZpZHUgUHJvIGVkaXRpb24gb253YXJkcycpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBvcGVudmlkdVRva2VuID0gZW5jb2RlVVJJQ29tcG9uZW50KGJ0b2Eob3BlbnZpZHVUb2tlbikpO1xuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0FwcGx5aW5nIFZpcnR1YWwgQmFja2dyb3VuZCB0byBzdHJlYW0gJyArIHRoaXMuc3RyZWFtSWQpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgYWZ0ZXJTY3JpcHRMb2FkZWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMuc3RyZWFtSWQgKyAnXycgKyB1dWlkdjQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lZGlhU3RyZWFtQ2xvbmUgPSB0aGlzLm1lZGlhU3RyZWFtIS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmlkZW9DbG9uZSA9IHRoaXMuc3RyZWFtTWFuYWdlci52aWRlb3NbMF0udmlkZW8uY2xvbmVOb2RlKGZhbHNlKSBhcyBIVE1MVmlkZW9FbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW9DbG9uZS5pZCA9IFZpcnR1YWxCYWNrZ3JvdW5kLlZpcnR1YWxCYWNrZ3JvdW5kLlNPVVJDRV9WSURFT19QUkVGSVggKyBpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvQ2xvbmUuc3JjT2JqZWN0ID0gbWVkaWFTdHJlYW1DbG9uZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvQ2xvbmUubXV0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aXJ0dWFsQmFja2dyb3VuZFNvdXJjZUVsZW1lbnRzID0geyB2aWRlb0Nsb25lLCBtZWRpYVN0cmVhbUNsb25lIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIFZpcnR1YWxCYWNrZ3JvdW5kLlZpcnR1YWxCYWNrZ3JvdW5kLmhpZGVIdG1sRWxlbWVudCh2aWRlb0Nsb25lLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgICAgICBWaXJ0dWFsQmFja2dyb3VuZC5WaXJ0dWFsQmFja2dyb3VuZC5hcHBlbmRIdG1sRWxlbWVudFRvSGlkZGVuQ29udGFpbmVyKHZpZGVvQ2xvbmUsIGlkKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdmlkZW9DbG9uZS5wbGF5KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFZCID0gbmV3IFZpcnR1YWxCYWNrZ3JvdW5kLlZpcnR1YWxCYWNrZ3JvdW5kKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVudmlkdVNlcnZlclVybDogbmV3IFVSTCh0b2tlblBhcmFtcy5odHRwVXJpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVudmlkdVRva2VuLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0VmlkZW86IHZpZGVvQ2xvbmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRSZXNvbHV0aW9uOiAnMTYweDk2JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRGcmFtZXJhdGU6IDI0XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbHRlcmVkVmlkZW86IEhUTUxWaWRlb0VsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdWQjpibHVyJzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJlZFZpZGVvID0gYXdhaXQgVkIuYmFja2dyb3VuZEJsdXIob3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdWQjppbWFnZSc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyZWRWaWRlbyA9IGF3YWl0IFZCLmJhY2tncm91bmRJbWFnZShvcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBWaXJ0dWFsIEJhY2tncm91bmQgZmlsdGVyOiAnICsgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlydHVhbEJhY2tncm91bmRTaW5rRWxlbWVudHMgPSB7IFZCLCB2aWRlbzogZmlsdGVyZWRWaWRlbyB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2aWRlb0Nsb25lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbU1hbmFnZXIucmVtb3RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLnJlcGxhY2VUcmFja0luTWVkaWFTdHJlYW0oKHRoaXMudmlydHVhbEJhY2tncm91bmRTaW5rRWxlbWVudHMudmlkZW8uc3JjT2JqZWN0IGFzIE1lZGlhU3RyZWFtKS5nZXRWaWRlb1RyYWNrcygpWzBdLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLnN0cmVhbU1hbmFnZXIgYXMgUHVibGlzaGVyKS5yZXBsYWNlVHJhY2tBdXgoKHRoaXMudmlydHVhbEJhY2tncm91bmRTaW5rRWxlbWVudHMudmlkZW8uc3JjT2JqZWN0IGFzIE1lZGlhU3RyZWFtKS5nZXRWaWRlb1RyYWNrcygpWzBdLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVBcHBseUZpbHRlcih1bmRlZmluZWQsIGZhbHNlKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLm5hbWUgPT09IE9wZW5WaWR1RXJyb3JOYW1lLlZJUlRVQUxfQkFDS0dST1VORF9FUlJPUikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVBcHBseUZpbHRlcihuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5WSVJUVUFMX0JBQ0tHUk9VTkRfRVJST1IsIGVycm9yLm1lc3NhZ2UpLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVBcHBseUZpbHRlcihlcnJvciwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgVmlydHVhbEJhY2tncm91bmQgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNjcmlwdDogSFRNTFNjcmlwdEVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic2NyaXB0XCIpO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHQudHlwZSA9IFwidGV4dC9qYXZhc2NyaXB0XCI7XG4gICAgICAgICAgICAgICAgICAgIHNjcmlwdC5zcmMgPSB0b2tlblBhcmFtcy5odHRwVXJpICsgJy9vcGVudmlkdS92aXJ0dWFsLWJhY2tncm91bmQvb3BlbnZpZHUtdmlydHVhbC1iYWNrZ3JvdW5kLmpzP3Rva2VuPScgKyBvcGVudmlkdVRva2VuO1xuICAgICAgICAgICAgICAgICAgICBzY3JpcHQub25sb2FkID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBhZnRlclNjcmlwdExvYWRlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobmV3IEZpbHRlcih0eXBlLCBvcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhZnRlclNjcmlwdExvYWRlZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKG5ldyBGaWx0ZXIodHlwZSwgb3B0aW9ucykpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIC8vIFNlcnZlciBmaWx0ZXJzXG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbi5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdCh0aGlzLnNlc3Npb24ubm90Q29ubmVjdGVkRXJyb3IoKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0FwcGx5aW5nIHNlcnZlciBmaWx0ZXIgdG8gc3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyAhPSBudWxsID8gb3B0aW9ucyA6IHt9O1xuICAgICAgICAgICAgICAgIGxldCBvcHRpb25zU3RyaW5nID0gb3B0aW9ucztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnNTdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnNTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zU3RyaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLm9wZW52aWR1LnNlbmRSZXF1ZXN0KFxuICAgICAgICAgICAgICAgICAgICAnYXBwbHlGaWx0ZXInLFxuICAgICAgICAgICAgICAgICAgICB7IHN0cmVhbUlkOiB0aGlzLnN0cmVhbUlkLCB0eXBlLCBvcHRpb25zOiBvcHRpb25zU3RyaW5nIH0sXG4gICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmVBcHBseUZpbHRlcihlcnJvciwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbiBhdWRpby92aWRlbyBmaWx0ZXIgcHJldmlvdXNseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBQcm9taXNlICh0byB3aGljaCB5b3UgY2FuIG9wdGlvbmFsbHkgc3Vic2NyaWJlIHRvKSB0aGF0IGlzIHJlc29sdmVkIGlmIHRoZSBwcmV2aW91c2x5IGFwcGxpZWQgZmlsdGVyIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSByZW1vdmVkIGFuZCByZWplY3RlZCB3aXRoIGFuIEVycm9yIG9iamVjdCBpbiBvdGhlciBjYXNlXG4gICAgICovXG4gICAgYXN5bmMgcmVtb3ZlRmlsdGVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5yZW1vdmVGaWx0ZXJBdXgoZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGludGVybmFsIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdCBhc3NvY2lhdGVkIHRvIHRoaXMgc3RyZWFtIChodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUlRDUGVlckNvbm5lY3Rpb24pXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBOYXRpdmUgUlRDUGVlckNvbm5lY3Rpb24gV2ViIEFQSSBvYmplY3RcbiAgICAgKi9cbiAgICBnZXRSVENQZWVyQ29ubmVjdGlvbigpOiBSVENQZWVyQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLndlYlJ0Y1BlZXIucGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaW50ZXJuYWwgTWVkaWFTdHJlYW0gb2JqZWN0IGFzc29jaWF0ZWQgdG8gdGhpcyBzdHJlYW0gKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9NZWRpYVN0cmVhbSlcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIE5hdGl2ZSBNZWRpYVN0cmVhbSBXZWIgQVBJIG9iamVjdFxuICAgICAqL1xuICAgIGdldE1lZGlhU3RyZWFtKCk6IE1lZGlhU3RyZWFtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVkaWFTdHJlYW0hO1xuICAgIH1cblxuICAgIC8qIEhpZGRlbiBtZXRob2RzICovXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlRmlsdGVyQXV4KGlzRGlzcG9zaW5nOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVSZW1vdmVGaWx0ZXIgPSAoZXJyb3IsIHRyaWdnZXJFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5maWx0ZXI7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignRXJyb3IgcmVtb3ZpbmcgZmlsdGVyIGZvciBTdHJlYW0gJyArIHRoaXMuc3RyZWFtSWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDQwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byByZW1vdmUgYSBmaWx0ZXJcIikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRmlsdGVyIHN1Y2Nlc3NmdWxseSByZW1vdmVkIGZyb20gU3RyZWFtICcgKyB0aGlzLnN0cmVhbUlkKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB0aGlzLmZpbHRlciE7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpbHRlcjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyaWdnZXJFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnNlc3Npb24sIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciEsIG9sZFZhbHVlLCAnYXBwbHlGaWx0ZXInKV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtUHJvcGVydHlDaGFuZ2VkJywgW25ldyBTdHJlYW1Qcm9wZXJ0eUNoYW5nZWRFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsIHRoaXMsICdmaWx0ZXInLCB0aGlzLmZpbHRlciEsIG9sZFZhbHVlLCAnYXBwbHlGaWx0ZXInKV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISF0aGlzLmZpbHRlcikge1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBmaWx0ZXIgYXBwbGllZFxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmlsdGVyPy50eXBlLnN0YXJ0c1dpdGgoJ1ZCOicpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2xpZW50IGZpbHRlcnNcblxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZWRpYVN0cmVhbUNsb25lID0gdGhpcy52aXJ0dWFsQmFja2dyb3VuZFNvdXJjZUVsZW1lbnRzIS5tZWRpYVN0cmVhbUNsb25lO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0Rpc3Bvc2luZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbU1hbmFnZXIucmVtb3RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc3RyZWFtTWFuYWdlci5yZXBsYWNlVHJhY2tJbk1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtQ2xvbmUuZ2V0VmlkZW9UcmFja3MoKVswXSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0ICh0aGlzLnN0cmVhbU1hbmFnZXIgYXMgUHVibGlzaGVyKS5yZXBsYWNlVHJhY2tBdXgobWVkaWFTdHJlYW1DbG9uZS5nZXRWaWRlb1RyYWNrcygpWzBdLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbUNsb25lLmdldFRyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpcnR1YWxCYWNrZ3JvdW5kU2lua0VsZW1lbnRzIS5WQi5jbGVhblVwKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnZpcnR1YWxCYWNrZ3JvdW5kU2lua0VsZW1lbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudmlydHVhbEJhY2tncm91bmRTb3VyY2VFbGVtZW50cztcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmVSZW1vdmVGaWx0ZXIodW5kZWZpbmVkLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlUmVtb3ZlRmlsdGVyKGVycm9yLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2VydmVyIGZpbHRlcnNcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2Vzc2lvbi5zZXNzaW9uQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QodGhpcy5zZXNzaW9uLm5vdENvbm5lY3RlZEVycm9yKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1JlbW92aW5nIGZpbHRlciBvZiBzdHJlYW0gJyArIHRoaXMuc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAncmVtb3ZlRmlsdGVyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgc3RyZWFtSWQ6IHRoaXMuc3RyZWFtSWQgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZVJlbW92ZUZpbHRlcihlcnJvciwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgbm8gZmlsdGVyIGFwcGxpZWRcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBPcGVuVmlkdUVycm9yKE9wZW5WaWR1RXJyb3JOYW1lLkdFTkVSSUNfRVJST1IsIFwiU3RyZWFtIFwiICsgdGhpcy5zdHJlYW1JZCArIFwiIGhhcyBubyBmaWx0ZXIgYXBwbGllZFwiKSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHNldE1lZGlhU3RyZWFtKG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1lZGlhU3RyZWFtID0gbWVkaWFTdHJlYW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHVwZGF0ZU1lZGlhU3RyZWFtSW5WaWRlb3MoKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdtZWRpYXN0cmVhbS11cGRhdGVkJywgW10pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBnZXRXZWJSdGNQZWVyKCk6IFdlYlJ0Y1BlZXIge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb015UmVtb3RlKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXNTdWJzY3JpYmVUb1JlbW90ZSA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXRPdXRib3VuZFN0cmVhbU9wdGlvbnMob3V0Ym91bmRTdHJlYW1PcHRzOiBPdXRib3VuZFN0cmVhbU9wdGlvbnMpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgPSBvdXRib3VuZFN0cmVhbU9wdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHN1YnNjcmliZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKGZhbHNlKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwdWJsaXNoKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbFN0cmVhbVJlYWR5VG9QdWJsaXNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclNlbmQoZmFsc2UpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLm9uY2UoJ3N0cmVhbS1yZWFkeS10by1wdWJsaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2goKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcG9zZVdlYlJ0Y1BlZXIoKTogdm9pZCB7XG4gICAgICAgIGxldCB3ZWJydGNJZDtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNQZWVyKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuZGlzcG9zZSgpO1xuICAgICAgICAgICAgd2VicnRjSWQgPSB0aGlzLndlYlJ0Y1BlZXIuZ2V0SWQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICBsb2dnZXIuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdPdXRib3VuZCAnIDogJ0luYm91bmQgJykgKyBcIlJUQ1BlZXJDb25uZWN0aW9uIHdpdGggaWQgW1wiICsgd2VicnRjSWQgKyBcIl0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgY2xvc2VkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFzeW5jIGRpc3Bvc2VNZWRpYVN0cmVhbSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCEhdGhpcy5maWx0ZXIgJiYgdGhpcy5maWx0ZXIudHlwZS5zdGFydHNXaXRoKCdWQjonKSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZUZpbHRlckF1eCh0cnVlKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKGBTdWNjZXNzIHJlbW92aW5nIFZpcnR1YWwgQmFja2dyb3VuZCBmaWx0ZXIgZm9yIHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9YCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHJlbW92aW5nIFZpcnR1YWwgQmFja2dyb3VuZCBmaWx0ZXIgZm9yIHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9YCwgZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLm1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubWVkaWFTdHJlYW07XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgc3Vic2NyaWJlVG9SZW1vdGUgbG9jYWwgTWVkaWFTdHJlYW0gbXVzdCBiZSBzdG9wcGVkXG4gICAgICAgIGlmICh0aGlzLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsTWVkaWFTdHJlYW1XaGVuU3Vic2NyaWJlZFRvUmVtb3RlLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMubG9jYWxNZWRpYVN0cmVhbVdoZW5TdWJzY3JpYmVkVG9SZW1vdGUuZ2V0VmlkZW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMubG9jYWxNZWRpYVN0cmVhbVdoZW5TdWJzY3JpYmVkVG9SZW1vdGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEhdGhpcy5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zcGVlY2hFdmVudC5zdG9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5zdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zcGVlY2hFdmVudDtcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuaW5mbygoISF0aGlzLm91dGJvdW5kU3RyZWFtT3B0cyA/ICdMb2NhbCAnIDogJ1JlbW90ZSAnKSArIFwiTWVkaWFTdHJlYW0gZnJvbSAnU3RyZWFtJyB3aXRoIGlkIFtcIiArIHRoaXMuc3RyZWFtSWQgKyAnXSBpcyBub3cgZGlzcG9zZWQnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzcGxheU15UmVtb3RlKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1N1YnNjcmliZVRvUmVtb3RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc1NlbmRBdWRpbygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICghIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLmF1ZGlvU291cmNlICE9PSBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGlzU2VuZFZpZGVvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gKCEhdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IG51bGwgJiZcbiAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgIT09IGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaXNTZW5kU2NyZWVuKCk6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgc2NyZWVuID0gdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZSA9PT0gJ3NjcmVlbic7XG4gICAgICAgIGlmIChwbGF0Zm9ybS5pc0VsZWN0cm9uKCkpIHtcbiAgICAgICAgICAgIHNjcmVlbiA9IHR5cGVvZiB0aGlzLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLnZpZGVvU291cmNlID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2Uuc3RhcnRzV2l0aCgnc2NyZWVuOicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzICYmIHNjcmVlbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZW5hYmxlSGFya1NwZWFraW5nRXZlbnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0SGFya0xpc3RlbmVySWZOb3RFeGlzdHMoKTtcbiAgICAgICAgaWYgKCF0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQgJiYgISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbignc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7IC8vIERpc2FibGUgJ29uY2UnIHZlcnNpb24gaWYgJ29uJyB2ZXJzaW9uIHdhcyB0cmlnZ2VyZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VIYXJrU3BlYWtpbmdFdmVudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpO1xuICAgICAgICBpZiAoIXRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UgJiYgISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub25jZSgnc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIGhhcyBiZWVuIGRpc2FibGVkIGluIHRoZSBtZWFudGltZSAoZm9yIGV4YW1wbGUgYnkgdGhlICdvbicgdmVyc2lvbikgZG8gbm90IHRyaWdnZXIgdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zZXNzaW9uLCAncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVIYXJrU3BlYWtpbmdFdmVudCh0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGRpc2FibGVIYXJrU3BlYWtpbmdFdmVudChkaXNhYmxlZEJ5T25jZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoZGlzYWJsZWRCeU9uY2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3BlYWtpbmdFbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSAnb24nIHZlcnNpb24gb2YgdGhpcyBzYW1lIGV2ZW50IGlzIGVuYWJsZWQgdG9vLiBEbyBub3QgcmVtb3ZlIHRoZSBoYXJrIGxpc3RlbmVyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2h1dHRpbmcgZG93biB0aGUgaGFyayBldmVudFxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkT25jZSkge1xuICAgICAgICAgICAgICAgIC8vIFNvbWUgb3RoZXIgaGFyayBldmVudCBpcyBlbmFibGVkLiBDYW5ub3Qgc3RvcCB0aGUgaGFyayBwcm9jZXNzLCBqdXN0IHJlbW92ZSB0aGUgc3BlY2lmaWMgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9mZignc3BlYWtpbmcnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gTm8gb3RoZXIgaGFyayBldmVudCBpcyBlbmFibGVkLiBXZSBjYW4gZ2V0IGVudGlyZWx5IHJpZCBvZiBpdFxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNwZWVjaEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpO1xuICAgICAgICBpZiAoIXRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWQgJiYgISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub24oJ3N0b3BwZWRfc3BlYWtpbmcnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uLmVtaXRFdmVudCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgW25ldyBQdWJsaXNoZXJTcGVha2luZ0V2ZW50KHRoaXMuc2Vzc2lvbiwgJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIHRoaXMuY29ubmVjdGlvbiwgdGhpcy5zdHJlYW1JZCldKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1hbmFnZXIuZW1pdEV2ZW50KCdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCBbbmV3IFB1Ymxpc2hlclNwZWFraW5nRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdGhpcy5jb25uZWN0aW9uLCB0aGlzLnN0cmVhbUlkKV0pO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7IC8vIERpc2FibGUgJ29uY2UnIHZlcnNpb24gaWYgJ29uJyB2ZXJzaW9uIHdhcyB0cmlnZ2VyZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VIYXJrU3RvcHBlZFNwZWFraW5nRXZlbnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2V0SGFya0xpc3RlbmVySWZOb3RFeGlzdHMoKTtcbiAgICAgICAgaWYgKCF0aGlzLmhhcmtTdG9wcGVkU3BlYWtpbmdFbmFibGVkT25jZSAmJiAhIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub25jZSgnc3RvcHBlZF9zcGVha2luZycsICgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGxpc3RlbmVyIGhhcyBiZWVuIGRpc2FibGVkIGluIHRoZSBtZWFudGltZSAoZm9yIGV4YW1wbGUgYnkgdGhlICdvbicgdmVyc2lvbikgZG8gbm90IHRyaWdnZXIgdGhlIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnNlc3Npb24sICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3B1Ymxpc2hlclN0b3BTcGVha2luZycsIFtuZXcgUHVibGlzaGVyU3BlYWtpbmdFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnLCB0aGlzLmNvbm5lY3Rpb24sIHRoaXMuc3RyZWFtSWQpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCh0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgKiBAaGlkZGVuXG4gICAgKi9cbiAgICBkaXNhYmxlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KGRpc2FibGVkQnlPbmNlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmICghIXRoaXMuc3BlZWNoRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoZGlzYWJsZWRCeU9uY2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgY2FuY2VsbGluZyB0aGUgJ29uY2UnIGxpc3RlbmVyIGZvciB0aGlzIGV2ZW50LCBidXQgdGhlICdvbicgdmVyc2lvblxuICAgICAgICAgICAgICAgICAgICAvLyBvZiB0aGlzIHNhbWUgZXZlbnQgaXMgZW5hYmxlZCB0b28uIERvIG5vdCByZW1vdmUgdGhlIGhhcmsgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2h1dHRpbmcgZG93biB0aGUgaGFyayBldmVudFxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1NwZWFraW5nRW5hYmxlZE9uY2UpIHtcbiAgICAgICAgICAgICAgICAvLyBTb21lIG90aGVyIGhhcmsgZXZlbnQgaXMgZW5hYmxlZC4gQ2Fubm90IHN0b3AgdGhlIGhhcmsgcHJvY2VzcywganVzdCByZW1vdmUgdGhlIHNwZWNpZmljIGxpc3RlbmVyXG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vZmYoJ3N0b3BwZWRfc3BlYWtpbmcnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gTm8gb3RoZXIgaGFyayBldmVudCBpcyBlbmFibGVkLiBXZSBjYW4gZ2V0IGVudGlyZWx5IHJpZCBvZiBpdFxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQuc3RvcCgpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNwZWVjaEV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudChmb3JjZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgfHwgZm9yY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uKCd2b2x1bWVfY2hhbmdlJywgaGFya0V2ZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkVmFsdWUgPSB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHsgbmV3VmFsdWU6IGhhcmtFdmVudCwgb2xkVmFsdWUgfTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudC5vbGRWb2x1bWVWYWx1ZSA9IGhhcmtFdmVudDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmVtaXRFdmVudCgnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzLnN0cmVhbU1hbmFnZXIsICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScsIHZhbHVlKV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhpcyB3YXkgd2hlbmV2ZXIgdGhlIE1lZGlhU3RyZWFtIG9iamVjdCBpcyBhdmFpbGFibGUsIHRoZSBldmVudCBsaXN0ZW5lciB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWRcbiAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVuYWJsZU9uY2VIYXJrVm9sdW1lQ2hhbmdlRXZlbnQoZm9yY2U6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0SGFya0xpc3RlbmVySWZOb3RFeGlzdHMoKSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSB8fCBmb3JjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9uY2UoJ3ZvbHVtZV9jaGFuZ2UnLCBoYXJrRXZlbnQgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHRoaXMuc3BlZWNoRXZlbnQub2xkVm9sdW1lVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0geyBuZXdWYWx1ZTogaGFya0V2ZW50LCBvbGRWYWx1ZSB9O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50Lm9sZFZvbHVtZVZhbHVlID0gaGFya0V2ZW50O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVIYXJrVm9sdW1lQ2hhbmdlRXZlbnQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWFuYWdlci5lbWl0RXZlbnQoJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcy5zdHJlYW1NYW5hZ2VyLCAnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnLCB2YWx1ZSldKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgd2F5IHdoZW5ldmVyIHRoZSBNZWRpYVN0cmVhbSBvYmplY3QgaXMgYXZhaWxhYmxlLCB0aGUgZXZlbnQgbGlzdGVuZXIgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGFkZGVkXG4gICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudChkaXNhYmxlZEJ5T25jZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoISF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhcmtWb2x1bWVDaGFuZ2VFbmFibGVkT25jZSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGRpc2FibGVkQnlPbmNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGNhbmNlbGxpbmcgdGhlICdvbmNlJyBsaXN0ZW5lciBmb3IgdGhpcyBldmVudCwgYnV0IHRoZSAnb24nIHZlcnNpb25cbiAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhpcyBzYW1lIGV2ZW50IGlzIGVuYWJsZWQgdG9vLiBEbyBub3QgcmVtb3ZlIHRoZSBoYXJrIGxpc3RlbmVyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFNodXR0aW5nIGRvd24gdGhlIGhhcmsgZXZlbnRcbiAgICAgICAgICAgIGlmICh0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLmhhcmtTcGVha2luZ0VuYWJsZWRPbmNlIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5oYXJrU3RvcHBlZFNwZWFraW5nRW5hYmxlZCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuaGFya1N0b3BwZWRTcGVha2luZ0VuYWJsZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgLy8gU29tZSBvdGhlciBoYXJrIGV2ZW50IGlzIGVuYWJsZWQuIENhbm5vdCBzdG9wIHRoZSBoYXJrIHByb2Nlc3MsIGp1c3QgcmVtb3ZlIHRoZSBzcGVjaWZpYyBsaXN0ZW5lclxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWNoRXZlbnQub2ZmKCd2b2x1bWVfY2hhbmdlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE5vIG90aGVyIGhhcmsgZXZlbnQgaXMgZW5hYmxlZC4gV2UgY2FuIGdldCBlbnRpcmVseSByaWQgb2YgaXRcbiAgICAgICAgICAgICAgICB0aGlzLnNwZWVjaEV2ZW50LnN0b3AoKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zcGVlY2hFdmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpc0xvY2FsKCk6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpbmJvdW5kIG9wdGlvbnMgdW5kZWZpbmVkIGFuZCBvdXRib3VuZCBvcHRpb25zIGRlZmluZWRcbiAgICAgICAgcmV0dXJuICghdGhpcy5pbmJvdW5kU3RyZWFtT3B0cyAmJiAhIXRoaXMub3V0Ym91bmRTdHJlYW1PcHRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGUoKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2ViUnRjU3RhdHMuZ2V0U2VsZWN0ZWRJY2VDYW5kaWRhdGVJbmZvKClcbiAgICAgICAgICAgICAgICAudGhlbihyZXBvcnQgPT4gcmVzb2x2ZShyZXBvcnQpKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdldFJlbW90ZUljZUNhbmRpZGF0ZUxpc3QoKTogUlRDSWNlQ2FuZGlkYXRlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWJSdGNQZWVyLnJlbW90ZUNhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZ2V0TG9jYWxJY2VDYW5kaWRhdGVMaXN0KCk6IFJUQ0ljZUNhbmRpZGF0ZVtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjUGVlci5sb2NhbENhbmRpZGF0ZXNRdWV1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgc3RyZWFtSWNlQ29ubmVjdGlvblN0YXRlQnJva2VuKCkge1xuICAgICAgICBpZiAoIXRoaXMuZ2V0V2ViUnRjUGVlcigpIHx8ICF0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0xvY2FsKCkgJiYgISF0aGlzLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLmZvcmNlTWVkaWFSZWNvbm5lY3Rpb25BZnRlck5ldHdvcmtEcm9wKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihgT3BlblZpZHUgQnJvd3NlciBhZHZhbmNlZCBjb25maWd1cmF0aW9uIG9wdGlvbiBcImZvcmNlTWVkaWFSZWNvbm5lY3Rpb25BZnRlck5ldHdvcmtEcm9wXCIgaXMgZW5hYmxlZC4gU3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSkgd2lsbCBmb3JjZSBhIHJlY29ubmVjdGlvbmApO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaWNlQ29ubmVjdGlvblN0YXRlOiBSVENJY2VDb25uZWN0aW9uU3RhdGUgPSB0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuaWNlQ29ubmVjdGlvblN0YXRlO1xuICAgICAgICByZXR1cm4gaWNlQ29ubmVjdGlvblN0YXRlICE9PSAnY29ubmVjdGVkJyAmJiBpY2VDb25uZWN0aW9uU3RhdGUgIT09ICdjb21wbGV0ZWQnO1xuICAgIH1cblxuICAgIC8qIFByaXZhdGUgbWV0aG9kcyAqL1xuXG4gICAgcHJpdmF0ZSBzZXRIYXJrTGlzdGVuZXJJZk5vdEV4aXN0cygpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNwZWVjaEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFya09wdGlvbnMgPSAhIXRoaXMuaGFya09wdGlvbnMgPyB0aGlzLmhhcmtPcHRpb25zIDogKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24ucHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zIHx8IHt9KTtcbiAgICAgICAgICAgICAgICBoYXJrT3B0aW9ucy5pbnRlcnZhbCA9ICh0eXBlb2YgaGFya09wdGlvbnMuaW50ZXJ2YWwgPT09ICdudW1iZXInKSA/IGhhcmtPcHRpb25zLmludGVydmFsIDogMTAwO1xuICAgICAgICAgICAgICAgIGhhcmtPcHRpb25zLnRocmVzaG9sZCA9ICh0eXBlb2YgaGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBoYXJrT3B0aW9ucy50aHJlc2hvbGQgOiAtNTA7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlY2hFdmVudCA9IGhhcmsodGhpcy5tZWRpYVN0cmVhbSwgaGFya09wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBzZXR1cFJlY29ubmVjdGlvbkV2ZW50RW1pdHRlcihyZXNvbHZlOiAodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZCwgcmVqZWN0OiAocmVhc29uPzogYW55KSA9PiB2b2lkKTogYm9vbGVhbiB7XG4gICAgICAgIGlmICh0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciA9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIG9uZ29pbmcgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICB0aGlzLnJlY29ubmVjdGlvbkV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9uZ29pbmcgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFRyeWluZyB0byByZWNvbm5lY3Qgc3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7dGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJ30pIGJ1dCBhbiBvbmdvaW5nIHJlY29ubmVjdGlvbiBwcm9jZXNzIGlzIGFjdGl2ZS4gV2FpdGluZyBmb3IgcmVzcG9uc2UuLi5gKTtcbiAgICAgICAgICAgIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyLm9uY2UoJ3N1Y2Nlc3MnLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXIub25jZSgnZXJyb3InLCBlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyU2VuZChyZWNvbm5lY3Q6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHVwUmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyKHJlc29sdmUsIHJlamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT25nb2luZyByZWNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gTWVkaWFTdHJlYW0gd2lsbCBhbHJlYWR5IGhhdmUgaGFyayBldmVudHMgZm9yIHJlY29ubmVjdGVkIHN0cmVhbXNcbiAgICAgICAgICAgICAgICB0aGlzLmluaXRIYXJrRXZlbnRzKCk7IC8vIEluaXQgaGFyayBldmVudHMgZm9yIHRoZSBsb2NhbCBzdHJlYW1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZmluYWxSZXNvbHZlID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI/LmVtaXRFdmVudCgnc3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbmFsUmVqZWN0ID0gZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI/LmVtaXRFdmVudCgnZXJyb3InLCBbZXJyb3JdKTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qgc3VjY2Vzc09mZmVyQ2FsbGJhY2sgPSAoc2RwT2ZmZXJQYXJhbSkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnU2VuZGluZyBTRFAgb2ZmZXIgdG8gcHVibGlzaCBhcyAnXG4gICAgICAgICAgICAgICAgICAgICsgdGhpcy5zdHJlYW1JZCwgc2RwT2ZmZXJQYXJhbSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBtZXRob2QgPSByZWNvbm5lY3QgPyAncmVjb25uZWN0U3RyZWFtJyA6ICdwdWJsaXNoVmlkZW8nO1xuICAgICAgICAgICAgICAgIGxldCBwYXJhbXM7XG4gICAgICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW06IHRoaXMuc3RyZWFtSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZHBTdHJpbmc6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCB0eXBlT2ZWaWRlbztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTZW5kVmlkZW8oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW8gPSAodHlwZW9mIE1lZGlhU3RyZWFtVHJhY2sgIT09ICd1bmRlZmluZWQnICYmIHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMudmlkZW9Tb3VyY2UgaW5zdGFuY2VvZiBNZWRpYVN0cmVhbVRyYWNrKSA/IFR5cGVPZlZpZGVvLkNVU1RPTSA6ICh0aGlzLmlzU2VuZFNjcmVlbigpID8gVHlwZU9mVmlkZW8uU0NSRUVOIDogVHlwZU9mVmlkZW8uQ0FNRVJBKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb0xvb3BiYWNrOiB0aGlzLmRpc3BsYXlNeVJlbW90ZSgpIHx8IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGFzQXVkaW86IHRoaXMuaXNTZW5kQXVkaW8oKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1ZpZGVvOiB0aGlzLmlzU2VuZFZpZGVvKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBhdWRpb0FjdGl2ZTogdGhpcy5hdWRpb0FjdGl2ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvQWN0aXZlOiB0aGlzLnZpZGVvQWN0aXZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZU9mVmlkZW8sXG4gICAgICAgICAgICAgICAgICAgICAgICBmcmFtZVJhdGU6ICEhdGhpcy5mcmFtZVJhdGUgPyB0aGlzLmZyYW1lUmF0ZSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmlkZW9EaW1lbnNpb25zOiBKU09OLnN0cmluZ2lmeSh0aGlzLnZpZGVvRGltZW5zaW9ucyksXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXI6IHRoaXMub3V0Ym91bmRTdHJlYW1PcHRzLnB1Ymxpc2hlclByb3BlcnRpZXMuZmlsdGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2RwT2ZmZXI6IHNkcE9mZmVyUGFyYW1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5zZW5kUmVxdWVzdChtZXRob2QsIHBhcmFtcywgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvci5jb2RlID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlamVjdChuZXcgT3BlblZpZHVFcnJvcihPcGVuVmlkdUVycm9yTmFtZS5PUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCwgXCJZb3UgZG9uJ3QgaGF2ZSBwZXJtaXNzaW9ucyB0byBwdWJsaXNoXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZWplY3QoJ0Vycm9yIG9uIHB1Ymxpc2hWaWRlbzogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc1JlbW90ZUFuc3dlcihyZXNwb25zZS5zZHBBbnN3ZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gcmVzcG9uc2UuaWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRpb25UaW1lID0gcmVzcG9uc2UuY3JlYXRlZEF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzTG9jYWxTdHJlYW1QdWJsaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hlZE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2NhbE1lZGlhU3RyZWFtV2hlblN1YnNjcmliZWRUb1JlbW90ZSA9IHRoaXMubWVkaWFTdHJlYW07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZChyZWNvbm5lY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW0tcmVjb25uZWN0ZWQtYnktcHVibGlzaGVyJywgW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbS1jcmVhdGVkLWJ5LXB1Ymxpc2hlcicsIFtdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRXZWJSdGNTdGF0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIidQdWJsaXNoZXInIChcIiArIHRoaXMuc3RyZWFtSWQgKyBcIikgc3VjY2Vzc2Z1bGx5IFwiICsgKHJlY29ubmVjdCA/IFwicmVjb25uZWN0ZWRcIiA6IFwicHVibGlzaGVkXCIpICsgXCIgdG8gc2Vzc2lvblwiKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgY29uZmlnOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB0aGlzLmhhc0F1ZGlvLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogdGhpcy5oYXNWaWRlbyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNpbXVsY2FzdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NpbXVsY2FzdCA/PyB0aGlzLnNlc3Npb24ub3BlbnZpZHUudmlkZW9TaW11bGNhc3QsXG4gICAgICAgICAgICAgICAgb25JY2VDYW5kaWRhdGU6IHRoaXMuY29ubmVjdGlvbi5zZW5kSWNlQ2FuZGlkYXRlLmJpbmQodGhpcy5jb25uZWN0aW9uKSxcbiAgICAgICAgICAgICAgICBvbkljZUNvbm5lY3Rpb25TdGF0ZUV4Y2VwdGlvbjogKGV4Y2VwdGlvbk5hbWU6IEV4Y2VwdGlvbkV2ZW50TmFtZSwgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogYW55KSA9PiB7IHRoaXMuc2Vzc2lvbi5lbWl0RXZlbnQoJ2V4Y2VwdGlvbicsIFtuZXcgRXhjZXB0aW9uRXZlbnQodGhpcy5zZXNzaW9uLCBleGNlcHRpb25OYW1lLCB0aGlzLCBtZXNzYWdlLCBkYXRhKV0pIH0sXG4gICAgICAgICAgICAgICAgaWNlU2VydmVyczogdGhpcy5nZXRJY2VTZXJ2ZXJzQ29uZigpLFxuICAgICAgICAgICAgICAgIG1lZGlhU3RyZWFtOiB0aGlzLm1lZGlhU3RyZWFtLFxuICAgICAgICAgICAgICAgIG1lZGlhU2VydmVyOiB0aGlzLnNlc3Npb24ub3BlbnZpZHUubWVkaWFTZXJ2ZXIsXG4gICAgICAgICAgICAgICAgdHlwZU9mVmlkZW86IHRoaXMudHlwZU9mVmlkZW8gPyBUeXBlT2ZWaWRlb1t0aGlzLnR5cGVPZlZpZGVvXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUubWVkaWFTZXJ2ZXIgIT09ICdtZWRpYXNvdXAnKSB7XG4gICAgICAgICAgICAgICAgLy8gU2ltdWxjYXN0IGlzIG9ubHkgc3VwcG9ydGVkIGJ5IG1lZGlhc291cFxuICAgICAgICAgICAgICAgIGNvbmZpZy5zaW11bGNhc3QgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmRpc3BsYXlNeVJlbW90ZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXJTZW5kcmVjdihjb25maWcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclNlbmRvbmx5KGNvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuYWRkSWNlQ29ubmVjdGlvblN0YXRlQ2hhbmdlTGlzdGVuZXIoJ3B1Ymxpc2hlciBvZiAnICsgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuY3JlYXRlT2ZmZXIoKS50aGVuKHNkcE9mZmVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0xvY2FsT2ZmZXIoc2RwT2ZmZXIpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3NPZmZlckNhbGxiYWNrKHNkcE9mZmVyLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVqZWN0KG5ldyBFcnJvcignKHB1Ymxpc2gpIFNEUCBwcm9jZXNzIGxvY2FsIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIGZpbmFsUmVqZWN0KG5ldyBFcnJvcignKHB1Ymxpc2gpIFNEUCBjcmVhdGUgb2ZmZXIgZXJyb3I6ICcgKyBKU09OLnN0cmluZ2lmeShlcnJvcikpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZmluYWxSZXNvbHZlRm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdDogYm9vbGVhbiwgcmVzb2x2ZTogKHZhbHVlOiB2b2lkIHwgUHJvbWlzZUxpa2U8dm9pZD4pID0+IHZvaWQpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCInU3Vic2NyaWJlcicgKFwiICsgdGhpcy5zdHJlYW1JZCArIFwiKSBzdWNjZXNzZnVsbHkgXCIgKyAocmVjb25uZWN0ID8gXCJyZWNvbm5lY3RlZFwiIDogXCJzdWJzY3JpYmVkXCIpKTtcbiAgICAgICAgdGhpcy5yZW1vdGVQZWVyU3VjY2Vzc2Z1bGx5RXN0YWJsaXNoZWQocmVjb25uZWN0KTtcbiAgICAgICAgdGhpcy5pbml0V2ViUnRjU3RhdHMoKTtcbiAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI/LmVtaXRFdmVudCgnc3VjY2VzcycpO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGZpbmFsUmVqZWN0Rm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdDogYm9vbGVhbiwgZXJyb3I6IGFueSwgcmVqZWN0OiAocmVhc29uPzogYW55KSA9PiB2b2lkKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIGZvciAnU3Vic2NyaWJlcicgKFwiICsgdGhpcy5zdHJlYW1JZCArIFwiKSB3aGlsZSB0cnlpbmcgdG8gXCIgKyAocmVjb25uZWN0ID8gXCJyZWNvbm5lY3RcIiA6IFwic3Vic2NyaWJlXCIpICsgXCI6IFwiICsgZXJyb3IudG9TdHJpbmcoKSk7XG4gICAgICAgIGlmIChyZWNvbm5lY3QpIHtcbiAgICAgICAgICAgIHRoaXMucmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyPy5lbWl0RXZlbnQoJ2Vycm9yJywgW2Vycm9yXSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5yZWNvbm5lY3Rpb25FdmVudEVtaXR0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyUmVjZWl2ZShyZWNvbm5lY3Q6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblxuICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHVwUmVjb25uZWN0aW9uRXZlbnRFbWl0dGVyKHJlc29sdmUsIHJlamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT25nb2luZyByZWNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5tZWRpYVNlcnZlciA9PT0gJ21lZGlhc291cCcpIHtcblxuICAgICAgICAgICAgICAgIC8vIFNlcnZlciBpbml0aWF0ZXMgbmVnb3RpYXRpb25cblxuICAgICAgICAgICAgICAgIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlRnJvbVNlcnZlcihyZWNvbm5lY3QpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuZmluYWxSZXNvbHZlRm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdCwgcmVzb2x2ZSkpXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB0aGlzLmZpbmFsUmVqZWN0Rm9yU3Vic2NyaXB0aW9uKHJlY29ubmVjdCwgZXJyb3IsIHJlamVjdCkpO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gQ2xpZW50IGluaXRpYXRlcyBuZWdvdGlhdGlvblxuXG4gICAgICAgICAgICAgICAgdGhpcy5pbml0V2ViUnRjUGVlclJlY2VpdmVGcm9tQ2xpZW50KHJlY29ubmVjdClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5maW5hbFJlc29sdmVGb3JTdWJzY3JpcHRpb24ocmVjb25uZWN0LCByZXNvbHZlKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuZmluYWxSZWplY3RGb3JTdWJzY3JpcHRpb24ocmVjb25uZWN0LCBlcnJvciwgcmVqZWN0KSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyUmVjZWl2ZUZyb21DbGllbnQocmVjb25uZWN0OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNvbXBsZXRlV2ViUnRjUGVlclJlY2VpdmUocmVjb25uZWN0LCBmYWxzZSlcbiAgICAgICAgICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzUmVtb3RlQW5zd2VyKHJlc3BvbnNlLnNkcEFuc3dlcilcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRXZWJSdGNQZWVyUmVjZWl2ZUZyb21TZXJ2ZXIocmVjb25uZWN0OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAvLyBTZXJ2ZXIgaW5pdGlhdGVzIG5lZ290aWF0aW9uXG4gICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ3ByZXBhcmVSZWNlaXZlVmlkZW9Gcm9tJywgeyBzZW5kZXI6IHRoaXMuc3RyZWFtSWQsIHJlY29ubmVjdCB9LCAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKCdFcnJvciBvbiBwcmVwYXJlUmVjZWl2ZVZpZGVvRnJvbTogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGxldGVXZWJSdGNQZWVyUmVjZWl2ZShyZWNvbm5lY3QsIGZhbHNlLCByZXNwb25zZS5zZHBPZmZlcilcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbXBsZXRlV2ViUnRjUGVlclJlY2VpdmUocmVjb25uZWN0OiBib29sZWFuLCBmb3JjaWJseVJlY29ubmVjdDogYm9vbGVhbiwgc2RwT2ZmZXJCeVNlcnZlcj86IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIidTZXNzaW9uLnN1YnNjcmliZShTdHJlYW0pJyBjYWxsZWRcIik7XG5cbiAgICAgICAgICAgIGNvbnN0IHNlbmRTZHBUb1NlcnZlciA9IChzZHBTdHJpbmc6IHN0cmluZykgPT4ge1xuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBTZW5kaW5nIGxvY2FsIFNEUCAkeyghIXNkcE9mZmVyQnlTZXJ2ZXIgPyAnYW5zd2VyJyA6ICdvZmZlcicpfSB0byBzdWJzY3JpYmUgdG8gJHt0aGlzLnN0cmVhbUlkfWAsIHNkcFN0cmluZyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBtZXRob2QgPSByZWNvbm5lY3QgPyAncmVjb25uZWN0U3RyZWFtJyA6ICdyZWNlaXZlVmlkZW9Gcm9tJztcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7fTtcbiAgICAgICAgICAgICAgICBwYXJhbXNbcmVjb25uZWN0ID8gJ3N0cmVhbScgOiAnc2VuZGVyJ10gPSB0aGlzLnN0cmVhbUlkO1xuICAgICAgICAgICAgICAgIGlmICghIXNkcE9mZmVyQnlTZXJ2ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zW3JlY29ubmVjdCA/ICdzZHBTdHJpbmcnIDogJ3NkcEFuc3dlciddID0gc2RwU3RyaW5nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtc1snc2RwT2ZmZXInXSA9IHNkcFN0cmluZztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbJ2ZvcmNpYmx5UmVjb25uZWN0J10gPSBmb3JjaWJseVJlY29ubmVjdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QobWV0aG9kLCBwYXJhbXMsIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignRXJyb3Igb24gJyArIG1ldGhvZCArICcgOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbmZpZzogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgbWVkaWFDb25zdHJhaW50czoge1xuICAgICAgICAgICAgICAgICAgICBhdWRpbzogdGhpcy5oYXNBdWRpbyxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRoaXMuaGFzVmlkZW8sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzaW11bGNhc3Q6IGZhbHNlLFxuICAgICAgICAgICAgICAgIG9uSWNlQ2FuZGlkYXRlOiB0aGlzLmNvbm5lY3Rpb24uc2VuZEljZUNhbmRpZGF0ZS5iaW5kKHRoaXMuY29ubmVjdGlvbiksXG4gICAgICAgICAgICAgICAgb25JY2VDb25uZWN0aW9uU3RhdGVFeGNlcHRpb246IChleGNlcHRpb25OYW1lOiBFeGNlcHRpb25FdmVudE5hbWUsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IGFueSkgPT4geyB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdleGNlcHRpb24nLCBbbmV3IEV4Y2VwdGlvbkV2ZW50KHRoaXMuc2Vzc2lvbiwgZXhjZXB0aW9uTmFtZSwgdGhpcywgbWVzc2FnZSwgZGF0YSldKSB9LFxuICAgICAgICAgICAgICAgIGljZVNlcnZlcnM6IHRoaXMuZ2V0SWNlU2VydmVyc0NvbmYoKSxcbiAgICAgICAgICAgICAgICBtZWRpYVNlcnZlcjogdGhpcy5zZXNzaW9uLm9wZW52aWR1Lm1lZGlhU2VydmVyLFxuICAgICAgICAgICAgICAgIHR5cGVPZlZpZGVvOiB0aGlzLnR5cGVPZlZpZGVvID8gVHlwZU9mVmlkZW9bdGhpcy50eXBlT2ZWaWRlb10gOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAocmVjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwb3NlV2ViUnRjUGVlcigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIgPSBuZXcgV2ViUnRjUGVlclJlY3Zvbmx5KGNvbmZpZyk7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIuYWRkSWNlQ29ubmVjdGlvblN0YXRlQ2hhbmdlTGlzdGVuZXIodGhpcy5zdHJlYW1JZCk7XG5cbiAgICAgICAgICAgIGlmICghIXNkcE9mZmVyQnlTZXJ2ZXIpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzUmVtb3RlT2ZmZXIoc2RwT2ZmZXJCeVNlcnZlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5jcmVhdGVBbnN3ZXIoKS50aGVuKHNkcEFuc3dlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndlYlJ0Y1BlZXIucHJvY2Vzc0xvY2FsQW5zd2VyKHNkcEFuc3dlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFNkcFRvU2VydmVyKHNkcEFuc3dlci5zZHAhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignKHN1YnNjcmliZSkgU0RQIHByb2Nlc3MgbG9jYWwgYW5zd2VyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBjcmVhdGUgYW5zd2VyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoJyhzdWJzY3JpYmUpIFNEUCBwcm9jZXNzIHJlbW90ZSBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgdGhpcy53ZWJSdGNQZWVyLmNyZWF0ZU9mZmVyKCkudGhlbihzZHBPZmZlciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjUGVlci5wcm9jZXNzTG9jYWxPZmZlcihzZHBPZmZlcikudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kU2RwVG9TZXJ2ZXIoc2RwT2ZmZXIuc2RwISk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgcHJvY2VzcyBsb2NhbCBvZmZlciBlcnJvcjogJyArIEpTT04uc3RyaW5naWZ5KGVycm9yKSkpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKCcoc3Vic2NyaWJlKSBTRFAgY3JlYXRlIG9mZmVyIGVycm9yOiAnICsgSlNPTi5zdHJpbmdpZnkoZXJyb3IpKSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHJlbW90ZVBlZXJTdWNjZXNzZnVsbHlFc3RhYmxpc2hlZChyZWNvbm5lY3Q6IGJvb2xlYW4pOiB2b2lkIHtcblxuICAgICAgICBpZiAocmVjb25uZWN0ICYmIHRoaXMubWVkaWFTdHJlYW0gIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gTm93IHdlIGNhbiBkZXN0cm95IHRoZSBleGlzdGluZyBNZWRpYVN0cmVhbVxuICAgICAgICAgICAgdGhpcy5kaXNwb3NlTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBuZXcgTWVkaWFTdHJlYW0oKTtcbiAgICAgICAgbGV0IHJlY2VpdmVyOiBSVENSdHBSZWNlaXZlcjtcbiAgICAgICAgZm9yIChyZWNlaXZlciBvZiB0aGlzLndlYlJ0Y1BlZXIucGMuZ2V0UmVjZWl2ZXJzKCkpIHtcbiAgICAgICAgICAgIGlmICghIXJlY2VpdmVyLnRyYWNrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5hZGRUcmFjayhyZWNlaXZlci50cmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdQZWVyIHJlbW90ZSBzdHJlYW0nLCB0aGlzLm1lZGlhU3RyZWFtKTtcblxuICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtKSB7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbU1hbmFnZXIgaW5zdGFuY2VvZiBTdWJzY3JpYmVyKSB7XG4gICAgICAgICAgICAgICAgLy8gQXBwbHkgU3Vic2NyaWJlclByb3BlcnRpZXMuc3Vic2NyaWJlVG9BdWRpbyBhbmQgU3Vic2NyaWJlclByb3BlcnRpZXMuc3Vic2NyaWJlVG9WaWRlb1xuICAgICAgICAgICAgICAgIGlmICghIXRoaXMubWVkaWFTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmFibGVkID0gcmVjb25uZWN0ID8gdGhpcy5hdWRpb0FjdGl2ZSA6ICEhKCh0aGlzLnN0cmVhbU1hbmFnZXIgYXMgU3Vic2NyaWJlcikucHJvcGVydGllcy5zdWJzY3JpYmVUb0F1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZWRpYVN0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdLmVuYWJsZWQgPSBlbmFibGVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5hYmxlZCA9IHJlY29ubmVjdCA/IHRoaXMudmlkZW9BY3RpdmUgOiAhISgodGhpcy5zdHJlYW1NYW5hZ2VyIGFzIFN1YnNjcmliZXIpLnByb3BlcnRpZXMuc3Vic2NyaWJlVG9WaWRlbyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5lbmFibGVkID0gZW5hYmxlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXBkYXRlTWVkaWFTdHJlYW1JblZpZGVvcygpO1xuICAgICAgICAgICAgdGhpcy5pbml0SGFya0V2ZW50cygpOyAvLyBJbml0IGhhcmsgZXZlbnRzIGZvciB0aGUgcmVtb3RlIHN0cmVhbVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0SGFya0V2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy5tZWRpYVN0cmVhbSEuZ2V0QXVkaW9UcmFja3MoKVswXSkge1xuICAgICAgICAgICAgLy8gSGFyayBldmVudHMgY2FuIG9ubHkgYmUgc2V0IGlmIGF1ZGlvIHRyYWNrIGlzIGF2YWlsYWJsZVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIHRydWUsIHRoaXMuc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZU9uY2VIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RhcnRTcGVha2luZycsIGZhbHNlLCB0aGlzLnN0cmVhbU1hbmFnZXIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVIYXJrU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgdHJ1ZSwgdGhpcy5zdHJlYW1NYW5hZ2VyKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlT25jZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbi5hbnlTcGVlY2hFdmVudExpc3RlbmVyRW5hYmxlZCgncHVibGlzaGVyU3RvcFNwZWFraW5nJywgZmFsc2UsIHRoaXMuc3RyZWFtTWFuYWdlcikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWRPbmNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVPbmNlSGFya1ZvbHVtZUNoYW5nZUV2ZW50KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaGFya1ZvbHVtZUNoYW5nZUVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUhhcmtWb2x1bWVDaGFuZ2VFdmVudCh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25JY2VDb25uZWN0aW9uU3RhdGVFeGNlcHRpb25IYW5kbGVyKGV4Y2VwdGlvbk5hbWU6IEV4Y2VwdGlvbkV2ZW50TmFtZSwgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogYW55KTogdm9pZCB7XG4gICAgICAgIHN3aXRjaCAoZXhjZXB0aW9uTmFtZSkge1xuICAgICAgICAgICAgY2FzZSBFeGNlcHRpb25FdmVudE5hbWUuSUNFX0NPTk5FQ1RJT05fRkFJTEVEOlxuICAgICAgICAgICAgICAgIHRoaXMub25JY2VDb25uZWN0aW9uRmFpbGVkKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEV4Y2VwdGlvbkV2ZW50TmFtZS5JQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5vbkljZUNvbm5lY3Rpb25EaXNjb25uZWN0ZWQoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlc3Npb24uZW1pdEV2ZW50KCdleGNlcHRpb24nLCBbbmV3IEV4Y2VwdGlvbkV2ZW50KHRoaXMuc2Vzc2lvbiwgZXhjZXB0aW9uTmFtZSwgdGhpcywgbWVzc2FnZSwgZGF0YSldKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uSWNlQ29ubmVjdGlvbkZhaWxlZCgpIHtcbiAgICAgICAgLy8gSW1tZWRpYXRlbHkgcmVjb25uZWN0LCBhcyB0aGlzIGlzIGEgdGVybWluYWwgZXJyb3JcbiAgICAgICAgbG9nZ2VyLmxvZyhgW0lDRV9DT05ORUNUSU9OX0ZBSUxFRF0gSGFuZGxpbmcgSUNFX0NPTk5FQ1RJT05fRkFJTEVEIGV2ZW50LiBSZWNvbm5lY3Rpbmcgc3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSlgKTtcbiAgICAgICAgdGhpcy5yZWNvbm5lY3RTdHJlYW1BbmRMb2dSZXN1bHRpbmdJY2VDb25uZWN0aW9uU3RhdGUoRXhjZXB0aW9uRXZlbnROYW1lLklDRV9DT05ORUNUSU9OX0ZBSUxFRCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkljZUNvbm5lY3Rpb25EaXNjb25uZWN0ZWQoKSB7XG4gICAgICAgIC8vIFdhaXQgdG8gc2VlIGlmIHRoZSBJQ0UgY29ubmVjdGlvbiBpcyBhYmxlIHRvIHJlY29ubmVjdFxuICAgICAgICBsb2dnZXIubG9nKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBIYW5kbGluZyBJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQgZXZlbnQuIFdhaXRpbmcgZm9yIElDRSB0byBiZSByZXN0b3JlZCBhbmQgcmVjb25uZWN0IHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9ICgkeyh0aGlzLmlzTG9jYWwoKSA/ICdQdWJsaXNoZXInIDogJ1N1YnNjcmliZXInKX0pIGlmIG5vdCBwb3NzaWJsZWApO1xuICAgICAgICBjb25zdCB0aW1lb3V0ID0gdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VDb25uZWN0aW9uRGlzY29ubmVjdGVkRXhjZXB0aW9uVGltZW91dCB8fCA0MDAwO1xuICAgICAgICB0aGlzLmF3YWl0V2ViUnRjUGVlckNvbm5lY3Rpb25TdGF0ZSh0aW1lb3V0KS50aGVuKHN0YXRlID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdmYWlsZWQnOlxuICAgICAgICAgICAgICAgICAgICAvLyBEbyBub3RoaW5nLCBhcyBhbiBJQ0VfQ09OTkVDVElPTl9GQUlMRUQgZXZlbnQgd2lsbCBoYXZlIGFscmVhZHkgcmFpc2VkXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBJQ0UgY29ubmVjdGlvbiBvZiBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBpcyBub3cgZmFpbGVkIGFmdGVyIElDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRGApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjb25uZWN0ZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coYFtJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURURdIElDRSBjb25uZWN0aW9uIG9mIHN0cmVhbSAke3RoaXMuc3RyZWFtSWR9ICgkeyh0aGlzLmlzTG9jYWwoKSA/ICdQdWJsaXNoZXInIDogJ1N1YnNjcmliZXInKX0pIGF1dG9tYXRpY2FsbHkgcmVzdG9yZWQgYWZ0ZXIgSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVELiBDdXJyZW50IElDRSBjb25uZWN0aW9uIHN0YXRlOiAke3N0YXRlfWApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNraW5nJzpcbiAgICAgICAgICAgICAgICBjYXNlICduZXcnOlxuICAgICAgICAgICAgICAgIGNhc2UgJ2Rpc2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc3Qgb2Ygc3RhdGVzXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEXSBJQ0UgY29ubmVjdGlvbiBvZiBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBjb3VsZG4ndCBiZSByZXN0b3JlZCBhZnRlciBJQ0VfQ09OTkVDVElPTl9ESVNDT05ORUNURUQgZXZlbnQuIEN1cnJlbnQgSUNFIGNvbm5lY3Rpb24gc3RhdGUgYWZ0ZXIgJHt0aW1lb3V0fSBtczogJHtzdGF0ZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RTdHJlYW1BbmRMb2dSZXN1bHRpbmdJY2VDb25uZWN0aW9uU3RhdGUoRXhjZXB0aW9uRXZlbnROYW1lLklDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHJlY29ubmVjdFN0cmVhbUFuZExvZ1Jlc3VsdGluZ0ljZUNvbm5lY3Rpb25TdGF0ZShldmVudDogc3RyaW5nKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBmaW5hbEljZVN0YXRlQWZ0ZXJSZWNvbm5lY3Rpb24gPSBhd2FpdCB0aGlzLnJlY29ubmVjdFN0cmVhbUFuZFJldHVybkljZUNvbm5lY3Rpb25TdGF0ZShldmVudCk7XG4gICAgICAgICAgICBzd2l0Y2ggKGZpbmFsSWNlU3RhdGVBZnRlclJlY29ubmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnY29tcGxldGVkJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhgWyR7ZXZlbnR9XSBTdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBzdWNjZXNzZnVsbHkgcmVjb25uZWN0ZWQgYWZ0ZXIgJHtldmVudH0uIEN1cnJlbnQgSUNFIGNvbm5lY3Rpb24gc3RhdGU6ICR7ZmluYWxJY2VTdGF0ZUFmdGVyUmVjb25uZWN0aW9ufWApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYFske2V2ZW50fV0gU3RyZWFtICR7dGhpcy5zdHJlYW1JZH0gKCR7KHRoaXMuaXNMb2NhbCgpID8gJ1B1Ymxpc2hlcicgOiAnU3Vic2NyaWJlcicpfSkgZmFpbGVkIHRvIHJlY29ubmVjdCBhZnRlciAke2V2ZW50fS4gQ3VycmVudCBJQ0UgY29ubmVjdGlvbiBzdGF0ZTogJHtmaW5hbEljZVN0YXRlQWZ0ZXJSZWNvbm5lY3Rpb259YCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBbJHtldmVudH1dIEVycm9yIHJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhZnRlciAke2V2ZW50fTogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVjb25uZWN0U3RyZWFtQW5kUmV0dXJuSWNlQ29ubmVjdGlvblN0YXRlKGV2ZW50OiBzdHJpbmcpOiBQcm9taXNlPFJUQ0ljZUNvbm5lY3Rpb25TdGF0ZT4ge1xuICAgICAgICBsb2dnZXIubG9nKGBbJHtldmVudH1dIFJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhZnRlciBldmVudCAke2V2ZW50fWApO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZWNvbm5lY3RTdHJlYW0oZXZlbnQpO1xuICAgICAgICAgICAgY29uc3QgdGltZW91dCA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlQ29ubmVjdGlvbkRpc2Nvbm5lY3RlZEV4Y2VwdGlvblRpbWVvdXQgfHwgNDAwMDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmF3YWl0V2ViUnRjUGVlckNvbm5lY3Rpb25TdGF0ZSh0aW1lb3V0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGBbJHtldmVudH1dIEVycm9yIHJlY29ubmVjdGluZyBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KS4gUmVhc29uOiAke2Vycm9yfWApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXdhaXRXZWJSdGNQZWVyQ29ubmVjdGlvblN0YXRlKDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZWNvbm5lY3RTdHJlYW0oZXZlbnQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCBpc1dzQ29ubmVjdGVkID0gYXdhaXQgdGhpcy5pc1dlYnNvY2tldENvbm5lY3RlZChldmVudCwgMzAwMCk7XG4gICAgICAgIGlmIChpc1dzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgICAvLyBUaGVyZSBpcyBjb25uZWN0aW9uIHRvIG9wZW52aWR1LXNlcnZlci4gVGhlIFJUQ1BlZXJDb25uZWN0aW9uIGlzIHRoZSBvbmx5IG9uZSBicm9rZW5cbiAgICAgICAgICAgIGxvZ2dlci5sb2coYFske2V2ZW50fV0gVHJ5aW5nIHRvIHJlY29ubmVjdCBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBhbmQgdGhlIHdlYnNvY2tldCBpcyBvcGVuZWRgKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXRXZWJSdGNQZWVyU2VuZCh0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdFdlYlJ0Y1BlZXJSZWNlaXZlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlcmUgaXMgbm8gY29ubmVjdGlvbiB0byBvcGVudmlkdS1zZXJ2ZXIuIE5vdGhpbmcgY2FuIGJlIGRvbmUuIFRoZSBhdXRvbWF0aWMgcmVjb25uZWN0aW9uXG4gICAgICAgICAgICAvLyBmZWF0dXJlIHNob3VsZCBoYW5kbGUgYSBwb3NzaWJsZSByZWNvbm5lY3Rpb24gb2YgUlRDUGVlckNvbm5lY3Rpb24gaW4gY2FzZSBuZXR3b3JrIGNvbWVzIGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGVycm9yTXNnID0gYFske2V2ZW50fV0gVHJ5aW5nIHRvIHJlY29ubmVjdCBzdHJlYW0gJHt0aGlzLnN0cmVhbUlkfSAoJHsodGhpcy5pc0xvY2FsKCkgPyAnUHVibGlzaGVyJyA6ICdTdWJzY3JpYmVyJyl9KSBidXQgdGhlIHdlYnNvY2tldCB3YXNuJ3Qgb3BlbmVkYDtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnJvck1zZyk7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcihlcnJvck1zZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGlzV2Vic29ja2V0Q29ubmVjdGVkKGV2ZW50OiBzdHJpbmcsIG1zUmVzcG9uc2VUaW1lb3V0OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdzUmVhZHlTdGF0ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5nZXRXc1JlYWR5U3RhdGUoKTtcbiAgICAgICAgICAgIGlmICh3c1JlYWR5U3RhdGUgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZVRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbJHtldmVudH1dIFdlYnNvY2tldCB0aW1lb3V0IG9mICR7bXNSZXNwb25zZVRpbWVvdXR9bXNgKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH0sIG1zUmVzcG9uc2VUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb24ub3BlbnZpZHUuc2VuZFJlcXVlc3QoJ2VjaG8nLCB7fSwgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2VUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEhZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgWyR7ZXZlbnR9XSBXZWJzb2NrZXQgJ2VjaG8nIHJldHVybmVkIGVycm9yOiAke2Vycm9yfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbJHtldmVudH1dIFdlYnNvY2tldCByZWFkeVN0YXRlIGlzICR7d3NSZWFkeVN0YXRlfWApO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBhd2FpdFdlYlJ0Y1BlZXJDb25uZWN0aW9uU3RhdGUodGltZW91dDogbnVtYmVyKTogUHJvbWlzZTxSVENJY2VDb25uZWN0aW9uU3RhdGU+IHtcbiAgICAgICAgbGV0IHN0YXRlID0gdGhpcy5nZXRSVENQZWVyQ29ubmVjdGlvbigpLmljZUNvbm5lY3Rpb25TdGF0ZTtcbiAgICAgICAgY29uc3QgaW50ZXJ2YWwgPSAxNTA7XG4gICAgICAgIGNvbnN0IGludGVydmFscyA9IE1hdGguY2VpbCh0aW1lb3V0IC8gaW50ZXJ2YWwpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGludGVydmFsczsgaSsrKSB7XG4gICAgICAgICAgICBzdGF0ZSA9IHRoaXMuZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5pY2VDb25uZWN0aW9uU3RhdGU7XG4gICAgICAgICAgICBpZiAoc3RhdGUgPT09ICdjb25uZWN0ZWQnIHx8IHN0YXRlID09PSAnY29tcGxldGVkJykge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU2xlZXBcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGludGVydmFsKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMgPSBuZXcgV2ViUnRjU3RhdHModGhpcyk7XG4gICAgICAgIHRoaXMud2ViUnRjU3RhdHMuaW5pdFdlYlJ0Y1N0YXRzKCk7XG5cbiAgICAgICAgLy9UT0RPOiBzZW5kIGNvbW1vbiB3ZWJydGMgc3RhdHMgZnJvbSBjbGllbnQgdG8gb3BlbnZpZHUtc2VydmVyXG4gICAgICAgIC8qaWYgKHRoaXMuc2Vzc2lvbi5vcGVudmlkdS53ZWJydGNTdGF0c0ludGVydmFsID4gMCkge1xuICAgICAgICAgICAgc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2F0aGVyU3RhdHNGb3JQZWVyKCkudGhlbihqc29uU3RhdHMgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBib2R5ID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbklkOiB0aGlzLnNlc3Npb24uc2Vzc2lvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRQcml2YXRlSWQ6IHRoaXMuY29ubmVjdGlvbi5ycGNTZXNzaW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGF0czoganNvblN0YXRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgICAgICB4aHIub3BlbignUE9TVCcsIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5odHRwVXJpICsgJy9lbGFzdGljc2VhcmNoL3dlYnJ0Yy1zdGF0cycsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgICAgICAgICAgICAgeGhyLnNlbmQoSlNPTi5zdHJpbmdpZnkoYm9keSkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9LCB0aGlzLnNlc3Npb24ub3BlbnZpZHUud2VicnRjU3RhdHNJbnRlcnZhbCAqIDEwMDApO1xuICAgICAgICB9Ki9cbiAgICB9XG5cbiAgICBwcml2YXRlIHN0b3BXZWJSdGNTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEhdGhpcy53ZWJSdGNTdGF0cyAmJiB0aGlzLndlYlJ0Y1N0YXRzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLndlYlJ0Y1N0YXRzLnN0b3BXZWJSdGNTdGF0cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJY2VTZXJ2ZXJzQ29uZigpOiBSVENJY2VTZXJ2ZXJbXSB8IHVuZGVmaW5lZCB7XG4gICAgICAgIGxldCByZXR1cm5WYWx1ZTtcbiAgICAgICAgaWYgKCEhdGhpcy5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzKSB7XG4gICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycyA9PT0gJ2ZyZWVpY2UnID9cbiAgICAgICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5vcGVudmlkdS5hZHZhbmNlZENvbmZpZ3VyYXRpb24uaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycykge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzLnNlc3Npb24ub3BlbnZpZHUuaWNlU2VydmVycztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdhdGhlclN0YXRzRm9yUGVlcigpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNMb2NhbCgpKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBQdWJsaXNoZXIgc3RyZWFtIHN0YXRzXG5cbiAgICAgICAgICAgICAgICB0aGlzLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuZ2V0U2VuZGVycygpLmZvckVhY2goc2VuZGVyID0+IHNlbmRlci5nZXRTdGF0cygpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLmZvckVhY2gocmVwb3J0ID0+IHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1JlcG9ydFdhbnRlZChyZXBvcnQpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbmFsUmVwb3J0ID0ge307XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0Wyd0eXBlJ10gPSByZXBvcnQudHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0Wyd0aW1lc3RhbXAnXSA9IHJlcG9ydC50aW1lc3RhbXA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnaWQnXSA9IHJlcG9ydC5pZDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29tbW9uIHRvIENocm9tZSwgRmlyZWZveCBhbmQgU2FmYXJpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3NzcmMnXSA9IHJlcG9ydC5zc3JjO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydmaXJDb3VudCddID0gcmVwb3J0LmZpckNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydwbGlDb3VudCddID0gcmVwb3J0LnBsaUNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WyduYWNrQ291bnQnXSA9IHJlcG9ydC5uYWNrQ291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3FwU3VtJ10gPSByZXBvcnQucXBTdW07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgbWVkaWEgdHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghIXJlcG9ydC5raW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5raW5kO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISFyZXBvcnQubWVkaWFUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IHJlcG9ydC5tZWRpYVR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIGRvZXMgbm90IGhhdmUgJ21lZGlhVHlwZScgZGVmaW5lZCBmb3IgaW5ib3VuZC1ydHAuIE11c3QgYmUgaW5mZXJyZWQgZnJvbSAnaWQnIGZpZWxkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9IChyZXBvcnQuaWQuaW5kZXhPZignVmlkZW9TdHJlYW0nKSAhPT0gLTEpID8gJ3ZpZGVvJyA6ICdhdWRpbyc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbmFsUmVwb3J0WydtZWRpYVR5cGUnXSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnZnJhbWVzRW5jb2RlZCddID0gcmVwb3J0LmZyYW1lc0VuY29kZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3BhY2tldHNTZW50J10gPSByZXBvcnQucGFja2V0c1NlbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2J5dGVzU2VudCddID0gcmVwb3J0LmJ5dGVzU2VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmb3IgQ2hyb21lIGFuZCBTYWZhcmlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ2NhbmRpZGF0ZS1wYWlyJyAmJiByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBmaW5hbCBzZWxlY3RlZCBjYW5kaWRhdGUgcGFpclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmFpbGFibGVPdXRnb2luZ0JpdHJhdGUnXSA9IHJlcG9ydC5hdmFpbGFibGVPdXRnb2luZ0JpdHJhdGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3J0dCddID0gcmVwb3J0LmN1cnJlbnRSb3VuZFRyaXBUaW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydhdmVyYWdlUnR0J10gPSByZXBvcnQudG90YWxSb3VuZFRyaXBUaW1lIC8gcmVwb3J0LnJlc3BvbnNlc1JlY2VpdmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IGZvciBGaXJlZm94ID49IDY2LjBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ3JlbW90ZS1pbmJvdW5kLXJ0cCcgfHwgcmVwb3J0LnR5cGUgPT09ICdyZW1vdGUtb3V0Ym91bmQtcnRwJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coZmluYWxSZXBvcnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgLy8gU3Vic2NyaWJlciBzdHJlYW0gc3RhdHNcblxuICAgICAgICAgICAgICAgIHRoaXMuZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5nZXRSZWNlaXZlcnMoKS5mb3JFYWNoKHJlY2VpdmVyID0+IHJlY2VpdmVyLmdldFN0YXRzKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuZm9yRWFjaChyZXBvcnQgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzUmVwb3J0V2FudGVkKHJlcG9ydCkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmluYWxSZXBvcnQgPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3R5cGUnXSA9IHJlcG9ydC50eXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3RpbWVzdGFtcCddID0gcmVwb3J0LnRpbWVzdGFtcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydpZCddID0gcmVwb3J0LmlkO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb21tb24gdG8gQ2hyb21lLCBGaXJlZm94IGFuZCBTYWZhcmlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXBvcnQudHlwZSA9PT0gJ2luYm91bmQtcnRwJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0Wydzc3JjJ10gPSByZXBvcnQuc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnZmlyQ291bnQnXSA9IHJlcG9ydC5maXJDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsncGxpQ291bnQnXSA9IHJlcG9ydC5wbGlDb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbmFja0NvdW50J10gPSByZXBvcnQubmFja0NvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydxcFN1bSddID0gcmVwb3J0LnFwU3VtO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IG1lZGlhIHR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoISFyZXBvcnQua2luZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSByZXBvcnQua2luZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCEhcmVwb3J0Lm1lZGlhVHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSByZXBvcnQubWVkaWFUeXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNhZmFyaSBkb2VzIG5vdCBoYXZlICdtZWRpYVR5cGUnIGRlZmluZWQgZm9yIGluYm91bmQtcnRwLiBNdXN0IGJlIGluZmVycmVkIGZyb20gJ2lkJyBmaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPSAocmVwb3J0LmlkLmluZGV4T2YoJ1ZpZGVvU3RyZWFtJykgIT09IC0xKSA/ICd2aWRlbycgOiAnYXVkaW8nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaW5hbFJlcG9ydFsnbWVkaWFUeXBlJ10gPT09ICd2aWRlbycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2ZyYW1lc0RlY29kZWQnXSA9IHJlcG9ydC5mcmFtZXNEZWNvZGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydwYWNrZXRzUmVjZWl2ZWQnXSA9IHJlcG9ydC5wYWNrZXRzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ3BhY2tldHNMb3N0J10gPSByZXBvcnQucGFja2V0c0xvc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxSZXBvcnRbJ2ppdHRlciddID0gcmVwb3J0LmppdHRlcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYnl0ZXNSZWNlaXZlZCddID0gcmVwb3J0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgZm9yIENocm9tZSBhbmQgU2FmYXJpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT09ICdjYW5kaWRhdGUtcGFpcicgJiYgcmVwb3J0LnRvdGFsUm91bmRUcmlwVGltZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgZmluYWwgc2VsZWN0ZWQgY2FuZGlkYXRlIHBhaXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYXZhaWxhYmxlSW5jb21pbmdCaXRyYXRlJ10gPSByZXBvcnQuYXZhaWxhYmxlSW5jb21pbmdCaXRyYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsUmVwb3J0WydydHQnXSA9IHJlcG9ydC5jdXJyZW50Um91bmRUcmlwVGltZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFJlcG9ydFsnYXZlcmFnZVJ0dCddID0gcmVwb3J0LnRvdGFsUm91bmRUcmlwVGltZSAvIHJlcG9ydC5yZXNwb25zZXNSZWNlaXZlZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBmb3IgRmlyZWZveCA+PSA2Ni4wXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT09ICdyZW1vdGUtaW5ib3VuZC1ydHAnIHx8IHJlcG9ydC50eXBlID09PSAncmVtb3RlLW91dGJvdW5kLXJ0cCcpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhmaW5hbFJlcG9ydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNSZXBvcnRXYW50ZWQocmVwb3J0OiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHJlcG9ydC50eXBlID09PSAnaW5ib3VuZC1ydHAnICYmICF0aGlzLmlzTG9jYWwoKSB8fFxuICAgICAgICAgICAgcmVwb3J0LnR5cGUgPT09ICdvdXRib3VuZC1ydHAnICYmIHRoaXMuaXNMb2NhbCgpIHx8XG4gICAgICAgICAgICAocmVwb3J0LnR5cGUgPT09ICdjYW5kaWRhdGUtcGFpcicgJiYgcmVwb3J0Lm5vbWluYXRlZCAmJiByZXBvcnQuYnl0ZXNTZW50ID4gMCk7XG4gICAgfVxuXG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi9TdHJlYW0nO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJy4vU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBFdmVudERpc3BhdGNoZXIgfSBmcm9tICcuL0V2ZW50RGlzcGF0Y2hlcic7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyVmlkZW8gfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0ludGVyZmFjZXMvUHVibGljL1N0cmVhbU1hbmFnZXJWaWRlbyc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyRXZlbnRNYXAgfSBmcm9tICcuLi9PcGVuVmlkdUludGVybmFsL0V2ZW50cy9FdmVudE1hcC9TdHJlYW1NYW5hZ2VyRXZlbnRNYXAnO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlckV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvU3RyZWFtTWFuYWdlckV2ZW50JztcbmltcG9ydCB7IFZpZGVvRWxlbWVudEV2ZW50IH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9FdmVudHMvVmlkZW9FbGVtZW50RXZlbnQnO1xuaW1wb3J0IHsgRXhjZXB0aW9uRXZlbnQsIEV4Y2VwdGlvbkV2ZW50TmFtZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRXZlbnRzL0V4Y2VwdGlvbkV2ZW50JztcbmltcG9ydCB7IFZpZGVvSW5zZXJ0TW9kZSB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvRW51bXMvVmlkZW9JbnNlcnRNb2RlJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuaW1wb3J0IHsgUGxhdGZvcm1VdGlscyB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvVXRpbHMvUGxhdGZvcm0nO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICogQGhpZGRlblxuICovXG5sZXQgcGxhdGZvcm06IFBsYXRmb3JtVXRpbHM7XG5cbi8qKlxuICogSW50ZXJmYWNlIGluIGNoYXJnZSBvZiBkaXNwbGF5aW5nIHRoZSBtZWRpYSBzdHJlYW1zIGluIHRoZSBIVE1MIERPTS4gVGhpcyB3cmFwcyBhbnkgW1tQdWJsaXNoZXJdXSBhbmQgW1tTdWJzY3JpYmVyXV0gb2JqZWN0LlxuICogWW91IGNhbiBpbnNlcnQgYXMgbWFueSB2aWRlbyBwbGF5ZXJzIGZvIHRoZSBzYW1lIFN0cmVhbSBhcyB5b3Ugd2FudCBieSBjYWxsaW5nIFtbU3RyZWFtTWFuYWdlci5hZGRWaWRlb0VsZW1lbnRdXSBvclxuICogW1tTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudF1dLlxuICogVGhlIHVzZSBvZiBTdHJlYW1NYW5hZ2VyIHdyYXBwZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHlvdSBkb24ndCBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYmV0d2VlbiBQdWJsaXNoZXIgb3IgU3Vic2NyaWJlciBzdHJlYW1zIG9yIGp1c3RcbiAqIHdhbnQgdG8gZGlyZWN0bHkgbWFuYWdlIHlvdXIgb3duIHZpZGVvIGVsZW1lbnRzIChldmVuIG1vcmUgdGhhbiBvbmUgdmlkZW8gZWxlbWVudCBwZXIgU3RyZWFtKS4gVGhpcyBzY2VuYXJpbyBpcyBwcmV0dHkgY29tbW9uIGluXG4gKiBkZWNsYXJhdGl2ZSwgTVZDIGZyb250ZW5kIGZyYW1ld29ya3Mgc3VjaCBhcyBBbmd1bGFyLCBSZWFjdCBvciBWdWUuanNcbiAqXG4gKiBTZWUgYXZhaWxhYmxlIGV2ZW50IGxpc3RlbmVycyBhdCBbW1N0cmVhbU1hbmFnZXJFdmVudE1hcF1dLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU3RyZWFtTWFuYWdlciBleHRlbmRzIEV2ZW50RGlzcGF0Y2hlciB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHJlcHJlc2VudGVkIGluIHRoZSBET00gYnkgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyXG4gICAgICovXG4gICAgc3RyZWFtOiBTdHJlYW07XG5cbiAgICAvKipcbiAgICAgKiBBbGwgdGhlIHZpZGVvcyBkaXNwbGF5aW5nIHRoZSBTdHJlYW0gb2YgdGhpcyBQdWJsaXNoZXIvU3Vic2NyaWJlclxuICAgICAqL1xuICAgIHZpZGVvczogU3RyZWFtTWFuYWdlclZpZGVvW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdGhlIFN0cmVhbSByZXByZXNlbnRlZCBpbiB0aGUgRE9NIGlzIGxvY2FsIG9yIHJlbW90ZVxuICAgICAqIC0gYGZhbHNlYCBmb3IgW1tQdWJsaXNoZXJdXVxuICAgICAqIC0gYHRydWVgIGZvciBbW1N1YnNjcmliZXJdXVxuICAgICAqL1xuICAgIHJlbW90ZTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFRoZSBET00gSFRNTEVsZW1lbnQgYXNzaWduZWQgYXMgdGFyZ2V0IGVsZW1lbnQgd2hlbiBjcmVhdGluZyB0aGUgdmlkZW8gZm9yIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlci4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIGBpZGAgYXR0cmlidXRlIG9mIHRoZSBET00gdmlkZW8gZWxlbWVudCBkaXNwbGF5aW5nIHRoZSBQdWJsaXNoZXIvU3Vic2NyaWJlcidzIHN0cmVhbS4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGRlZmluZWQgaWY6XG4gICAgICogLSBbW1B1Ymxpc2hlcl1dIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgbWV0aG9kIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIHdpdGggYSB2YWxpZCBgdGFyZ2V0RWxlbWVudGAgcGFyYW1ldGVyXG4gICAgICogLSBbW1N1YnNjcmliZXJdXSBoYXMgYmVlbiBpbml0aWFsaXplZCBieSBjYWxsaW5nIG1ldGhvZCBbW1Nlc3Npb24uc3Vic2NyaWJlXV0gd2l0aCBhIHZhbGlkIGB0YXJnZXRFbGVtZW50YCBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBpZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaXJzdFZpZGVvRWxlbWVudD86IFN0cmVhbU1hbmFnZXJWaWRlbztcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY2FuUGxheUxpc3RlbmVyOiBFdmVudExpc3RlbmVyO1xuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcml2YXRlIHN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQ/OiBOb2RlSlMuVGltZW91dDtcbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcHJpdmF0ZSBsYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc3RyZWFtOiBTdHJlYW0sIHRhcmdldEVsZW1lbnQ/OiBIVE1MRWxlbWVudCB8IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBwbGF0Zm9ybSA9IFBsYXRmb3JtVXRpbHMuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbW90ZSA9ICF0aGlzLnN0cmVhbS5pc0xvY2FsKCk7XG5cbiAgICAgICAgaWYgKCEhdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGFyZ2V0RWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0YXJnRWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0RWxlbWVudCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGFyZ0VsID0gdGFyZ2V0RWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEhdGFyZ0VsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudDogdGFyZ0VsLFxuICAgICAgICAgICAgICAgICAgICB2aWRlbzogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6ICcnLFxuICAgICAgICAgICAgICAgICAgICBjYW5wbGF5TGlzdGVuZXJBZGRlZDogZmFsc2VcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5pc1NhZmFyaUJyb3dzZXIoKSB8fCAocGxhdGZvcm0uaXNJUGhvbmVPcklQYWQoKSAmJiAocGxhdGZvcm0uaXNDaHJvbWVNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNFZGdlTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzT3BlcmFNb2JpbGVCcm93c2VyKCkgfHwgcGxhdGZvcm0uaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXJzdFZpZGVvRWxlbWVudC52aWRlby5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXRFbGVtZW50ID0gdGFyZ0VsO1xuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA9IHRhcmdFbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY2FuUGxheUxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5kZWFjdGl2YXRlU3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dCgpO1xuICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3N0cmVhbVBsYXlpbmcnLCBbbmV3IFN0cmVhbU1hbmFnZXJFdmVudCh0aGlzLCAnc3RyZWFtUGxheWluZycsIHVuZGVmaW5lZCldKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25dXVxuICAgICAqL1xuICAgIG9uPEsgZXh0ZW5kcyBrZXlvZiBTdHJlYW1NYW5hZ2VyRXZlbnRNYXA+KHR5cGU6IEssIGhhbmRsZXI6IChldmVudDogU3RyZWFtTWFuYWdlckV2ZW50TWFwW0tdKSA9PiB2b2lkKTogdGhpcyB7XG5cbiAgICAgICAgc3VwZXIub25BdXgodHlwZSwgXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBieSAnXCIgKyAodGhpcy5yZW1vdGUgPyAnU3Vic2NyaWJlcicgOiAnUHVibGlzaGVyJykgKyBcIidcIiwgaGFuZGxlcik7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICd2aWRlb0VsZW1lbnRDcmVhdGVkJykge1xuICAgICAgICAgICAgaWYgKCEhdGhpcy5zdHJlYW0gJiYgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudENyZWF0ZWQnLCBbbmV3IFZpZGVvRWxlbWVudEV2ZW50KHRoaXMudmlkZW9zWzBdLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXp5TGF1bmNoVmlkZW9FbGVtZW50Q3JlYXRlZEV2ZW50ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1QbGF5aW5nJykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zWzBdICYmIHRoaXMudmlkZW9zWzBdLnZpZGVvICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uY3VycmVudFRpbWUgPiAwICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucGF1c2VkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmVuZGVkID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLnJlYWR5U3RhdGUgPT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgnc3RyZWFtUGxheWluZycsIFtuZXcgU3RyZWFtTWFuYWdlckV2ZW50KHRoaXMsICdzdHJlYW1QbGF5aW5nJywgdW5kZWZpbmVkKV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnN0cmVhbS5oYXNBdWRpbykge1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVuYWJsZUhhcmtTcGVha2luZ0V2ZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lbmFibGVIYXJrU3RvcHBlZFNwZWFraW5nRXZlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2UnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZW5hYmxlSGFya1ZvbHVtZUNoYW5nZUV2ZW50KGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWUgW1tFdmVudERpc3BhdGNoZXIub25jZV1dXG4gICAgICovXG4gICAgb25jZTxLIGV4dGVuZHMga2V5b2YgU3RyZWFtTWFuYWdlckV2ZW50TWFwPih0eXBlOiBLLCBoYW5kbGVyOiAoZXZlbnQ6IFN0cmVhbU1hbmFnZXJFdmVudE1hcFtLXSkgPT4gdm9pZCk6IHRoaXMge1xuXG4gICAgICAgIHN1cGVyLm9uY2VBdXgodHlwZSwgXCJFdmVudCAnXCIgKyB0eXBlICsgXCInIHRyaWdnZXJlZCBvbmNlIGJ5ICdcIiArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArIFwiJ1wiLCBoYW5kbGVyKTtcblxuICAgICAgICBpZiAodHlwZSA9PT0gJ3ZpZGVvRWxlbWVudENyZWF0ZWQnKSB7XG4gICAgICAgICAgICBpZiAoISF0aGlzLnN0cmVhbSAmJiB0aGlzLmxhenlMYXVuY2hWaWRlb0VsZW1lbnRDcmVhdGVkRXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCgndmlkZW9FbGVtZW50Q3JlYXRlZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQodGhpcy52aWRlb3NbMF0udmlkZW8sIHRoaXMsICd2aWRlb0VsZW1lbnRDcmVhdGVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbVBsYXlpbmcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb3NbMF0gJiYgdGhpcy52aWRlb3NbMF0udmlkZW8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5jdXJyZW50VGltZSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvc1swXS52aWRlby5wYXVzZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8uZW5kZWQgPT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3NbMF0udmlkZW8ucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCdzdHJlYW1QbGF5aW5nJywgW25ldyBTdHJlYW1NYW5hZ2VyRXZlbnQodGhpcywgJ3N0cmVhbVBsYXlpbmcnLCB1bmRlZmluZWQpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLmhhc0F1ZGlvKSB7XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0YXJ0U3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZW5hYmxlT25jZUhhcmtTcGVha2luZ0V2ZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3B1Ymxpc2hlclN0b3BTcGVha2luZycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5lbmFibGVPbmNlSGFya1N0b3BwZWRTcGVha2luZ0V2ZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlJykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmVuYWJsZU9uY2VIYXJrVm9sdW1lQ2hhbmdlRXZlbnQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlZSBbW0V2ZW50RGlzcGF0Y2hlci5vZmZdXVxuICAgICAqL1xuICAgIG9mZjxLIGV4dGVuZHMga2V5b2YgU3RyZWFtTWFuYWdlckV2ZW50TWFwPih0eXBlOiBLLCBoYW5kbGVyPzogKGV2ZW50OiBTdHJlYW1NYW5hZ2VyRXZlbnRNYXBbS10pID0+IHZvaWQpOiB0aGlzIHtcblxuICAgICAgICBzdXBlci5vZmZBdXgodHlwZSwgaGFuZGxlcik7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdGFydFNwZWFraW5nJykge1xuICAgICAgICAgICAgLy8gQm90aCBTdHJlYW1NYW5hZ2VyIGFuZCBTZXNzaW9uIGNhbiBoYXZlIFwicHVibGlzaGVyU3RhcnRTcGVha2luZ1wiIGV2ZW50IGxpc3RlbmVyc1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nU3RhcnRTcGVha2luZ0V2ZW50TGlzdGVuZXJzID0gdGhpcy5lZS5nZXRMaXN0ZW5lcnModHlwZSkubGVuZ3RoICsgdGhpcy5zdHJlYW0uc2Vzc2lvbi5lZS5nZXRMaXN0ZW5lcnModHlwZSkubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1N0YXJ0U3BlYWtpbmdFdmVudExpc3RlbmVycyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc2FibGVIYXJrU3BlYWtpbmdFdmVudChmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdwdWJsaXNoZXJTdG9wU3BlYWtpbmcnKSB7XG4gICAgICAgICAgICAvLyBCb3RoIFN0cmVhbU1hbmFnZXIgYW5kIFNlc3Npb24gY2FuIGhhdmUgXCJwdWJsaXNoZXJTdG9wU3BlYWtpbmdcIiBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgICAgIGNvbnN0IHJlbWFpbmluZ1N0b3BTcGVha2luZ0V2ZW50TGlzdGVuZXJzID0gdGhpcy5lZS5nZXRMaXN0ZW5lcnModHlwZSkubGVuZ3RoICsgdGhpcy5zdHJlYW0uc2Vzc2lvbi5lZS5nZXRMaXN0ZW5lcnModHlwZSkubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1N0b3BTcGVha2luZ0V2ZW50TGlzdGVuZXJzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW0uZGlzYWJsZUhhcmtTdG9wcGVkU3BlYWtpbmdFdmVudChmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZScpIHtcbiAgICAgICAgICAgIC8vIE9ubHkgU3RyZWFtTWFuYWdlciBjYW4gaGF2ZSBcInN0cmVhbUF1ZGlvVm9sdW1lQ2hhbmdlXCIgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgICAgICBjb25zdCByZW1haW5pbmdWb2x1bWVFdmVudExpc3RlbmVycyA9IHRoaXMuZWUuZ2V0TGlzdGVuZXJzKHR5cGUpLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChyZW1haW5pbmdWb2x1bWVFdmVudExpc3RlbmVycyA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc2FibGVIYXJrVm9sdW1lQ2hhbmdlRXZlbnQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYHZpZGVvYCBlbGVtZW50IHBhcmFtZXRlciBkaXNwbGF5IHRoaXMgW1tzdHJlYW1dXS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlXG4gICAgICogW21hbmFnaW5nIHRoZSB2aWRlbyBlbGVtZW50cyBvbiB5b3VyIG93bl0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpXG4gICAgICpcbiAgICAgKiBDYWxsaW5nIHRoaXMgbWV0aG9kIHdpdGggYSB2aWRlbyBhbHJlYWR5IGFkZGVkIHRvIG90aGVyIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgY2F1c2UgdGhlIHZpZGVvIGVsZW1lbnQgdG8gYmVcbiAgICAgKiBkaXNhc3NvY2lhdGVkIGZyb20gdGhhdCBwcmV2aW91cyBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgdG8gYmUgYXNzb2NpYXRlZCB0byB0aGlzIG9uZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIDEgaWYgdGhlIHZpZGVvIHdhc24ndCBhc3NvY2lhdGVkIHRvIGFueSBvdGhlciBQdWJsaXNoZXIvU3Vic2NyaWJlciBhbmQgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGFkZGVkIHRvIHRoaXMgb25lLlxuICAgICAqIDAgaWYgdGhlIHZpZGVvIHdhcyBhbHJlYWR5IGFkZGVkIHRvIHRoaXMgUHVibGlzaGVyL1N1YnNjcmliZXIuIC0xIGlmIHRoZSB2aWRlbyB3YXMgcHJldmlvdXNseSBhc3NvY2lhdGVkIHRvIGFueSBvdGhlclxuICAgICAqIFB1Ymxpc2hlci9TdWJzY3JpYmVyIGFuZCBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBmcm9tIHRoYXQgb25lIGFuZCBwcm9wZXJseSBhZGRlZCB0byB0aGlzIG9uZS5cbiAgICAgKi9cbiAgICBhZGRWaWRlb0VsZW1lbnQodmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpZGVvUHJvcGVydGllcyh2aWRlbyk7XG5cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSAmJiB0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgaWYgKHZpZGVvLnNyY09iamVjdCAhPT0gdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKSkge1xuICAgICAgICAgICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdmlkZW8gZWxlbWVudCBpcyBhbHJlYWR5IHBhcnQgb2YgdGhpcyBTdHJlYW1NYW5hZ2VyIGRvIG5vdGhpbmdcbiAgICAgICAgZm9yIChjb25zdCB2IG9mIHRoaXMudmlkZW9zKSB7XG4gICAgICAgICAgICBpZiAodi52aWRlbyA9PT0gdmlkZW8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXR1cm5OdW1iZXIgPSAxO1xuXG4gICAgICAgIGZvciAoY29uc3Qgc3RyZWFtTWFuYWdlciBvZiB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzKSB7XG4gICAgICAgICAgICBpZiAoc3RyZWFtTWFuYWdlci5kaXNhc3NvY2lhdGVWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5OdW1iZXIgPSAtMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuZm9yRWFjaChzdHJlYW1NYW5hZ2VyID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXIuZGlzYXNzb2NpYXRlVmlkZW8odmlkZW8pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnB1c2hOZXdTdHJlYW1NYW5hZ2VyVmlkZW8oe1xuICAgICAgICAgICAgdmlkZW8sXG4gICAgICAgICAgICBpZDogdmlkZW8uaWQsXG4gICAgICAgICAgICBjYW5wbGF5TGlzdGVuZXJBZGRlZDogZmFsc2VcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbG9nZ2VyLmluZm8oJ05ldyB2aWRlbyBlbGVtZW50IGFzc29jaWF0ZWQgdG8gJywgdGhpcyk7XG5cbiAgICAgICAgcmV0dXJuIHJldHVybk51bWJlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZpZGVvIGVsZW1lbnQgZGlzcGxheWluZyB0aGlzIFtbc3RyZWFtXV0uIFRoaXMgYWxsb3dzIHlvdSB0byBoYXZlIG11bHRpcGxlIHZpZGVvIGVsZW1lbnRzIGRpc3BsYXlpbmcgdGhlIHNhbWUgbWVkaWEgc3RyZWFtLlxuICAgICAqXG4gICAgICogIyMjIyBFdmVudHMgZGlzcGF0Y2hlZFxuICAgICAqXG4gICAgICogVGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgYHZpZGVvRWxlbWVudENyZWF0ZWRgIGV2ZW50IG9uY2UgdGhlIEhUTUwgdmlkZW8gZWxlbWVudCBoYXMgYmVlbiBhZGRlZCB0byBET00uIFNlZSBbW1ZpZGVvRWxlbWVudEV2ZW50XV1cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0YXJnZXRFbGVtZW50IEhUTUwgRE9NIGVsZW1lbnQgKG9yIGl0cyBgaWRgIGF0dHJpYnV0ZSkgaW4gd2hpY2ggdGhlIHZpZGVvIGVsZW1lbnQgb2YgdGhlIFB1Ymxpc2hlci9TdWJzY3JpYmVyIHdpbGwgYmUgaW5zZXJ0ZWRcbiAgICAgKiBAcGFyYW0gaW5zZXJ0TW9kZSBIb3cgdGhlIHZpZGVvIGVsZW1lbnQgd2lsbCBiZSBpbnNlcnRlZCBhY2NvcmRpbmdseSB0byBgdGFyZ2V0RWxlbWV0YFxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgSFRNTFZpZGVvRWxlbWVudFxuICAgICAqL1xuICAgIGNyZWF0ZVZpZGVvRWxlbWVudCh0YXJnZXRFbGVtZW50Pzogc3RyaW5nIHwgSFRNTEVsZW1lbnQsIGluc2VydE1vZGU/OiBWaWRlb0luc2VydE1vZGUpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgbGV0IHRhcmdFbDtcbiAgICAgICAgaWYgKHR5cGVvZiB0YXJnZXRFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGFyZ0VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoIXRhcmdFbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoZSBwcm92aWRlZCAndGFyZ2V0RWxlbWVudCcgY291bGRuJ3QgYmUgcmVzb2x2ZWQgdG8gYW55IEhUTUwgZWxlbWVudDogXCIgKyB0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0YXJnZXRFbGVtZW50IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRhcmdFbCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgcHJvdmlkZWQgJ3RhcmdldEVsZW1lbnQnIGNvdWxkbid0IGJlIHJlc29sdmVkIHRvIGFueSBIVE1MIGVsZW1lbnQ6IFwiICsgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2aWRlbyA9IHRoaXMuY3JlYXRlVmlkZW8oKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplVmlkZW9Qcm9wZXJ0aWVzKHZpZGVvKTtcblxuICAgICAgICBsZXQgaW5zTW9kZSA9ICEhaW5zZXJ0TW9kZSA/IGluc2VydE1vZGUgOiBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICBzd2l0Y2ggKGluc01vZGUpIHtcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLkFGVEVSOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5wYXJlbnROb2RlISEuaW5zZXJ0QmVmb3JlKHZpZGVvLCB0YXJnRWwubmV4dFNpYmxpbmcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBWaWRlb0luc2VydE1vZGUuQVBQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5CRUZPUkU6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZpZGVvSW5zZXJ0TW9kZS5QUkVQRU5EOlxuICAgICAgICAgICAgICAgIHRhcmdFbC5pbnNlcnRCZWZvcmUodmlkZW8sIHRhcmdFbC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgVmlkZW9JbnNlcnRNb2RlLlJFUExBQ0U6XG4gICAgICAgICAgICAgICAgdGFyZ0VsLnBhcmVudE5vZGUhIS5yZXBsYWNlQ2hpbGQodmlkZW8sIHRhcmdFbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGluc01vZGUgPSBWaWRlb0luc2VydE1vZGUuQVBQRU5EO1xuICAgICAgICAgICAgICAgIHRhcmdFbC5hcHBlbmRDaGlsZCh2aWRlbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2OiBTdHJlYW1NYW5hZ2VyVmlkZW8gPSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50OiB0YXJnRWwsXG4gICAgICAgICAgICB2aWRlbyxcbiAgICAgICAgICAgIGluc2VydE1vZGU6IGluc01vZGUsXG4gICAgICAgICAgICBpZDogdmlkZW8uaWQsXG4gICAgICAgICAgICBjYW5wbGF5TGlzdGVuZXJBZGRlZDogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHYpO1xuXG4gICAgICAgIHRoaXMuZWUuZW1pdEV2ZW50KCd2aWRlb0VsZW1lbnRDcmVhdGVkJywgW25ldyBWaWRlb0VsZW1lbnRFdmVudCh2LnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50Q3JlYXRlZCcpXSk7XG4gICAgICAgIHRoaXMubGF6eUxhdW5jaFZpZGVvRWxlbWVudENyZWF0ZWRFdmVudCA9ICEhdGhpcy5maXJzdFZpZGVvRWxlbWVudDtcblxuICAgICAgICByZXR1cm4gdmlkZW87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgY3VycmVudCBjb25maWd1cmF0aW9uIGZvciB0aGUgW1tQdWJsaXNoZXJTcGVha2luZ0V2ZW50XV0gZmVhdHVyZSBhbmQgdGhlIFtTdHJlYW1NYW5hZ2VyRXZlbnQuc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2VdKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvY2xhc3Nlcy9TdHJlYW1NYW5hZ2VyRXZlbnQuaHRtbCkgZmVhdHVyZSBmb3IgdGhpcyBzcGVjaWZpY1xuICAgICAqIFN0cmVhbU1hbmFnZXIgYXVkaW8gc3RyZWFtLCBvdmVycmlkaW5nIHRoZSBnbG9iYWwgb3B0aW9ucyBzZXQgd2l0aCBbW09wZW5WaWR1LnNldEFkdmFuY2VkQ29uZmlndXJhdGlvbl1dLiBUaGlzIHdheSB5b3UgY2FuIGN1c3RvbWl6ZSB0aGUgYXVkaW8gZXZlbnRzIG9wdGlvbnNcbiAgICAgKiBmb3IgZWFjaCBzcGVjaWZpYyBTdHJlYW1NYW5hZ2VyIGFuZCBjaGFuZ2UgdGhlbSBkeW5hbWljYWxseS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnMgTmV3IG9wdGlvbnMgdG8gYmUgYXBwbGllZCB0byB0aGlzIFN0cmVhbU1hbmFnZXIncyBhdWRpbyBzdHJlYW0uIEl0IGlzIGFuIG9iamVjdCB3aGljaCBpbmNsdWRlcyB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHByb3BlcnRpZXM6XG4gICAgICogLSBgaW50ZXJ2YWxgOiAobnVtYmVyKSBob3cgZnJlcXVlbnRseSB0aGUgYW5hbHlzZXIgcG9sbHMgdGhlIGF1ZGlvIHN0cmVhbSB0byBjaGVjayBpZiBzcGVha2luZyBoYXMgc3RhcnRlZC9zdG9wcGVkIG9yIGF1ZGlvIHZvbHVtZSBoYXMgY2hhbmdlZC4gRGVmYXVsdCAqKjEwMCoqIChtcylcbiAgICAgKiAtIGB0aHJlc2hvbGRgOiAobnVtYmVyKSB0aGUgdm9sdW1lIGF0IHdoaWNoIF9wdWJsaXNoZXJTdGFydFNwZWFraW5nXywgX3B1Ymxpc2hlclN0b3BTcGVha2luZ18gZXZlbnRzIHdpbGwgYmUgZmlyZWQuIERlZmF1bHQgKiotNTAqKiAoZEIpXG4gICAgICovXG4gICAgdXBkYXRlUHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zKHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9uczogeyBpbnRlcnZhbD86IG51bWJlciwgdGhyZXNob2xkPzogbnVtYmVyIH0pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY3VycmVudEhhcmtPcHRpb25zID0gISF0aGlzLnN0cmVhbS5oYXJrT3B0aW9ucyA/IHRoaXMuc3RyZWFtLmhhcmtPcHRpb25zIDogKHRoaXMuc3RyZWFtLnNlc3Npb24ub3BlbnZpZHUuYWR2YW5jZWRDb25maWd1cmF0aW9uLnB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucyB8fCB7fSk7XG4gICAgICAgIGNvbnN0IG5ld0ludGVydmFsID0gKHR5cGVvZiBwdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnMuaW50ZXJ2YWwgPT09ICdudW1iZXInKSA/XG4gICAgICAgICAgICBwdWJsaXNoZXJTcGVha2luZ0V2ZW50c09wdGlvbnMuaW50ZXJ2YWwgOiAoKHR5cGVvZiBjdXJyZW50SGFya09wdGlvbnMuaW50ZXJ2YWwgPT09ICdudW1iZXInKSA/IGN1cnJlbnRIYXJrT3B0aW9ucy5pbnRlcnZhbCA6IDEwMCk7XG4gICAgICAgIGNvbnN0IG5ld1RocmVzaG9sZCA9ICh0eXBlb2YgcHVibGlzaGVyU3BlYWtpbmdFdmVudHNPcHRpb25zLnRocmVzaG9sZCA9PT0gJ251bWJlcicpID9cbiAgICAgICAgICAgIHB1Ymxpc2hlclNwZWFraW5nRXZlbnRzT3B0aW9ucy50aHJlc2hvbGQgOiAoKHR5cGVvZiBjdXJyZW50SGFya09wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykgPyBjdXJyZW50SGFya09wdGlvbnMudGhyZXNob2xkIDogLTUwKTtcbiAgICAgICAgdGhpcy5zdHJlYW0uaGFya09wdGlvbnMgPSB7XG4gICAgICAgICAgICBpbnRlcnZhbDogbmV3SW50ZXJ2YWwsXG4gICAgICAgICAgICB0aHJlc2hvbGQ6IG5ld1RocmVzaG9sZFxuICAgICAgICB9O1xuICAgICAgICBpZiAoISF0aGlzLnN0cmVhbS5zcGVlY2hFdmVudCkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc3BlZWNoRXZlbnQuc2V0SW50ZXJ2YWwobmV3SW50ZXJ2YWwpO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc3BlZWNoRXZlbnQuc2V0VGhyZXNob2xkKG5ld1RocmVzaG9sZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGluaXRpYWxpemVWaWRlb1Byb3BlcnRpZXModmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCEoIXRoaXMucmVtb3RlICYmIHRoaXMuc3RyZWFtLmRpc3BsYXlNeVJlbW90ZSgpKSkge1xuICAgICAgICAgICAgLy8gQXZvaWQgc2V0dGluZyB0aGUgTWVkaWFTdHJlYW0gaW50byB0aGUgc3JjT2JqZWN0IGlmIHJlbW90ZSBzdWJzY3JpcHRpb24gYmVmb3JlIHB1Ymxpc2hpbmdcbiAgICAgICAgICAgIGlmICh2aWRlby5zcmNPYmplY3QgIT09IHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBzcmNPYmplY3QgYWxyZWFkeSBzZXQgZG9uJ3QgZG8gaXQgYWdhaW5cbiAgICAgICAgICAgICAgICB2aWRlby5zcmNPYmplY3QgPSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZpZGVvLmF1dG9wbGF5ID0gdHJ1ZTtcbiAgICAgICAgdmlkZW8uY29udHJvbHMgPSBmYWxzZTtcblxuICAgICAgICBpZiAocGxhdGZvcm0uaXNTYWZhcmlCcm93c2VyKCkgfHwgKHBsYXRmb3JtLmlzSVBob25lT3JJUGFkKCkgJiYgKHBsYXRmb3JtLmlzQ2hyb21lTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRWRnZU1vYmlsZUJyb3dzZXIoKSB8fCBwbGF0Zm9ybS5pc09wZXJhTW9iaWxlQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzRmlyZWZveE1vYmlsZUJyb3dzZXIoKSkpKSB7XG4gICAgICAgICAgICB2aWRlby5zZXRBdHRyaWJ1dGUoJ3BsYXlzaW5saW5lJywgJ3RydWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdmlkZW8uaWQpIHtcbiAgICAgICAgICAgIHZpZGVvLmlkID0gKHRoaXMucmVtb3RlID8gJ3JlbW90ZS0nIDogJ2xvY2FsLScpICsgJ3ZpZGVvLScgKyB0aGlzLnN0cmVhbS5zdHJlYW1JZDtcbiAgICAgICAgICAgIC8vIERFUFJFQ0FURUQgcHJvcGVydHk6IGFzc2lnbiBvbmNlIHRoZSBwcm9wZXJ0eSBpZCBpZiB0aGUgdXNlciBwcm92aWRlZCBhIHZhbGlkIHRhcmdldEVsZW1lbnRcbiAgICAgICAgICAgIGlmICghdGhpcy5pZCAmJiAhIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB2aWRlby5pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnJlbW90ZSAmJiB0aGlzLmlzTWlycm9yZWRWaWRlbyh2aWRlbykpIHtcbiAgICAgICAgICAgIC8vIFN1YnNjcmliZXIgdmlkZW8gYXNzb2NpYXRlZCB0byBhIHByZXZpb3VzbHkgbWlycm9yZWQgdmlkZW8gZWxlbWVudFxuICAgICAgICAgICAgdGhpcy5yZW1vdmVNaXJyb3JWaWRlbyh2aWRlbyk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMucmVtb3RlICYmICF0aGlzLnN0cmVhbS5kaXNwbGF5TXlSZW1vdGUoKSkge1xuICAgICAgICAgICAgLy8gUHVibGlzaGVyIHZpZGVvXG4gICAgICAgICAgICB2aWRlby5tdXRlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy5pc01pcnJvcmVkVmlkZW8odmlkZW8pICYmICF0aGlzLnN0cmVhbS5vdXRib3VuZFN0cmVhbU9wdHMucHVibGlzaGVyUHJvcGVydGllcy5taXJyb3IpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdmlkZW8gd2FzIGFscmVhZHkgcm90YXRlZCBhbmQgbm93IGlzIHNldCB0byBub3QgbWlycm9yXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVNaXJyb3JWaWRlbyh2aWRlbyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RyZWFtLm91dGJvdW5kU3RyZWFtT3B0cy5wdWJsaXNoZXJQcm9wZXJ0aWVzLm1pcnJvciAmJiAhdGhpcy5zdHJlYW0uaXNTZW5kU2NyZWVuKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdmlkZW8gaXMgbm93IHNldCB0byBtaXJyb3IgYW5kIGlzIG5vdCBzY3JlZW4gc2hhcmVcbiAgICAgICAgICAgICAgICB0aGlzLm1pcnJvclZpZGVvKHZpZGVvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICByZW1vdmVBbGxWaWRlb3MoKTogdm9pZCB7XG4gICAgICAgIGZvciAobGV0IGkgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLnN0cmVhbU1hbmFnZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW0uc2Vzc2lvbi5zdHJlYW1NYW5hZ2Vyc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWRlb3MuZm9yRWFjaChzdHJlYW1NYW5hZ2VyVmlkZW8gPT4ge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIG9uY2FucGxheSBldmVudCBsaXN0ZW5lciAob25seSBPcGVuVmlkdSBicm93c2VyIGxpc3RlbmVyLCBub3QgdGhlIHVzZXIgb25lcylcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyAmJiAhIXN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHJlYW1NYW5hZ2VyVmlkZW8uY2FucGxheUxpc3RlbmVyQWRkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICghIXN0cmVhbU1hbmFnZXJWaWRlby50YXJnZXRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgZnJvbSBET00gdmlkZW9zIGNyZWF0ZWQgYnkgT3BlblZpZHUgQnJvd3NlciAodGhvc2UgZ2VuZXJhdGVkIGJ5IHBhc3NpbmcgYSB2YWxpZCB0YXJnZXRFbGVtZW50IGluIE9wZW5WaWR1LmluaXRQdWJsaXNoZXJcbiAgICAgICAgICAgICAgICAvLyBhbmQgU2Vzc2lvbi5zdWJzY3JpYmUgb3IgdGhvc2UgY3JlYXRlZCBieSBTdHJlYW1NYW5hZ2VyLmNyZWF0ZVZpZGVvRWxlbWVudCkuIEFsbCB0aGlzIHZpZGVvcyB0cmlnZ2VyZWQgYSB2aWRlb0VsZW1lbnRDcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLnBhcmVudE5vZGUhLnJlbW92ZUNoaWxkKHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgdGhpcy5lZS5lbWl0RXZlbnQoJ3ZpZGVvRWxlbWVudERlc3Ryb3llZCcsIFtuZXcgVmlkZW9FbGVtZW50RXZlbnQoc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvLCB0aGlzLCAndmlkZW9FbGVtZW50RGVzdHJveWVkJyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJlbW92ZSBzcmNPYmplY3QgZnJvbSB0aGUgdmlkZW9cbiAgICAgICAgICAgIHRoaXMucmVtb3ZlU3JjT2JqZWN0KHN0cmVhbU1hbmFnZXJWaWRlbyk7XG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBjb2xsZWN0aW9uIG9mIHZpZGVvcyBldmVyeSB2aWRlbyBtYW5hZ2VkIGJ5IE9wZW5WaWR1IEJyb3dzZXJcbiAgICAgICAgICAgIHRoaXMudmlkZW9zLmZpbHRlcih2ID0+ICF2LnRhcmdldEVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGlzYXNzb2NpYXRlVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGRpc2Fzc29jaWF0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnZpZGVvcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMudmlkZW9zW2ldLnZpZGVvID09PSB2aWRlbykge1xuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9zW2ldLnZpZGVvLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb3Muc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIGRpc2Fzc29jaWF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdWaWRlbyBlbGVtZW50IGRpc2Fzc29jaWF0ZWQgZnJvbSAnLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlzYXNzb2NpYXRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgYWRkUGxheUV2ZW50VG9GaXJzdFZpZGVvKCkge1xuICAgICAgICBpZiAoKCEhdGhpcy52aWRlb3NbMF0pICYmICghIXRoaXMudmlkZW9zWzBdLnZpZGVvKSAmJiAoIXRoaXMudmlkZW9zWzBdLmNhbnBsYXlMaXN0ZW5lckFkZGVkKSkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmF0ZVN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQoKTtcbiAgICAgICAgICAgIHRoaXMudmlkZW9zWzBdLnZpZGVvLmFkZEV2ZW50TGlzdGVuZXIoJ2NhbnBsYXknLCB0aGlzLmNhblBsYXlMaXN0ZW5lcik7XG4gICAgICAgICAgICB0aGlzLnZpZGVvc1swXS5jYW5wbGF5TGlzdGVuZXJBZGRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgdXBkYXRlTWVkaWFTdHJlYW0obWVkaWFTdHJlYW06IE1lZGlhU3RyZWFtKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLmZvckVhY2goc3RyZWFtTWFuYWdlclZpZGVvID0+IHtcbiAgICAgICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBtZWRpYVN0cmVhbTtcbiAgICAgICAgICAgIGlmIChwbGF0Zm9ybS5pc0lvbmljSW9zKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBpT1MgSW9uaWMuIExJTUlUQVRJT046IG11c3QgcmVpbnNlcnQgdGhlIHZpZGVvIGluIHRoZSBET00gZm9yXG4gICAgICAgICAgICAgICAgLy8gdGhlIG1lZGlhIHN0cmVhbSB0byBiZSB1cGRhdGVkXG4gICAgICAgICAgICAgICAgY29uc3QgdlBhcmVudCA9IHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1ZpZGVvID0gc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvO1xuICAgICAgICAgICAgICAgIHZQYXJlbnQhIS5yZXBsYWNlQ2hpbGQobmV3VmlkZW8sIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlbyk7XG4gICAgICAgICAgICAgICAgc3RyZWFtTWFuYWdlclZpZGVvLnZpZGVvID0gbmV3VmlkZW87XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBlbWl0RXZlbnQodHlwZTogc3RyaW5nLCBldmVudEFycmF5OiBhbnlbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmVlLmVtaXRFdmVudCh0eXBlLCBldmVudEFycmF5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAqIEBoaWRkZW5cbiAgICAqL1xuICAgIGNyZWF0ZVZpZGVvKCk6IEhUTUxWaWRlb0VsZW1lbnQge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgcmVtb3ZlU3JjT2JqZWN0KHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHN0cmVhbU1hbmFnZXJWaWRlby52aWRlby5zcmNPYmplY3QgPSBudWxsO1xuICAgICAgICB0aGlzLmRlYWN0aXZhdGVTdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFic3RyYWN0IHJlcGxhY2VUcmFja0luTWVkaWFTdHJlYW0odHJhY2s6IE1lZGlhU3RyZWFtVHJhY2ssIHVwZGF0ZUxhc3RDb25zdHJhaW50czogYm9vbGVhbik6IFByb21pc2U8dm9pZD47XG5cbiAgICAvKiBQcml2YXRlIG1ldGhvZHMgKi9cblxuICAgIHByb3RlY3RlZCBwdXNoTmV3U3RyZWFtTWFuYWdlclZpZGVvKHN0cmVhbU1hbmFnZXJWaWRlbzogU3RyZWFtTWFuYWdlclZpZGVvKSB7XG4gICAgICAgIHRoaXMudmlkZW9zLnB1c2goc3RyZWFtTWFuYWdlclZpZGVvKTtcbiAgICAgICAgdGhpcy5hZGRQbGF5RXZlbnRUb0ZpcnN0VmlkZW8oKTtcbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMuaW5kZXhPZih0aGlzKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLnNlc3Npb24uc3RyZWFtTWFuYWdlcnMucHVzaCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbWlycm9yVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCFwbGF0Zm9ybS5pc0lvbmljSW9zKCkpIHtcbiAgICAgICAgICAgIHZpZGVvLnN0eWxlLnRyYW5zZm9ybSA9ICdyb3RhdGVZKDE4MGRlZyknO1xuICAgICAgICAgICAgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3JvdGF0ZVkoMTgwZGVnKSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbW92ZU1pcnJvclZpZGVvKHZpZGVvOiBIVE1MVmlkZW9FbGVtZW50KTogdm9pZCB7XG4gICAgICAgIHZpZGVvLnN0eWxlLnRyYW5zZm9ybSA9ICd1bnNldCc7XG4gICAgICAgIHZpZGVvLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9ICd1bnNldCc7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc01pcnJvcmVkVmlkZW8odmlkZW86IEhUTUxWaWRlb0VsZW1lbnQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHZpZGVvLnN0eWxlLnRyYW5zZm9ybSA9PT0gJ3JvdGF0ZVkoMTgwZGVnKScgfHwgdmlkZW8uc3R5bGUud2Via2l0VHJhbnNmb3JtID09PSAncm90YXRlWSgxODBkZWcpJztcbiAgICB9XG5cbiAgICBwcml2YXRlIGFjdGl2YXRlU3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZSkge1xuICAgICAgICAgICAgLy8gRXhjZXB0aW9uRXZlbnQgTk9fU1RSRUFNX1BMQVlJTkdfRVZFTlQgaXMgb25seSBmb3Igc3Vic2NyaWJlcnNcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFRoZSB0aW1lb3V0IGlzIGFscmVhZHkgYWN0aXZhdGVkXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gVHJpZ2dlciBFeGNlcHRpb25FdmVudCBOT19TVFJFQU1fUExBWUlOR19FVkVOVCBpZiBhZnRlciB0aW1lb3V0IHRoZXJlIGlzIG5vICdjYW5wbGF5JyBldmVudFxuICAgICAgICBjb25zdCBtc1RpbWVvdXQgPSB0aGlzLnN0cmVhbS5zZXNzaW9uLm9wZW52aWR1LmFkdmFuY2VkQ29uZmlndXJhdGlvbi5ub1N0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQgfHwgNDAwMDtcbiAgICAgICAgdGhpcy5zdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtc2cgPSAnU3RyZWFtTWFuYWdlciBvZiBTdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyAoJyArICh0aGlzLnJlbW90ZSA/ICdTdWJzY3JpYmVyJyA6ICdQdWJsaXNoZXInKSArICcpIGRpZCBub3QgdHJpZ2dlciBcInN0cmVhbVBsYXlpbmdcIiBldmVudCBpbiAnICsgbXNUaW1lb3V0ICsgJyBtcyc7XG4gICAgICAgICAgICBsb2dnZXIud2Fybihtc2cpO1xuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5lbWl0RXZlbnQoJ2V4Y2VwdGlvbicsIFtuZXcgRXhjZXB0aW9uRXZlbnQodGhpcy5zdHJlYW0uc2Vzc2lvbiwgRXhjZXB0aW9uRXZlbnROYW1lLk5PX1NUUkVBTV9QTEFZSU5HX0VWRU5ULCAoPGFueT50aGlzKSBhcyBTdWJzY3JpYmVyLCBtc2cpXSk7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0O1xuICAgICAgICB9LCBtc1RpbWVvdXQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZGVhY3RpdmF0ZVN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQoKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnN0cmVhbVBsYXlpbmdFdmVudEV4Y2VwdGlvblRpbWVvdXQgYXMgYW55KTtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3RyZWFtUGxheWluZ0V2ZW50RXhjZXB0aW9uVGltZW91dDtcbiAgICB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuL1N0cmVhbSc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi9TdHJlYW1NYW5hZ2VyJztcbmltcG9ydCB7IFN1YnNjcmliZXJQcm9wZXJ0aWVzIH0gZnJvbSAnLi4vT3BlblZpZHVJbnRlcm5hbC9JbnRlcmZhY2VzL1B1YmxpYy9TdWJzY3JpYmVyUHJvcGVydGllcyc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL09wZW5WaWR1SW50ZXJuYWwvTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIFBhY2tzIHJlbW90ZSBtZWRpYSBzdHJlYW1zLiBQYXJ0aWNpcGFudHMgYXV0b21hdGljYWxseSByZWNlaXZlIHRoZW0gd2hlbiBvdGhlcnMgcHVibGlzaCB0aGVpciBzdHJlYW1zLiBJbml0aWFsaXplZCB3aXRoIFtbU2Vzc2lvbi5zdWJzY3JpYmVdXSBtZXRob2RcbiAqIFxuICogU2VlIGF2YWlsYWJsZSBldmVudCBsaXN0ZW5lcnMgYXQgW1tTdHJlYW1NYW5hZ2VyRXZlbnRNYXBdXS5cbiAqL1xuZXhwb3J0IGNsYXNzIFN1YnNjcmliZXIgZXh0ZW5kcyBTdHJlYW1NYW5hZ2VyIHtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBwcm9wZXJ0aWVzOiBTdWJzY3JpYmVyUHJvcGVydGllcztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzdHJlYW06IFN0cmVhbSwgdGFyZ0VsOiBzdHJpbmcgfCBIVE1MRWxlbWVudCwgcHJvcGVydGllczogU3Vic2NyaWJlclByb3BlcnRpZXMpIHtcbiAgICAgICAgc3VwZXIoc3RyZWFtLCB0YXJnRWwpO1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSB0aGlzLnRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtO1xuICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZSBvciB1bnN1YnNjcmliZSBmcm9tIHRoZSBhdWRpbyBzdHJlYW0gKGlmIGF2YWlsYWJsZSkuIENhbGxpbmcgdGhpcyBtZXRob2QgdHdpY2UgaW4gYSByb3cgcGFzc2luZyBzYW1lIHZhbHVlIHdpbGwgaGF2ZSBubyBlZmZlY3RcbiAgICAgKiBAcGFyYW0gdmFsdWUgYHRydWVgIHRvIHN1YnNjcmliZSB0byB0aGUgYXVkaW8gc3RyZWFtLCBgZmFsc2VgIHRvIHVuc3Vic2NyaWJlIGZyb20gaXRcbiAgICAgKi9cbiAgICBzdWJzY3JpYmVUb0F1ZGlvKHZhbHVlOiBib29sZWFuKTogU3Vic2NyaWJlciB7XG4gICAgICAgIHRoaXMuc3RyZWFtLmdldE1lZGlhU3RyZWFtKCkuZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgICAgdHJhY2suZW5hYmxlZCA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zdHJlYW0uYXVkaW9BY3RpdmUgPSB2YWx1ZTtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCInU3Vic2NyaWJlcicgaGFzIFwiICsgKHZhbHVlID8gJ3N1YnNjcmliZWQgdG8nIDogJ3Vuc3Vic2NyaWJlZCBmcm9tJykgKyAnIGl0cyBhdWRpbyBzdHJlYW0nKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3Vic2NyaWJlIG9yIHVuc3Vic2NyaWJlIGZyb20gdGhlIHZpZGVvIHN0cmVhbSAoaWYgYXZhaWxhYmxlKS4gQ2FsbGluZyB0aGlzIG1ldGhvZCB0d2ljZSBpbiBhIHJvdyBwYXNzaW5nIHNhbWUgdmFsdWUgd2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgICAqIEBwYXJhbSB2YWx1ZSBgdHJ1ZWAgdG8gc3Vic2NyaWJlIHRvIHRoZSB2aWRlbyBzdHJlYW0sIGBmYWxzZWAgdG8gdW5zdWJzY3JpYmUgZnJvbSBpdFxuICAgICAqL1xuICAgIHN1YnNjcmliZVRvVmlkZW8odmFsdWU6IGJvb2xlYW4pOiBTdWJzY3JpYmVyIHtcbiAgICAgICAgdGhpcy5zdHJlYW0uZ2V0TWVkaWFTdHJlYW0oKS5nZXRWaWRlb1RyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgICAgICB0cmFjay5lbmFibGVkID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnN0cmVhbS52aWRlb0FjdGl2ZSA9IHZhbHVlO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIidTdWJzY3JpYmVyJyBoYXMgXCIgKyAodmFsdWUgPyAnc3Vic2NyaWJlZCB0bycgOiAndW5zdWJzY3JpYmVkIGZyb20nKSArICcgaXRzIHZpZGVvIHN0cmVhbScpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKiBIaWRkZW4gbWV0aG9kcyAqL1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFzeW5jIHJlcGxhY2VUcmFja0luTWVkaWFTdHJlYW0odHJhY2s6IE1lZGlhU3RyZWFtVHJhY2ssIHVwZGF0ZUxhc3RDb25zdHJhaW50czogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBtZWRpYVN0cmVhbTogTWVkaWFTdHJlYW0gPSB0aGlzLnN0cmVhbS5nZXRNZWRpYVN0cmVhbSgpO1xuICAgICAgICBsZXQgcmVtb3ZlZFRyYWNrOiBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICBpZiAodHJhY2sua2luZCA9PT0gJ3ZpZGVvJykge1xuICAgICAgICAgICAgcmVtb3ZlZFRyYWNrID0gbWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXTtcbiAgICAgICAgICAgIGlmICh1cGRhdGVMYXN0Q29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5sYXN0VmlkZW9UcmFja0NvbnN0cmFpbnRzID0gdHJhY2suZ2V0Q29uc3RyYWludHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbW92ZWRUcmFjayA9IG1lZGlhU3RyZWFtLmdldEF1ZGlvVHJhY2tzKClbMF07XG4gICAgICAgIH1cbiAgICAgICAgbWVkaWFTdHJlYW0ucmVtb3ZlVHJhY2socmVtb3ZlZFRyYWNrKTtcbiAgICAgICAgcmVtb3ZlZFRyYWNrLnN0b3AoKTtcbiAgICAgICAgbWVkaWFTdHJlYW0uYWRkVHJhY2sodHJhY2spO1xuICAgIH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5leHBvcnQgZW51bSBMb2NhbFJlY29yZGVyU3RhdGUge1xuICAgIFJFQURZID0gJ1JFQURZJyxcbiAgICBSRUNPUkRJTkcgPSAnUkVDT1JESU5HJyxcbiAgICBQQVVTRUQgPSAnUEFVU0VEJyxcbiAgICBGSU5JU0hFRCA9ICdGSU5JU0hFRCdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBEZWZpbmVzIHByb3BlcnR5IFtbT3BlblZpZHVFcnJvci5uYW1lXV1cbiAqL1xuZXhwb3J0IGVudW0gT3BlblZpZHVFcnJvck5hbWUge1xuXG4gICAgLyoqXG4gICAgICogQnJvd3NlciBpcyBub3Qgc3VwcG9ydGVkIGJ5IE9wZW5WaWR1LlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbU2Vzc2lvbi5jb25uZWN0XV1cbiAgICAgKi9cbiAgICBCUk9XU0VSX05PVF9TVVBQT1JURUQgPSAnQlJPV1NFUl9OT1RfU1VQUE9SVEVEJyxcblxuICAgIC8qKlxuICAgICAqIFRoZSB1c2VyIGhhc24ndCBncmFudGVkIHBlcm1pc3Npb25zIHRvIHRoZSByZXF1aXJlZCBpbnB1dCBkZXZpY2Ugd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgREVWSUNFX0FDQ0VTU19ERU5JRUQgPSAnREVWSUNFX0FDQ0VTU19ERU5JRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIHJlcXVpcmVkIGlucHV0IGRldmljZSBpcyBwcm9iYWJseSBiZWluZyB1c2VkIGJ5IG90aGVyIHByb2Nlc3Mgd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgaXQuXG4gICAgICogVGhpcyBlcnJvciBjYW4gYWxzbyBiZSB0cmlnZ2VyZWQgd2hlbiB0aGUgdXNlciBncmFudGVkIHBlcm1pc3Npb24gdG8gdXNlIHRoZSBkZXZpY2VzIGJ1dCBhIGhhcmR3YXJlXG4gICAgICogZXJyb3Igb2NjdXJyZWQgYXQgdGhlIE9TLCBicm93c2VyIG9yIHdlYiBwYWdlIGxldmVsLCB3aGljaCBwcmV2ZW50ZWQgYWNjZXNzIHRvIHRoZSBkZXZpY2UuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIERFVklDRV9BTFJFQURZX0lOX1VTRSA9IFwiREVWSUNFX0FMUkVBRFlfSU5fVVNFXCIsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCBwZXJtaXNzaW9ucyB0byBjYXB0dXJlIHNvbWUgZGVza3RvcCBzY3JlZW4gd2hlbiB0aGUgYnJvd3NlciBhc2tlZCBmb3IgdGhlbS5cbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgU0NSRUVOX0NBUFRVUkVfREVOSUVEID0gJ1NDUkVFTl9DQVBUVVJFX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgc2NyZWVuIHNoYXJpbmcuXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIFNDUkVFTl9TSEFSSU5HX05PVF9TVVBQT1JURUQgPSAnU0NSRUVOX1NIQVJJTkdfTk9UX1NVUFBPUlRFRCcsXG5cbiAgICAvKipcbiAgICAgKiBPbmx5IGZvciBDaHJvbWUsIHRoZXJlJ3Mgbm8gc2NyZWVuIHNoYXJpbmcgZXh0ZW5zaW9uIGluc3RhbGxlZFxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBTQ1JFRU5fRVhURU5TSU9OX05PVF9JTlNUQUxMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9OT1RfSU5TVEFMTEVEJyxcblxuICAgIC8qKlxuICAgICAqIE9ubHkgZm9yIENocm9tZSwgdGhlIHNjcmVlbiBzaGFyaW5nIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgYnV0IGlzIGRpc2FibGVkXG4gICAgICogUmV0dXJuZWQgdXBvbiB1bnN1Y2Nlc3NmdWwgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgW1tPcGVuVmlkdS5nZXRVc2VyTWVkaWFdXVxuICAgICAqL1xuICAgIFNDUkVFTl9FWFRFTlNJT05fRElTQUJMRUQgPSAnU0NSRUVOX0VYVEVOU0lPTl9ESVNBQkxFRCcsXG5cbiAgICAvKipcbiAgICAgKiBObyB2aWRlbyBpbnB1dCBkZXZpY2UgZm91bmQgd2l0aCB0aGUgcHJvdmlkZWQgZGV2aWNlSWQgKHByb3BlcnR5IFtbUHVibGlzaGVyUHJvcGVydGllcy52aWRlb1NvdXJjZV1dKVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBJTlBVVF9WSURFT19ERVZJQ0VfTk9UX0ZPVU5EID0gJ0lOUFVUX1ZJREVPX0RFVklDRV9OT1RfRk9VTkQnLFxuXG4gICAgLyoqXG4gICAgICogTm8gYXVkaW8gaW5wdXQgZGV2aWNlIGZvdW5kIHdpdGggdGhlIHByb3ZpZGVkIGRldmljZUlkIChwcm9wZXJ0eSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuYXVkaW9Tb3VyY2VdXSlcbiAgICAgKiBSZXR1cm5lZCB1cG9uIHVuc3VjY2Vzc2Z1bCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBbW09wZW5WaWR1LmdldFVzZXJNZWRpYV1dXG4gICAgICovXG4gICAgSU5QVVRfQVVESU9fREVWSUNFX05PVF9GT1VORCA9ICdJTlBVVF9BVURJT19ERVZJQ0VfTk9UX0ZPVU5EJyxcblxuICAgIC8qKlxuICAgICAqIFRoZXJlIHdhcyBhbiB1bmtub3duIGVycm9yIHdoZW4gdHJ5aW5nIHRvIGFjY2VzcyB0aGUgc3BlY2lmaWVkIGF1ZGlvIGRldmljZVxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBJTlBVVF9BVURJT19ERVZJQ0VfR0VORVJJQ19FUlJPUiA9ICdJTlBVVF9BVURJT19ERVZJQ0VfR0VORVJJQ19FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgW1tPcGVuVmlkdS5pbml0UHVibGlzaGVyXV0gb3IgIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV0gaGFzIGJlZW4gY2FsbGVkIHdpdGggcHJvcGVydGllcyBgdmlkZW9Tb3VyY2VgIGFuZCBgYXVkaW9Tb3VyY2VgIG9mXG4gICAgICogW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gcGFyYW1ldGVyIGJvdGggc2V0IHRvICpmYWxzZSogb3IgKm51bGwqXG4gICAgICovXG4gICAgTk9fSU5QVVRfU09VUkNFX1NFVCA9ICdOT19JTlBVVF9TT1VSQ0VfU0VUJyxcblxuICAgIC8qKlxuICAgICAqIFNvbWUgbWVkaWEgcHJvcGVydHkgb2YgW1tQdWJsaXNoZXJQcm9wZXJ0aWVzXV0gc3VjaCBhcyBgZnJhbWVSYXRlYCBvciBgcmVzb2x1dGlvbmAgaXMgbm90IHN1cHBvcnRlZFxuICAgICAqIGJ5IHRoZSBpbnB1dCBkZXZpY2VzICh3aGVuZXZlciBpdCBpcyBwb3NzaWJsZSB0aGV5IGFyZSBhdXRvbWF0aWNhbGx5IGFkanVzdGVkIHRvIHRoZSBtb3N0IHNpbWlsYXIgdmFsdWUpLlxuICAgICAqIFJldHVybmVkIHVwb24gdW5zdWNjZXNzZnVsIFtbT3BlblZpZHUuaW5pdFB1Ymxpc2hlcl1dIG9yIFtbT3BlblZpZHUuZ2V0VXNlck1lZGlhXV1cbiAgICAgKi9cbiAgICBQVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUiA9ICdQVUJMSVNIRVJfUFJPUEVSVElFU19FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgY2xpZW50IHRyaWVkIHRvIGNhbGwgYSBtZXRob2Qgd2l0aG91dCB0aGUgcmVxdWlyZWQgcGVybWlzc2lvbnMuIFRoaXMgY2FuIG9jY3VyIGZvciBtZXRob2RzIFtbU2Vzc2lvbi5wdWJsaXNoXV0sXG4gICAgICogW1tTZXNzaW9uLmZvcmNlVW5wdWJsaXNoXV0sIFtbU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3RdXSwgW1tTdHJlYW0uYXBwbHlGaWx0ZXJdXSwgW1tTdHJlYW0ucmVtb3ZlRmlsdGVyXV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCA9ICdPUEVOVklEVV9QRVJNSVNTSU9OX0RFTklFRCcsXG5cbiAgICAvKipcbiAgICAgKiBUaGVyZSBpcyBubyBjb25uZWN0aW9uIHRvIHRoZSBTZXNzaW9uLiBUaGlzIGVycm9yIHdpbGwgYmUgdGhyb3duIHdoZW4gYW55IG1ldGhvZCByZXF1aXJpbmcgYSBjb25uZWN0aW9uIHRvXG4gICAgICogb3BlbnZpZHUtc2VydmVyIGlzIGNhbGxlZCBiZWZvcmUgc3VjY2Vzc2Z1bGx5IGNhbGxpbmcgbWV0aG9kIFtbU2Vzc2lvbi5jb25uZWN0XV1cbiAgICAgKi9cbiAgICBPUEVOVklEVV9OT1RfQ09OTkVDVEVEID0gJ09QRU5WSURVX05PVF9DT05ORUNURUQnLFxuXG4gICAgLyoqXG4gICAgICogRXJyb3IgcmVsYXRlZCB0byBbVmlydHVhbCBCYWNrZ3JvdW5kXSgvZW4vc3RhYmxlL2FkdmFuY2VkLWZlYXR1cmVzL3ZpcnR1YWwtYmFja2dyb3VuZC8pXG4gICAgICovXG4gICAgVklSVFVBTF9CQUNLR1JPVU5EX0VSUk9SID0gJ1ZJUlRVQUxfQkFDS0dST1VORF9FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmljIGVycm9yXG4gICAgICovXG4gICAgR0VORVJJQ19FUlJPUiA9ICdHRU5FUklDX0VSUk9SJ1xufVxuXG4vKipcbiAqIFNpbXBsZSBvYmplY3QgdG8gaWRlbnRpZnkgcnVudGltZSBlcnJvcnMgb24gdGhlIGNsaWVudCBzaWRlXG4gKi9cbmV4cG9ydCBjbGFzcyBPcGVuVmlkdUVycm9yIHtcblxuICAgIC8qKlxuICAgICAqIFVuaXF1ZWx5IGlkZW50aWZ5aW5nIG5hbWUgb2YgdGhlIGVycm9yXG4gICAgICovXG4gICAgbmFtZTogT3BlblZpZHVFcnJvck5hbWU7XG5cbiAgICAvKipcbiAgICAgKiBGdWxsIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvclxuICAgICAqL1xuICAgIG1lc3NhZ2U6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBPcGVuVmlkdUVycm9yTmFtZSwgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmV4cG9ydCBlbnVtIFR5cGVPZlZpZGVvIHtcbiAgICBDQU1FUkEgPSAnQ0FNRVJBJyxcbiAgICBTQ1JFRU4gPSAnU0NSRUVOJyxcbiAgICBDVVNUT00gPSAnQ1VTVE9NJyxcbiAgICBJUENBTSA9ICdJUENBTSdcbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLyoqXG4gKiBIb3cgdGhlIHZpZGVvIHdpbGwgYmUgaW5zZXJ0ZWQgaW4gdGhlIERPTSBmb3IgUHVibGlzaGVycyBhbmQgU3Vic2NyaWJlcnMuIFNlZSBbW1B1Ymxpc2hlclByb3BlcnRpZXMuaW5zZXJ0TW9kZV1dIGFuZCBbW1N1YnNjcmliZXJQcm9wZXJ0aWVzLmluc2VydE1vZGVdXVxuICovXG5leHBvcnQgZW51bSBWaWRlb0luc2VydE1vZGUge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYWZ0ZXIgdGhlIHRhcmdldCBlbGVtZW50IChhcyBuZXh0IHNpYmxpbmcpXG4gICAgICovXG4gICAgQUZURVIgPSAnQUZURVInLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIGluc2VydGVkIGFzIGxhc3QgY2hpbGQgb2YgdGhlIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgQVBQRU5EID0gJ0FQUEVORCcsXG4gICAgLyoqXG4gICAgICogVmlkZW8gaW5zZXJ0ZWQgYmVmb3JlIHRoZSB0YXJnZXQgZWxlbWVudCAoYXMgcHJldmlvdXMgc2libGluZylcbiAgICAgKi9cbiAgICBCRUZPUkUgPSAnQkVGT1JFJyxcbiAgICAvKipcbiAgICAgKiBWaWRlbyBpbnNlcnRlZCBhcyBmaXJzdCBjaGlsZCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICAgKi9cbiAgICBQUkVQRU5EID0gJ1BSRVBFTkQnLFxuICAgIC8qKlxuICAgICAqIFZpZGVvIHJlcGxhY2VzIHRhcmdldCBlbGVtZW50XG4gICAgICovXG4gICAgUkVQTEFDRSA9ICdSRVBMQUNFJ1xuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnk6XG4gKiAtIFtbY29ubmVjdGlvbkNyZWF0ZWRdXVxuICogLSBbW2Nvbm5lY3Rpb25EZXN0cm95ZWRdXVxuICovXG5leHBvcnQgY2xhc3MgQ29ubmVjdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdGlvbiBvYmplY3QgdGhhdCB3YXMgY3JlYXRlZCBvciBkZXN0cm95ZWRcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogRm9yIGBjb25uZWN0aW9uRGVzdHJveWVkYCBldmVudDpcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB0aGUgcmVtb3RlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IG90aGVyIHVzZXIgY2FsbGluZyBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWBcbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHJlbW90ZSB1c2VyIGhhcyBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwic2Vzc2lvbkNsb3NlZEJ5U2VydmVyXCI6IHRoZSBTZXNzaW9uIGhhcyBiZWVuIGNsb3NlZCBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwibmV0d29ya0Rpc2Nvbm5lY3RcIjogdGhlIHJlbW90ZSB1c2VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqIC0gXCJub2RlQ3Jhc2hlZFwiOiBhIG5vZGUgaGFzIGNyYXNoZWQgaW4gdGhlIHNlcnZlciBzaWRlXG4gICAgICpcbiAgICAgKiBGb3IgYGNvbm5lY3Rpb25DcmVhdGVkYCBldmVudCBhbiBlbXB0eSBzdHJpbmdcbiAgICAgKi9cbiAgICByZWFzb246IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjYW5jZWxhYmxlOiBib29sZWFuLCB0YXJnZXQ6IFNlc3Npb24sIHR5cGU6IHN0cmluZywgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBDb25uZWN0aW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuXG4vKipcbiAqICoqVGhpcyBmZWF0dXJlIGlzIHBhcnQgb2YgT3BlblZpZHUgUHJvIHRpZXIqKiA8YSBocmVmPVwiaHR0cHM6Ly9kb2NzLm9wZW52aWR1LmlvL2VuL3N0YWJsZS9vcGVudmlkdS1wcm8vXCIgc3R5bGU9XCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGJhY2tncm91bmQtY29sb3I6IHJnYigwLCAxMzYsIDE3MCk7IGNvbG9yOiB3aGl0ZTsgZm9udC13ZWlnaHQ6IGJvbGQ7IHBhZGRpbmc6IDBweCA1cHg7IG1hcmdpbi1yaWdodDogNXB4OyBib3JkZXItcmFkaXVzOiAzcHg7IGZvbnQtc2l6ZTogMTNweDsgbGluZS1oZWlnaHQ6MjFweDsgZm9udC1mYW1pbHk6IE1vbnRzZXJyYXQsIHNhbnMtc2VyaWZcIj5QUk88L2E+XG4gKlxuICogVHJpZ2dlcmVkIGJ5IFtbY29ubmVjdGlvblByb3BlcnR5Q2hhbmdlZF1dXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25uZWN0aW9uUHJvcGVydHlDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgQ29ubmVjdGlvbiB3aG9zZSBwcm9wZXJ0eSBoYXMgY2hhbmdlZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcHJvcGVydHkgb2YgdGhlIHN0cmVhbSB0aGF0IGNoYW5nZWQuIFRoaXMgdmFsdWUgaXMgZWl0aGVyIGBcInJvbGVcImAgb3IgYFwicmVjb3JkXCJgXG4gICAgICovXG4gICAgY2hhbmdlZFByb3BlcnR5OiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBOZXcgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChhZnRlciBjaGFuZ2UsIGN1cnJlbnQgdmFsdWUpXG4gICAgICovXG4gICAgbmV3VmFsdWU6IE9iamVjdDtcblxuICAgIC8qKlxuICAgICAqIFByZXZpb3VzIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSAoYmVmb3JlIGNoYW5nZSlcbiAgICAgKi9cbiAgICBvbGRWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgY29ubmVjdGlvbjogQ29ubmVjdGlvbiwgY2hhbmdlZFByb3BlcnR5OiBzdHJpbmcsIG5ld1ZhbHVlOiBPYmplY3QsIG9sZFZhbHVlOiBPYmplY3QpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgJ2Nvbm5lY3Rpb25Qcm9wZXJ0eUNoYW5nZWQnKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5jaGFuZ2VkUHJvcGVydHkgPSBjaGFuZ2VkUHJvcGVydHk7XG4gICAgICAgIHRoaXMubmV3VmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgdGhpcy5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9GaWx0ZXInO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgZXZlbnQgaGFzIGEgZGVmYXVsdCBiZWhhdmlvciB0aGF0IG1heSBiZSBwcmV2ZW50ZWQgYnkgY2FsbGluZyBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV1cbiAgICAgKi9cbiAgICBjYW5jZWxhYmxlOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9iamVjdCB0aGF0IGRpc3BhdGNoZWQgdGhlIGV2ZW50XG4gICAgICovXG4gICAgdGFyZ2V0OiBTZXNzaW9uIHwgU3RyZWFtTWFuYWdlciB8IEZpbHRlcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0eXBlIG9mIGV2ZW50LiBUaGlzIGlzIHRoZSBzYW1lIHN0cmluZyB5b3UgcGFzcyBhcyBmaXJzdCBwYXJhbWV0ZXIgd2hlbiBjYWxsaW5nIG1ldGhvZCBgb24oKWAgb2YgYW55IG9iamVjdCBpbXBsZW1lbnRpbmcgW1tFdmVudERpc3BhdGNoZXJdXSBpbnRlcmZhY2VcbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaGFzQmVlblByZXZlbnRlZCA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIgfCBGaWx0ZXIsIHR5cGU6IHN0cmluZykge1xuICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBkZWZhdWx0IGJlYWhpdm91ciBvZiB0aGUgZXZlbnQgaGFzIGJlZW4gcHJldmVudGVkIG9yIG5vdC4gQ2FsbCBbW0V2ZW50LnByZXZlbnREZWZhdWx0XV0gdG8gcHJldmVudCBpdFxuICAgICAqL1xuICAgIGlzRGVmYXVsdFByZXZlbnRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzQmVlblByZXZlbnRlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmV2ZW50cyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgZXZlbnQuIFRoZSBmb2xsb3dpbmcgZXZlbnRzIGhhdmUgYSBkZWZhdWx0IGJlaGF2aW9yOlxuICAgICAqXG4gICAgICogLSBgc2Vzc2lvbkRpc2Nvbm5lY3RlZGA6IGRpc3BhdGNoZWQgYnkgW1tTZXNzaW9uXV0gb2JqZWN0LCBhdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlcyB0aGUgbGVhdmluZyBwYXJ0aWNpcGFudCBmcm9tIGV2ZXJ5IFN1YnNjcmliZXIgb2JqZWN0IG9mIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIGVhY2ggU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgZWFjaCBTdWJzY3JpYmVyIG9iamVjdCB3aWxsIGFsc28gZGlzcGF0Y2ggYSBgdmlkZW9FbGVtZW50RGVzdHJveWVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIC0gYHN0cmVhbURlc3Ryb3llZGA6XG4gICAgICogICAtIElmIGRpc3BhdGNoZWQgYnkgYSBbW1B1Ymxpc2hlcl1dICgqeW91KiBoYXZlIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSBzdG9wcyBhbGwgbWVkaWEgdHJhY2tzIGFuZCBkZWxldGVzIGFueSBIVE1MIHZpZGVvIGVsZW1lbnQgYXNzb2NpYXRlZCB0byBpdCAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YFxuICAgICAqIGluIG1ldGhvZCBbW09wZW5WaWR1LmluaXRQdWJsaXNoZXJdXSBvciBieSBjYWxsaW5nIFtbUHVibGlzaGVyLmNyZWF0ZVZpZGVvRWxlbWVudF1dKS4gRm9yIGV2ZXJ5IHZpZGVvIHJlbW92ZWQsIHRoZSBQdWJsaXNoZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqICAgLSBJZiBkaXNwYXRjaGVkIGJ5IFtbU2Vzc2lvbl1dICgqb3RoZXIgdXNlciogaGFzIHVucHVibGlzaGVkKTogYXV0b21hdGljYWxseSB1bnN1YnNjcmliZXMgdGhlIHByb3BlciBTdWJzY3JpYmVyIG9iamVjdCBmcm9tIHRoZSBzZXNzaW9uICh0aGlzIGluY2x1ZGVzIGNsb3NpbmcgdGhlIFJUQ1BlZXJDb25uZWN0aW9uIGFuZCBkaXNwb3NpbmcgYWxsIE1lZGlhU3RyZWFtVHJhY2tzKVxuICAgICAqIGFuZCBhbHNvIGRlbGV0ZXMgYW55IEhUTUwgdmlkZW8gZWxlbWVudCBhc3NvY2lhdGVkIHRvIHRoYXQgU3Vic2NyaWJlciAob25seSB0aG9zZSBjcmVhdGVkIGJ5IE9wZW5WaWR1IEJyb3dzZXIsIGVpdGhlciBieSBwYXNzaW5nIGEgdmFsaWQgcGFyYW1ldGVyIGFzIGB0YXJnZXRFbGVtZW50YCBpbiBtZXRob2QgW1tTZXNzaW9uLnN1YnNjcmliZV1dIG9yXG4gICAgICogYnkgY2FsbGluZyBbW1N1YnNjcmliZXIuY3JlYXRlVmlkZW9FbGVtZW50XV0pLiBGb3IgZXZlcnkgdmlkZW8gcmVtb3ZlZCwgdGhlIFN1YnNjcmliZXIgb2JqZWN0IHdpbGwgYWxzbyBkaXNwYXRjaCBhIGB2aWRlb0VsZW1lbnREZXN0cm95ZWRgIGV2ZW50LlxuICAgICAqL1xuICAgIHByZXZlbnREZWZhdWx0KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICAgICAgdGhpcy5jYWxsRGVmYXVsdEJlaGF2aW9yID0gKCkgPT4geyB9O1xuICAgICAgICB0aGlzLmhhc0JlZW5QcmV2ZW50ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBhYnN0cmFjdCBjYWxsRGVmYXVsdEJlaGF2aW9yKCk7XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IFN1YnNjcmliZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdWJzY3JpYmVyJztcbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5cblxuLyoqXG4gKiBEZWZpbmVzIHByb3BlcnR5IFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dXG4gKi9cbmV4cG9ydCBlbnVtIEV4Y2VwdGlvbkV2ZW50TmFtZSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGVyZSB3YXMgYW4gdW5leHBlY3RlZCBlcnJvciBvbiB0aGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBhbiBJQ0UgY2FuZGlkYXRlIGdlbmVyYXRlZCBhbmQgc2VudCBieSB0aGUgY2xpZW50LXNpZGUuXG4gICAgICogXG4gICAgICogW1tFeGNlcHRpb25FdmVudF1dIG9iamVjdHMgd2l0aCB0aGlzIFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dIHdpbGwgaGF2ZSBhcyBbW0V4Y2VwdGlvbkV2ZW50Lm9yaWdpbl1dIHByb3BlcnR5IGEgW1tTZXNzaW9uXV0gb2JqZWN0LlxuICAgICAqL1xuICAgIElDRV9DQU5ESURBVEVfRVJST1IgPSAnSUNFX0NBTkRJREFURV9FUlJPUicsXG5cbiAgICAvKipcbiAgICAgKiBUaGUgW0lDRSBjb25uZWN0aW9uIHN0YXRlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUlRDUGVlckNvbm5lY3Rpb24vaWNlQ29ubmVjdGlvblN0YXRlKVxuICAgICAqIG9mIGFuIFtSVENQZWVyQ29ubmVjdGlvbl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JUQ1BlZXJDb25uZWN0aW9uKSByZWFjaGVkIGBmYWlsZWRgIHN0YXR1cy5cbiAgICAgKiBcbiAgICAgKiBUaGlzIGlzIGEgdGVybWluYWwgZXJyb3IgdGhhdCB3b24ndCBoYXZlIGFueSBraW5kIG9mIHBvc3NpYmxlIHJlY292ZXJ5LiBJZiB0aGUgY2xpZW50IGlzIHN0aWxsIGNvbm5lY3RlZCB0byBPcGVuVmlkdSBTZXJ2ZXIsXG4gICAgICogdGhlbiBhbiBhdXRvbWF0aWMgcmVjb25uZWN0aW9uIHByb2Nlc3Mgb2YgdGhlIG1lZGlhIHN0cmVhbSBpcyBpbW1lZGlhdGVseSBwZXJmb3JtZWQuIElmIHRoZSBJQ0UgY29ubmVjdGlvbiBoYXMgYnJva2VuIGR1ZSB0b1xuICAgICAqIGEgdG90YWwgbmV0d29yayBkcm9wLCB0aGVuIG5vIGF1dG9tYXRpYyByZWNvbm5lY3Rpb24gcHJvY2VzcyB3aWxsIGJlIHBvc3NpYmxlLlxuICAgICAqIFxuICAgICAqIFtbRXhjZXB0aW9uRXZlbnRdXSBvYmplY3RzIHdpdGggdGhpcyBbW0V4Y2VwdGlvbkV2ZW50Lm5hbWVdXSB3aWxsIGhhdmUgYXMgW1tFeGNlcHRpb25FdmVudC5vcmlnaW5dXSBwcm9wZXJ0eSBhIFtbU3RyZWFtXV0gb2JqZWN0LlxuICAgICAqL1xuICAgIElDRV9DT05ORUNUSU9OX0ZBSUxFRCA9ICdJQ0VfQ09OTkVDVElPTl9GQUlMRUQnLFxuXG4gICAgLyoqXG4gICAgICogVGhlIFtJQ0UgY29ubmVjdGlvbiBzdGF0ZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JUQ1BlZXJDb25uZWN0aW9uL2ljZUNvbm5lY3Rpb25TdGF0ZSlcbiAgICAgKiBvZiBhbiBbUlRDUGVlckNvbm5lY3Rpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SVENQZWVyQ29ubmVjdGlvbikgcmVhY2hlZCBgZGlzY29ubmVjdGVkYCBzdGF0dXMuXG4gICAgICogXG4gICAgICogVGhpcyBpcyBub3QgYSB0ZXJtaW5hbCBlcnJvciwgYW5kIGl0IGlzIHBvc3NpYmxlIGZvciB0aGUgSUNFIGNvbm5lY3Rpb24gdG8gYmUgcmVjb25uZWN0ZWQuIElmIHRoZSBjbGllbnQgaXMgc3RpbGwgY29ubmVjdGVkIHRvXG4gICAgICogT3BlblZpZHUgU2VydmVyIGFuZCBhZnRlciBjZXJ0YWluIHRpbWVvdXQgdGhlIElDRSBjb25uZWN0aW9uIGhhcyBub3QgcmVhY2hlZCBhIHN1Y2Nlc3Mgb3IgdGVybWluYWwgc3RhdHVzLCB0aGVuIGFuIGF1dG9tYXRpY1xuICAgICAqIHJlY29ubmVjdGlvbiBwcm9jZXNzIG9mIHRoZSBtZWRpYSBzdHJlYW0gaXMgcGVyZm9ybWVkLiBJZiB0aGUgSUNFIGNvbm5lY3Rpb24gaGFzIGJyb2tlbiBkdWUgdG8gYSB0b3RhbCBuZXR3b3JrIGRyb3AsIHRoZW4gbm9cbiAgICAgKiBhdXRvbWF0aWMgcmVjb25uZWN0aW9uIHByb2Nlc3Mgd2lsbCBiZSBwb3NzaWJsZS5cbiAgICAgKiBcbiAgICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGUgdGltZW91dCBmb3IgdGhlIHJlY29ubmVjdGlvbiBhdHRlbXB0IHdpdGggcHJvcGVydHkgW1tPcGVuVmlkdUFkdmFuY2VkQ29uZmlndXJhdGlvbi5pY2VDb25uZWN0aW9uRGlzY29ubmVjdGVkRXhjZXB0aW9uVGltZW91dF1dLFxuICAgICAqIHdoaWNoIGJ5IGRlZmF1bHQgaXMgNDAwMCBtaWxsaXNlY29uZHMuXG4gICAgICogXG4gICAgICogW1tFeGNlcHRpb25FdmVudF1dIG9iamVjdHMgd2l0aCB0aGlzIFtbRXhjZXB0aW9uRXZlbnQubmFtZV1dIHdpbGwgaGF2ZSBhcyBbW0V4Y2VwdGlvbkV2ZW50Lm9yaWdpbl1dIHByb3BlcnR5IGEgW1tTdHJlYW1dXSBvYmplY3QuXG4gICAgICovXG4gICAgSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVEID0gJ0lDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRCcsXG5cbiAgICAvKipcbiAgICAgKiBBIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBoYXMgbm90IGZpcmVkIGV2ZW50IGBzdHJlYW1QbGF5aW5nYCBhZnRlciBjZXJ0YWluIHRpbWVvdXQuIGBzdHJlYW1QbGF5aW5nYCBldmVudCBiZWxvbmdzIHRvIFtbU3RyZWFtTWFuYWdlckV2ZW50XV1cbiAgICAgKiBjYXRlZ29yeS4gSXQgd3JhcHMgV2ViIEFQSSBuYXRpdmUgZXZlbnQgW2NhbnBsYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MTWVkaWFFbGVtZW50L2NhbnBsYXlfZXZlbnQpLlxuICAgICAqIFxuICAgICAqIE9wZW5WaWR1IEJyb3dzZXIgY2FuIHRha2UgY2FyZSBvZiB0aGUgdmlkZW8gcGxheWVycyAoc2VlIFtoZXJlXSgvZW4vc3RhYmxlL2NoZWF0c2hlZXQvbWFuYWdlLXZpZGVvcy8jbGV0LW9wZW52aWR1LXRha2UtY2FyZS1vZi10aGUtdmlkZW8tcGxheWVycykpLFxuICAgICAqIG9yIHlvdSBjYW4gdGFrZSBjYXJlIG9mIHZpZGVvIHBsYXllcnMgb24geW91ciBvd24gKHNlZSBbaGVyZV0oL2VuL3N0YWJsZS9jaGVhdHNoZWV0L21hbmFnZS12aWRlb3MvI3lvdS10YWtlLWNhcmUtb2YtdGhlLXZpZGVvLXBsYXllcnMpKS5cbiAgICAgKiBFaXRoZXIgd2F5LCB3aGVuZXZlciBhIFtbU3Vic2NyaWJlcl1dIG9iamVjdCBpcyBjb21tYW5kZWQgdG8gYXR0YWNoIGl0cyBbW1N0cmVhbV1dIHRvIGEgdmlkZW8gZWxlbWVudCwgaXQgaXMgc3VwcG9zZWQgdG8gZmlyZSBgc3RyZWFtUGxheWluZ2BcbiAgICAgKiBldmVudCBzaG9ydGx5IGFmdGVyLiBJZiBpdCBkb2VzIG5vdCwgdGhlbiB3ZSBjYW4gc2FmZWx5IGFzc3VtZSB0aGF0IHNvbWV0aGluZyB3cm9uZyBoYXMgaGFwcGVuZWQgd2hpbGUgcGxheWluZyB0aGUgcmVtb3RlIHZpZGVvIGFuZCB0aGUgXG4gICAgICogYXBwbGljYXRpb24gbWF5IGJlIG5vdGlmaWVkIHRocm91Z2ggdGhpcyBzcGVjaWZpYyBFeGNlcHRpb25FdmVudC5cbiAgICAgKiBcbiAgICAgKiBUaGUgdGltZW91dCBjYW4gYmUgY29uZmlndXJlZCB3aXRoIHByb3BlcnR5IFtbT3BlblZpZHVBZHZhbmNlZENvbmZpZ3VyYXRpb24ubm9TdHJlYW1QbGF5aW5nRXZlbnRFeGNlcHRpb25UaW1lb3V0XV0uIEJ5IGRlZmF1bHQgaXQgaXMgNDAwMCBtaWxsaXNlY29uZHMuXG4gICAgICogXG4gICAgICogVGhpcyBpcyBqdXN0IGFuIGluZm9ybWF0aXZlIGV4Y2VwdGlvbi4gSXQgb25seSBtZWFucyB0aGF0IGEgcmVtb3RlIFN0cmVhbSB0aGF0IGlzIHN1cHBvc2VkIHRvIGJlIHBsYXlpbmcgYnkgYSB2aWRlbyBwbGF5ZXIgaGFzIG5vdCBkb25lIHNvXG4gICAgICogaW4gYSByZWFzb25hYmxlIHRpbWUuIEJ1dCB0aGUgbGFjayBvZiB0aGUgZXZlbnQgY2FuIGJlIGNhdXNlZCBieSBtdWx0aXBsZSByZWFzb25zLiBJZiBhIFN1YnNjcmliZXIgaXMgbm90IHBsYXlpbmcgaXRzIFN0cmVhbSwgdGhlIG9yaWdpblxuICAgICAqIG9mIHRoZSBwcm9ibGVtIGNvdWxkIGJlIGxvY2F0ZWQgYXQgdGhlIFB1Ymxpc2hlciBzaWRlLiBPciBtYXkgYmUgY2F1c2VkIGJ5IGEgdHJhbnNpZW50IG5ldHdvcmsgcHJvYmxlbS4gQnV0IGl0IGFsc28gY291bGQgYmUgYSBwcm9ibGVtIHdpdGhcbiAgICAgKiBhdXRvcGxheSBwZXJtaXNzaW9ucy4gQm90dG9tIGxpbmUsIHRoZSBjYXVzZSBjYW4gYmUgdmVyeSB2YXJpZWQsIGFuZCBkZXBlbmRpbmcgb24gdGhlIGFwcGxpY2F0aW9uIHRoZSBsYWNrIG9mIHRoZSBldmVudCBjb3VsZCBldmVuIGJlIGV4cGVjdGVkLlxuICAgICAqIFxuICAgICAqIFtbRXhjZXB0aW9uRXZlbnRdXSBvYmplY3RzIHdpdGggdGhpcyBbW0V4Y2VwdGlvbkV2ZW50Lm5hbWVdXSB3aWxsIGhhdmUgYXMgW1tFeGNlcHRpb25FdmVudC5vcmlnaW5dXSBwcm9wZXJ0eSBhIFtbU3Vic2NyaWJlcl1dIG9iamVjdC5cbiAgICAgKi9cbiAgICBOT19TVFJFQU1fUExBWUlOR19FVkVOVCA9ICdOT19TVFJFQU1fUExBWUlOR19FVkVOVCdcbn1cblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnkgW1tTZXNzaW9uRXZlbnRNYXAuZXhjZXB0aW9uXV1cbiAqL1xuZXhwb3J0IGNsYXNzIEV4Y2VwdGlvbkV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogTmFtZSBvZiB0aGUgZXhjZXB0aW9uXG4gICAgICovXG4gICAgbmFtZTogRXhjZXB0aW9uRXZlbnROYW1lO1xuXG4gICAgLyoqXG4gICAgICogT2JqZWN0IGFmZmVjdGVkIGJ5IHRoZSBleGNlcHRpb24uIERlcGVuZGluZyBvbiB0aGUgW1tFeGNlcHRpb25FdmVudC5uYW1lXV0gcHJvcGVydHk6XG4gICAgICogLSBbW1Nlc3Npb25dXTogYElDRV9DQU5ESURBVEVfRVJST1JgXG4gICAgICogLSBbW1N0cmVhbV1dOiBgSUNFX0NPTk5FQ1RJT05fRkFJTEVEYCwgYElDRV9DT05ORUNUSU9OX0RJU0NPTk5FQ1RFRGBcbiAgICAgKiAtIFtbU3Vic2NyaWJlcl1dOiBgTk9fU1RSRUFNX1BMQVlJTkdfRVZFTlRgXG4gICAgICovXG4gICAgb3JpZ2luOiBTZXNzaW9uIHwgU3RyZWFtIHwgU3Vic2NyaWJlcjtcblxuICAgIC8qKlxuICAgICAqIEluZm9ybWF0aXZlIGRlc2NyaXB0aW9uIG9mIHRoZSBleGNlcHRpb25cbiAgICAgKi9cbiAgICBtZXNzYWdlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBBbnkgZXh0cmEgaW5mb3JtYXRpb24gYXNzb2NpYXRlZCB0byB0aGUgZXhjZXB0aW9uXG4gICAgICovXG4gICAgZGF0YT86IGFueTtcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzZXNzaW9uOiBTZXNzaW9uLCBuYW1lOiBFeGNlcHRpb25FdmVudE5hbWUsIG9yaWdpbjogU2Vzc2lvbiB8IFN0cmVhbSB8IFN1YnNjcmliZXIsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IGFueSkge1xuICAgICAgICBzdXBlcihmYWxzZSwgc2Vzc2lvbiwgJ2V4Y2VwdGlvbicpO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9yaWdpbiA9IG9yaWdpbjtcbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBGaWx0ZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9GaWx0ZXInO1xuXG5cbi8qKlxuICogRGVmaW5lcyBldmVyeSBldmVudCBkaXNwYXRjaGVkIGJ5IGF1ZGlvL3ZpZGVvIHN0cmVhbSBmaWx0ZXJzLiBZb3UgY2FuIHN1YnNjcmliZSB0byBmaWx0ZXIgZXZlbnRzIGJ5IGNhbGxpbmcgW1tGaWx0ZXIuYWRkRXZlbnRMaXN0ZW5lcl1dXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWx0ZXJFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIERhdGEgb2YgdGhlIGV2ZW50XG4gICAgICovXG4gICAgZGF0YTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogRmlsdGVyLCBldmVudFR5cGU6IHN0cmluZywgZGF0YTogT2JqZWN0KSB7XG4gICAgICAgIHN1cGVyKGZhbHNlLCB0YXJnZXQsIGV2ZW50VHlwZSk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuXG4vKipcbiAqIFRyaWdnZXJlZCBieSBbW25ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkXV1cbiAqL1xuZXhwb3J0IGNsYXNzIE5ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBOZXcgdmFsdWUgb2YgdGhlIG5ldHdvcmsgcXVhbGl0eSBsZXZlbFxuICAgICAqL1xuICAgIG5ld1ZhbHVlOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBPbGQgdmFsdWUgb2YgdGhlIG5ldHdvcmsgcXVhbGl0eSBsZXZlbFxuICAgICAqL1xuICAgIG9sZFZhbHVlOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDb25uZWN0aW9uIGZvciB3aG9tIHRoZSBuZXR3b3JrIHF1YWxpdHkgbGV2ZWwgY2hhbmdlZFxuICAgICAqL1xuICAgIGNvbm5lY3Rpb246IENvbm5lY3Rpb25cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24sIG5ld1ZhbHVlOiBudW1iZXIsIG9sZFZhbHVlOiBudW1iZXIsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24pIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgJ25ldHdvcmtRdWFsaXR5TGV2ZWxDaGFuZ2VkJyk7XG4gICAgICAgIHRoaXMubmV3VmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgdGhpcy5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBjb25uZWN0aW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tZW1wdHlcbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkgeyB9XG5cbn1cbiIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L0Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG5cbi8qKlxuICogVHJpZ2dlcmVkIGJ5OlxuICogLSBgcHVibGlzaGVyU3RhcnRTcGVha2luZ2AgKGF2YWlsYWJsZSBmb3IgW1Nlc3Npb25dKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvaW50ZXJmYWNlcy9TZXNzaW9uRXZlbnRNYXAuaHRtbCNwdWJsaXNoZXJTdGFydFNwZWFraW5nKSBhbmQgW1N0cmVhbU1hbmFnZXJdKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvaW50ZXJmYWNlcy9TdHJlYW1NYW5hZ2VyRXZlbnRNYXAuaHRtbCNwdWJsaXNoZXJTdGFydFNwZWFraW5nKSBvYmplY3RzKVxuICogLSBgcHVibGlzaGVyU3RvcFNwZWFraW5nYCAoYXZhaWxhYmxlIGZvciBbU2Vzc2lvbl0oL2VuL3N0YWJsZS9hcGkvb3BlbnZpZHUtYnJvd3Nlci9pbnRlcmZhY2VzL1Nlc3Npb25FdmVudE1hcC5odG1sI3B1Ymxpc2hlclN0b3BTcGVha2luZykgYW5kIFtTdHJlYW1NYW5hZ2VyXSgvZW4vc3RhYmxlL2FwaS9vcGVudmlkdS1icm93c2VyL2ludGVyZmFjZXMvU3RyZWFtTWFuYWdlckV2ZW50TWFwLmh0bWwjcHVibGlzaGVyU3RvcFNwZWFraW5nKSBvYmplY3RzKVxuICovXG5leHBvcnQgY2xhc3MgUHVibGlzaGVyU3BlYWtpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzdGFydGVkIG9yIHN0b3BwZWQgc3BlYWtpbmdcbiAgICAgKi9cbiAgICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmVhbUlkIG9mIHRoZSBTdHJlYW0gYWZmZWN0ZWQgYnkgdGhlIHNwZWFraW5nIGV2ZW50XG4gICAgICovXG4gICAgc3RyZWFtSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IFNlc3Npb24gfCBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHN0cmVhbUlkOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICAgIHRoaXMuc3RyZWFtSWQgPSBzdHJlYW1JZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5cblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnk6XG4gKiAtIFtbcmVjb3JkaW5nU3RhcnRlZF1dXG4gKiAtIFtbcmVjb3JkaW5nU3RvcHBlZF1dXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWNvcmRpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvcmRpbmcgSUQgZ2VuZXJhdGVkIGluIG9wZW52aWR1LXNlcnZlclxuICAgICAqL1xuICAgIGlkOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcmVjb3JkaW5nIG5hbWUgeW91IHN1cHBsaWVkIHRvIG9wZW52aWR1LXNlcnZlci4gRm9yIGV4YW1wbGUsIHRvIG5hbWUgeW91ciByZWNvcmRpbmcgZmlsZSBNWV9SRUNPUkRJTkc6XG4gICAgICogLSBXaXRoICoqQVBJIFJFU1QqKjogUE9TVCB0byBgL2FwaS9yZWNvcmRpbmdzL3N0YXJ0YCBwYXNzaW5nIEpTT04gYm9keSBge1wic2Vzc2lvblwiOlwic2Vzc2lvbklkXCIsXCJuYW1lXCI6XCJNWV9SRUNPUkRJTkdcIn1gXG4gICAgICogLSBXaXRoICoqb3BlbnZpZHUtamF2YS1jbGllbnQqKjogYE9wZW5WaWR1LnN0YXJ0UmVjb3JkaW5nKHNlc3Npb25JZCwgXCJNWV9SRUNPUkRJTkdcIilgIG9yIGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIG5ldyBSZWNvcmRpbmdQcm9wZXJ0aWVzLkJ1aWxkZXIoKS5uYW1lKFwiTVlfUkVDT1JESU5HXCIpLmJ1aWxkKCkpYFxuICAgICAqIC0gV2l0aCAqKm9wZW52aWR1LW5vZGUtY2xpZW50Kio6IGBPcGVuVmlkdS5zdGFydFJlY29yZGluZyhzZXNzaW9uSWQsIFwiTVlfUkVDT1JESU5HXCIpYCBvciBgT3BlblZpZHUuc3RhcnRSZWNvcmRpbmcoc2Vzc2lvbklkLCB7bmFtZTogXCJNWV9SRUNPUkRJTkdcIn0pYFxuICAgICAqXG4gICAgICogSWYgbm8gbmFtZSBpcyBzdXBwbGllZCwgdGhpcyBwcm9wZXJ0eSB3aWxsIGJlIHVuZGVmaW5lZCBhbmQgdGhlIHJlY29yZGVkIGZpbGUgd2lsbCBiZSBuYW1lZCBhZnRlciBwcm9wZXJ0eSBbW2lkXV1cbiAgICAgKi9cbiAgICBuYW1lPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdyZWNvcmRpbmdTdG9wcGVkJyBldmVudDpcbiAgICAgKiAtIFwicmVjb3JkaW5nU3RvcHBlZEJ5U2VydmVyXCI6IHRoZSByZWNvcmRpbmcgaGFzIGJlZW4gZ3JhY2VmdWxseSBzdG9wcGVkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJhdXRvbWF0aWNTdG9wXCI6IHNlZSBbQXV0b21hdGljIHN0b3Agb2YgcmVjb3JkaW5nc10oL2VuL3N0YWJsZS9hZHZhbmNlZC1mZWF0dXJlcy9yZWNvcmRpbmcvI2F1dG9tYXRpYy1zdG9wLW9mLXJlY29yZGluZ3MpXG4gICAgICogLSBcIm5vZGVDcmFzaGVkXCI6IGEgbm9kZSBoYXMgY3Jhc2hlZCBpbiB0aGUgc2VydmVyIHNpZGVcbiAgICAgKlxuICAgICAqIEZvciAncmVjb3JkaW5nU3RhcnRlZCcgZW1wdHkgc3RyaW5nXG4gICAgICovXG4gICAgcmVhc29uPzogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiwgdHlwZTogc3RyaW5nLCBpZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHJlYXNvbj86IHN0cmluZykge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICBpZiAobmFtZSAhPT0gaWQpIHtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTctMjAyMiBPcGVuVmlkdSAoaHR0cHM6Ly9vcGVudmlkdS5pbylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG5pbXBvcnQgeyBFdmVudCB9IGZyb20gJy4vRXZlbnQnO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgT3BlblZpZHVMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvT3BlblZpZHVMb2dnZXInO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnkgW1tzZXNzaW9uRGlzY29ubmVjdGVkXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25EaXNjb25uZWN0ZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcblxuICAgIC8qKlxuICAgICAqIC0gXCJkaXNjb25uZWN0XCI6IHlvdSBoYXZlIGNhbGxlZCBgU2Vzc2lvbi5kaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiB5b3UgaGF2ZSBiZWVuIGV2aWN0ZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSBvdGhlciB1c2VyIGNhbGxpbmcgYFNlc3Npb24uZm9yY2VEaXNjb25uZWN0KClgXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5U2VydmVyXCI6IHlvdSBoYXZlIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB5b3VyIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZC4gQmVmb3JlIGEgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50IHdpdGggdGhpcyByZWFzb24gaXMgdHJpZ2dlcmVkLFxuICAgICAqICAgICAgU2Vzc2lvbiBvYmplY3Qgd2lsbCBhbHdheXMgaGF2ZSBwcmV2aW91c2x5IGRpc3BhdGNoZWQgYSBgcmVjb25uZWN0aW5nYCBldmVudC4gSWYgdGhlIHJlY29ubmVjdGlvbiBwcm9jZXNzIHN1Y2NlZWRzLFxuICAgICAqICAgICAgU2Vzc2lvbiBvYmplY3Qgd2lsbCBkaXNwYXRjaCBhIGByZWNvbm5lY3RlZGAgZXZlbnQuIElmIGl0IGZhaWxzLCBTZXNzaW9uIG9iamVjdCB3aWxsIGRpc3BhdGNoIGEgU2Vzc2lvbkRpc2Nvbm5lY3RlZEV2ZW50XG4gICAgICogICAgICB3aXRoIHJlYXNvbiBcIm5ldHdvcmtEaXNjb25uZWN0XCJcbiAgICAgKiAtIFwibm9kZUNyYXNoZWRcIjogYSBub2RlIGhhcyBjcmFzaGVkIGluIHRoZSBzZXJ2ZXIgc2lkZS4gWW91IGNhbiB1c2UgdGhpcyByZWFzb24gdG8gYXNrIHlvdXIgYXBwbGljYXRpb24ncyBiYWNrZW5kIHRvIHJlY29ubmVjdCBcbiAgICAgKiB0byBhIG5ldyBzZXNzaW9uIHRvIHJlcGxhY2UgdGhlIGNyYXNoZWQgb25lXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCByZWFzb246IHN0cmluZykge1xuICAgICAgICBzdXBlcih0cnVlLCB0YXJnZXQsICdzZXNzaW9uRGlzY29ubmVjdGVkJyk7XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkge1xuXG4gICAgICAgIGxvZ2dlci5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW9yIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuXG4gICAgICAgIGNvbnN0IHNlc3Npb24gPSA8U2Vzc2lvbj50aGlzLnRhcmdldDtcblxuICAgICAgICAvLyBEaXNwb3NlIGFuZCBkZWxldGUgYWxsIHJlbW90ZSBDb25uZWN0aW9uc1xuICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmZvckVhY2gocmVtb3RlQ29ubmVjdGlvbiA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSByZW1vdGVDb25uZWN0aW9uLmNvbm5lY3Rpb25JZDtcbiAgICAgICAgICAgIGlmICghIXNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbSEuZGlzcG9zZVdlYlJ0Y1BlZXIoKTtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5zdHJlYW0hLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5zdHJlYW0hLnN0cmVhbU1hbmFnZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9ucy5nZXQoY29ubmVjdGlvbklkKT8uc3RyZWFtIS5zdHJlYW1NYW5hZ2VyLnJlbW92ZUFsbFZpZGVvcygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IHNlc3Npb24ucmVtb3RlQ29ubmVjdGlvbnMuZ2V0KGNvbm5lY3Rpb25JZCk/LnN0cmVhbT8uc3RyZWFtSWQ7XG4gICAgICAgICAgICAgICAgaWYgKCEhc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5yZW1vdGVTdHJlYW1zQ3JlYXRlZC5kZWxldGUoc3RyZWFtSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmdldChjb25uZWN0aW9uSWQpPy5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZXNzaW9uLnJlbW90ZUNvbm5lY3Rpb25zLmRlbGV0ZShjb25uZWN0aW9uSWQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9Db25uZWN0aW9uJztcbmltcG9ydCB7IFNlc3Npb24gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TZXNzaW9uJztcblxuXG4vKipcbiAqIFRyaWdnZXJlZCBieSBbW1Nlc3Npb25FdmVudE1hcC5zaWduYWxdXVxuICovXG5leHBvcnQgY2xhc3MgU2lnbmFsRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdHlwZSBvZiBzaWduYWwuIEl0IGlzIHN0cmluZyBgXCJzaWduYWxcImAgZm9yIHRob3NlIHNpZ25hbHMgc2VudCB3aXRoIG5vIFtbU2lnbmFsT3B0aW9ucy50eXBlXV0gcHJvcGVydHksIGFuZCBgXCJzaWduYWw6dHlwZVwiYCBpZiB3YXMgc2VudCB3aXRoIGEgXG4gICAgICogdmFsaWQgW1tTaWduYWxPcHRpb25zLnR5cGVdXSBwcm9wZXJ0eS5cbiAgICAgKlxuICAgICAqIFRoZSBjbGllbnQgbXVzdCBiZSBzcGVjaWZpY2FsbHkgc3Vic2NyaWJlZCB0byBgU2Vzc2lvbi5vbignc2lnbmFsOnR5cGUnLCBmdW5jdGlvbihzaWduYWxFdmVudCkgey4uLn0pYCB0byB0cmlnZ2VyIHRoYXQgdHlwZSBvZiBzaWduYWwuXG4gICAgICpcbiAgICAgKiBTdWJzY3JpYmluZyB0byBgU2Vzc2lvbi5vbignc2lnbmFsJywgZnVuY3Rpb24oc2lnbmFsRXZlbnQpIHsuLi59KWAgd2lsbCB0cmlnZ2VyIGFsbCBzaWduYWxzLCBubyBtYXR0ZXIgdGhlaXIgdHlwZS5cbiAgICAgKi9cbiAgICB0eXBlOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbWVzc2FnZSBvZiB0aGUgc2lnbmFsIChjYW4gYmUgZW1wdHkpXG4gICAgICovXG4gICAgZGF0YT86IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBjbGllbnQgdGhhdCBzZW50IHRoZSBzaWduYWwuIFRoaXMgcHJvcGVydHkgaXMgdW5kZWZpbmVkIGlmIHRoZSBzaWduYWxcbiAgICAgKiB3YXMgZGlyZWN0bHkgZ2VuZXJhdGVkIGJ5IHRoZSBhcHBsaWNhdGlvbiBzZXJ2ZXIgKG5vdCBieSBvdGhlciBjbGllbnQpXG4gICAgICovXG4gICAgZnJvbT86IENvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTZXNzaW9uLCB0eXBlPzogc3RyaW5nLCBkYXRhPzogc3RyaW5nLCBmcm9tPzogQ29ubmVjdGlvbikge1xuICAgICAgICBzdXBlcihmYWxzZSwgdGFyZ2V0LCAnc2lnbmFsJyk7XG4gICAgICAgIGlmICghIXR5cGUpIHtcbiAgICAgICAgICAgIHRoaXMudHlwZSA9ICdzaWduYWw6JyArIHR5cGU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5mcm9tID0gZnJvbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9QdWJsaXNoZXInO1xuaW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1Nlc3Npb24nO1xuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcblxuLyoqXG4gKiBAaGlkZGVuXG4gKi9cbmNvbnN0IGxvZ2dlcjogT3BlblZpZHVMb2dnZXIgPSBPcGVuVmlkdUxvZ2dlci5nZXRJbnN0YW5jZSgpO1xuXG4vKipcbiAqIFRyaWdnZXJlZCBieTpcbiAqIC0gYHN0cmVhbUNyZWF0ZWRgIChhdmFpbGFibGUgZm9yIFtTZXNzaW9uXSgvZW4vc3RhYmxlL2FwaS9vcGVudmlkdS1icm93c2VyL2ludGVyZmFjZXMvU2Vzc2lvbkV2ZW50TWFwLmh0bWwjc3RyZWFtQ3JlYXRlZCkgYW5kIFtQdWJsaXNoZXJdKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvaW50ZXJmYWNlcy9QdWJsaXNoZXJFdmVudE1hcC5odG1sI3N0cmVhbUNyZWF0ZWQpIG9iamVjdHMpXG4gKiAtIGBzdHJlYW1EZXN0cm95ZWRdYCAoYXZhaWxhYmxlIGZvciBbU2Vzc2lvbl0oL2VuL3N0YWJsZS9hcGkvb3BlbnZpZHUtYnJvd3Nlci9pbnRlcmZhY2VzL1Nlc3Npb25FdmVudE1hcC5odG1sI3N0cmVhbURlc3Ryb3llZCkgYW5kIFtQdWJsaXNoZXJdKC9lbi9zdGFibGUvYXBpL29wZW52aWR1LWJyb3dzZXIvaW50ZXJmYWNlcy9QdWJsaXNoZXJFdmVudE1hcC5odG1sI3N0cmVhbURlc3Ryb3llZCkgb2JqZWN0cylcbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogU3RyZWFtIG9iamVjdCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogRm9yICdzdHJlYW1EZXN0cm95ZWQnIGV2ZW50OlxuICAgICAqIC0gXCJ1bnB1Ymxpc2hcIjogbWV0aG9kIGBTZXNzaW9uLnVucHVibGlzaCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZGlzY29ubmVjdFwiOiBtZXRob2QgYFNlc3Npb24uZGlzY29ubmVjdCgpYCBoYXMgYmVlbiBjYWxsZWRcbiAgICAgKiAtIFwiZm9yY2VVbnB1Ymxpc2hCeVVzZXJcIjogc29tZSB1c2VyIGhhcyBjYWxsZWQgYFNlc3Npb24uZm9yY2VVbnB1Ymxpc2goKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlRGlzY29ubmVjdEJ5VXNlclwiOiBzb21lIHVzZXIgaGFzIGNhbGxlZCBgU2Vzc2lvbi5mb3JjZURpc2Nvbm5lY3QoKWAgb3ZlciB0aGUgU3RyZWFtXG4gICAgICogLSBcImZvcmNlVW5wdWJsaXNoQnlTZXJ2ZXJcIjogdGhlIHVzZXIncyBzdHJlYW0gaGFzIGJlZW4gdW5wdWJsaXNoZWQgZnJvbSB0aGUgU2Vzc2lvbiBieSB0aGUgYXBwbGljYXRpb25cbiAgICAgKiAtIFwiZm9yY2VEaXNjb25uZWN0QnlTZXJ2ZXJcIjogdGhlIHVzZXIgaGFzIGJlZW4gZXZpY3RlZCBmcm9tIHRoZSBTZXNzaW9uIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJzZXNzaW9uQ2xvc2VkQnlTZXJ2ZXJcIjogdGhlIFNlc3Npb24gaGFzIGJlZW4gY2xvc2VkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICAgICAqIC0gXCJuZXR3b3JrRGlzY29ubmVjdFwiOiB0aGUgdXNlcidzIG5ldHdvcmsgY29ubmVjdGlvbiBoYXMgZHJvcHBlZFxuICAgICAqIC0gXCJub2RlQ3Jhc2hlZFwiOiBhIG5vZGUgaGFzIGNyYXNoZWQgaW4gdGhlIHNlcnZlciBzaWRlXG4gICAgICpcbiAgICAgKiBGb3IgJ3N0cmVhbUNyZWF0ZWQnIGVtcHR5IHN0cmluZ1xuICAgICAqL1xuICAgIHJlYXNvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbmNlbGFibGU6IGJvb2xlYW4sIHRhcmdldDogU2Vzc2lvbiB8IFB1Ymxpc2hlciwgdHlwZTogc3RyaW5nLCBzdHJlYW06IFN0cmVhbSwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoY2FuY2VsYWJsZSwgdGFyZ2V0LCB0eXBlKTtcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgICAgIHRoaXMucmVhc29uID0gcmVhc29uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBoaWRkZW5cbiAgICAgKi9cbiAgICBjYWxsRGVmYXVsdEJlaGF2aW9yKCkge1xuICAgICAgICBpZiAodGhpcy50eXBlID09PSAnc3RyZWFtRGVzdHJveWVkJykge1xuXG4gICAgICAgICAgICBpZiAodGhpcy50YXJnZXQgaW5zdGFuY2VvZiBTZXNzaW9uKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3RlIFN0cmVhbVxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiQ2FsbGluZyBkZWZhdWx0IGJlaGF2aW9yIHVwb24gJ1wiICsgdGhpcy50eXBlICsgXCInIGV2ZW50IGRpc3BhdGNoZWQgYnkgJ1Nlc3Npb24nXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VXZWJSdGNQZWVyKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMudGFyZ2V0IGluc3RhbmNlb2YgUHVibGlzaGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gTG9jYWwgU3RyZWFtXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJDYWxsaW5nIGRlZmF1bHQgYmVoYXZpb3IgdXBvbiAnXCIgKyB0aGlzLnR5cGUgKyBcIicgZXZlbnQgZGlzcGF0Y2hlZCBieSAnUHVibGlzaGVyJ1wiKTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKCg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5zY3JlZW5TaGFyZVJlc2l6ZUludGVydmFsKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbS5pc0xvY2FsU3RyZWFtUmVhZHlUb1B1Ymxpc2ggPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBQdWJsaXNoZXIgb2JqZWN0IGZyb20gT3BlblZpZHUgcHVibGlzaGVycyBhcnJheVxuICAgICAgICAgICAgICAgIGNvbnN0IG9wZW52aWR1UHVibGlzaGVycyA9ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KS5vcGVudmlkdS5wdWJsaXNoZXJzO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlbnZpZHVQdWJsaXNoZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcGVudmlkdVB1Ymxpc2hlcnNbaV0gPT09ICg8UHVibGlzaGVyPnRoaXMudGFyZ2V0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BlbnZpZHVQdWJsaXNoZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEaXNwb3NlIHRoZSBNZWRpYVN0cmVhbSBsb2NhbCBvYmplY3RcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtLmRpc3Bvc2VNZWRpYVN0cmVhbSgpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgZnJvbSBET00gYWxsIHZpZGVvIGVsZW1lbnRzIGFzc29jaWF0ZWQgdG8gdGhpcyBTdHJlYW0sIGlmIHRoZXJlJ3MgYSBTdHJlYW1NYW5hZ2VyIGRlZmluZWRcbiAgICAgICAgICAgIC8vIChtZXRob2QgU2Vzc2lvbi5zdWJzY3JpYmUgbXVzdCBoYXZlIGJlZW4gY2FsbGVkKVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIpIHRoaXMuc3RyZWFtLnN0cmVhbU1hbmFnZXIucmVtb3ZlQWxsVmlkZW9zKCk7XG5cbiAgICAgICAgICAgIC8vIERlbGV0ZSBzdHJlYW0gZnJvbSBTZXNzaW9uLnJlbW90ZVN0cmVhbXNDcmVhdGVkIG1hcFxuICAgICAgICAgICAgdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVTdHJlYW1zQ3JlYXRlZC5kZWxldGUodGhpcy5zdHJlYW0uc3RyZWFtSWQpO1xuXG4gICAgICAgICAgICAvLyBEZWxldGUgU3RyZWFtT3B0aW9uc1NlcnZlciBmcm9tIHJlbW90ZSBDb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCByZW1vdGVDb25uZWN0aW9uID0gdGhpcy5zdHJlYW0uc2Vzc2lvbi5yZW1vdGVDb25uZWN0aW9ucy5nZXQodGhpcy5zdHJlYW0uY29ubmVjdGlvbi5jb25uZWN0aW9uSWQpO1xuICAgICAgICAgICAgaWYgKCEhcmVtb3RlQ29ubmVjdGlvbiAmJiAhIXJlbW90ZUNvbm5lY3Rpb24ucmVtb3RlT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbU9wdGlvbnNTZXJ2ZXIgPSByZW1vdGVDb25uZWN0aW9uLnJlbW90ZU9wdGlvbnMuc3RyZWFtcztcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gc3RyZWFtT3B0aW9uc1NlcnZlci5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZWFtT3B0aW9uc1NlcnZlcltpXS5pZCA9PT0gdGhpcy5zdHJlYW0uc3RyZWFtSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbU9wdGlvbnNTZXJ2ZXIuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuaW1wb3J0IHsgRXZlbnQgfSBmcm9tICcuL0V2ZW50JztcbmltcG9ydCB7IFN0cmVhbU1hbmFnZXIgfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW1NYW5hZ2VyJztcblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnk6XG4gKiAtIFtbc3RyZWFtUGxheWluZ11dXG4gKiAtIFtbc3RyZWFtQXVkaW9Wb2x1bWVDaGFuZ2VdXVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTWFuYWdlckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogRm9yIGBzdHJlYW1BdWRpb1ZvbHVtZUNoYW5nZWAgZXZlbnQ6XG4gICAgICogLSBge25ld1ZhbHVlOiBudW1iZXIsIG9sZFZhbHVlOiBudW1iZXJ9YDogbmV3IGFuZCBvbGQgYXVkaW8gdm9sdW1lIHZhbHVlcy4gVGhlc2UgdmFsdWVzIGFyZSBiZXR3ZWVuIC0xMDAgKHNpbGVuY2UpIGFuZCAwIChsb3VkZXN0IHBvc3NpYmxlIHZvbHVtZSkuXG4gICAgICogVGhleSBhcmUgbm90IGV4YWN0IGFuZCBkZXBlbmQgb24gaG93IHRoZSBicm93c2VyIGlzIG1hbmFnaW5nIHRoZSBhdWRpbyB0cmFjaywgYnV0IC0xMDAgYW5kIDAgY2FuIGJlIHRha2VuIGFzIGxpbWl0IHZhbHVlcy5cbiAgICAgKiBcbiAgICAgKiBGb3IgYHN0cmVhbVBsYXlpbmdgIGV2ZW50IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIHZhbHVlOiBPYmplY3QgfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcsIHZhbHVlOiBPYmplY3QgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTZXNzaW9uIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU2Vzc2lvbic7XG5pbXBvcnQgeyBTdHJlYW0gfSBmcm9tICcuLi8uLi9PcGVuVmlkdS9TdHJlYW0nO1xuaW1wb3J0IHsgU3RyZWFtTWFuYWdlciB9IGZyb20gJy4uLy4uL09wZW5WaWR1L1N0cmVhbU1hbmFnZXInO1xuXG4vKipcbiAqIFRyaWdnZXJlZCBieSBgc3RyZWFtUHJvcGVydHlDaGFuZ2VkYCAoYXZhaWxhYmxlIGZvciBbU2Vzc2lvbl0oL2VuL3N0YWJsZS9hcGkvb3BlbnZpZHUtYnJvd3Nlci9pbnRlcmZhY2VzL1Nlc3Npb25FdmVudE1hcC5odG1sI3N0cmVhbVByb3BlcnR5Q2hhbmdlZCkgYW5kIFtTdHJlYW1NYW5hZ2VyXSgvZW4vc3RhYmxlL2FwaS9vcGVudmlkdS1icm93c2VyL2ludGVyZmFjZXMvU3RyZWFtTWFuYWdlckV2ZW50TWFwLmh0bWwjc3RyZWFtUHJvcGVydHlDaGFuZ2VkKSBvYmplY3RzKVxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtUHJvcGVydHlDaGFuZ2VkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgU3RyZWFtIHdob3NlIHByb3BlcnR5IGhhcyBjaGFuZ2VkLiBZb3UgY2FuIGFsd2F5cyBpZGVudGlmeSB0aGUgdXNlciBwdWJsaXNoaW5nIHRoZSBjaGFuZ2VkIHN0cmVhbSBieSBjb25zdWx0aW5nIHByb3BlcnR5IFtbU3RyZWFtLmNvbm5lY3Rpb25dXVxuICAgICAqL1xuICAgIHN0cmVhbTogU3RyZWFtO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHByb3BlcnR5IG9mIHRoZSBzdHJlYW0gdGhhdCBjaGFuZ2VkLiBUaGlzIHZhbHVlIGlzIGVpdGhlciBgXCJ2aWRlb0FjdGl2ZVwiYCwgYFwiYXVkaW9BY3RpdmVcImAsIGBcInZpZGVvRGltZW5zaW9uc1wiYCBvciBgXCJmaWx0ZXJcImBcbiAgICAgKi9cbiAgICBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENhdXNlIG9mIHRoZSBjaGFuZ2Ugb24gdGhlIHN0cmVhbSdzIHByb3BlcnR5OlxuICAgICAqIC0gRm9yIGB2aWRlb0FjdGl2ZWA6IGBcInB1Ymxpc2hWaWRlb1wiYFxuICAgICAqIC0gRm9yIGBhdWRpb0FjdGl2ZWA6IGBcInB1Ymxpc2hBdWRpb1wiYFxuICAgICAqIC0gRm9yIGB2aWRlb0RpbWVuc2lvbnNgOiBgXCJkZXZpY2VSb3RhdGVkXCJgLCBgXCJzY3JlZW5SZXNpemVkXCJgIG9yIGBcInRyYWNrUmVwbGFjZWRcImBcbiAgICAgKiAtIEZvciBgZmlsdGVyYDogYFwiYXBwbHlGaWx0ZXJcImAsIGBcImV4ZWNGaWx0ZXJNZXRob2RcImAgb3IgYFwicmVtb3ZlRmlsdGVyXCJgXG4gICAgICovXG4gICAgcmVhc29uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBOZXcgdmFsdWUgb2YgdGhlIHByb3BlcnR5IChhZnRlciBjaGFuZ2UsIGN1cnJlbnQgdmFsdWUpXG4gICAgICovXG4gICAgbmV3VmFsdWU6IE9iamVjdDtcblxuICAgIC8qKlxuICAgICAqIFByZXZpb3VzIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSAoYmVmb3JlIGNoYW5nZSlcbiAgICAgKi9cbiAgICBvbGRWYWx1ZTogT2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHRhcmdldDogU2Vzc2lvbiB8IFN0cmVhbU1hbmFnZXIsIHN0cmVhbTogU3RyZWFtLCBjaGFuZ2VkUHJvcGVydHk6IHN0cmluZywgbmV3VmFsdWU6IE9iamVjdCwgb2xkVmFsdWU6IE9iamVjdCwgcmVhc29uOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgJ3N0cmVhbVByb3BlcnR5Q2hhbmdlZCcpO1xuICAgICAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICAgICAgdGhpcy5jaGFuZ2VkUHJvcGVydHkgPSBjaGFuZ2VkUHJvcGVydHk7XG4gICAgICAgIHRoaXMubmV3VmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgdGhpcy5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWVtcHR5XG4gICAgY2FsbERlZmF1bHRCZWhhdmlvcigpIHsgfVxuXG59IiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCB7IEV2ZW50IH0gZnJvbSAnLi9FdmVudCc7XG5pbXBvcnQgeyBTdHJlYW1NYW5hZ2VyIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtTWFuYWdlcic7XG5cblxuLyoqXG4gKiBUcmlnZ2VyZWQgYnk6XG4gKiAtIFtbdmlkZW9FbGVtZW50Q3JlYXRlZF1dXG4gKiAtIFtbdmlkZW9FbGVtZW50RGVzdHJveWVkXV1cbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvRWxlbWVudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuXG4gICAgLyoqXG4gICAgICogVmlkZW8gZWxlbWVudCB0aGF0IHdhcyBjcmVhdGVkIG9yIGRlc3Ryb3llZFxuICAgICAqL1xuICAgIGVsZW1lbnQ6IEhUTUxWaWRlb0VsZW1lbnQ7XG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCwgdGFyZ2V0OiBTdHJlYW1NYW5hZ2VyLCB0eXBlOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoZmFsc2UsIHRhcmdldCwgdHlwZSk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1lbXB0eVxuICAgIGNhbGxEZWZhdWx0QmVoYXZpb3IoKSB7IH1cblxufSIsImZ1bmN0aW9uIE1hcHBlcigpIHtcbiAgdmFyIHNvdXJjZXMgPSB7fTtcblxuXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGtleSBpbiBzb3VyY2VzKSB7XG4gICAgICB2YXIgc291cmNlID0gc291cmNlc1trZXldO1xuXG4gICAgICBmb3IgKHZhciBrZXkyIGluIHNvdXJjZSlcbiAgICAgICAgY2FsbGJhY2soc291cmNlW2tleTJdKTtcbiAgICB9O1xuICB9O1xuXG4gIHRoaXMuZ2V0ID0gZnVuY3Rpb24gKGlkLCBzb3VyY2UpIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmIChpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIHJldHVybiBpZHNbaWRdO1xuICB9O1xuXG4gIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24gKGlkLCBzb3VyY2UpIHtcbiAgICB2YXIgaWRzID0gc291cmNlc1tzb3VyY2VdO1xuICAgIGlmIChpZHMgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuO1xuXG4gICAgZGVsZXRlIGlkc1tpZF07XG5cbiAgICAvLyBDaGVjayBpdCdzIGVtcHR5XG4gICAgZm9yICh2YXIgaSBpbiBpZHMpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIGRlbGV0ZSBzb3VyY2VzW3NvdXJjZV07XG4gIH07XG5cbiAgdGhpcy5zZXQgPSBmdW5jdGlvbiAodmFsdWUsIGlkLCBzb3VyY2UpIHtcbiAgICBpZiAodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlKGlkLCBzb3VyY2UpO1xuXG4gICAgdmFyIGlkcyA9IHNvdXJjZXNbc291cmNlXTtcbiAgICBpZiAoaWRzID09IHVuZGVmaW5lZClcbiAgICAgIHNvdXJjZXNbc291cmNlXSA9IGlkcyA9IHt9O1xuXG4gICAgaWRzW2lkXSA9IHZhbHVlO1xuICB9O1xufTtcblxuXG5NYXBwZXIucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uIChpZCwgc291cmNlKSB7XG4gIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGlkLCBzb3VyY2UpO1xuICBpZiAodmFsdWUgPT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdGhpcy5yZW1vdmUoaWQsIHNvdXJjZSk7XG5cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcHBlcjsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIEpzb25ScGNDbGllbnQgPSByZXF1aXJlKCcuL2pzb25ycGNjbGllbnQnKTtcblxuXG5leHBvcnRzLkpzb25ScGNDbGllbnQgPSBKc29uUnBjQ2xpZW50OyIsIi8qXG4gKiAoQykgQ29weXJpZ2h0IDIwMTQgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG52YXIgUnBjQnVpbGRlciA9IHJlcXVpcmUoJy4uLycpO1xudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3RyYW5zcG9ydHMvd2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbicpO1xudmFyIE9wZW5WaWR1TG9nZ2VyID0gcmVxdWlyZSgnLi4vLi4vLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJykuT3BlblZpZHVMb2dnZXI7XG5cbkRhdGUubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiArbmV3IERhdGU7XG59O1xuXG52YXIgUElOR19JTlRFUlZBTCA9IDUwMDA7XG5cbnZhciBSRUNPTk5FQ1RJTkcgPSAnUkVDT05ORUNUSU5HJztcbnZhciBDT05ORUNURUQgPSAnQ09OTkVDVEVEJztcbnZhciBESVNDT05ORUNURUQgPSAnRElTQ09OTkVDVEVEJztcblxudmFyIExvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG5cbi8qKlxuICpcbiAqIGhlYXJ0YmVhdDogaW50ZXJ2YWwgaW4gbXMgZm9yIGVhY2ggaGVhcnRiZWF0IG1lc3NhZ2UsXG4gKiA8cHJlPlxuICogd3MgOiB7XG4gKiBcdHVyaSA6IFVSSSB0byBjb25udGVjdCB0byxcbiAqIFx0b25jb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gY29ubmVjdGlvbiBpcyBzdWNjZXNzZnVsLFxuICogXHRvbmRpc2Nvbm5lY3QgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgbG9zdCAobWF4IHJldHJpZXMgZm9yIHJlY29ubmVjdGluZyByZWFjaGVkKSxcbiAqIFx0b25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG4gKiBcdG9ucmVjb25uZWN0ZWQgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBzdWNjZXNzZnVsbHkgcmVjb25uZWN0cyxcbiAqIFx0b25lcnJvciA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGVyZSBpcyBhbiBlcnJvclxuICogfSxcbiAqIHJwYyA6IHtcbiAqIFx0cmVxdWVzdFRpbWVvdXQgOiB0aW1lb3V0IGZvciBhIHJlcXVlc3QsXG4gKiBcdHNlc3Npb25TdGF0dXNDaGFuZ2VkOiBjYWxsYmFjayBtZXRob2QgZm9yIGNoYW5nZXMgaW4gc2Vzc2lvbiBzdGF0dXMsXG4gKiBcdG1lZGlhUmVuZWdvdGlhdGlvbjogbWVkaWFSZW5lZ290aWF0aW9uXG4gKiB9XG4gKiA8L3ByZT5cbiAqL1xuZnVuY3Rpb24gSnNvblJwY0NsaWVudChjb25maWd1cmF0aW9uKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgd3NDb25maWcgPSBjb25maWd1cmF0aW9uLndzO1xuXG4gICAgdmFyIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gPSAtMTtcblxuICAgIHZhciBwaW5nTmV4dE51bSA9IDA7XG4gICAgdmFyIGVuYWJsZWRQaW5ncyA9IHRydWU7XG4gICAgdmFyIHBpbmdQb25nU3RhcnRlZCA9IGZhbHNlO1xuICAgIHZhciBwaW5nSW50ZXJ2YWw7XG5cbiAgICB2YXIgc3RhdHVzID0gRElTQ09OTkVDVEVEO1xuXG4gICAgdmFyIG9ucmVjb25uZWN0aW5nID0gd3NDb25maWcub25yZWNvbm5lY3Rpbmc7XG4gICAgdmFyIG9ucmVjb25uZWN0ZWQgPSB3c0NvbmZpZy5vbnJlY29ubmVjdGVkO1xuICAgIHZhciBvbmNvbm5lY3RlZCA9IHdzQ29uZmlnLm9uY29ubmVjdGVkO1xuICAgIHZhciBvbmVycm9yID0gd3NDb25maWcub25lcnJvcjtcblxuICAgIGNvbmZpZ3VyYXRpb24ucnBjLnB1bGwgPSBmdW5jdGlvbiAocGFyYW1zLCByZXF1ZXN0KSB7XG4gICAgICAgIHJlcXVlc3QucmVwbHkobnVsbCwgXCJwdXNoXCIpO1xuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05SRUNPTk5FQ1RJTkcgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IFJFQ09OTkVDVElORykge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gUkVDT05ORUNUSU5HIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OUkVDT05ORUNUSU5HIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RvcFBpbmcoKTtcblxuICAgICAgICBzdGF0dXMgPSBSRUNPTk5FQ1RJTkc7XG4gICAgICAgIGlmIChvbnJlY29ubmVjdGluZykge1xuICAgICAgICAgICAgb25yZWNvbm5lY3RpbmcoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9ucmVjb25uZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIi0tLS0tLS0tLSBPTlJFQ09OTkVDVEVEIC0tLS0tLS0tLS0tXCIpO1xuICAgICAgICBpZiAoc3RhdHVzID09PSBDT05ORUNURUQpIHtcbiAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIldlYnNvY2tldCBhbHJlYWR5IGluIENPTk5FQ1RFRCBzdGF0ZSB3aGVuIHJlY2VpdmluZyBhIG5ldyBPTlJFQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCk7XG5cbiAgICAgICAgaWYgKG9ucmVjb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIG9ucmVjb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdzQ29uZmlnLm9uY29ubmVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05DT05ORUNURUQgLS0tLS0tLS0tLS1cIik7XG4gICAgICAgIGlmIChzdGF0dXMgPT09IENPTk5FQ1RFRCkge1xuICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiV2Vic29ja2V0IGFscmVhZHkgaW4gQ09OTkVDVEVEIHN0YXRlIHdoZW4gcmVjZWl2aW5nIGEgbmV3IE9OQ09OTkVDVEVEIG1lc3NhZ2UuIElnbm9yaW5nIGl0XCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0YXR1cyA9IENPTk5FQ1RFRDtcblxuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICB1c2VQaW5nKCk7XG5cbiAgICAgICAgaWYgKG9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBvbmNvbm5lY3RlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgd3NDb25maWcub25lcnJvciA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCItLS0tLS0tLS0gT05FUlJPUiAtLS0tLS0tLS0tLVwiKTtcblxuICAgICAgICBzdGF0dXMgPSBESVNDT05ORUNURUQ7XG5cbiAgICAgICAgc3RvcFBpbmcoKTtcblxuICAgICAgICBpZiAob25lcnJvcikge1xuICAgICAgICAgICAgb25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgd3MgPSBuZXcgV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbih3c0NvbmZpZyk7XG5cbiAgICBMb2dnZXIuZGVidWcoJ0Nvbm5lY3Rpbmcgd2Vic29ja2V0IHRvIFVSSTogJyArIHdzQ29uZmlnLnVyaSk7XG5cbiAgICB2YXIgcnBjQnVpbGRlck9wdGlvbnMgPSB7XG4gICAgICAgIHJlcXVlc3RfdGltZW91dDogY29uZmlndXJhdGlvbi5ycGMucmVxdWVzdFRpbWVvdXQsXG4gICAgICAgIHBpbmdfcmVxdWVzdF90aW1lb3V0OiBjb25maWd1cmF0aW9uLnJwYy5oZWFydGJlYXRSZXF1ZXN0VGltZW91dFxuICAgIH07XG5cbiAgICB2YXIgcnBjID0gbmV3IFJwY0J1aWxkZXIoUnBjQnVpbGRlci5wYWNrZXJzLkpzb25SUEMsIHJwY0J1aWxkZXJPcHRpb25zLCB3cyxcbiAgICAgICAgZnVuY3Rpb24gKHJlcXVlc3QpIHtcblxuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKCdSZWNlaXZlZCByZXF1ZXN0OiAnICsgSlNPTi5zdHJpbmdpZnkocmVxdWVzdCkpO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jID0gY29uZmlndXJhdGlvbi5ycGNbcmVxdWVzdC5tZXRob2RdO1xuXG4gICAgICAgICAgICAgICAgaWYgKGZ1bmMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoXCJNZXRob2QgXCIgKyByZXF1ZXN0Lm1ldGhvZCArIFwiIG5vdCByZWdpc3RlcmVkIGluIGNsaWVudFwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmdW5jKHJlcXVlc3QucGFyYW1zLCByZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuZXJyb3IoJ0V4Y2VwdGlvbiBwcm9jZXNzaW5nIHJlcXVlc3Q6ICcgKyBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdGhpcy5zZW5kID0gZnVuY3Rpb24gKG1ldGhvZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuXG4gICAgICAgIHZhciByZXF1ZXN0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgcnBjLmVuY29kZShtZXRob2QsIHBhcmFtcywgZnVuY3Rpb24gKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SOlwiICsgZXJyb3IubWVzc2FnZSArIFwiIGluIFJlcXVlc3Q6IG1ldGhvZDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgKyBcIiBwYXJhbXM6XCIgKyBKU09OLnN0cmluZ2lmeShwYXJhbXMpICsgXCIgcmVxdWVzdDpcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5yZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5lcnJvcihcIkVSUk9SIERBVEE6XCIgKyBKU09OLnN0cmluZ2lmeShlcnJvci5kYXRhKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICAgICAgICAgIGVycm9yLnJlcXVlc3RUaW1lID0gcmVxdWVzdFRpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9IHVuZGVmaW5lZCAmJiByZXN1bHQudmFsdWUgIT09ICdwb25nJykge1xuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoJ1Jlc3BvbnNlOiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVOb3RSZWNvbm5lY3RJZkxlc3NUaGFuKCkge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gXCIgKyBwaW5nTmV4dE51bSArICcgKG9sZD0nICtcbiAgICAgICAgICAgIG5vdFJlY29ubmVjdElmTnVtTGVzc1RoYW4gKyAnKScpO1xuICAgICAgICBub3RSZWNvbm5lY3RJZk51bUxlc3NUaGFuID0gcGluZ05leHROdW07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VuZFBpbmcoKSB7XG4gICAgICAgIGlmIChlbmFibGVkUGluZ3MpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbmdOZXh0TnVtID09IDAgfHwgcGluZ05leHROdW0gPT0gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IGNvbmZpZ3VyYXRpb24uaGVhcnRiZWF0IHx8IFBJTkdfSU5URVJWQUxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGluZ05leHROdW0rKztcblxuICAgICAgICAgICAgc2VsZi5zZW5kKCdwaW5nJywgcGFyYW1zLCAoZnVuY3Rpb24gKHBpbmdOdW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGVycm9yLCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJFcnJvciBpbiBwaW5nIHJlcXVlc3QgI1wiICsgcGluZ051bSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IubWVzc2FnZSArIFwiKVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwaW5nTnVtID4gbm90UmVjb25uZWN0SWZOdW1MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vdFJlY29ubmVjdElmTGVzc1RoYW4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJTZXJ2ZXIgZGlkIG5vdCByZXNwb25kIHRvIHBpbmcgbWVzc2FnZSAjXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaW5nTnVtICsgXCIuIFJlY29ubmVjdGluZy4uLiBcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd3MucmVjb25uZWN0V3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKHBpbmdOZXh0TnVtKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuZGVidWcoXCJUcnlpbmcgdG8gc2VuZCBwaW5nLCBidXQgcGluZyBpcyBub3QgZW5hYmxlZFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogSWYgY29uZmlndXJhdGlvbi5oZWFyYmVhdCBoYXMgYW55IHZhbHVlLCB0aGUgcGluZy1wb25nIHdpbGwgd29yayB3aXRoIHRoZSBpbnRlcnZhbFxuICAgICAqIG9mIGNvbmZpZ3VyYXRpb24uaGVhcmJlYXRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1c2VQaW5nKCkge1xuICAgICAgICBpZiAoIXBpbmdQb25nU3RhcnRlZCkge1xuICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiU3RhcnRpbmcgcGluZyAoaWYgY29uZmlndXJlZClcIilcbiAgICAgICAgICAgIHBpbmdQb25nU3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLmhlYXJ0YmVhdCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwaW5nSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChzZW5kUGluZywgY29uZmlndXJhdGlvbi5oZWFydGJlYXQpO1xuICAgICAgICAgICAgICAgIHNlbmRQaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdG9wUGluZygpIHtcbiAgICAgICAgY2xlYXJJbnRlcnZhbChwaW5nSW50ZXJ2YWwpO1xuICAgICAgICBwaW5nUG9uZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgZW5hYmxlZFBpbmdzID0gZmFsc2U7XG4gICAgICAgIHBpbmdOZXh0TnVtID0gLTE7XG4gICAgICAgIHJwYy5jYW5jZWwoKTtcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlID0gZnVuY3Rpb24gKGNvZGUsIHJlYXNvbikge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJDbG9zaW5nICB3aXRoIGNvZGU6IFwiICsgY29kZSArIFwiIGJlY2F1c2U6IFwiICsgcmVhc29uKTtcbiAgICAgICAgaWYgKHBpbmdJbnRlcnZhbCAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsZWFyaW5nIHBpbmcgaW50ZXJ2YWxcIik7XG4gICAgICAgICAgICBjbGVhckludGVydmFsKHBpbmdJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcGluZ1BvbmdTdGFydGVkID0gZmFsc2U7XG4gICAgICAgIGVuYWJsZWRQaW5ncyA9IGZhbHNlO1xuICAgICAgICB3cy5jbG9zZShjb2RlLCByZWFzb24pO1xuICAgIH1cblxuICAgIHRoaXMucmVjb25uZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB3cy5yZWNvbm5lY3RXcygpO1xuICAgIH1cblxuICAgIHRoaXMucmVzZXRQaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBlbmFibGVkUGluZ3MgPSB0cnVlO1xuICAgICAgICBwaW5nTmV4dE51bSA9IDA7XG4gICAgICAgIHVzZVBpbmcoKTtcbiAgICB9XG5cbiAgICB0aGlzLmdldFJlYWR5U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB3cy5nZXRSZWFkeVN0YXRlKCk7XG4gICAgfVxufVxuXG5cbm1vZHVsZS5leHBvcnRzID0gSnNvblJwY0NsaWVudDsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxudmFyIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24gPSByZXF1aXJlKCcuL3dlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24nKTtcblxuZXhwb3J0cy5XZWJTb2NrZXRXaXRoUmVjb25uZWN0aW9uID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDEzLTIwMTUgS3VyZW50byAoaHR0cDovL2t1cmVudG8ub3JnLylcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIE9wZW5WaWR1TG9nZ2VyID0gcmVxdWlyZSgnLi4vLi4vLi4vLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJykuT3BlblZpZHVMb2dnZXI7XG52YXIgTG9nZ2VyID0gT3BlblZpZHVMb2dnZXIuZ2V0SW5zdGFuY2UoKTtcblxudmFyIE1BWF9SRVRSSUVTID0gMjAwMDsgLy8gRm9yZXZlci4uLlxudmFyIFJFVFJZX1RJTUVfTVMgPSAzMDAwOyAvLyBGSVhNRTogSW1wbGVtZW50IGV4cG9uZW50aWFsIHdhaXQgdGltZXMuLi5cblxudmFyIENPTk5FQ1RJTkcgPSAwO1xudmFyIE9QRU4gPSAxO1xudmFyIENMT1NJTkcgPSAyO1xudmFyIENMT1NFRCA9IDM7XG5cbi8qXG5jb25maWcgPSB7XG51cmkgOiB3c1VyaSxcbm9uY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIGNvbm5lY3Rpb24gaXMgc3VjY2Vzc2Z1bCxcbm9uZGlzY29ubmVjdCA6IGNhbGxiYWNrIG1ldGhvZCB0byBpbnZva2Ugd2hlbiB0aGUgY29ubmVjdGlvbiBpcyBsb3N0IChtYXggcmV0cmllcyBmb3IgcmVjb25uZWN0aW5nIHJlYWNoZWQpLFxub25yZWNvbm5lY3RpbmcgOiBjYWxsYmFjayBtZXRob2QgdG8gaW52b2tlIHdoZW4gdGhlIGNsaWVudCBpcyByZWNvbm5lY3RpbmcsXG5vbnJlY29ubmVjdGVkIDogY2FsbGJhY2sgbWV0aG9kIHRvIGludm9rZSB3aGVuIHRoZSBjbGllbnQgc3VjY2Vzc2Z1bGx5IHJlY29ubmVjdHMsXG59O1xuKi9cbmZ1bmN0aW9uIFdlYlNvY2tldFdpdGhSZWNvbm5lY3Rpb24oY29uZmlnKSB7XG4gICAgdmFyIGNsb3NpbmcgPSBmYWxzZTtcbiAgICB2YXIgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcjtcbiAgICB2YXIgd3NVcmkgPSBjb25maWcudXJpO1xuICAgIHZhciByZWNvbm5lY3RpbmcgPSBmYWxzZTtcblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuXG4gICAgd3Mub25vcGVuID0gKCkgPT4ge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJXZWJTb2NrZXQgY29ubmVjdGVkIHRvIFwiICsgd3NVcmkpO1xuICAgICAgICBpZiAoY29uZmlnLm9uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICBjb25maWcub25jb25uZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmVycm9yID0gZXJyb3IgPT4ge1xuICAgICAgICBMb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICBcIkNvdWxkIG5vdCBjb25uZWN0IHRvIFwiICsgd3NVcmkgKyBcIiAoaW52b2tpbmcgb25lcnJvciBpZiBkZWZpbmVkKVwiLFxuICAgICAgICAgICAgZXJyb3JcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNvbmZpZy5vbmVycm9yKSB7XG4gICAgICAgICAgICBjb25maWcub25lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFyIHJlY29ubmVjdGlvbk9uQ2xvc2UgPSAoKSA9PiB7XG4gICAgICAgIGlmICh3cy5yZWFkeVN0YXRlID09PSBDTE9TRUQpIHtcbiAgICAgICAgICAgIGlmIChjbG9zaW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLmRlYnVnKFwiQ29ubmVjdGlvbiBjbG9zZWQgYnkgdXNlclwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZpZy5pc21hc3Rlcm5vZGVjcmFzaGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLmVycm9yKFwiTWFzdGVyIE5vZGUgaGFzIGNyYXNoZWQuIFN0b3BwaW5nIHJlY29ubmVjdGlvbiBwcm9jZXNzXCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNvbm5lY3Rpb24gY2xvc2VkIHVuZXhwZWN0ZWRseS4gUmVjb25uZWN0aW5nLi4uXCIpO1xuICAgICAgICAgICAgICAgICAgICByZWNvbm5lY3QoTUFYX1JFVFJJRVMsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcIkNsb3NlIGNhbGxiYWNrIGZyb20gcHJldmlvdXMgd2Vic29ja2V0LiBJZ25vcmluZyBpdFwiKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdChtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgIFwicmVjb25uZWN0IChhdHRlbXB0ICNcIiArIG51bVJldHJpZXMgKyBcIiwgbWF4PVwiICsgbWF4UmV0cmllcyArIFwiKVwiXG4gICAgICAgICk7XG4gICAgICAgIGlmIChudW1SZXRyaWVzID09PSAxKSB7XG4gICAgICAgICAgICBpZiAocmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgICAgICAgIFwiVHJ5aW5nIHRvIHJlY29ubmVjdCB3aGVuIGFscmVhZHkgcmVjb25uZWN0aW5nLi4uIElnbm9yaW5nIHRoaXMgcmVjb25uZWN0aW9uLlwiXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29uZmlnLm9ucmVjb25uZWN0aW5nKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLm9ucmVjb25uZWN0aW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVjb25uZWN0QXV4KG1heFJldHJpZXMsIG51bVJldHJpZXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFJlY29ubmVjdGlvblF1ZXJ5UGFyYW1zSWZNaXNzaW5nKHVyaVN0cmluZykge1xuICAgICAgICB2YXIgc2VhcmNoUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcygobmV3IFVSTCh1cmlTdHJpbmcpKS5zZWFyY2gpO1xuICAgICAgICBpZiAoIXNlYXJjaFBhcmFtcy5oYXMoXCJyZWNvbm5lY3RcIikpIHtcbiAgICAgICAgICAgIHVyaVN0cmluZyA9IChBcnJheS5mcm9tKHNlYXJjaFBhcmFtcykubGVuZ3RoID4gMCkgPyAodXJpU3RyaW5nICsgJyZyZWNvbm5lY3Q9dHJ1ZScpIDogKHVyaVN0cmluZyArICc/cmVjb25uZWN0PXRydWUnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXJpU3RyaW5nO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlY29ubmVjdEF1eChtYXhSZXRyaWVzLCBudW1SZXRyaWVzKSB7XG4gICAgICAgIExvZ2dlci5kZWJ1ZyhcIlJlY29ubmVjdGlvbiBhdHRlbXB0ICNcIiArIG51bVJldHJpZXMpO1xuICAgICAgICB3cy5jbG9zZSg0MTA0LCAnQ29ubmVjdGlvbiBjbG9zZWQgZm9yIHJlY29ubmVjdGlvbicpO1xuXG4gICAgICAgIHdzVXJpID0gYWRkUmVjb25uZWN0aW9uUXVlcnlQYXJhbXNJZk1pc3Npbmcod3NVcmkpO1xuICAgICAgICB3cyA9IG5ldyBXZWJTb2NrZXQod3NVcmkpO1xuXG4gICAgICAgIHdzLm9ub3BlbiA9ICgpID0+IHtcbiAgICAgICAgICAgIExvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICBcIlJlY29ubmVjdGVkIHRvIFwiICsgd3NVcmkgKyBcIiBhZnRlciBcIiArIG51bVJldHJpZXMgKyBcIiBhdHRlbXB0cy4uLlwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmVjb25uZWN0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKCk7XG4gICAgICAgICAgICBpZiAoY29uZmlnLm9ucmVjb25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5vbnJlY29ubmVjdGVkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3cy5vbmNsb3NlID0gcmVjb25uZWN0aW9uT25DbG9zZTtcbiAgICAgICAgfTtcblxuICAgICAgICB3cy5vbmVycm9yID0gZXJyb3IgPT4ge1xuICAgICAgICAgICAgTG9nZ2VyLndhcm4oXCJSZWNvbm5lY3Rpb24gZXJyb3I6IFwiLCBlcnJvcik7XG4gICAgICAgICAgICBpZiAobnVtUmV0cmllcyA9PT0gbWF4UmV0cmllcykge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcub25kaXNjb25uZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5vbmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWNvbm5lY3QobWF4UmV0cmllcywgbnVtUmV0cmllcyArIDEpO1xuICAgICAgICAgICAgICAgIH0sIFJFVFJZX1RJTUVfTVMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHRoaXMuY2xvc2UgPSAoY29kZSwgcmVhc29uKSA9PiB7XG4gICAgICAgIGNsb3NpbmcgPSB0cnVlO1xuICAgICAgICB3cy5jbG9zZShjb2RlLCByZWFzb24pO1xuICAgIH07XG5cbiAgICB0aGlzLnJlY29ubmVjdFdzID0gKCkgPT4ge1xuICAgICAgICBMb2dnZXIuZGVidWcoXCJyZWNvbm5lY3RXc1wiKTtcbiAgICAgICAgcmVjb25uZWN0KE1BWF9SRVRSSUVTLCAxKTtcbiAgICB9O1xuXG4gICAgdGhpcy5zZW5kID0gbWVzc2FnZSA9PiB7XG4gICAgICAgIHdzLnNlbmQobWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lciA9ICh0eXBlLCBjYWxsYmFjaykgPT4ge1xuICAgICAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgd3MuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG4gICAgICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5nZXRSZWFkeVN0YXRlID0gKCkgPT4ge1xuICAgICAgICByZXR1cm4gd3MucmVhZHlTdGF0ZTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gV2ViU29ja2V0V2l0aFJlY29ubmVjdGlvbjsiLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE0IEt1cmVudG8gKGh0dHA6Ly9rdXJlbnRvLm9yZy8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuXG52YXIgZGVmaW5lUHJvcGVydHlfSUU4ID0gZmFsc2VcbmlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHtcbiAgdHJ5IHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIFwieFwiLCB7fSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBkZWZpbmVQcm9wZXJ0eV9JRTggPSB0cnVlXG4gIH1cbn1cblxuLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZFxuaWYgKCFGdW5jdGlvbi5wcm90b3R5cGUuYmluZCkge1xuICBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChvVGhpcykge1xuICAgIGlmICh0eXBlb2YgdGhpcyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gY2xvc2VzdCB0aGluZyBwb3NzaWJsZSB0byB0aGUgRUNNQVNjcmlwdCA1XG4gICAgICAvLyBpbnRlcm5hbCBJc0NhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGdW5jdGlvbi5wcm90b3R5cGUuYmluZCAtIHdoYXQgaXMgdHJ5aW5nIHRvIGJlIGJvdW5kIGlzIG5vdCBjYWxsYWJsZScpO1xuICAgIH1cblxuICAgIHZhciBhQXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXG4gICAgICBmVG9CaW5kID0gdGhpcyxcbiAgICAgIGZOT1AgPSBmdW5jdGlvbiAoKSB7fSxcbiAgICAgIGZCb3VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZUb0JpbmQuYXBwbHkodGhpcyBpbnN0YW5jZW9mIGZOT1AgJiYgb1RoaXMgP1xuICAgICAgICAgIHRoaXMgOlxuICAgICAgICAgIG9UaGlzLFxuICAgICAgICAgIGFBcmdzLmNvbmNhdChBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICB9O1xuXG4gICAgZk5PUC5wcm90b3R5cGUgPSB0aGlzLnByb3RvdHlwZTtcbiAgICBmQm91bmQucHJvdG90eXBlID0gbmV3IGZOT1AoKTtcblxuICAgIHJldHVybiBmQm91bmQ7XG4gIH07XG59XG5cblxudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcjtcblxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKTtcblxudmFyIHBhY2tlcnMgPSByZXF1aXJlKCcuL3BhY2tlcnMnKTtcbnZhciBNYXBwZXIgPSByZXF1aXJlKCcuL01hcHBlcicpO1xuXG5cbnZhciBCQVNFX1RJTUVPVVQgPSA1MDAwO1xuXG5cbmZ1bmN0aW9uIHVuaWZ5UmVzcG9uc2VNZXRob2RzKHJlc3BvbnNlTWV0aG9kcykge1xuICBpZiAoIXJlc3BvbnNlTWV0aG9kcykgcmV0dXJuIHt9O1xuXG4gIGZvciAodmFyIGtleSBpbiByZXNwb25zZU1ldGhvZHMpIHtcbiAgICB2YXIgdmFsdWUgPSByZXNwb25zZU1ldGhvZHNba2V5XTtcblxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycpXG4gICAgICByZXNwb25zZU1ldGhvZHNba2V5XSA9IHtcbiAgICAgICAgcmVzcG9uc2U6IHZhbHVlXG4gICAgICB9XG4gIH07XG5cbiAgcmV0dXJuIHJlc3BvbnNlTWV0aG9kcztcbn07XG5cbmZ1bmN0aW9uIHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCkge1xuICBpZiAoIXRyYW5zcG9ydCkgcmV0dXJuO1xuXG4gIC8vIFRyYW5zcG9ydCBhcyBhIGZ1bmN0aW9uXG4gIGlmICh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4ge1xuICAgICAgc2VuZDogdHJhbnNwb3J0XG4gICAgfTtcblxuICAvLyBXZWJTb2NrZXQgJiBEYXRhQ2hhbm5lbFxuICBpZiAodHJhbnNwb3J0LnNlbmQgaW5zdGFuY2VvZiBGdW5jdGlvbilcbiAgICByZXR1cm4gdHJhbnNwb3J0O1xuXG4gIC8vIE1lc3NhZ2UgQVBJIChJbnRlci13aW5kb3cgJiBXZWJXb3JrZXIpXG4gIGlmICh0cmFuc3BvcnQucG9zdE1lc3NhZ2UgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LnBvc3RNZXNzYWdlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBTdHJlYW0gQVBJXG4gIGlmICh0cmFuc3BvcnQud3JpdGUgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHRyYW5zcG9ydC5zZW5kID0gdHJhbnNwb3J0LndyaXRlO1xuICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gIH1cblxuICAvLyBUcmFuc3BvcnRzIHRoYXQgb25seSBjYW4gcmVjZWl2ZSBtZXNzYWdlcywgYnV0IG5vdCBzZW5kXG4gIGlmICh0cmFuc3BvcnQub25tZXNzYWdlICE9PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYgKHRyYW5zcG9ydC5wYXVzZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSByZXR1cm47XG5cbiAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVHJhbnNwb3J0IGlzIG5vdCBhIGZ1bmN0aW9uIG5vciBhIHZhbGlkIG9iamVjdFwiKTtcbn07XG5cblxuLyoqXG4gKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyBub3RpZmljYXRpb25cbiAqXG4gKiBAY2xhc3NcbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kIC1tZXRob2Qgb2YgdGhlIG5vdGlmaWNhdGlvblxuICogQHBhcmFtIHBhcmFtcyAtIHBhcmFtZXRlcnMgb2YgdGhlIG5vdGlmaWNhdGlvblxuICovXG5mdW5jdGlvbiBScGNOb3RpZmljYXRpb24obWV0aG9kLCBwYXJhbXMpIHtcbiAgaWYgKGRlZmluZVByb3BlcnR5X0lFOCkge1xuICAgIHRoaXMubWV0aG9kID0gbWV0aG9kXG4gICAgdGhpcy5wYXJhbXMgPSBwYXJhbXNcbiAgfSBlbHNlIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ21ldGhvZCcsIHtcbiAgICAgIHZhbHVlOiBtZXRob2QsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwYXJhbXMnLCB7XG4gICAgICB2YWx1ZTogcGFyYW1zLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH0pO1xuICB9XG59O1xuXG5cbi8qKlxuICogQGNsYXNzXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHBhY2tlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0aW9uc11cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gW3RyYW5zcG9ydF1cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb25SZXF1ZXN0XVxuICovXG5mdW5jdGlvbiBScGNCdWlsZGVyKHBhY2tlciwgb3B0aW9ucywgdHJhbnNwb3J0LCBvblJlcXVlc3QpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmICghcGFja2VyKVxuICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignUGFja2VyIGlzIG5vdCBkZWZpbmVkJyk7XG5cbiAgaWYgKCFwYWNrZXIucGFjayB8fCAhcGFja2VyLnVucGFjaylcbiAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhY2tlciBpcyBpbnZhbGlkJyk7XG5cbiAgdmFyIHJlc3BvbnNlTWV0aG9kcyA9IHVuaWZ5UmVzcG9uc2VNZXRob2RzKHBhY2tlci5yZXNwb25zZU1ldGhvZHMpO1xuXG5cbiAgaWYgKG9wdGlvbnMgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGlmICh0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBvblJlcXVlc3RcIik7XG5cbiAgICBvblJlcXVlc3QgPSBvcHRpb25zO1xuICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICBvcHRpb25zID0gdW5kZWZpbmVkO1xuICB9O1xuXG4gIGlmIChvcHRpb25zICYmIG9wdGlvbnMuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgaWYgKHRyYW5zcG9ydCAmJiAhKHRyYW5zcG9ydCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gdHJhbnNwb3J0O1xuICAgIHRyYW5zcG9ydCA9IG9wdGlvbnM7XG4gICAgb3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZiAodHJhbnNwb3J0IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICBpZiAob25SZXF1ZXN0ICE9IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgb25SZXF1ZXN0XCIpO1xuXG4gICAgb25SZXF1ZXN0ID0gdHJhbnNwb3J0O1xuICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgfTtcblxuICBpZiAodHJhbnNwb3J0ICYmIHRyYW5zcG9ydC5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pXG4gICAgaWYgKG9uUmVxdWVzdCAmJiAhKG9uUmVxdWVzdCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSlcbiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIk9ubHkgYSBmdW5jdGlvbiBjYW4gYmUgYWZ0ZXIgdHJhbnNwb3J0XCIpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cbiAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG5cbiAgaWYgKG9uUmVxdWVzdClcbiAgICB0aGlzLm9uKCdyZXF1ZXN0Jywgb25SZXF1ZXN0KTtcblxuXG4gIGlmIChkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgdGhpcy5wZWVySUQgPSBvcHRpb25zLnBlZXJJRFxuICBlbHNlXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdwZWVySUQnLCB7XG4gICAgICB2YWx1ZTogb3B0aW9ucy5wZWVySURcbiAgICB9KTtcblxuICB2YXIgbWF4X3JldHJpZXMgPSBvcHRpb25zLm1heF9yZXRyaWVzIHx8IDA7XG5cblxuICBmdW5jdGlvbiB0cmFuc3BvcnRNZXNzYWdlKGV2ZW50KSB7XG4gICAgc2VsZi5kZWNvZGUoZXZlbnQuZGF0YSB8fCBldmVudCk7XG4gIH07XG5cbiAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgfVxuICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIC8vIFJlbW92ZSBsaXN0ZW5lciBmcm9tIG9sZCB0cmFuc3BvcnRcbiAgICBpZiAodHJhbnNwb3J0KSB7XG4gICAgICAvLyBXM0MgdHJhbnNwb3J0c1xuICAgICAgaWYgKHRyYW5zcG9ydC5yZW1vdmVFdmVudExpc3RlbmVyKVxuICAgICAgICB0cmFuc3BvcnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuXG4gICAgICAvLyBOb2RlLmpzIFN0cmVhbXMgQVBJXG4gICAgICBlbHNlIGlmICh0cmFuc3BvcnQucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgIHRyYW5zcG9ydC5yZW1vdmVMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBTZXQgbGlzdGVuZXIgb24gbmV3IHRyYW5zcG9ydFxuICAgIGlmICh2YWx1ZSkge1xuICAgICAgLy8gVzNDIHRyYW5zcG9ydHNcbiAgICAgIGlmICh2YWx1ZS5hZGRFdmVudExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdHJhbnNwb3J0TWVzc2FnZSk7XG5cbiAgICAgIC8vIE5vZGUuanMgU3RyZWFtcyBBUElcbiAgICAgIGVsc2UgaWYgKHZhbHVlLmFkZExpc3RlbmVyKVxuICAgICAgICB2YWx1ZS5hZGRMaXN0ZW5lcignZGF0YScsIHRyYW5zcG9ydE1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh2YWx1ZSk7XG4gIH1cblxuICBpZiAoIWRlZmluZVByb3BlcnR5X0lFOClcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ3RyYW5zcG9ydCcsIHtcbiAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgIHNldDogdGhpcy5zZXRUcmFuc3BvcnQuYmluZCh0aGlzKVxuICAgIH0pXG5cbiAgdGhpcy5zZXRUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuXG4gIHZhciByZXF1ZXN0X3RpbWVvdXQgPSBvcHRpb25zLnJlcXVlc3RfdGltZW91dCB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBwaW5nX3JlcXVlc3RfdGltZW91dCA9IG9wdGlvbnMucGluZ19yZXF1ZXN0X3RpbWVvdXQgfHwgcmVxdWVzdF90aW1lb3V0O1xuICB2YXIgcmVzcG9uc2VfdGltZW91dCA9IG9wdGlvbnMucmVzcG9uc2VfdGltZW91dCB8fCBCQVNFX1RJTUVPVVQ7XG4gIHZhciBkdXBsaWNhdGVzX3RpbWVvdXQgPSBvcHRpb25zLmR1cGxpY2F0ZXNfdGltZW91dCB8fCBCQVNFX1RJTUVPVVQ7XG5cblxuICB2YXIgcmVxdWVzdElEID0gMDtcblxuICB2YXIgcmVxdWVzdHMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciByZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG4gIHZhciBwcm9jZXNzZWRSZXNwb25zZXMgPSBuZXcgTWFwcGVyKCk7XG5cbiAgdmFyIG1lc3NhZ2UyS2V5ID0ge307XG5cblxuICAvKipcbiAgICogU3RvcmUgdGhlIHJlc3BvbnNlIHRvIHByZXZlbnQgdG8gcHJvY2VzcyBkdXBsaWNhdGUgcmVxdWVzdCBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVSZXNwb25zZShtZXNzYWdlLCBpZCwgZGVzdCkge1xuICAgIHZhciByZXNwb25zZSA9IHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAvKiogVGltZW91dCB0byBhdXRvLWNsZWFuIG9sZCByZXNwb25zZXMgKi9cbiAgICAgIHRpbWVvdXQ6IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJlc3BvbnNlcy5yZW1vdmUoaWQsIGRlc3QpO1xuICAgICAgICB9LFxuICAgICAgICByZXNwb25zZV90aW1lb3V0KVxuICAgIH07XG5cbiAgICByZXNwb25zZXMuc2V0KHJlc3BvbnNlLCBpZCwgZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFN0b3JlIHRoZSByZXNwb25zZSB0byBpZ25vcmUgZHVwbGljYXRlZCBtZXNzYWdlcyBsYXRlclxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmVQcm9jZXNzZWRSZXNwb25zZShhY2ssIGZyb20pIHtcbiAgICB2YXIgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBwcm9jZXNzZWRSZXNwb25zZXMucmVtb3ZlKGFjaywgZnJvbSk7XG4gICAgICB9LFxuICAgICAgZHVwbGljYXRlc190aW1lb3V0KTtcblxuICAgIHByb2Nlc3NlZFJlc3BvbnNlcy5zZXQodGltZW91dCwgYWNrLCBmcm9tKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRhdGlvbiBvZiBhIFJQQyByZXF1ZXN0XG4gICAqXG4gICAqIEBjbGFzc1xuICAgKiBAZXh0ZW5kcyBScGNOb3RpZmljYXRpb25cbiAgICpcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpZCAtIGlkZW50aWZpZXIgb2YgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIFtmcm9tXSAtIHNvdXJjZSBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqL1xuICBmdW5jdGlvbiBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZCwgZnJvbSwgdHJhbnNwb3J0KSB7XG4gICAgUnBjTm90aWZpY2F0aW9uLmNhbGwodGhpcywgbWV0aG9kLCBwYXJhbXMpO1xuXG4gICAgdGhpcy5nZXRUcmFuc3BvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdHJhbnNwb3J0O1xuICAgIH1cbiAgICB0aGlzLnNldFRyYW5zcG9ydCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodmFsdWUpO1xuICAgIH1cblxuICAgIGlmICghZGVmaW5lUHJvcGVydHlfSUU4KVxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICd0cmFuc3BvcnQnLCB7XG4gICAgICAgIGdldDogdGhpcy5nZXRUcmFuc3BvcnQuYmluZCh0aGlzKSxcbiAgICAgICAgc2V0OiB0aGlzLnNldFRyYW5zcG9ydC5iaW5kKHRoaXMpXG4gICAgICB9KVxuXG4gICAgdmFyIHJlc3BvbnNlID0gcmVzcG9uc2VzLmdldChpZCwgZnJvbSk7XG5cbiAgICAvKipcbiAgICAgKiBAY29uc3RhbnQge0Jvb2xlYW59IGR1cGxpY2F0ZWRcbiAgICAgKi9cbiAgICBpZiAoISh0cmFuc3BvcnQgfHwgc2VsZi5nZXRUcmFuc3BvcnQoKSkpIHtcbiAgICAgIGlmIChkZWZpbmVQcm9wZXJ0eV9JRTgpXG4gICAgICAgIHRoaXMuZHVwbGljYXRlZCA9IEJvb2xlYW4ocmVzcG9uc2UpXG4gICAgICBlbHNlXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnZHVwbGljYXRlZCcsIHtcbiAgICAgICAgICB2YWx1ZTogQm9vbGVhbihyZXNwb25zZSlcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlTWV0aG9kID0gcmVzcG9uc2VNZXRob2RzW21ldGhvZF07XG5cbiAgICB0aGlzLnBhY2sgPSBwYWNrZXIucGFjay5iaW5kKHBhY2tlciwgdGhpcywgaWQpXG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtFcnJvcn0gW2Vycm9yXVxuICAgICAqIEBwYXJhbSB7Kn0gW3Jlc3VsdF1cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5yZXBseSA9IGZ1bmN0aW9uIChlcnJvciwgcmVzdWx0LCB0cmFuc3BvcnQpIHtcbiAgICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBlcnJvciAmJiBlcnJvci5zZW5kIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgaWYgKHJlc3VsdCAhPSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgICB0cmFuc3BvcnQgPSBlcnJvcjtcbiAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgZXJyb3IgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8XG4gICAgICAgIHJlc3VsdCAmJiByZXN1bHQuc2VuZCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgIGlmICh0cmFuc3BvcnQgIT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgICAgdHJhbnNwb3J0ID0gcmVzdWx0O1xuICAgICAgICByZXN1bHQgPSBudWxsO1xuICAgICAgfTtcblxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KTtcblxuICAgICAgLy8gRHVwbGljYXRlZCByZXF1ZXN0LCByZW1vdmUgb2xkIHJlc3BvbnNlIHRpbWVvdXRcbiAgICAgIGlmIChyZXNwb25zZSlcbiAgICAgICAgY2xlYXJUaW1lb3V0KHJlc3BvbnNlLnRpbWVvdXQpO1xuXG4gICAgICBpZiAoZnJvbSAhPSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgIGVycm9yLmRlc3QgPSBmcm9tO1xuXG4gICAgICAgIGlmIChyZXN1bHQpXG4gICAgICAgICAgcmVzdWx0LmRlc3QgPSBmcm9tO1xuICAgICAgfTtcblxuICAgICAgdmFyIG1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyByZXF1ZXN0IG9yIG92ZXJyaWRlbiBvbmUsIGNyZWF0ZSBuZXcgcmVzcG9uc2Ugd2l0aCBwcm92aWRlZCBkYXRhXG4gICAgICBpZiAoZXJyb3IgfHwgcmVzdWx0ICE9IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoc2VsZi5wZWVySUQgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgZXJyb3IuZnJvbSA9IHNlbGYucGVlcklEO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJlc3VsdC5mcm9tID0gc2VsZi5wZWVySUQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm90b2NvbCBpbmRpY2F0ZXMgdGhhdCByZXNwb25zZXMgaGFzIG93biByZXF1ZXN0IG1ldGhvZHNcbiAgICAgICAgaWYgKHJlc3BvbnNlTWV0aG9kKSB7XG4gICAgICAgICAgaWYgKHJlc3BvbnNlTWV0aG9kLmVycm9yID09IHVuZGVmaW5lZCAmJiBlcnJvcilcbiAgICAgICAgICAgIG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvclxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIG1ldGhvZCA9IGVycm9yID9cbiAgICAgICAgICAgICAgcmVzcG9uc2VNZXRob2QuZXJyb3IgOlxuICAgICAgICAgICAgICByZXNwb25zZU1ldGhvZC5yZXNwb25zZTtcblxuICAgICAgICAgICAgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgIHBhcmFtczogZXJyb3IgfHwgcmVzdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlXG4gICAgICAgICAgbWVzc2FnZSA9IHtcbiAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgIHJlc3VsdDogcmVzdWx0XG4gICAgICAgICAgfTtcblxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSwgaWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBEdXBsaWNhdGUgJiBub3Qtb3ZlcnJpZGVuIHJlcXVlc3QsIHJlLXNlbmQgb2xkIHJlc3BvbnNlXG4gICAgICBlbHNlIGlmIChyZXNwb25zZSlcbiAgICAgICAgbWVzc2FnZSA9IHJlc3BvbnNlLm1lc3NhZ2U7XG5cbiAgICAgIC8vIE5ldyBlbXB0eSByZXBseSwgcmVzcG9uc2UgbnVsbCB2YWx1ZVxuICAgICAgZWxzZVxuICAgICAgICBtZXNzYWdlID0gcGFja2VyLnBhY2soe1xuICAgICAgICAgIHJlc3VsdDogbnVsbFxuICAgICAgICB9LCBpZCk7XG5cbiAgICAgIC8vIFN0b3JlIHRoZSByZXNwb25zZSB0byBwcmV2ZW50IHRvIHByb2Nlc3MgYSBkdXBsaWNhdGVkIHJlcXVlc3QgbGF0ZXJcbiAgICAgIHN0b3JlUmVzcG9uc2UobWVzc2FnZSwgaWQsIGZyb20pO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCByZXNwb25zZSBzbyBpdCBjYW4gYmUgZGlyZWN0bHkgc2VuZCBiYWNrXG4gICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuXG4gICAgICBpZiAodHJhbnNwb3J0KVxuICAgICAgICByZXR1cm4gdHJhbnNwb3J0LnNlbmQobWVzc2FnZSk7XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH1cbiAgfTtcbiAgaW5oZXJpdHMoUnBjUmVxdWVzdCwgUnBjTm90aWZpY2F0aW9uKTtcblxuXG4gIGZ1bmN0aW9uIGNhbmNlbChtZXNzYWdlKSB7XG4gICAgdmFyIGtleSA9IG1lc3NhZ2UyS2V5W21lc3NhZ2VdO1xuICAgIGlmICgha2V5KSByZXR1cm47XG5cbiAgICBkZWxldGUgbWVzc2FnZTJLZXlbbWVzc2FnZV07XG5cbiAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLnBvcChrZXkuaWQsIGtleS5kZXN0KTtcbiAgICBpZiAoIXJlcXVlc3QpIHJldHVybjtcblxuICAgIGNsZWFyVGltZW91dChyZXF1ZXN0LnRpbWVvdXQpO1xuXG4gICAgLy8gU3RhcnQgZHVwbGljYXRlZCByZXNwb25zZXMgdGltZW91dFxuICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2Uoa2V5LmlkLCBrZXkuZGVzdCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93IHRvIGNhbmNlbCBhIHJlcXVlc3QgYW5kIGRvbid0IHdhaXQgZm9yIGEgcmVzcG9uc2VcbiAgICpcbiAgICogSWYgYG1lc3NhZ2VgIGlzIG5vdCBnaXZlbiwgY2FuY2VsIGFsbCB0aGUgcmVxdWVzdFxuICAgKi9cbiAgdGhpcy5jYW5jZWwgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgIGlmIChtZXNzYWdlKSByZXR1cm4gY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgZm9yICh2YXIgbWVzc2FnZSBpbiBtZXNzYWdlMktleSlcbiAgICAgIGNhbmNlbChtZXNzYWdlKTtcbiAgfTtcblxuXG4gIHRoaXMuY2xvc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gUHJldmVudCB0byByZWNlaXZlIG5ldyBtZXNzYWdlc1xuICAgIHZhciB0cmFuc3BvcnQgPSB0aGlzLmdldFRyYW5zcG9ydCgpO1xuICAgIGlmICh0cmFuc3BvcnQgJiYgdHJhbnNwb3J0LmNsb3NlKVxuICAgICAgdHJhbnNwb3J0LmNsb3NlKDQwMDMsIFwiQ2FuY2VsIHJlcXVlc3RcIik7XG5cbiAgICAvLyBSZXF1ZXN0ICYgcHJvY2Vzc2VkIHJlc3BvbnNlc1xuICAgIHRoaXMuY2FuY2VsKCk7XG5cbiAgICBwcm9jZXNzZWRSZXNwb25zZXMuZm9yRWFjaChjbGVhclRpbWVvdXQpO1xuXG4gICAgLy8gUmVzcG9uc2VzXG4gICAgcmVzcG9uc2VzLmZvckVhY2goZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBjbGVhclRpbWVvdXQocmVzcG9uc2UudGltZW91dCk7XG4gICAgfSk7XG4gIH07XG5cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuZCBlbmNvZGUgYSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2QgLW1ldGhvZCBvZiB0aGUgbm90aWZpY2F0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBwYXJhbWV0ZXJzIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIFtkZXN0XSAtIGRlc3RpbmF0aW9uIG9mIHRoZSBub3RpZmljYXRpb25cbiAgICogQHBhcmFtIHtvYmplY3R9IFt0cmFuc3BvcnRdIC0gdHJhbnNwb3J0IHdoZXJlIHRvIHNlbmQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIFtjYWxsYmFja10gLSBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHJlc3BvbnNlIHRvIHRoaXMgcmVxdWVzdCBpc1xuICAgKiAgIHJlY2VpdmVkLiBJZiBub3QgZGVmaW5lZCwgYSBub3RpZmljYXRpb24gd2lsbCBiZSBzZW5kIGluc3RlYWRcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gQSByYXcgSnNvblJQQyAyLjAgcmVxdWVzdCBvciBub3RpZmljYXRpb24gc3RyaW5nXG4gICAqL1xuICB0aGlzLmVuY29kZSA9IGZ1bmN0aW9uIChtZXRob2QsIHBhcmFtcywgZGVzdCwgdHJhbnNwb3J0LCBjYWxsYmFjaykge1xuICAgIC8vIEZpeCBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgaWYgKHBhcmFtcyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBpZiAoZGVzdCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrID0gcGFyYW1zO1xuICAgICAgdHJhbnNwb3J0ID0gdW5kZWZpbmVkO1xuICAgICAgZGVzdCA9IHVuZGVmaW5lZDtcbiAgICAgIHBhcmFtcyA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2UgaWYgKGRlc3QgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgaWYgKHRyYW5zcG9ydCAhPSB1bmRlZmluZWQpXG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlRoZXJlIGNhbid0IGJlIHBhcmFtZXRlcnMgYWZ0ZXIgY2FsbGJhY2tcIik7XG5cbiAgICAgIGNhbGxiYWNrID0gZGVzdDtcbiAgICAgIHRyYW5zcG9ydCA9IHVuZGVmaW5lZDtcbiAgICAgIGRlc3QgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIGlmICh0cmFuc3BvcnQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgaWYgKGNhbGxiYWNrICE9IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFwiVGhlcmUgY2FuJ3QgYmUgcGFyYW1ldGVycyBhZnRlciBjYWxsYmFja1wiKTtcblxuICAgICAgY2FsbGJhY2sgPSB0cmFuc3BvcnQ7XG4gICAgICB0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGlmIChzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgcGFyYW1zLmZyb20gPSBzZWxmLnBlZXJJRDtcbiAgICB9O1xuXG4gICAgaWYgKGRlc3QgIT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG5cbiAgICAgIHBhcmFtcy5kZXN0ID0gZGVzdDtcbiAgICB9O1xuXG4gICAgLy8gRW5jb2RlIG1lc3NhZ2VcbiAgICB2YXIgbWVzc2FnZSA9IHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICB9O1xuXG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICB2YXIgaWQgPSByZXF1ZXN0SUQrKztcbiAgICAgIHZhciByZXRyaWVkID0gMDtcblxuICAgICAgbWVzc2FnZSA9IHBhY2tlci5wYWNrKG1lc3NhZ2UsIGlkKTtcblxuICAgICAgZnVuY3Rpb24gZGlzcGF0Y2hDYWxsYmFjayhlcnJvciwgcmVzdWx0KSB7XG4gICAgICAgIHNlbGYuY2FuY2VsKG1lc3NhZ2UpO1xuXG4gICAgICAgIGNhbGxiYWNrKGVycm9yLCByZXN1bHQpO1xuICAgICAgfTtcblxuICAgICAgdmFyIHJlcXVlc3QgPSB7XG4gICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgIGNhbGxiYWNrOiBkaXNwYXRjaENhbGxiYWNrLFxuICAgICAgICByZXNwb25zZU1ldGhvZHM6IHJlc3BvbnNlTWV0aG9kc1ttZXRob2RdIHx8IHt9XG4gICAgICB9O1xuXG4gICAgICB2YXIgZW5jb2RlX3RyYW5zcG9ydCA9IHVuaWZ5VHJhbnNwb3J0KHRyYW5zcG9ydCk7XG5cbiAgICAgIGZ1bmN0aW9uIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCkge1xuICAgICAgICB2YXIgcnQgPSAobWV0aG9kID09PSAncGluZycgPyBwaW5nX3JlcXVlc3RfdGltZW91dCA6IHJlcXVlc3RfdGltZW91dCk7XG4gICAgICAgIHJlcXVlc3QudGltZW91dCA9IHNldFRpbWVvdXQodGltZW91dCwgcnQgKiBNYXRoLnBvdygyLCByZXRyaWVkKyspKTtcbiAgICAgICAgbWVzc2FnZTJLZXlbbWVzc2FnZV0gPSB7XG4gICAgICAgICAgaWQ6IGlkLFxuICAgICAgICAgIGRlc3Q6IGRlc3RcbiAgICAgICAgfTtcbiAgICAgICAgcmVxdWVzdHMuc2V0KHJlcXVlc3QsIGlkLCBkZXN0KTtcblxuICAgICAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgZW5jb2RlX3RyYW5zcG9ydCB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgICBpZiAodHJhbnNwb3J0KVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChtZXNzYWdlKTtcblxuICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHJldHJ5KHRyYW5zcG9ydCkge1xuICAgICAgICB0cmFuc3BvcnQgPSB1bmlmeVRyYW5zcG9ydCh0cmFuc3BvcnQpO1xuXG4gICAgICAgIGNvbnNvbGUud2FybihyZXRyaWVkICsgJyByZXRyeSBmb3IgcmVxdWVzdCBtZXNzYWdlOicsIG1lc3NhZ2UpO1xuXG4gICAgICAgIHZhciB0aW1lb3V0ID0gcHJvY2Vzc2VkUmVzcG9uc2VzLnBvcChpZCwgZGVzdCk7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcblxuICAgICAgICByZXR1cm4gc2VuZFJlcXVlc3QodHJhbnNwb3J0KTtcbiAgICAgIH07XG5cbiAgICAgIGZ1bmN0aW9uIHRpbWVvdXQoKSB7XG4gICAgICAgIGlmIChyZXRyaWVkIDwgbWF4X3JldHJpZXMpXG4gICAgICAgICAgcmV0dXJuIHJldHJ5KHRyYW5zcG9ydCk7XG5cbiAgICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyB0aW1lZCBvdXQnKTtcbiAgICAgICAgZXJyb3IucmVxdWVzdCA9IG1lc3NhZ2U7XG5cbiAgICAgICAgZXJyb3IucmV0cnkgPSByZXRyeTtcblxuICAgICAgICBkaXNwYXRjaENhbGxiYWNrKGVycm9yKVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbmRSZXF1ZXN0KHRyYW5zcG9ydCk7XG4gICAgfTtcblxuICAgIC8vIFJldHVybiB0aGUgcGFja2VkIG1lc3NhZ2VcbiAgICBtZXNzYWdlID0gcGFja2VyLnBhY2sobWVzc2FnZSk7XG5cbiAgICB0cmFuc3BvcnQgPSB0cmFuc3BvcnQgfHwgdGhpcy5nZXRUcmFuc3BvcnQoKTtcbiAgICBpZiAodHJhbnNwb3J0KVxuICAgICAgcmV0dXJuIHRyYW5zcG9ydC5zZW5kKG1lc3NhZ2UpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIERlY29kZSBhbmQgcHJvY2VzcyBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBvZiB0aGUgbWVzc2FnZVxuICAgKlxuICAgKiBAcmV0dXJucyB7UnBjTm90aWZpY2F0aW9ufFJwY1JlcXVlc3R8dW5kZWZpbmVkfSAtIHRoZSByZXByZXNlbnRhdGlvbiBvZiB0aGVcbiAgICogICBub3RpZmljYXRpb24gb3IgdGhlIHJlcXVlc3QuIElmIGEgcmVzcG9uc2Ugd2FzIHByb2Nlc3NlZCwgaXQgd2lsbCByZXR1cm5cbiAgICogICBgdW5kZWZpbmVkYCB0byBub3RpZnkgdGhhdCBpdCB3YXMgcHJvY2Vzc2VkXG4gICAqXG4gICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gLSBNZXNzYWdlIGlzIG5vdCBkZWZpbmVkXG4gICAqL1xuICB0aGlzLmRlY29kZSA9IGZ1bmN0aW9uIChtZXNzYWdlLCB0cmFuc3BvcnQpIHtcbiAgICBpZiAoIW1lc3NhZ2UpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWVzc2FnZSBpcyBub3QgZGVmaW5lZFwiKTtcblxuICAgIHRyeSB7XG4gICAgICBtZXNzYWdlID0gcGFja2VyLnVucGFjayhtZXNzYWdlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBJZ25vcmUgaW52YWxpZCBtZXNzYWdlc1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoZSwgbWVzc2FnZSk7XG4gICAgfTtcblxuICAgIHZhciBpZCA9IG1lc3NhZ2UuaWQ7XG4gICAgdmFyIGFjayA9IG1lc3NhZ2UuYWNrO1xuICAgIHZhciBtZXRob2QgPSBtZXNzYWdlLm1ldGhvZDtcbiAgICB2YXIgcGFyYW1zID0gbWVzc2FnZS5wYXJhbXMgfHwge307XG5cbiAgICB2YXIgZnJvbSA9IHBhcmFtcy5mcm9tO1xuICAgIHZhciBkZXN0ID0gcGFyYW1zLmRlc3Q7XG5cbiAgICAvLyBJZ25vcmUgbWVzc2FnZXMgc2VuZCBieSB1c1xuICAgIGlmIChzZWxmLnBlZXJJRCAhPSB1bmRlZmluZWQgJiYgZnJvbSA9PSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuXG4gICAgLy8gTm90aWZpY2F0aW9uXG4gICAgaWYgKGlkID09IHVuZGVmaW5lZCAmJiBhY2sgPT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YXIgbm90aWZpY2F0aW9uID0gbmV3IFJwY05vdGlmaWNhdGlvbihtZXRob2QsIHBhcmFtcyk7XG5cbiAgICAgIGlmIChzZWxmLmVtaXQoJ3JlcXVlc3QnLCBub3RpZmljYXRpb24pKSByZXR1cm47XG4gICAgICByZXR1cm4gbm90aWZpY2F0aW9uO1xuICAgIH07XG5cblxuICAgIGZ1bmN0aW9uIHByb2Nlc3NSZXF1ZXN0KCkge1xuICAgICAgLy8gSWYgd2UgaGF2ZSBhIHRyYW5zcG9ydCBhbmQgaXQncyBhIGR1cGxpY2F0ZWQgcmVxdWVzdCwgcmVwbHkgaW5tZWRpYXRseVxuICAgICAgdHJhbnNwb3J0ID0gdW5pZnlUcmFuc3BvcnQodHJhbnNwb3J0KSB8fCBzZWxmLmdldFRyYW5zcG9ydCgpO1xuICAgICAgaWYgKHRyYW5zcG9ydCkge1xuICAgICAgICB2YXIgcmVzcG9uc2UgPSByZXNwb25zZXMuZ2V0KGlkLCBmcm9tKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlKVxuICAgICAgICAgIHJldHVybiB0cmFuc3BvcnQuc2VuZChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgIH07XG5cbiAgICAgIHZhciBpZEFjayA9IChpZCAhPSB1bmRlZmluZWQpID8gaWQgOiBhY2s7XG4gICAgICB2YXIgcmVxdWVzdCA9IG5ldyBScGNSZXF1ZXN0KG1ldGhvZCwgcGFyYW1zLCBpZEFjaywgZnJvbSwgdHJhbnNwb3J0KTtcblxuICAgICAgaWYgKHNlbGYuZW1pdCgncmVxdWVzdCcsIHJlcXVlc3QpKSByZXR1cm47XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpIHtcbiAgICAgIHJlcXVlc3QuY2FsbGJhY2soZXJyb3IsIHJlc3VsdCk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGR1cGxpY2F0ZWRSZXNwb25zZSh0aW1lb3V0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZXNwb25zZSBhbHJlYWR5IHByb2Nlc3NlZFwiLCBtZXNzYWdlKTtcblxuICAgICAgLy8gVXBkYXRlIGR1cGxpY2F0ZWQgcmVzcG9uc2VzIHRpbWVvdXRcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgIHN0b3JlUHJvY2Vzc2VkUmVzcG9uc2UoYWNrLCBmcm9tKTtcbiAgICB9O1xuXG5cbiAgICAvLyBSZXF1ZXN0LCBvciByZXNwb25zZSB3aXRoIG93biBtZXRob2RcbiAgICBpZiAobWV0aG9kKSB7XG4gICAgICAvLyBDaGVjayBpZiBpdCdzIGEgcmVzcG9uc2Ugd2l0aCBvd24gbWV0aG9kXG4gICAgICBpZiAoZGVzdCA9PSB1bmRlZmluZWQgfHwgZGVzdCA9PSBzZWxmLnBlZXJJRCkge1xuICAgICAgICB2YXIgcmVxdWVzdCA9IHJlcXVlc3RzLmdldChhY2ssIGZyb20pO1xuICAgICAgICBpZiAocmVxdWVzdCkge1xuICAgICAgICAgIHZhciByZXNwb25zZU1ldGhvZHMgPSByZXF1ZXN0LnJlc3BvbnNlTWV0aG9kcztcblxuICAgICAgICAgIGlmIChtZXRob2QgPT0gcmVzcG9uc2VNZXRob2RzLmVycm9yKVxuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NSZXNwb25zZShyZXF1ZXN0LCBwYXJhbXMpO1xuXG4gICAgICAgICAgaWYgKG1ldGhvZCA9PSByZXNwb25zZU1ldGhvZHMucmVzcG9uc2UpXG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIG51bGwsIHBhcmFtcyk7XG5cbiAgICAgICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICAgIGlmIChwcm9jZXNzZWQpXG4gICAgICAgICAgcmV0dXJuIGR1cGxpY2F0ZWRSZXNwb25zZShwcm9jZXNzZWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXF1ZXN0XG4gICAgICByZXR1cm4gcHJvY2Vzc1JlcXVlc3QoKTtcbiAgICB9O1xuXG4gICAgdmFyIGVycm9yID0gbWVzc2FnZS5lcnJvcjtcbiAgICB2YXIgcmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG5cbiAgICAvLyBJZ25vcmUgcmVzcG9uc2VzIG5vdCBzZW5kIHRvIHVzXG4gICAgaWYgKGVycm9yICYmIGVycm9yLmRlc3QgJiYgZXJyb3IuZGVzdCAhPSBzZWxmLnBlZXJJRCkgcmV0dXJuO1xuICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0LmRlc3QgJiYgcmVzdWx0LmRlc3QgIT0gc2VsZi5wZWVySUQpIHJldHVybjtcblxuICAgIC8vIFJlc3BvbnNlXG4gICAgdmFyIHJlcXVlc3QgPSByZXF1ZXN0cy5nZXQoYWNrLCBmcm9tKTtcbiAgICBpZiAoIXJlcXVlc3QpIHtcbiAgICAgIHZhciBwcm9jZXNzZWQgPSBwcm9jZXNzZWRSZXNwb25zZXMuZ2V0KGFjaywgZnJvbSk7XG4gICAgICBpZiAocHJvY2Vzc2VkKVxuICAgICAgICByZXR1cm4gZHVwbGljYXRlZFJlc3BvbnNlKHByb2Nlc3NlZCk7XG5cbiAgICAgIHJldHVybiBjb25zb2xlLndhcm4oXCJObyBjYWxsYmFjayB3YXMgZGVmaW5lZCBmb3IgdGhpcyBtZXNzYWdlXCIsIG1lc3NhZ2UpO1xuICAgIH07XG5cbiAgICAvLyBQcm9jZXNzIHJlc3BvbnNlXG4gICAgcHJvY2Vzc1Jlc3BvbnNlKHJlcXVlc3QsIGVycm9yLCByZXN1bHQpO1xuICB9O1xufTtcbmluaGVyaXRzKFJwY0J1aWxkZXIsIEV2ZW50RW1pdHRlcik7XG5cblxuUnBjQnVpbGRlci5ScGNOb3RpZmljYXRpb24gPSBScGNOb3RpZmljYXRpb247XG5cblxubW9kdWxlLmV4cG9ydHMgPSBScGNCdWlsZGVyO1xuXG52YXIgY2xpZW50cyA9IHJlcXVpcmUoJy4vY2xpZW50cycpO1xudmFyIHRyYW5zcG9ydHMgPSByZXF1aXJlKCcuL2NsaWVudHMvdHJhbnNwb3J0cycpO1xuXG5ScGNCdWlsZGVyLmNsaWVudHMgPSBjbGllbnRzO1xuUnBjQnVpbGRlci5jbGllbnRzLnRyYW5zcG9ydHMgPSB0cmFuc3BvcnRzO1xuUnBjQnVpbGRlci5wYWNrZXJzID0gcGFja2VyczsiLCIvKipcbiAqIEpzb25SUEMgMi4wIHBhY2tlclxuICovXG5cbi8qKlxuICogUGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gbWVzc2FnZSAtIG9iamVjdCB0byBiZSBwYWNrYWdlZC4gSXQgcmVxdWlyZXMgdG8gaGF2ZSBhbGwgdGhlXG4gKiAgIGZpZWxkcyBuZWVkZWQgYnkgdGhlIEpzb25SUEMgMi4wIG1lc3NhZ2UgdGhhdCBpdCdzIGdvaW5nIHRvIGJlIGdlbmVyYXRlZFxuICpcbiAqIEByZXR1cm4ge1N0cmluZ30gLSB0aGUgc3RyaW5naWZpZWQgSnNvblJQQyAyLjAgbWVzc2FnZVxuICovXG5mdW5jdGlvbiBwYWNrKG1lc3NhZ2UsIGlkKSB7XG4gIHZhciByZXN1bHQgPSB7XG4gICAganNvbnJwYzogXCIyLjBcIlxuICB9O1xuXG4gIC8vIFJlcXVlc3RcbiAgaWYgKG1lc3NhZ2UubWV0aG9kKSB7XG4gICAgcmVzdWx0Lm1ldGhvZCA9IG1lc3NhZ2UubWV0aG9kO1xuXG4gICAgaWYgKG1lc3NhZ2UucGFyYW1zKVxuICAgICAgcmVzdWx0LnBhcmFtcyA9IG1lc3NhZ2UucGFyYW1zO1xuXG4gICAgLy8gUmVxdWVzdCBpcyBhIG5vdGlmaWNhdGlvblxuICAgIGlmIChpZCAhPSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQuaWQgPSBpZDtcbiAgfVxuXG4gIC8vIFJlc3BvbnNlXG4gIGVsc2UgaWYgKGlkICE9IHVuZGVmaW5lZCkge1xuICAgIGlmIChtZXNzYWdlLmVycm9yKSB7XG4gICAgICBpZiAobWVzc2FnZS5yZXN1bHQgIT09IHVuZGVmaW5lZClcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkJvdGggcmVzdWx0IGFuZCBlcnJvciBhcmUgZGVmaW5lZFwiKTtcblxuICAgICAgcmVzdWx0LmVycm9yID0gbWVzc2FnZS5lcnJvcjtcbiAgICB9IGVsc2UgaWYgKG1lc3NhZ2UucmVzdWx0ICE9PSB1bmRlZmluZWQpXG4gICAgICByZXN1bHQucmVzdWx0ID0gbWVzc2FnZS5yZXN1bHQ7XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkXCIpO1xuXG4gICAgcmVzdWx0LmlkID0gaWQ7XG4gIH07XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHJlc3VsdCk7XG59O1xuXG4vKipcbiAqIFVucGFjayBhIEpzb25SUEMgMi4wIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSAtIHN0cmluZyB3aXRoIHRoZSBjb250ZW50IG9mIHRoZSBKc29uUlBDIDIuMCBtZXNzYWdlXG4gKlxuICogQHRocm93cyB7VHlwZUVycm9yfSAtIEludmFsaWQgSnNvblJQQyB2ZXJzaW9uXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAtIG9iamVjdCBmaWxsZWQgd2l0aCB0aGUgSnNvblJQQyAyLjAgbWVzc2FnZSBjb250ZW50XG4gKi9cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKSB7XG4gIHZhciByZXN1bHQgPSBtZXNzYWdlO1xuXG4gIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgfHwgbWVzc2FnZSBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgIHJlc3VsdCA9IEpTT04ucGFyc2UobWVzc2FnZSk7XG4gIH1cblxuICAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgbWVzc2FnZVxuXG4gIHZhciB2ZXJzaW9uID0gcmVzdWx0Lmpzb25ycGM7XG4gIGlmICh2ZXJzaW9uICE9PSAnMi4wJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBKc29uUlBDIHZlcnNpb24gJ1wiICsgdmVyc2lvbiArIFwiJzogXCIgKyBtZXNzYWdlKTtcblxuICAvLyBSZXNwb25zZVxuICBpZiAocmVzdWx0Lm1ldGhvZCA9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAocmVzdWx0LmlkID09IHVuZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2U6IFwiICsgbWVzc2FnZSk7XG5cbiAgICB2YXIgcmVzdWx0X2RlZmluZWQgPSByZXN1bHQucmVzdWx0ICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIGVycm9yX2RlZmluZWQgPSByZXN1bHQuZXJyb3IgIT09IHVuZGVmaW5lZDtcblxuICAgIC8vIENoZWNrIG9ubHkgcmVzdWx0IG9yIGVycm9yIGlzIGRlZmluZWQsIG5vdCBib3RoIG9yIG5vbmVcbiAgICBpZiAocmVzdWx0X2RlZmluZWQgJiYgZXJyb3JfZGVmaW5lZClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJCb3RoIHJlc3VsdCBhbmQgZXJyb3IgYXJlIGRlZmluZWQ6IFwiICsgbWVzc2FnZSk7XG5cbiAgICBpZiAoIXJlc3VsdF9kZWZpbmVkICYmICFlcnJvcl9kZWZpbmVkKVxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5vIHJlc3VsdCBvciBlcnJvciBpcyBkZWZpbmVkOiBcIiArIG1lc3NhZ2UpO1xuXG4gICAgcmVzdWx0LmFjayA9IHJlc3VsdC5pZDtcbiAgICBkZWxldGUgcmVzdWx0LmlkO1xuICB9XG5cbiAgLy8gUmV0dXJuIHVucGFja2VkIG1lc3NhZ2VcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblxuZXhwb3J0cy5wYWNrID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrOyIsImZ1bmN0aW9uIHBhY2sobWVzc2FnZSkge1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTm90IHlldCBpbXBsZW1lbnRlZFwiKTtcbn07XG5cbmZ1bmN0aW9uIHVucGFjayhtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJOb3QgeWV0IGltcGxlbWVudGVkXCIpO1xufTtcblxuZXhwb3J0cy5wYWNrID0gcGFjaztcbmV4cG9ydHMudW5wYWNrID0gdW5wYWNrOyIsInZhciBKc29uUlBDID0gcmVxdWlyZSgnLi9Kc29uUlBDJyk7XG52YXIgWG1sUlBDID0gcmVxdWlyZSgnLi9YbWxSUEMnKTtcblxuXG5leHBvcnRzLkpzb25SUEMgPSBKc29uUlBDO1xuZXhwb3J0cy5YbWxSUEMgPSBYbWxSUEM7IiwidHlwZSBDb25zb2xlRnVuY3Rpb24gPSAoLi4uZGF0YTogYW55KSA9PiB2b2lkO1xuZXhwb3J0IGNsYXNzIENvbnNvbGVMb2dnZXIge1xuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxvZ2dlcjogQ29uc29sZVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGxvZzogQ29uc29sZUZ1bmN0aW9uXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgaW5mbzogQ29uc29sZUZ1bmN0aW9uXG5cbiAgICAvKipcbiAgICAgKiBAaGlkZGVuXG4gICAgICovXG4gICAgZGVidWc6IENvbnNvbGVGdW5jdGlvblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIHdhcm46IENvbnNvbGVGdW5jdGlvblxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGVycm9yOiBDb25zb2xlRnVuY3Rpb25cblxuICAgIGNvbnN0cnVjdG9yKGNvbnNvbGU6IENvbnNvbGUpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBjb25zb2xlO1xuICAgICAgICB0aGlzLmxvZyA9IHdpbmRvdy5jb25zb2xlLmxvZyxcbiAgICAgICAgdGhpcy5pbmZvID0gd2luZG93LmNvbnNvbGUuaW5mbyxcbiAgICAgICAgdGhpcy5kZWJ1ZyA9IHdpbmRvdy5jb25zb2xlLmRlYnVnLFxuICAgICAgICB0aGlzLndhcm4gPSB3aW5kb3cuY29uc29sZS53YXJuLFxuICAgICAgICB0aGlzLmVycm9yID0gd2luZG93LmNvbnNvbGUuZXJyb3JcbiAgICB9XG59IiwiaW1wb3J0IHsgSkwgfSBmcm9tICdqc25sb2cnXG5pbXBvcnQgeyBPcGVuVmlkdSB9IGZyb20gXCIuLi8uLi9PcGVuVmlkdS9PcGVuVmlkdVwiO1xuaW1wb3J0IHsgQ29uc29sZUxvZ2dlciB9IGZyb20gJy4vQ29uc29sZUxvZ2dlcic7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlckNvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi9PcGVuVmlkdUxvZ2dlckNvbmZpZ3VyYXRpb25cIjtcblxuZXhwb3J0IGNsYXNzIE9wZW5WaWR1TG9nZ2VyIHtcblxuXHRwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogT3BlblZpZHVMb2dnZXI7XG5cblx0cHJpdmF0ZSBKU05MT0dfVVJMOiBzdHJpbmcgPSBcIi9vcGVudmlkdS9lbGsvb3BlbnZpZHUtYnJvd3Nlci1sb2dzXCI7XG5cdHByaXZhdGUgTUFYX0pTTkxPR19CQVRDSF9MT0dfTUVTU0FHRVM6IG51bWJlciA9IDEwMDtcblx0cHJpdmF0ZSBNQVhfTVNFQ09ORFNfQkFUQ0hfTUVTU0FHRVM6IG51bWJlciA9IDUwMDA7XG5cdHByaXZhdGUgTUFYX0xFTkdUSF9TVFJJTkdfSlNPTjogbnVtYmVyID0gMTAwMDtcblxuXHRwcml2YXRlIGRlZmF1bHRDb25zb2xlTG9nZ2VyOiBDb25zb2xlTG9nZ2VyID0gbmV3IENvbnNvbGVMb2dnZXIod2luZG93LmNvbnNvbGUpO1xuXG5cdHByaXZhdGUgY3VycmVudEFwcGVuZGVyOiBhbnk7XG5cblx0cHJpdmF0ZSBpc1Byb2RNb2RlID0gZmFsc2U7XG5cdHByaXZhdGUgaXNKU05Mb2dTZXR1cCA9IGZhbHNlO1xuXG5cdC8vIFRoaXMgdHdvIHZhcmlhYmxlcyBhcmUgdXNlZCB0byByZXN0YXJ0IEpTTkxvZ1xuXHQvLyBvbiBkaWZmZXJlbnQgc2Vzc2lvbnMgYW5kIGRpZmZlcmVudCB1c2VySWRzXG5cdHByaXZhdGUgbG9nZ2luZ1Nlc3Npb25JZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRzdGF0aWMgY29uZmlndXJlSlNOTG9nKG9wZW5WaWR1OiBPcGVuVmlkdSwgdG9rZW46IHN0cmluZykge1xuXHRcdHRyeSB7XG5cdFx0XHQvLyBJZiBkZXYgbW9kZSBvci4uLlxuXHRcdFx0aWYgKCh3aW5kb3dbJ0xPR19KU05MT0dfUkVTVUxUUyddKSB8fFxuXHRcdFx0XHQvLyBJZiBpbnN0YW5jZSBpcyBjcmVhdGVkIGFuZCBpdCBpcyBPcGVuVmlkdSBQcm9cblx0XHRcdFx0KHRoaXMuaW5zdGFuY2UgJiYgb3BlblZpZHUuaXNBdExlYXN0UHJvXG5cdFx0XHRcdFx0Ly8gSWYgbG9ncyBhcmUgZW5hYmxlZFxuXHRcdFx0XHRcdCYmIHRoaXMuaW5zdGFuY2UuaXNPcGVuVmlkdUJyb3dzZXJMb2dzRGVidWdBY3RpdmUob3BlblZpZHUpXG5cdFx0XHRcdFx0Ly8gT25seSByZWNvbmZpZ3VyZSBpdCBpZiBzZXNzaW9uIG9yIGZpbmFsVXNlcklkIGhhcyBjaGFuZ2VkXG5cdFx0XHRcdFx0JiYgdGhpcy5pbnN0YW5jZS5jYW5Db25maWd1cmVKU05Mb2cob3BlblZpZHUsIHRoaXMuaW5zdGFuY2UpKSkge1xuXG5cdFx0XHRcdC8vIENoZWNrIGlmIGFwcCBsb2dzIGNhbiBiZSBzZW50XG5cdFx0XHRcdC8vIGFuZCByZXBsYWNlIGNvbnNvbGUubG9nIGZ1bmN0aW9uIHRvIHNlbmRcblx0XHRcdFx0Ly8gbG9ncyBvZiB0aGUgYXBwbGljYXRpb25cblx0XHRcdFx0aWYgKG9wZW5WaWR1LnNlbmRCcm93c2VyTG9ncyA9PT0gT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uLmRlYnVnX2FwcCkge1xuXHRcdFx0XHRcdHRoaXMuaW5zdGFuY2UucmVwbGFjZVdpbmRvd0NvbnNvbGUoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGlzSlNOTG9nU2V0dXAgd2lsbCBub3QgYmUgdHJ1ZSB1bnRpbCBjb21wbGV0ZWQgc2V0dXBcblx0XHRcdFx0dGhpcy5pbnN0YW5jZS5pc0pTTkxvZ1NldHVwID0gZmFsc2U7XG5cdFx0XHRcdHRoaXMuaW5zdGFuY2UuaW5mbyhcIkNvbmZpZ3VyaW5nIEpTTkxvZ3MuXCIpO1xuXG5cdFx0XHRcdGNvbnN0IGZpbmFsVXNlcklkID0gb3BlblZpZHUuZmluYWxVc2VySWQ7XG5cdFx0XHRcdGNvbnN0IHNlc3Npb25JZCA9IG9wZW5WaWR1LnNlc3Npb24uc2Vzc2lvbklkO1xuXG5cdFx0XHRcdGNvbnN0IGJlZm9yZVNlbmRDYWxsYmFjayA9ICh4aHIpID0+IHtcblx0XHRcdFx0XHQvLyBJZiA0MDEgb3IgNDAzIG9yIDQwNCBtb2RpZnkgcmVhZHkgYW5kIHN0YXR1cyBzbyBKU05Mb2cgZG9uJ3QgcmV0cnkgdG8gc2VuZCBsb2dzXG5cdFx0XHRcdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL21wZXJkZWNrL2pzbmxvZy5qcy9ibG9iL3YyLjMwLjAvanNubG9nLnRzI0w4MDUtTDgxOFxuXHRcdFx0XHRcdGNvbnN0IHBhcmVudFJlYWR5U3RhdGVGdW5jdGlvbiA9IHhoci5vbnJlYWR5c3RhdGVjaGFuZ2U7XG5cdFx0XHRcdFx0eGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9ICgpID0+IHtcblx0XHRcdFx0XHRcdGlmICh0aGlzLmlzSW52YWxpZFJlc3BvbnNlKHhocikpIHtcblx0XHRcdFx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KHhociwgXCJyZWFkeVN0YXRlXCIsIHsgdmFsdWU6IDQgfSk7XG5cdFx0XHRcdFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh4aHIsIFwic3RhdHVzXCIsIHsgdmFsdWU6IDIwMCB9KTtcblx0XHRcdFx0XHRcdFx0Ly8gRGlzYWJsZSBKU05Mb2cgdG9vIHRvIG5vdCBzZW5kIHBlcmlvZGljYWxseSBlcnJvcnNcblx0XHRcdFx0XHRcdFx0dGhpcy5pbnN0YW5jZS5kaXNhYmxlTG9nZ2VyKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRwYXJlbnRSZWFkeVN0YXRlRnVuY3Rpb24oKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBIZWFkZXJzIHRvIGlkZW50aWZ5IGFuZCBhdXRoZW50aWNhdGUgbG9nc1xuXHRcdFx0XHRcdHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdBdXRob3JpemF0aW9uJywgXCJCYXNpYyBcIiArIGJ0b2EoYCR7ZmluYWxVc2VySWR9JS8lJHtzZXNzaW9uSWR9YCArIFwiOlwiICsgdG9rZW4pKTtcblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlcignWC1SZXF1ZXN0ZWQtV2l0aCcsICdYTUxIdHRwUmVxdWVzdCcpXG5cdFx0XHRcdFx0Ly8gQWRkaXRpb25hbCBoZWFkZXJzIGZvciBPcGVuVmlkdVxuXHRcdFx0XHRcdHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdPVi1GaW5hbC1Vc2VyLUlkJywgZmluYWxVc2VySWQpO1xuXHRcdFx0XHRcdHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdPVi1TZXNzaW9uLUlkJywgc2Vzc2lvbklkKTtcblx0XHRcdFx0XHR4aHIuc2V0UmVxdWVzdEhlYWRlcignT1YtVG9rZW4nLCB0b2tlbik7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDcmVhdGlvbiBvZiB0aGUgYXBwZW5kZXIuXG5cdFx0XHRcdHRoaXMuaW5zdGFuY2UuY3VycmVudEFwcGVuZGVyID0gSkwuY3JlYXRlQWpheEFwcGVuZGVyKGBhcHBlbmRlci0ke2ZpbmFsVXNlcklkfS0ke3Nlc3Npb25JZH1gKTtcblx0XHRcdFx0dGhpcy5pbnN0YW5jZS5jdXJyZW50QXBwZW5kZXIuc2V0T3B0aW9ucyh7XG5cdFx0XHRcdFx0YmVmb3JlU2VuZDogYmVmb3JlU2VuZENhbGxiYWNrLFxuXHRcdFx0XHRcdG1heEJhdGNoU2l6ZTogMTAwMCxcblx0XHRcdFx0XHRiYXRjaFNpemU6IHRoaXMuaW5zdGFuY2UuTUFYX0pTTkxPR19CQVRDSF9MT0dfTUVTU0FHRVMsXG5cdFx0XHRcdFx0YmF0Y2hUaW1lb3V0OiB0aGlzLmluc3RhbmNlLk1BWF9NU0VDT05EU19CQVRDSF9NRVNTQUdFU1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQvLyBBdm9pZCBjaXJjdWxhciBkZXBlbmRlbmNpZXNcblx0XHRcdFx0Y29uc3QgbG9nU2VyaWFsaXplciA9IChvYmopOiBzdHJpbmcgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IGdldENpcmN1bGFyUmVwbGFjZXIgPSAoKSA9PiB7XG5cdFx0XHRcdFx0XHRjb25zdCBzZWVuID0gbmV3IFdlYWtTZXQoKTtcblx0XHRcdFx0XHRcdHJldHVybiAoa2V5LCB2YWx1ZSkgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAodHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmIHZhbHVlICE9IG51bGwpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoc2Vlbi5oYXModmFsdWUpIHx8IChIVE1MRWxlbWVudCAmJiB2YWx1ZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRzZWVuLmFkZCh2YWx1ZSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0Ly8gQ3V0IGxvbmcgbWVzc2FnZXNcblx0XHRcdFx0XHRsZXQgc3RyaW5naWZ5SnNvbiA9IEpTT04uc3RyaW5naWZ5KG9iaiwgZ2V0Q2lyY3VsYXJSZXBsYWNlcigpKTtcblx0XHRcdFx0XHRpZiAoc3RyaW5naWZ5SnNvbi5sZW5ndGggPiB0aGlzLmluc3RhbmNlLk1BWF9MRU5HVEhfU1RSSU5HX0pTT04pIHtcblx0XHRcdFx0XHRcdHN0cmluZ2lmeUpzb24gPSBgJHtzdHJpbmdpZnlKc29uLnN1YnN0cmluZygwLCB0aGlzLmluc3RhbmNlLk1BWF9MRU5HVEhfU1RSSU5HX0pTT04pfS4uLmA7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKHdpbmRvd1snTE9HX0pTTkxPR19SRVNVTFRTJ10pIHtcblx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKHN0cmluZ2lmeUpzb24pO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHJldHVybiBzdHJpbmdpZnlKc29uO1xuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIEluaXRpYWxpemUgSkwgdG8gc2VuZCBsb2dzXG5cdFx0XHRcdEpMLnNldE9wdGlvbnMoe1xuXHRcdFx0XHRcdGRlZmF1bHRBamF4VXJsOiBvcGVuVmlkdS5odHRwVXJpICsgdGhpcy5pbnN0YW5jZS5KU05MT0dfVVJMLFxuXHRcdFx0XHRcdHNlcmlhbGl6ZTogbG9nU2VyaWFsaXplcixcblx0XHRcdFx0XHRlbmFibGVkOiB0cnVlXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRKTCgpLnNldE9wdGlvbnMoe1xuXHRcdFx0XHRcdGFwcGVuZGVyczogW3RoaXMuaW5zdGFuY2UuY3VycmVudEFwcGVuZGVyXVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHR0aGlzLmluc3RhbmNlLmlzSlNOTG9nU2V0dXAgPSB0cnVlO1xuXHRcdFx0XHR0aGlzLmluc3RhbmNlLmxvZ2dpbmdTZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG5cdFx0XHRcdHRoaXMuaW5zdGFuY2UuaW5mbyhcIkpTTkxvZyBjb25maWd1cmVkLlwiKTtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHQvLyBQcmludCBlcnJvclxuXHRcdFx0Y29uc29sZS5lcnJvcihcIkVycm9yIGNvbmZpZ3VyaW5nIEpTTkxvZzogXCIpO1xuXHRcdFx0Y29uc29sZS5lcnJvcihlKTtcblx0XHRcdC8vIFJlc3RvcmUgZGVmYXVsdHMgdmFsdWVzIGp1c3QgaW4gY2FzZSBhbnkgZXhjZXB0aW9uIGhhcHBlbi1cblx0XHRcdHRoaXMuaW5zdGFuY2UuZGlzYWJsZUxvZ2dlcigpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0SW5zdGFuY2UoKTogT3BlblZpZHVMb2dnZXIge1xuXHRcdGlmICghT3BlblZpZHVMb2dnZXIuaW5zdGFuY2UpIHtcblx0XHRcdE9wZW5WaWR1TG9nZ2VyLmluc3RhbmNlID0gbmV3IE9wZW5WaWR1TG9nZ2VyKCk7XG5cdFx0fVxuXHRcdHJldHVybiBPcGVuVmlkdUxvZ2dlci5pbnN0YW5jZTtcblx0fVxuXG5cdHByaXZhdGUgc3RhdGljIGlzSW52YWxpZFJlc3BvbnNlKHhocjogWE1MSHR0cFJlcXVlc3QpIHtcblx0XHRyZXR1cm4geGhyLnN0YXR1cyA9PSA0MDEgfHwgeGhyLnN0YXR1cyA9PSA0MDMgfHwgeGhyLnN0YXR1cyA9PSA0MDQgfHwgeGhyLnN0YXR1cyA9PSAwO1xuXHR9XG5cblx0cHJpdmF0ZSBjYW5Db25maWd1cmVKU05Mb2cob3BlblZpZHU6IE9wZW5WaWR1LCBsb2dnZXI6IE9wZW5WaWR1TG9nZ2VyKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIG9wZW5WaWR1LnNlc3Npb24uc2Vzc2lvbklkICE9IGxvZ2dlci5sb2dnaW5nU2Vzc2lvbklkXG5cdH1cblxuXHRwcml2YXRlIGlzT3BlblZpZHVCcm93c2VyTG9nc0RlYnVnQWN0aXZlKG9wZW5WaWR1OiBPcGVuVmlkdSkge1xuXHRcdHJldHVybiBvcGVuVmlkdS5zZW5kQnJvd3NlckxvZ3MgPT09IE9wZW5WaWR1TG9nZ2VyQ29uZmlndXJhdGlvbi5kZWJ1ZyB8fFxuXHRcdFx0b3BlblZpZHUuc2VuZEJyb3dzZXJMb2dzID09PSBPcGVuVmlkdUxvZ2dlckNvbmZpZ3VyYXRpb24uZGVidWdfYXBwO1xuXHR9XG5cblx0Ly8gUmV0dXJuIGNvbnNvbGUgZnVuY3Rpb25zIHdpdGgganNubG9nIGludGVncmF0aW9uXG5cdHByaXZhdGUgZ2V0Q29uc29sZVdpdGhKU05Mb2coKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uIChvcGVuVmlkdUxvZ2dlcjogT3BlblZpZHVMb2dnZXIpIHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdGxvZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcblx0XHRcdFx0XHRvcGVuVmlkdUxvZ2dlci5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2cuYXBwbHkob3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdFx0XHRcdGlmIChvcGVuVmlkdUxvZ2dlci5pc0pTTkxvZ1NldHVwKSB7XG5cdFx0XHRcdFx0XHRKTCgpLmluZm8oYXJndW1lbnRzKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGluZm86IGZ1bmN0aW9uICguLi5hcmdzKSB7XG5cdFx0XHRcdFx0b3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIuaW5mby5hcHBseShvcGVuVmlkdUxvZ2dlci5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0aWYgKG9wZW5WaWR1TG9nZ2VyLmlzSlNOTG9nU2V0dXApIHtcblx0XHRcdFx0XHRcdEpMKCkuaW5mbyhhcmd1bWVudHMpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0ZGVidWc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG5cdFx0XHRcdFx0b3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIuZGVidWcuYXBwbHkob3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHR3YXJuOiBmdW5jdGlvbiAoLi4uYXJncykge1xuXHRcdFx0XHRcdG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLndhcm4uYXBwbHkob3BlblZpZHVMb2dnZXIuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdFx0XHRcdGlmIChvcGVuVmlkdUxvZ2dlci5pc0pTTkxvZ1NldHVwKSB7XG5cdFx0XHRcdFx0XHRKTCgpLndhcm4oYXJndW1lbnRzKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGVycm9yOiBmdW5jdGlvbiAoLi4uYXJncykge1xuXHRcdFx0XHRcdG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmVycm9yLmFwcGx5KG9wZW5WaWR1TG9nZ2VyLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHRcdFx0XHRpZiAob3BlblZpZHVMb2dnZXIuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0XHRcdFx0SkwoKS5lcnJvcihhcmd1bWVudHMpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9KHRoaXMpO1xuXHR9XG5cblx0cHJpdmF0ZSByZXBsYWNlV2luZG93Q29uc29sZSgpIHtcblx0XHR3aW5kb3cuY29uc29sZSA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyO1xuXHRcdHdpbmRvdy5jb25zb2xlLmxvZyA9IHRoaXMuZ2V0Q29uc29sZVdpdGhKU05Mb2coKS5sb2c7XG5cdFx0d2luZG93LmNvbnNvbGUuaW5mbyA9IHRoaXMuZ2V0Q29uc29sZVdpdGhKU05Mb2coKS5pbmZvO1xuXHRcdHdpbmRvdy5jb25zb2xlLmRlYnVnID0gdGhpcy5nZXRDb25zb2xlV2l0aEpTTkxvZygpLmRlYnVnO1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4gPSB0aGlzLmdldENvbnNvbGVXaXRoSlNOTG9nKCkud2Fybjtcblx0XHR3aW5kb3cuY29uc29sZS5lcnJvciA9IHRoaXMuZ2V0Q29uc29sZVdpdGhKU05Mb2coKS5lcnJvcjtcblx0fVxuXG5cdHByaXZhdGUgZGlzYWJsZUxvZ2dlcigpIHtcblx0XHRKTC5zZXRPcHRpb25zKHsgZW5hYmxlZDogZmFsc2UgfSk7XG5cdFx0dGhpcy5pc0pTTkxvZ1NldHVwID0gZmFsc2U7XG5cdFx0dGhpcy5sb2dnaW5nU2Vzc2lvbklkID0gdW5kZWZpbmVkO1xuXHRcdHRoaXMuY3VycmVudEFwcGVuZGVyID0gdW5kZWZpbmVkO1xuXHRcdHdpbmRvdy5jb25zb2xlID0gdGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXI7XG5cdFx0d2luZG93LmNvbnNvbGUubG9nID0gdGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2c7XG5cdFx0d2luZG93LmNvbnNvbGUuaW5mbyA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuaW5mbztcblx0XHR3aW5kb3cuY29uc29sZS5kZWJ1ZyA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuZGVidWc7XG5cdFx0d2luZG93LmNvbnNvbGUud2FybiA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIud2Fybjtcblx0XHR3aW5kb3cuY29uc29sZS5lcnJvciA9IHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuZXJyb3I7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0bG9nKC4uLmFyZ3M6IGFueVtdKSB7XG5cdFx0aWYgKCF0aGlzLmlzUHJvZE1vZGUpIHtcblx0XHRcdHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nLmFwcGx5KHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5pc0pTTkxvZ1NldHVwKSB7XG5cdFx0XHRKTCgpLmluZm8oYXJndW1lbnRzKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0ZGVidWcoLi4uYXJnczogYW55W10pIHtcblx0XHRpZiAoIXRoaXMuaXNQcm9kTW9kZSkge1xuXHRcdFx0dGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5kZWJ1Zy5hcHBseSh0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmxvZ2dlciwgYXJndW1lbnRzKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0aW5mbyguLi5hcmdzOiBhbnlbXSkge1xuXHRcdGlmICghdGhpcy5pc1Byb2RNb2RlKSB7XG5cdFx0XHR0aGlzLmRlZmF1bHRDb25zb2xlTG9nZ2VyLmluZm8uYXBwbHkodGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmlzSlNOTG9nU2V0dXApIHtcblx0XHRcdEpMKCkuaW5mbyhhcmd1bWVudHMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHR3YXJuKC4uLmFyZ3M6IGFueVtdKSB7XG5cdFx0dGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci53YXJuLmFwcGx5KHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIubG9nZ2VyLCBhcmd1bWVudHMpO1xuXHRcdGlmICh0aGlzLmlzSlNOTG9nU2V0dXApIHtcblx0XHRcdEpMKCkud2Fybihhcmd1bWVudHMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRlcnJvciguLi5hcmdzOiBhbnlbXSkge1xuXHRcdHRoaXMuZGVmYXVsdENvbnNvbGVMb2dnZXIuZXJyb3IuYXBwbHkodGhpcy5kZWZhdWx0Q29uc29sZUxvZ2dlci5sb2dnZXIsIGFyZ3VtZW50cyk7XG5cdFx0aWYgKHRoaXMuaXNKU05Mb2dTZXR1cCkge1xuXHRcdFx0SkwoKS5lcnJvcihhcmd1bWVudHMpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRmbHVzaCgpIHtcblx0XHRpZiAodGhpcy5pc0pTTkxvZ1NldHVwICYmIHRoaXMuY3VycmVudEFwcGVuZGVyICE9IG51bGwpIHtcblx0XHRcdHRoaXMuY3VycmVudEFwcGVuZGVyLnNlbmRCYXRjaCgpO1xuXHRcdH1cblx0fVxuXG5cdGVuYWJsZVByb2RNb2RlKCkge1xuXHRcdHRoaXMuaXNQcm9kTW9kZSA9IHRydWU7XG5cdH1cblxufVxuIiwiZXhwb3J0IGVudW0gT3BlblZpZHVMb2dnZXJDb25maWd1cmF0aW9uIHtcbiAgICBkaXNhYmxlZCA9ICdkaXNhYmxlZCcsXG4gICAgZGVidWcgPSAnZGVidWcnLFxuICAgIGRlYnVnX2FwcCA9ICdkZWJ1Z19hcHAnXG59IiwiLy8gTGFzdCB0aW1lIHVwZGF0ZWQgb24gSnVuZSAwOCwgMjAxOFxuXG4vLyBMYXRlc3QgZmlsZSBjYW4gYmUgZm91bmQgaGVyZTogaHR0cHM6Ly9jZG4ud2VicnRjLWV4cGVyaW1lbnQuY29tL2dldFNjcmVlbklkLmpzXG5cbi8vIE11YXogS2hhbiAgICAgICAgIC0gd3d3Lk11YXpLaGFuLmNvbVxuLy8gTUlUIExpY2Vuc2UgICAgICAgLSB3d3cuV2ViUlRDLUV4cGVyaW1lbnQuY29tL2xpY2VuY2Vcbi8vIERvY3VtZW50YXRpb24gICAgIC0gaHR0cHM6Ly9naXRodWIuY29tL211YXota2hhbi9nZXRTY3JlZW5JZC5cblxuLy8gX19fX19fX19fX19fX19cbi8vIGdldFNjcmVlbklkLmpzXG5cbi8qXG5nZXRTY3JlZW5JZChmdW5jdGlvbiAoZXJyb3IsIHNvdXJjZUlkLCBzY3JlZW5fY29uc3RyYWludHMpIHtcbiAgICAvLyBlcnJvciAgICA9PSBudWxsIHx8ICdwZXJtaXNzaW9uLWRlbmllZCcgfHwgJ25vdC1pbnN0YWxsZWQnIHx8ICdpbnN0YWxsZWQtZGlzYWJsZWQnIHx8ICdub3QtY2hyb21lJ1xuICAgIC8vIHNvdXJjZUlkID09IG51bGwgfHwgJ3N0cmluZycgfHwgJ2ZpcmVmb3gnXG5cbiAgICBpZihtaWNyb3NvZnRFZGdlKSB7XG4gICAgICAgIG5hdmlnYXRvci5nZXREaXNwbGF5TWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHNjcmVlbl9jb25zdHJhaW50cykudGhlbihvblN1Y2Nlc3MpY2F0Y2gob25GYWlsdXJlKTtcbiAgICB9XG59LCAncGFzcyBzZWNvbmQgcGFyYW1ldGVyIG9ubHkgaWYgeW91IHdhbnQgc3lzdGVtIGF1ZGlvJyk7XG4qL1xuXG53aW5kb3cuZ2V0U2NyZWVuSWQgPSBmdW5jdGlvbiAoZmlyZWZveFN0cmluZywgY2FsbGJhY2ssIGN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICBpZiAobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdFZGdlJykgIT09IC0xICYmICghIW5hdmlnYXRvci5tc1NhdmVPck9wZW5CbG9iIHx8ICEhbmF2aWdhdG9yLm1zU2F2ZUJsb2IpKSB7XG4gICAgICAgIC8vIG1pY3Jvc29mdCBlZGdlID0+IG5hdmlnYXRvci5nZXREaXNwbGF5TWVkaWEoc2NyZWVuX2NvbnN0cmFpbnRzKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTtcbiAgICAgICAgY2FsbGJhY2soe1xuICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBmb3IgRmlyZWZveDpcbiAgICAvLyBzb3VyY2VJZCA9PSAnZmlyZWZveCdcbiAgICAvLyBzY3JlZW5fY29uc3RyYWludHMgPSB7Li4ufVxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgJ2ZpcmVmb3gnLCB7XG4gICAgICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgICAgIG1vek1lZGlhU291cmNlOiBmaXJlZm94U3RyaW5nLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiBmaXJlZm94U3RyaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcblxuICAgIGZ1bmN0aW9uIG9uSUZyYW1lQ2FsbGJhY2soZXZlbnQpIHtcbiAgICAgICAgaWYgKCFldmVudC5kYXRhKSByZXR1cm47XG5cbiAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGEuY2hyb21lTWVkaWFTb3VyY2VJZCA9PT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygncGVybWlzc2lvbi1kZW5pZWQnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgZXZlbnQuZGF0YS5jaHJvbWVNZWRpYVNvdXJjZUlkLCBnZXRTY3JlZW5Db25zdHJhaW50cyhudWxsLCBldmVudC5kYXRhLmNocm9tZU1lZGlhU291cmNlSWQsIGV2ZW50LmRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2spKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5kYXRhLmNocm9tZUV4dGVuc2lvblN0YXR1cykge1xuICAgICAgICAgICAgY2FsbGJhY2soZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMsIG51bGwsIGdldFNjcmVlbkNvbnN0cmFpbnRzKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKSk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgZXZlbnQgbGlzdGVuZXIgaXMgbm8gbW9yZSBuZWVkZWRcbiAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgb25JRnJhbWVDYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgc2V0VGltZW91dChwb3N0R2V0U291cmNlSWRNZXNzYWdlLCAxMDApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwb3N0R2V0U291cmNlSWRNZXNzYWdlKGN1c3RvbV9wYXJhbWV0ZXIpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzKGVycm9yLCBzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICB2YXIgc2NyZWVuX2NvbnN0cmFpbnRzID0ge1xuICAgICAgICBhdWRpbzogZmFsc2UsXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogZXJyb3IgPyAnc2NyZWVuJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCA+IDE5MjAgPyB3aW5kb3cuc2NyZWVuLndpZHRoIDogMTkyMCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID4gMTA4MCA/IHdpbmRvdy5zY3JlZW4uaGVpZ2h0IDogMTA4MFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmICghIWNhblJlcXVlc3RBdWRpb1RyYWNrKSB7XG4gICAgICAgIHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyA9IHtcbiAgICAgICAgICAgIG1hbmRhdG9yeToge1xuICAgICAgICAgICAgICAgIGNocm9tZU1lZGlhU291cmNlOiBlcnJvciA/ICdzY3JlZW4nIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIC8vIGVjaG9DYW5jZWxsYXRpb246IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcHRpb25hbDogW11cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoc291cmNlSWQpIHtcbiAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG5cbiAgICAgICAgaWYgKHNjcmVlbl9jb25zdHJhaW50cy5hdWRpbyAmJiBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5KSB7XG4gICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuYXVkaW8ubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzY3JlZW5fY29uc3RyYWludHM7XG59XG5cbmZ1bmN0aW9uIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcikge1xuICAgIGlmICghaWZyYW1lKSB7XG4gICAgICAgIGxvYWRJRnJhbWUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcG9zdEdldFNvdXJjZUlkTWVzc2FnZShjdXN0b21fcGFyYW1ldGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWlmcmFtZS5pc0xvYWRlZCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHBvc3RHZXRTb3VyY2VJZE1lc3NhZ2UoY3VzdG9tX3BhcmFtZXRlcik7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWN1c3RvbV9wYXJhbWV0ZXIpIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEhY3VzdG9tX3BhcmFtZXRlci5mb3JFYWNoKSB7XG4gICAgICAgIGlmcmFtZS5jb250ZW50V2luZG93LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICAgIGNhcHR1cmVDdXN0b21Tb3VyY2VJZDogY3VzdG9tX3BhcmFtZXRlclxuICAgICAgICB9LCAnKicpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWZyYW1lLmNvbnRlbnRXaW5kb3cucG9zdE1lc3NhZ2Uoe1xuICAgICAgICAgICAgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvOiB0cnVlXG4gICAgICAgIH0sICcqJyk7XG4gICAgfVxufVxuXG52YXIgaWZyYW1lO1xuXG4vLyB0aGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gUlRDTXVsdGlDb25uZWN0aW9uIHYzXG53aW5kb3cuZ2V0U2NyZWVuQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBsb2FkSUZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0U2NyZWVuSWQoZnVuY3Rpb24gKGVycm9yLCBzb3VyY2VJZCwgc2NyZWVuX2NvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICBpZiAoIXNjcmVlbl9jb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHRydWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2NyZWVuX2NvbnN0cmFpbnRzLnZpZGVvKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsb2FkSUZyYW1lKGxvYWRDYWxsYmFjaykge1xuICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgbG9hZENhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBpZnJhbWUub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZnJhbWUuaXNMb2FkZWQgPSB0cnVlO1xuICAgICAgICBsb2FkQ2FsbGJhY2soKTtcbiAgICB9O1xuICAgIGlmcmFtZS5zcmMgPSAnaHR0cHM6Ly9vcGVudmlkdS5naXRodWIuaW8vb3BlbnZpZHUtc2NyZWVuLXNoYXJpbmctY2hyb21lLWV4dGVuc2lvbi8nO1xuICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIChkb2N1bWVudC5ib2R5IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbn1cblxud2luZG93LmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIC8vIGZvciBGaXJlZm94OlxuICAgIGlmICghIW5hdmlnYXRvci5tb3pHZXRVc2VyTWVkaWEpIHtcbiAgICAgICAgY2FsbGJhY2soJ2luc3RhbGxlZC1lbmFibGVkJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIG9uSUZyYW1lQ2FsbGJhY2spO1xuXG4gICAgZnVuY3Rpb24gb25JRnJhbWVDYWxsYmFjayhldmVudCkge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGEpIHJldHVybjtcblxuICAgICAgICBpZiAoZXZlbnQuZGF0YS5jaHJvbWVFeHRlbnNpb25TdGF0dXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGV2ZW50LmRhdGEuY2hyb21lRXh0ZW5zaW9uU3RhdHVzKTtcblxuICAgICAgICAgICAgLy8gdGhpcyBldmVudCBsaXN0ZW5lciBpcyBubyBtb3JlIG5lZWRlZFxuICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBvbklGcmFtZUNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG59O1xuXG5mdW5jdGlvbiBwb3N0R2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzTWVzc2FnZSgpIHtcbiAgICBpZiAoIWlmcmFtZSkge1xuICAgICAgICBsb2FkSUZyYW1lKHBvc3RHZXRDaHJvbWVFeHRlbnNpb25TdGF0dXNNZXNzYWdlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaWZyYW1lLmlzTG9hZGVkKSB7XG4gICAgICAgIHNldFRpbWVvdXQocG9zdEdldENocm9tZUV4dGVuc2lvblN0YXR1c01lc3NhZ2UsIDEwMCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZnJhbWUuY29udGVudFdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgIGdldENocm9tZUV4dGVuc2lvblN0YXR1czogdHJ1ZVxuICAgIH0sICcqJyk7XG59XG5cbmV4cG9ydHMuZ2V0U2NyZWVuSWQgPSB3aW5kb3cuZ2V0U2NyZWVuSWQ7IiwiLy8gZ2xvYmFsIHZhcmlhYmxlc1xudmFyIGNocm9tZU1lZGlhU291cmNlID0gJ3NjcmVlbic7XG52YXIgc291cmNlSWQ7XG52YXIgc2NyZWVuQ2FsbGJhY2s7XG5cbmlmKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50ICE9PSAndW5kZWZpbmVkJyl7XG4gICAgdmFyIGlzRmlyZWZveCA9IHR5cGVvZiB3aW5kb3cuSW5zdGFsbFRyaWdnZXIgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBpc09wZXJhID0gISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDA7XG4gICAgdmFyIGlzQ2hyb21lID0gISF3aW5kb3cuY2hyb21lICYmICFpc09wZXJhO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50Lm9yaWdpbiAhPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgb25NZXNzYWdlQ2FsbGJhY2soZXZlbnQuZGF0YSk7XG4gICAgfSk7XG59XG5cbi8vIGFuZCB0aGUgZnVuY3Rpb24gdGhhdCBoYW5kbGVzIHJlY2VpdmVkIG1lc3NhZ2VzXG5mdW5jdGlvbiBvbk1lc3NhZ2VDYWxsYmFjayhkYXRhKSB7XG4gICAgLy8gXCJjYW5jZWxcIiBidXR0b24gaXMgY2xpY2tlZFxuICAgIGlmIChkYXRhID09ICdQZXJtaXNzaW9uRGVuaWVkRXJyb3InKSB7XG4gICAgICAgIGlmIChzY3JlZW5DYWxsYmFjaylcbiAgICAgICAgICAgIHJldHVybiBzY3JlZW5DYWxsYmFjaygnUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGVybWlzc2lvbkRlbmllZEVycm9yJyk7XG4gICAgfVxuICAgIC8vIGV4dGVuc2lvbiBub3RpZmllZCBoaXMgcHJlc2VuY2VcbiAgICBpZiAoZGF0YSA9PSAncnRjbXVsdGljb25uZWN0aW9uLWV4dGVuc2lvbi1sb2FkZWQnKSB7XG4gICAgICAgIGNocm9tZU1lZGlhU291cmNlID0gJ2Rlc2t0b3AnO1xuICAgIH1cbiAgICAvLyBleHRlbnNpb24gc2hhcmVkIHRlbXAgc291cmNlSWRcbiAgICBpZiAoZGF0YS5zb3VyY2VJZCAmJiBzY3JlZW5DYWxsYmFjaykge1xuICAgICAgICBzY3JlZW5DYWxsYmFjayhzb3VyY2VJZCA9IGRhdGEuc291cmNlSWQsIGRhdGEuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPT09IHRydWUpO1xuICAgIH1cbn1cblxuLy8gdGhpcyBtZXRob2QgY2FuIGJlIHVzZWQgdG8gY2hlY2sgaWYgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWQgJiBlbmFibGVkLlxuZnVuY3Rpb24gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGUoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm47XG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykgcmV0dXJuIGNhbGxiYWNrKHRydWUpO1xuXG4gICAgLy8gYXNrIGV4dGVuc2lvbiBpZiBpdCBpcyBhdmFpbGFibGVcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2FyZS15b3UtdGhlcmUnLCAnKicpO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgfSBlbHNlIGNhbGxiYWNrKHRydWUpO1xuICAgIH0sIDIwMDApO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIGdldCBcInNvdXJjZS1pZFwiIGZyb20gdGhlIGV4dGVuc2lvblxuZnVuY3Rpb24gZ2V0U291cmNlSWQoY2FsbGJhY2spIHtcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICB0aHJvdyAnXCJjYWxsYmFja1wiIHBhcmFtZXRlciBpcyBtYW5kYXRvcnkuJztcbiAgICBpZiAoc291cmNlSWQpXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2dldC1zb3VyY2VJZCcsICcqJyk7XG59XG5cbi8vIHRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gZ2V0IFwic291cmNlLWlkXCIgZnJvbSB0aGUgZXh0ZW5zaW9uXG5mdW5jdGlvbiBnZXRDdXN0b21Tb3VyY2VJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFhcnIgfHwgIWFyci5mb3JFYWNoKSB0aHJvdyAnXCJhcnJcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGFuZCBpdCBtdXN0IGJlIGFuIGFycmF5Lic7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG5cbiAgICBpZiAoc291cmNlSWQpIHJldHVybiBjYWxsYmFjayhzb3VyY2VJZCk7XG5cbiAgICBzY3JlZW5DYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHdpbmRvdy5wb3N0TWVzc2FnZSh7XG4gICAgICAgICdnZXQtY3VzdG9tLXNvdXJjZUlkJzogYXJyXG4gICAgfSwgJyonKTtcbn1cblxuLy8gdGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCB0byBnZXQgXCJzb3VyY2UtaWRcIiBmcm9tIHRoZSBleHRlbnNpb25cbmZ1bmN0aW9uIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykgdGhyb3cgJ1wiY2FsbGJhY2tcIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5Lic7XG4gICAgaWYgKHNvdXJjZUlkKSByZXR1cm4gY2FsbGJhY2soc291cmNlSWQpO1xuXG4gICAgc2NyZWVuQ2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ2F1ZGlvLXBsdXMtdGFiJywgJyonKTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2hyb21lRXh0ZW5zaW9uU3RhdHVzKGV4dGVuc2lvbmlkLCBjYWxsYmFjaykge1xuICAgIGlmIChpc0ZpcmVmb3gpXG4gICAgICAgIHJldHVybiBjYWxsYmFjaygnbm90LWNocm9tZScpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9IDIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBleHRlbnNpb25pZDtcbiAgICAgICAgZXh0ZW5zaW9uaWQgPSAnbGZjZ2ZlcGFmbm9iZGxvZWNjaG5mYWNsaWJlbmpvbGQnOyAvLyBkZWZhdWx0IGV4dGVuc2lvbi1pZFxuICAgIH1cbiAgICB2YXIgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcbiAgICBpbWFnZS5zcmMgPSAnY2hyb21lLWV4dGVuc2lvbjovLycgKyBleHRlbnNpb25pZCArICcvaWNvbi5wbmcnO1xuICAgIGltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hyb21lTWVkaWFTb3VyY2UgPSAnc2NyZWVuJztcbiAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdhcmUteW91LXRoZXJlJywgJyonKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lTWVkaWFTb3VyY2UgPT0gJ3NjcmVlbicpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWRpc2FibGVkJyk7XG4gICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygnaW5zdGFsbGVkLWVuYWJsZWQnKTtcbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBpbWFnZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygnbm90LWluc3RhbGxlZCcpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvKGNhbGxiYWNrKSB7XG4gICAgZ2V0U2NyZWVuQ29uc3RyYWludHMoY2FsbGJhY2ssIHRydWUpO1xufVxuXG4vLyB0aGlzIGZ1bmN0aW9uIGV4cGxhaW5zIGhvdyB0byB1c2UgYWJvdmUgbWV0aG9kcy9vYmplY3RzXG5mdW5jdGlvbiBnZXRTY3JlZW5Db25zdHJhaW50cyhjYWxsYmFjaywgY2FwdHVyZVNvdXJjZUlkV2l0aEF1ZGlvKSB7XG4gICAgc291cmNlSWQgPSAnJztcbiAgICB2YXIgZmlyZWZveFNjcmVlbkNvbnN0cmFpbnRzID0ge1xuICAgICAgICBtb3pNZWRpYVNvdXJjZTogJ3dpbmRvdycsXG4gICAgICAgIG1lZGlhU291cmNlOiAnd2luZG93J1xuICAgIH07XG4gICAgaWYgKGlzRmlyZWZveClcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGZpcmVmb3hTY3JlZW5Db25zdHJhaW50cyk7XG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgZGVmaW5lcyBnZXRVc2VyTWVkaWEgY29uc3RyYWludHNcbiAgICAvLyB0aGF0IHdpbGwgYmUgdXNlZCB0byBjYXB0dXJlIGNvbnRlbnQgb2Ygc2NyZWVuXG4gICAgdmFyIHNjcmVlbl9jb25zdHJhaW50cyA9IHtcbiAgICAgICAgbWFuZGF0b3J5OiB7XG4gICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogY2hyb21lTWVkaWFTb3VyY2UsXG4gICAgICAgICAgICBtYXhXaWR0aDogc2NyZWVuLndpZHRoID4gMTkyMCA/IHNjcmVlbi53aWR0aCA6IDE5MjAsXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IHNjcmVlbi5oZWlnaHQgPiAxMDgwID8gc2NyZWVuLmhlaWdodCA6IDEwODBcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgfTtcbiAgICAvLyB0aGlzIHN0YXRlbWVudCB2ZXJpZmllcyBjaHJvbWUgZXh0ZW5zaW9uIGF2YWlsYWJpbGl0eVxuICAgIC8vIGlmIGluc3RhbGxlZCBhbmQgYXZhaWxhYmxlIHRoZW4gaXQgd2lsbCBpbnZva2UgZXh0ZW5zaW9uIEFQSVxuICAgIC8vIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGNvbW1hbmQtbGluZSBiYXNlZCBzY3JlZW4gY2FwdHVyaW5nIEFQSVxuICAgIGlmIChjaHJvbWVNZWRpYVNvdXJjZSA9PSAnZGVza3RvcCcgJiYgIXNvdXJjZUlkKSB7XG4gICAgICAgIGlmIChjYXB0dXJlU291cmNlSWRXaXRoQXVkaW8pIHtcbiAgICAgICAgICAgIGdldFNvdXJjZUlkV2l0aEF1ZGlvKGZ1bmN0aW9uIChzb3VyY2VJZCwgY2FuUmVxdWVzdEF1ZGlvVHJhY2spIHtcbiAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcblxuICAgICAgICAgICAgICAgIGlmIChjYW5SZXF1ZXN0QXVkaW9UcmFjaykge1xuICAgICAgICAgICAgICAgICAgICBzY3JlZW5fY29uc3RyYWludHMuY2FuUmVxdWVzdEF1ZGlvVHJhY2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzb3VyY2VJZCA9PSAnUGVybWlzc2lvbkRlbmllZEVycm9yJyA/IHNvdXJjZUlkIDogbnVsbCwgc2NyZWVuX2NvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZ2V0U291cmNlSWQoZnVuY3Rpb24gKHNvdXJjZUlkKSB7XG4gICAgICAgICAgICAgICAgc2NyZWVuX2NvbnN0cmFpbnRzLm1hbmRhdG9yeS5jaHJvbWVNZWRpYVNvdXJjZUlkID0gc291cmNlSWQ7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soc291cmNlSWQgPT0gJ1Blcm1pc3Npb25EZW5pZWRFcnJvcicgPyBzb3VyY2VJZCA6IG51bGwsIHNjcmVlbl9jb25zdHJhaW50cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gdGhpcyBzdGF0ZW1lbnQgc2V0cyBnZXRzICdzb3VyY2VJZFwiIGFuZCBzZXRzIFwiY2hyb21lTWVkaWFTb3VyY2VJZFwiXG4gICAgaWYgKGNocm9tZU1lZGlhU291cmNlID09ICdkZXNrdG9wJykge1xuICAgICAgICBzY3JlZW5fY29uc3RyYWludHMubWFuZGF0b3J5LmNocm9tZU1lZGlhU291cmNlSWQgPSBzb3VyY2VJZDtcbiAgICB9XG5cbiAgICAvLyBub3cgaW52b2tpbmcgbmF0aXZlIGdldFVzZXJNZWRpYSBBUElcbiAgICBjYWxsYmFjayhudWxsLCBzY3JlZW5fY29uc3RyYWludHMpO1xufVxuXG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzID0gZ2V0U2NyZWVuQ29uc3RyYWludHM7XG5leHBvcnRzLmdldFNjcmVlbkNvbnN0cmFpbnRzV2l0aEF1ZGlvID0gZ2V0U2NyZWVuQ29uc3RyYWludHNXaXRoQXVkaW87XG5leHBvcnRzLmlzQ2hyb21lRXh0ZW5zaW9uQXZhaWxhYmxlID0gaXNDaHJvbWVFeHRlbnNpb25BdmFpbGFibGU7XG5leHBvcnRzLmdldENocm9tZUV4dGVuc2lvblN0YXR1cyA9IGdldENocm9tZUV4dGVuc2lvblN0YXR1cztcbmV4cG9ydHMuZ2V0U291cmNlSWQgPSBnZXRTb3VyY2VJZDsiLCJpbXBvcnQgcGxhdGZvcm0gPSByZXF1aXJlKCdwbGF0Zm9ybScpO1xuXG5leHBvcnQgY2xhc3MgUGxhdGZvcm1VdGlscyB7XG5cdHByb3RlY3RlZCBzdGF0aWMgaW5zdGFuY2U6IFBsYXRmb3JtVXRpbHM7XG5cdGNvbnN0cnVjdG9yKCkgeyB9XG5cblx0c3RhdGljIGdldEluc3RhbmNlKCk6IFBsYXRmb3JtVXRpbHMge1xuXHRcdGlmICghdGhpcy5pbnN0YW5jZSkge1xuXHRcdFx0dGhpcy5pbnN0YW5jZSA9IG5ldyBQbGF0Zm9ybVV0aWxzKCk7XG5cdFx0fVxuXHRcdHJldHVybiBQbGF0Zm9ybVV0aWxzLmluc3RhbmNlO1xuXHR9XG5cblx0cHVibGljIGlzQ2hyb21lQnJvd3NlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0ubmFtZSA9PT0gXCJDaHJvbWVcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNTYWZhcmlCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIlNhZmFyaVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0Nocm9tZU1vYmlsZUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHBsYXRmb3JtLm5hbWUgPT09IFwiQ2hyb21lIE1vYmlsZVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0ZpcmVmb3hCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIkZpcmVmb3hcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNGaXJlZm94TW9iaWxlQnJvd3NlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0ubmFtZSA9PT0gXCJGaXJlZm94IE1vYmlsZVwiIHx8IHBsYXRmb3JtLm5hbWUgPT09IFwiRmlyZWZveCBmb3IgaU9TXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzT3BlcmFCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIk9wZXJhXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzT3BlcmFNb2JpbGVCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIk9wZXJhIE1vYmlsZVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0VkZ2VCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybT8udmVyc2lvbiA/IHBhcnNlRmxvYXQocGxhdGZvcm0udmVyc2lvbikgOiAtMTtcblx0XHRyZXR1cm4gcGxhdGZvcm0ubmFtZSA9PT0gXCJNaWNyb3NvZnQgRWRnZVwiICYmIHZlcnNpb24gPj0gODA7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzRWRnZU1vYmlsZUJyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgdmVyc2lvbiA9IHBsYXRmb3JtPy52ZXJzaW9uID8gcGFyc2VGbG9hdChwbGF0Zm9ybS52ZXJzaW9uKSA6IC0xO1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIk1pY3Jvc29mdCBFZGdlXCIgJiYgKHBsYXRmb3JtLm9zPy5mYW1pbHkgPT09ICdBbmRyb2lkJyB8fCBwbGF0Zm9ybS5vcz8uZmFtaWx5ID09PSAnaU9TJykgJiYgdmVyc2lvbiA+IDQ1O1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0FuZHJvaWRCcm93c2VyKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIkFuZHJvaWQgQnJvd3NlclwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0VsZWN0cm9uKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lID09PSBcIkVsZWN0cm9uXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGlzU2Ftc3VuZ0Jyb3dzZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIChcblx0XHRcdHBsYXRmb3JtLm5hbWUgPT09IFwiU2Ftc3VuZyBJbnRlcm5ldCBNb2JpbGVcIiB8fFxuXHRcdFx0cGxhdGZvcm0ubmFtZSA9PT0gXCJTYW1zdW5nIEludGVybmV0XCJcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0lQaG9uZU9ySVBhZCgpOiBib29sZWFuIHtcblx0XHRjb25zdCB1c2VyQWdlbnQgPSAhIXBsYXRmb3JtLnVhID8gcGxhdGZvcm0udWEgOiBuYXZpZ2F0b3IudXNlckFnZW50O1xuXHRcdGNvbnN0IGlzVG91Y2hhYmxlID0gXCJvbnRvdWNoZW5kXCIgaW4gZG9jdW1lbnQ7XG5cdFx0Y29uc3QgaXNJUGFkID0gL1xcYihcXHcqTWFjaW50b3NoXFx3KilcXGIvLnRlc3QodXNlckFnZW50KSAmJiBpc1RvdWNoYWJsZTtcblx0XHRjb25zdCBpc0lQaG9uZSA9XG5cdFx0XHQvXFxiKFxcdyppUGhvbmVcXHcqKVxcYi8udGVzdCh1c2VyQWdlbnQpICYmXG5cdFx0XHQvXFxiKFxcdypNb2JpbGVcXHcqKVxcYi8udGVzdCh1c2VyQWdlbnQpICYmXG5cdFx0XHRpc1RvdWNoYWJsZTtcblx0XHRyZXR1cm4gaXNJUGFkIHx8IGlzSVBob25lO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0lPU1dpdGhTYWZhcmkoKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgdXNlckFnZW50ID0gISFwbGF0Zm9ybS51YSA/IHBsYXRmb3JtLnVhIDogbmF2aWdhdG9yLnVzZXJBZ2VudDtcblx0XHRyZXR1cm4gdGhpcy5pc0lQaG9uZU9ySVBhZCgpICYmIChcblx0XHRcdC9cXGIoXFx3KkFwcGxlXFx3KilcXGIvLnRlc3QobmF2aWdhdG9yLnZlbmRvcikgJiZcblx0XHRcdC9cXGIoXFx3KlNhZmFyaVxcdyopXFxiLy50ZXN0KHVzZXJBZ2VudCkgJiZcblx0XHRcdCEvXFxiKFxcdypDcmlPU1xcdyopXFxiLy50ZXN0KHVzZXJBZ2VudCkgJiZcblx0XHRcdCEvXFxiKFxcdypGeGlPU1xcdyopXFxiLy50ZXN0KHVzZXJBZ2VudClcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc0lvbmljSW9zKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLmlzSVBob25lT3JJUGFkKCkgJiYgcGxhdGZvcm0udWEhIS5pbmRleE9mKFwiU2FmYXJpXCIpID09PSAtMTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNJb25pY0FuZHJvaWQoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIChcblx0XHRcdHBsYXRmb3JtLm9zISEuZmFtaWx5ID09PSBcIkFuZHJvaWRcIiAmJiBwbGF0Zm9ybS5uYW1lID09IFwiQW5kcm9pZCBCcm93c2VyXCJcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc01vYmlsZURldmljZSgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0ub3MhIS5mYW1pbHkgPT09IFwiaU9TXCIgfHwgcGxhdGZvcm0ub3MhIS5mYW1pbHkgPT09IFwiQW5kcm9pZFwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBpc1JlYWN0TmF0aXZlKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgaXNDaHJvbWl1bSgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5pc0Nocm9tZUJyb3dzZXIoKSB8fCB0aGlzLmlzQ2hyb21lTW9iaWxlQnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzT3BlcmFCcm93c2VyKCkgfHwgdGhpcy5pc09wZXJhTW9iaWxlQnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzRWRnZUJyb3dzZXIoKSB8fCB0aGlzLmlzRWRnZU1vYmlsZUJyb3dzZXIoKSB8fFxuXHRcdFx0dGhpcy5pc1NhbXN1bmdCcm93c2VyKCkgfHxcblx0XHRcdHRoaXMuaXNJb25pY0FuZHJvaWQoKSB8fCB0aGlzLmlzSW9uaWNJb3MoKSB8fFxuXHRcdFx0dGhpcy5pc0VsZWN0cm9uKCk7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGNhblNjcmVlblNoYXJlKCk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IHZlcnNpb24gPSBwbGF0Zm9ybT8udmVyc2lvbiA/IHBhcnNlRmxvYXQocGxhdGZvcm0udmVyc2lvbikgOiAtMTtcblx0XHQvLyBSZWplY3QgbW9iaWxlIGRldmljZXNcblx0XHRpZiAodGhpcy5pc01vYmlsZURldmljZSgpKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiAoXG5cdFx0XHR0aGlzLmlzQ2hyb21lQnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzRmlyZWZveEJyb3dzZXIoKSB8fFxuXHRcdFx0dGhpcy5pc09wZXJhQnJvd3NlcigpIHx8XG5cdFx0XHR0aGlzLmlzRWxlY3Ryb24oKSB8fFxuXHRcdFx0dGhpcy5pc0VkZ2VCcm93c2VyKCkgfHxcblx0XHRcdCh0aGlzLmlzU2FmYXJpQnJvd3NlcigpICYmIHZlcnNpb24gPj0gMTMpXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgZ2V0TmFtZSgpOiBzdHJpbmcge1xuXHRcdHJldHVybiBwbGF0Zm9ybS5uYW1lIHx8IFwiXCI7XG5cdH1cblxuXHQvKipcblx0ICogQGhpZGRlblxuXHQgKi9cblx0cHVibGljIGdldFZlcnNpb24oKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0udmVyc2lvbiB8fCBcIlwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIEBoaWRkZW5cblx0ICovXG5cdHB1YmxpYyBnZXRGYW1pbHkoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0ub3MhIS5mYW1pbHkgfHwgXCJcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBAaGlkZGVuXG5cdCAqL1xuXHRwdWJsaWMgZ2V0RGVzY3JpcHRpb24oKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gcGxhdGZvcm0uZGVzY3JpcHRpb24gfHwgXCJcIjtcblx0fVxufVxuIiwiLypcbiAqIChDKSBDb3B5cmlnaHQgMjAxNy0yMDIyIE9wZW5WaWR1IChodHRwczovL29wZW52aWR1LmlvKVxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKlxuICovXG5cbmltcG9ydCBmcmVlaWNlID0gcmVxdWlyZSgnZnJlZWljZScpO1xuaW1wb3J0IHsgdjQgYXMgdXVpZHY0IH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBUeXBlT2ZWaWRlbyB9IGZyb20gJy4uL0VudW1zL1R5cGVPZlZpZGVvJztcbmltcG9ydCB7IEV4Y2VwdGlvbkV2ZW50TmFtZSB9IGZyb20gJy4uL0V2ZW50cy9FeGNlcHRpb25FdmVudCc7XG5pbXBvcnQgeyBPcGVuVmlkdUxvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9PcGVuVmlkdUxvZ2dlcic7XG5pbXBvcnQgeyBQbGF0Zm9ybVV0aWxzIH0gZnJvbSAnLi4vVXRpbHMvUGxhdGZvcm0nO1xuXG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIHtcbiAgICBtZWRpYUNvbnN0cmFpbnRzOiB7XG4gICAgICAgIGF1ZGlvOiBib29sZWFuO1xuICAgICAgICB2aWRlbzogYm9vbGVhbjtcbiAgICB9O1xuICAgIHNpbXVsY2FzdDogYm9vbGVhbjtcbiAgICBtZWRpYVNlcnZlcjogc3RyaW5nO1xuICAgIG9uSWNlQ2FuZGlkYXRlOiAoZXZlbnQ6IFJUQ0ljZUNhbmRpZGF0ZSkgPT4gdm9pZDtcbiAgICBvbkljZUNvbm5lY3Rpb25TdGF0ZUV4Y2VwdGlvbjogKGV4Y2VwdGlvbk5hbWU6IEV4Y2VwdGlvbkV2ZW50TmFtZSwgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogYW55KSA9PiB2b2lkO1xuICAgIGljZVNlcnZlcnM/OiBSVENJY2VTZXJ2ZXJbXTtcbiAgICBtZWRpYVN0cmVhbT86IE1lZGlhU3RyZWFtIHwgbnVsbDtcbiAgICBtb2RlPzogJ3NlbmRvbmx5JyB8ICdyZWN2b25seScgfCAnc2VuZHJlY3YnO1xuICAgIGlkPzogc3RyaW5nO1xuICAgIHR5cGVPZlZpZGVvOiBUeXBlT2ZWaWRlbyB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGNsYXNzIFdlYlJ0Y1BlZXIge1xuICAgIHBjOiBSVENQZWVyQ29ubmVjdGlvbjtcbiAgICByZW1vdGVDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG4gICAgbG9jYWxDYW5kaWRhdGVzUXVldWU6IFJUQ0ljZUNhbmRpZGF0ZVtdID0gW107XG5cbiAgICAvLyBTYW1lIGFzIFdlYlJ0Y1BlZXJDb25maWd1cmF0aW9uIGJ1dCB3aXRob3V0IG9wdGlvbmFsIGZpZWxkcy5cbiAgICBwcm90ZWN0ZWQgY29uZmlndXJhdGlvbjogUmVxdWlyZWQ8V2ViUnRjUGVlckNvbmZpZ3VyYXRpb24+O1xuXG4gICAgcHJpdmF0ZSBpY2VDYW5kaWRhdGVMaXN0OiBSVENJY2VDYW5kaWRhdGVbXSA9IFtdO1xuICAgIHByaXZhdGUgY2FuZGlkYXRlZ2F0aGVyaW5nZG9uZSA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogV2ViUnRjUGVlckNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uID0ge1xuICAgICAgICAgICAgLi4uY29uZmlndXJhdGlvbixcbiAgICAgICAgICAgIGljZVNlcnZlcnM6XG4gICAgICAgICAgICAgICAgISFjb25maWd1cmF0aW9uLmljZVNlcnZlcnMgJiZcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhdGlvbi5pY2VTZXJ2ZXJzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICAgICAgPyBjb25maWd1cmF0aW9uLmljZVNlcnZlcnNcbiAgICAgICAgICAgICAgICAgICAgOiBmcmVlaWNlKCksXG4gICAgICAgICAgICBtZWRpYVN0cmVhbTpcbiAgICAgICAgICAgICAgICBjb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgPyBjb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtXG4gICAgICAgICAgICAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICAgIG1vZGU6ICEhY29uZmlndXJhdGlvbi5tb2RlID8gY29uZmlndXJhdGlvbi5tb2RlIDogXCJzZW5kcmVjdlwiLFxuICAgICAgICAgICAgaWQ6ICEhY29uZmlndXJhdGlvbi5pZCA/IGNvbmZpZ3VyYXRpb24uaWQgOiB0aGlzLmdlbmVyYXRlVW5pcXVlSWQoKSxcbiAgICAgICAgfTtcbiAgICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgW1dlYlJ0Y1BlZXJdIGNvbmZpZ3VyYXRpb246XFxuJHtKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZ3VyYXRpb24sIG51bGwsIDIpfWApO1xuXG4gICAgICAgIHRoaXMucGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oeyBpY2VTZXJ2ZXJzOiB0aGlzLmNvbmZpZ3VyYXRpb24uaWNlU2VydmVycyB9KTtcblxuICAgICAgICB0aGlzLnBjLmFkZEV2ZW50TGlzdGVuZXIoXCJpY2VjYW5kaWRhdGVcIiwgKGV2ZW50OiBSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gYFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQuY2FuZGlkYXRlYCBpcyBzdXBwb3NlZCB0byBiZSBhbiBSVENJY2VDYW5kaWRhdGU6XG4gICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jZG9tLXJ0Y3BlZXJjb25uZWN0aW9uaWNlZXZlbnQtY2FuZGlkYXRlXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBCdXQgaW4gcHJhY3RpY2UsIGl0IGlzIGFjdHVhbGx5IGFuIFJUQ0ljZUNhbmRpZGF0ZUluaXQgdGhhdCBjYW4gYmUgdXNlZCB0b1xuICAgICAgICAgICAgICAgIC8vIG9idGFpbiBhIHByb3BlciBjYW5kaWRhdGUsIHVzaW5nIHRoZSBSVENJY2VDYW5kaWRhdGUgY29uc3RydWN0b3I6XG4gICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93M2MuZ2l0aHViLmlvL3dlYnJ0Yy1wYy8jZG9tLXJ0Y2ljZWNhbmRpZGF0ZS1jb25zdHJ1Y3RvclxuICAgICAgICAgICAgICAgIGNvbnN0IGNhbmRpZGF0ZUluaXQ6IFJUQ0ljZUNhbmRpZGF0ZUluaXQgPSBldmVudC5jYW5kaWRhdGUgYXMgUlRDSWNlQ2FuZGlkYXRlSW5pdDtcbiAgICAgICAgICAgICAgICBjb25zdCBpY2VDYW5kaWRhdGUgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZUluaXQpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgaWYgKGljZUNhbmRpZGF0ZS5jYW5kaWRhdGUgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9jYWxDYW5kaWRhdGVzUXVldWUucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5wYy5hZGRFdmVudExpc3RlbmVyKCdzaWduYWxpbmdzdGF0ZWNoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnc3RhYmxlJykge1xuICAgICAgICAgICAgICAgIC8vIFNEUCBPZmZlci9BbnN3ZXIgZmluaXNoZWQuIEFkZCBzdG9yZWQgcmVtb3RlIGNhbmRpZGF0ZXMuXG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuaWNlQ2FuZGlkYXRlTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBjYW5kaWRhdGUgPSB0aGlzLmljZUNhbmRpZGF0ZUxpc3Quc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYy5hZGRJY2VDYW5kaWRhdGUoPFJUQ0ljZUNhbmRpZGF0ZT5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZ2V0SWQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlndXJhdGlvbi5pZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBmcmVlcyB0aGUgcmVzb3VyY2VzIHVzZWQgYnkgV2ViUnRjUGVlclxuICAgICAqL1xuICAgIGRpc3Bvc2UoKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnRGlzcG9zaW5nIFdlYlJ0Y1BlZXInKTtcbiAgICAgICAgaWYgKHRoaXMucGMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMucGMuY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlID0gW107XG4gICAgICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlc1F1ZXVlID0gW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBERVBSRUNBVEVEIExFR0FDWSBNRVRIT0Q6IE9sZCBXZWJSVEMgdmVyc2lvbnMgZG9uJ3QgaW1wbGVtZW50XG4gICAgLy8gVHJhbnNjZWl2ZXJzLCBhbmQgaW5zdGVhZCBkZXBlbmQgb24gdGhlIGRlcHJlY2F0ZWRcbiAgICAvLyBcIm9mZmVyVG9SZWNlaXZlQXVkaW9cIiBhbmQgXCJvZmZlclRvUmVjZWl2ZVZpZGVvXCIuXG4gICAgcHJpdmF0ZSBjcmVhdGVPZmZlckxlZ2FjeSgpOiBQcm9taXNlPFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQ+IHtcbiAgICAgICAgaWYgKCEhdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICB0aGlzLmRlcHJlY2F0ZWRQZWVyQ29ubmVjdGlvblRyYWNrQXBpKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBoYXNBdWRpbyA9IHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLmF1ZGlvO1xuICAgICAgICBjb25zdCBoYXNWaWRlbyA9IHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvO1xuXG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIG9mZmVyVG9SZWNlaXZlQXVkaW86IHRoaXMuY29uZmlndXJhdGlvbi5tb2RlICE9PSBcInNlbmRvbmx5XCIgJiYgaGFzQXVkaW8sXG4gICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSAhPT0gXCJzZW5kb25seVwiICYmIGhhc1ZpZGVvLFxuICAgICAgICB9O1xuXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIltjcmVhdGVPZmZlckxlZ2FjeV0gUlRDUGVlckNvbm5lY3Rpb24uY3JlYXRlT2ZmZXIoKSBvcHRpb25zOlwiLCBKU09OLnN0cmluZ2lmeShvcHRpb25zKSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGMuY3JlYXRlT2ZmZXIob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBTRFAgb2ZmZXIgZnJvbSB0aGUgbG9jYWwgUlRDUGVlckNvbm5lY3Rpb24gdG8gc2VuZCB0byB0aGUgb3RoZXIgcGVlci5cbiAgICAgKiBPbmx5IGlmIHRoZSBuZWdvdGlhdGlvbiB3YXMgaW5pdGlhdGVkIGJ5IHRoaXMgcGVlci5cbiAgICAgKi9cbiAgICBhc3luYyBjcmVhdGVPZmZlcigpOiBQcm9taXNlPFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQ+IHtcbiAgICAgICAgLy8gVE9ETzogRGVsZXRlIHRoaXMgY29uZGl0aW9uYWwgd2hlbiBhbGwgc3VwcG9ydGVkIGJyb3dzZXJzIGFyZVxuICAgICAgICAvLyBtb2Rlcm4gZW5vdWdoIHRvIGltcGxlbWVudCB0aGUgVHJhbnNjZWl2ZXIgbWV0aG9kcy5cbiAgICAgICAgaWYgKCEoXCJhZGRUcmFuc2NlaXZlclwiIGluIHRoaXMucGMpKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICAgICAgICBcIltjcmVhdGVPZmZlcl0gTWV0aG9kIFJUQ1BlZXJDb25uZWN0aW9uLmFkZFRyYW5zY2VpdmVyKCkgaXMgTk9UIGF2YWlsYWJsZTsgdXNpbmcgTEVHQUNZIG9mZmVyVG9SZWNlaXZle0F1ZGlvLFZpZGVvfVwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlT2ZmZXJMZWdhY3koKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcIltjcmVhdGVPZmZlcl0gTWV0aG9kIFJUQ1BlZXJDb25uZWN0aW9uLmFkZFRyYW5zY2VpdmVyKCkgaXMgYXZhaWxhYmxlOyB1c2luZyBpdFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwZWMgZG9jOiBodHRwczovL3czYy5naXRodWIuaW8vd2VicnRjLXBjLyNkb20tcnRjcGVlcmNvbm5lY3Rpb24tYWRkdHJhbnNjZWl2ZXJcblxuICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLm1vZGUgIT09IFwicmVjdm9ubHlcIikge1xuICAgICAgICAgICAgLy8gVG8gc2VuZCBtZWRpYSwgYXNzdW1lIHRoYXQgYWxsIGRlc2lyZWQgbWVkaWEgdHJhY2tzIGhhdmUgYmVlblxuICAgICAgICAgICAgLy8gYWxyZWFkeSBhZGRlZCBieSBoaWdoZXIgbGV2ZWwgY29kZSB0byBvdXIgTWVkaWFTdHJlYW0uXG5cbiAgICAgICAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgW1dlYlJ0Y1BlZXIuY3JlYXRlT2ZmZXJdIERpcmVjdGlvbiBpcyAnJHt0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZX0nLCBidXQgbm8gc3RyZWFtIHdhcyBjb25maWd1cmVkIHRvIGJlIHNlbnRgXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCB0cmFjayBvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFTdHJlYW0uZ2V0VHJhY2tzKCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0Y0luaXQ6IFJUQ1J0cFRyYW5zY2VpdmVySW5pdCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZSxcbiAgICAgICAgICAgICAgICAgICAgc3RyZWFtczogW3RoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbV0sXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGlmICh0cmFjay5raW5kID09PSBcInZpZGVvXCIgJiYgdGhpcy5jb25maWd1cmF0aW9uLnNpbXVsY2FzdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVxdWVzdGVkIHNpemUgaXMgZW5vdWdoIHRvIGFzayBmb3IgMyBsYXllcnMuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNrU2V0dGluZ3MgPSB0cmFjay5nZXRTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFja0NvbnN0cyA9IHRyYWNrLmdldENvbnN0cmFpbnRzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhY2tXaWR0aDogbnVtYmVyID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrU2V0dGluZ3Mud2lkdGggPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0cmFja0NvbnN0cy53aWR0aCBhcyBDb25zdHJhaW5VTG9uZ1JhbmdlKS5pZGVhbCA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgKHRyYWNrQ29uc3RzLndpZHRoIGFzIG51bWJlcikgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgIDA7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNrSGVpZ2h0OiBudW1iZXIgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2tTZXR0aW5ncy5oZWlnaHQgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0cmFja0NvbnN0cy5oZWlnaHQgYXMgQ29uc3RyYWluVUxvbmdSYW5nZSkuaWRlYWwgPz9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0cmFja0NvbnN0cy5oZWlnaHQgYXMgbnVtYmVyKSA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgMDtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVPZmZlcl0gVmlkZW8gdHJhY2sgZGltZW5zaW9uczogJHt0cmFja1dpZHRofXgke3RyYWNrSGVpZ2h0fWApO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNrUGl4ZWxzID0gdHJhY2tXaWR0aCAqIHRyYWNrSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBsZXQgbWF4TGF5ZXJzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRyYWNrUGl4ZWxzID49IDk2MCAqIDU0MCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4TGF5ZXJzID0gMztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0cmFja1BpeGVscyA+PSA0ODAgKiAyNzApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heExheWVycyA9IDI7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhMYXllcnMgPSAxO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGNJbml0LnNlbmRFbmNvZGluZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgbCA9IDA7IGwgPCBtYXhMYXllcnM7IGwrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF5ZXJEaXYgPSAyICoqIChtYXhMYXllcnMgLSBsIC0gMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuY29kaW5nOiBSVENSdHBFbmNvZGluZ1BhcmFtZXRlcnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmlkOiBcInJkaXZcIiArIGxheWVyRGl2LnRvU3RyaW5nKCksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlIC0tIFByb3BlcnR5IG1pc3NpbmcgZnJvbSBET00gdHlwZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGFiaWxpdHlNb2RlOiBcIkwxVDFcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChbXCJkZXRhaWxcIiwgXCJ0ZXh0XCJdLmluY2x1ZGVzKHRyYWNrLmNvbnRlbnRIaW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByaW9yaXRpemUgYmVzdCByZXNvbHV0aW9uLCBmb3IgbWF4aW11bSBwaWN0dXJlIGRldGFpbC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNvZGluZy5zY2FsZVJlc29sdXRpb25Eb3duQnkgPSAxLjA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlIC0tIFByb3BlcnR5IG1pc3NpbmcgZnJvbSBET00gdHlwZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2RpbmcubWF4RnJhbWVyYXRlID0gTWF0aC5mbG9vcigzMCAvIGxheWVyRGl2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2Rpbmcuc2NhbGVSZXNvbHV0aW9uRG93bkJ5ID0gbGF5ZXJEaXY7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRjSW5pdC5zZW5kRW5jb2RpbmdzLnB1c2goZW5jb2RpbmcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgdGMgPSB0aGlzLnBjLmFkZFRyYW5zY2VpdmVyKHRyYWNrLCB0Y0luaXQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRyYWNrLmtpbmQgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICBsZXQgc2VuZFBhcmFtcyA9IHRjLnNlbmRlci5nZXRQYXJhbWV0ZXJzKCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBuZWVkU2V0UGFyYW1zID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZW5kUGFyYW1zLmRlZ3JhZGF0aW9uUHJlZmVyZW5jZT8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWdyYWRhdGlvblByZWZlcmVuY2UgZm9yIHZpZGVvOiBcImJhbGFuY2VkXCIsIFwibWFpbnRhaW4tZnJhbWVyYXRlXCIsIFwibWFpbnRhaW4tcmVzb2x1dGlvblwiLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cudzMub3JnL1RSLzIwMTgvQ1Itd2VicnRjLTIwMTgwOTI3LyNkb20tcnRjZGVncmFkYXRpb25wcmVmZXJlbmNlXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoW1wiZGV0YWlsXCIsIFwidGV4dFwiXS5pbmNsdWRlcyh0cmFjay5jb250ZW50SGludCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUGFyYW1zLmRlZ3JhZGF0aW9uUHJlZmVyZW5jZSA9IFwibWFpbnRhaW4tcmVzb2x1dGlvblwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kUGFyYW1zLmRlZ3JhZGF0aW9uUHJlZmVyZW5jZSA9IFwiYmFsYW5jZWRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFtjcmVhdGVPZmZlcl0gVmlkZW8gc2VuZGVyIERlZ3JhZGF0aW9uIFByZWZlcmVuY2Ugc2V0OiAke3NlbmRQYXJhbXMuZGVncmFkYXRpb25QcmVmZXJlbmNlfWBcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBGaXJlZm94IGltcGxlbWVudHMgZGVncmFkYXRpb25QcmVmZXJlbmNlIG9uIGVhY2ggaW5kaXZpZHVhbCBlbmNvZGluZyFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIChzZXQgaXQgb24gZXZlcnkgZWxlbWVudCBvZiB0aGUgc2VuZFBhcmFtcy5lbmNvZGluZ3MgYXJyYXkpXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG5lZWRTZXRQYXJhbXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRklYTUU6IENoZWNrIHRoYXQgdGhlIHNpbXVsY2FzdCBlbmNvZGluZ3Mgd2VyZSBhcHBsaWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IGRvZXNuJ3QgaW1wbGVtZW50IGBSVENSdHBUcmFuc2NlaXZlckluaXQuc2VuZEVuY29kaW5nc2BcbiAgICAgICAgICAgICAgICAgICAgLy8gc28gdGhlIG9ubHkgd2F5IHRvIGVuYWJsZSBzaW11bGNhc3QgaXMgd2l0aCBgUlRDUnRwU2VuZGVyLnNldFBhcmFtZXRlcnMoKWAuXG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgbmV4dCBibG9jayBjYW4gYmUgZGVsZXRlZCB3aGVuIEZpcmVmb3ggZml4ZXMgYnVnICMxMzk2OTE4OlxuICAgICAgICAgICAgICAgICAgICAvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzk2OTE4XG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgIC8vIE5PVEU6IFRoaXMgaXMgZG9uZSBpbiBhIHdheSB0aGF0IGlzIGNvbXBhdGlibGUgd2l0aCBhbGwgYnJvd3NlcnMsIHRvIHNhdmUgb25cbiAgICAgICAgICAgICAgICAgICAgLy8gYnJvd3Nlci1jb25kaXRpb25hbCBjb2RlLiBUaGUgaWRlYSBjb21lcyBmcm9tIFdlYlJUQyBBZGFwdGVyLmpzOlxuICAgICAgICAgICAgICAgICAgICAvLyAqIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJydGNIYWNrcy9hZGFwdGVyL2lzc3Vlcy85OThcbiAgICAgICAgICAgICAgICAgICAgLy8gKiBodHRwczovL2dpdGh1Yi5jb20vd2VicnRjSGFja3MvYWRhcHRlci9ibG9iL3Y3LjcuMC9zcmMvanMvZmlyZWZveC9maXJlZm94X3NoaW0uanMjTDIzMS1MMjU1XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZ3VyYXRpb24uc2ltdWxjYXN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VuZFBhcmFtcy5lbmNvZGluZ3M/Lmxlbmd0aCAhPT0gdGNJbml0LnNlbmRFbmNvZGluZ3MhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRQYXJhbXMuZW5jb2RpbmdzID0gdGNJbml0LnNlbmRFbmNvZGluZ3MhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmVlZFNldFBhcmFtcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAobmVlZFNldFBhcmFtcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbY3JlYXRlT2ZmZXJdIFNldHRpbmcgbmV3IFJUQ1J0cFNlbmRQYXJhbWV0ZXJzIHRvIHZpZGVvIHNlbmRlcmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0Yy5zZW5kZXIuc2V0UGFyYW1ldGVycyhzZW5kUGFyYW1zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1lc3NhZ2UgPSBgW1dlYlJ0Y1BlZXIuY3JlYXRlT2ZmZXJdIENhbm5vdCBzZXQgUlRDUnRwU2VuZFBhcmFtZXRlcnMgdG8gdmlkZW8gc2VuZGVyYDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlICs9IGA6ICR7ZXJyb3IubWVzc2FnZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBERUJVRzogVW5jb21tZW50IGZvciBkZXRhaWxzLlxuICAgICAgICAgICAgICAgIC8vIGlmICh0cmFjay5raW5kID09PSBcInZpZGVvXCIgJiYgdGhpcy5jb25maWd1cmF0aW9uLnNpbXVsY2FzdCkge1xuICAgICAgICAgICAgICAgIC8vICAgICAvLyBQcmludCBicm93c2VyIGNhcGFiaWxpdGllcy5cbiAgICAgICAgICAgICAgICAvLyAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgICAgICAgICAgLy8gICAgIGxvZ2dlci5kZWJ1ZyhgW2NyZWF0ZU9mZmVyXSBUcmFuc2NlaXZlciBzZW5kIGNhcGFiaWxpdGllcyAoc3RhdGljKTpcXG4ke0pTT04uc3RyaW5naWZ5KFJUQ1J0cFNlbmRlci5nZXRDYXBhYmlsaXRpZXM/LihcInZpZGVvXCIpLCBudWxsLCAyKX1gKTtcbiAgICAgICAgICAgICAgICAvLyAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgICAgICAgICAgLy8gICAgIGxvZ2dlci5kZWJ1ZyhgW2NyZWF0ZU9mZmVyXSBUcmFuc2NlaXZlciByZWN2IGNhcGFiaWxpdGllcyAoc3RhdGljKTpcXG4ke0pTT04uc3RyaW5naWZ5KFJUQ1J0cFJlY2VpdmVyLmdldENhcGFiaWxpdGllcz8uKFwidmlkZW9cIiksIG51bGwsIDIpfWApO1xuXG4gICAgICAgICAgICAgICAgLy8gICAgIC8vIFByaW50IHJlcXVlc3RlZCBUcmFuc2NlaXZlciBlbmNvZGluZ3MgYW5kIHBhcmFtZXRlcnMuXG4gICAgICAgICAgICAgICAgLy8gICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICAgICAgICAgIC8vICAgICBsb2dnZXIuZGVidWcoYFtjcmVhdGVPZmZlcl0gVHJhbnNjZWl2ZXIgc2VuZCBlbmNvZGluZ3MgKHJlcXVlc3RlZCk6XFxuJHtKU09OLnN0cmluZ2lmeSh0Y0luaXQuc2VuZEVuY29kaW5ncywgbnVsbCwgMil9YCk7XG4gICAgICAgICAgICAgICAgLy8gICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICAgICAgICAgIC8vICAgICBsb2dnZXIuZGVidWcoYFtjcmVhdGVPZmZlcl0gVHJhbnNjZWl2ZXIgc2VuZCBwYXJhbWV0ZXJzIChhY2NlcHRlZCk6XFxuJHtKU09OLnN0cmluZ2lmeSh0Yy5zZW5kZXIuZ2V0UGFyYW1ldGVycygpLCBudWxsLCAyKX1gKTtcbiAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUbyBqdXN0IHJlY2VpdmUgbWVkaWEsIGNyZWF0ZSBuZXcgcmVjdm9ubHkgdHJhbnNjZWl2ZXJzLlxuICAgICAgICAgICAgZm9yIChjb25zdCBraW5kIG9mIFtcImF1ZGlvXCIsIFwidmlkZW9cIl0pIHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgbWVkaWEga2luZCBzaG91bGQgYmUgdXNlZC5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzW2tpbmRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYVN0cmVhbSA9IG5ldyBNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkVHJhbnNjZWl2ZXIoa2luZCwge1xuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb246IHRoaXMuY29uZmlndXJhdGlvbi5tb2RlLFxuICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBbdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtXSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzZHBPZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHNkcE9mZmVyID0gYXdhaXQgdGhpcy5wYy5jcmVhdGVPZmZlcigpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbGV0IG1lc3NhZ2UgPSBgW1dlYlJ0Y1BlZXIuY3JlYXRlT2ZmZXJdIEJyb3dzZXIgZmFpbGVkIGNyZWF0aW5nIGFuIFNEUCBPZmZlcmA7XG4gICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgKz0gYDogJHtlcnJvci5tZXNzYWdlfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2RwT2ZmZXI7XG4gICAgfVxuXG4gICAgZGVwcmVjYXRlZFBlZXJDb25uZWN0aW9uVHJhY2tBcGkoKSB7XG4gICAgICAgIGZvciAoY29uc3QgdHJhY2sgb2YgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtIS5nZXRUcmFja3MoKSkge1xuICAgICAgICAgICAgdGhpcy5wYy5hZGRUcmFjayh0cmFjaywgdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhU3RyZWFtISk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIFNEUCBhbnN3ZXIgZnJvbSB0aGUgbG9jYWwgUlRDUGVlckNvbm5lY3Rpb24gdG8gc2VuZCB0byB0aGUgb3RoZXIgcGVlclxuICAgICAqIE9ubHkgaWYgdGhlIG5lZ290aWF0aW9uIHdhcyBpbml0aWF0ZWQgYnkgdGhlIG90aGVyIHBlZXJcbiAgICAgKi9cbiAgICBjcmVhdGVBbnN3ZXIoKTogUHJvbWlzZTxSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0PiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAvLyBUT0RPOiBEZWxldGUgdGhpcyBjb25kaXRpb25hbCB3aGVuIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMgYXJlXG4gICAgICAgICAgICAvLyBtb2Rlcm4gZW5vdWdoIHRvIGltcGxlbWVudCB0aGUgVHJhbnNjZWl2ZXIgbWV0aG9kcy5cbiAgICAgICAgICAgIGlmIChcImdldFRyYW5zY2VpdmVyc1wiIGluIHRoaXMucGMpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoXCJbY3JlYXRlQW5zd2VyXSBNZXRob2QgUlRDUGVlckNvbm5lY3Rpb24uZ2V0VHJhbnNjZWl2ZXJzKCkgaXMgYXZhaWxhYmxlOyB1c2luZyBpdFwiKTtcblxuICAgICAgICAgICAgICAgIC8vIEVuc3VyZSB0aGF0IHRoZSBQZWVyQ29ubmVjdGlvbiBhbHJlYWR5IGNvbnRhaW5zIG9uZSBUcmFuc2NlaXZlclxuICAgICAgICAgICAgICAgIC8vIGZvciBlYWNoIGtpbmQgb2YgbWVkaWEuXG4gICAgICAgICAgICAgICAgLy8gVGhlIFRyYW5zY2VpdmVycyBzaG91bGQgaGF2ZSBiZWVuIGFscmVhZHkgY3JlYXRlZCBpbnRlcm5hbGx5IGJ5XG4gICAgICAgICAgICAgICAgLy8gdGhlIFBDIGl0c2VsZiwgd2hlbiBgcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oc2RwT2ZmZXIpYCB3YXMgY2FsbGVkLlxuXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBraW5kIG9mIFtcImF1ZGlvXCIsIFwidmlkZW9cIl0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIG1lZGlhIGtpbmQgc2hvdWxkIGJlIHVzZWQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLm1lZGlhQ29uc3RyYWludHNba2luZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IHRjID0gdGhpcy5wY1xuICAgICAgICAgICAgICAgICAgICAgICAgLmdldFRyYW5zY2VpdmVycygpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgodGMpID0+IHRjLnJlY2VpdmVyLnRyYWNrLmtpbmQgPT09IGtpbmQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0Yykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRW5mb3JjZSBvdXIgZGVzaXJlZCBkaXJlY3Rpb24uXG4gICAgICAgICAgICAgICAgICAgICAgICB0Yy5kaXJlY3Rpb24gPSB0aGlzLmNvbmZpZ3VyYXRpb24ubW9kZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGAke2tpbmR9IHJlcXVlc3RlZCwgYnV0IG5vIHRyYW5zY2VpdmVyIHdhcyBjcmVhdGVkIGZyb20gcmVtb3RlIGRlc2NyaXB0aW9uYCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5wY1xuICAgICAgICAgICAgICAgICAgICAuY3JlYXRlQW5zd2VyKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKHNkcEFuc3dlcikgPT4gcmVzb2x2ZShzZHBBbnN3ZXIpKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiByZWplY3QoZXJyb3IpKTtcblxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIC8vIFRPRE86IERlbGV0ZSBlbHNlIGJyYW5jaCB3aGVuIGFsbCBzdXBwb3J0ZWQgYnJvd3NlcnMgYXJlXG4gICAgICAgICAgICAgICAgLy8gbW9kZXJuIGVub3VnaCB0byBpbXBsZW1lbnQgdGhlIFRyYW5zY2VpdmVyIG1ldGhvZHNcblxuICAgICAgICAgICAgICAgIGxldCBvZmZlckF1ZGlvLCBvZmZlclZpZGVvID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoISF0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cykge1xuICAgICAgICAgICAgICAgICAgICBvZmZlckF1ZGlvID0gKHR5cGVvZiB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA9PT0gJ2Jvb2xlYW4nKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVkaWFDb25zdHJhaW50cy5hdWRpbyA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIG9mZmVyVmlkZW8gPSAodHlwZW9mIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvID09PSAnYm9vbGVhbicpID9cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZWRpYUNvbnN0cmFpbnRzLnZpZGVvIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mZmVyVG9SZWNlaXZlQXVkaW86IG9mZmVyQXVkaW8sXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZlclRvUmVjZWl2ZVZpZGVvOiBvZmZlclZpZGVvXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGMhLmNyZWF0ZUFuc3dlcihjb25zdHJhaW50cylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKHNkcEFuc3dlciA9PiByZXNvbHZlKHNkcEFuc3dlcikpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGVsc2UsIHRoZXJlIGlzIG5vdGhpbmcgdG8gZG87IHRoZSBsZWdhY3kgY3JlYXRlQW5zd2VyKCkgb3B0aW9ucyBkb1xuICAgICAgICAgICAgLy8gbm90IG9mZmVyIGFueSBjb250cm9sIG92ZXIgd2hpY2ggdHJhY2tzIGFyZSBpbmNsdWRlZCBpbiB0aGUgYW5zd2VyLlxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIHBlZXIgaW5pdGlhdGVkIG5lZ290aWF0aW9uLiBTdGVwIDEvNCBvZiBTRFAgb2ZmZXItYW5zd2VyIHByb3RvY29sXG4gICAgICovXG4gICAgcHJvY2Vzc0xvY2FsT2ZmZXIob2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvY2FsRGVzY3JpcHRpb24gPSB0aGlzLnBjLmxvY2FsRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgICAgIGlmICghIWxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnTG9jYWwgZGVzY3JpcHRpb24gc2V0JywgbG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoJ0xvY2FsIGRlc2NyaXB0aW9uIGlzIG5vdCBkZWZpbmVkJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3RoZXIgcGVlciBpbml0aWF0ZWQgbmVnb3RpYXRpb24uIFN0ZXAgMi80IG9mIFNEUCBvZmZlci1hbnN3ZXIgcHJvdG9jb2xcbiAgICAgKi9cbiAgICBwcm9jZXNzUmVtb3RlT2ZmZXIoc2RwT2ZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgb2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ29mZmVyJyxcbiAgICAgICAgICAgICAgICBzZHA6IHNkcE9mZmVyXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKCdTRFAgb2ZmZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJywgb2ZmZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KCdSVENQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQgd2hlbiB0cnlpbmcgdG8gc2V0IHJlbW90ZSBkZXNjcmlwdGlvbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRSZW1vdGVEZXNjcmlwdGlvbihvZmZlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKCkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPdGhlciBwZWVyIGluaXRpYXRlZCBuZWdvdGlhdGlvbi4gU3RlcCAzLzQgb2YgU0RQIG9mZmVyLWFuc3dlciBwcm90b2NvbFxuICAgICAqL1xuICAgIHByb2Nlc3NMb2NhbEFuc3dlcihhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnU0RQIGFuc3dlciBjcmVhdGVkLCBzZXR0aW5nIGxvY2FsIGRlc2NyaXB0aW9uJyk7XG4gICAgICAgICAgICBpZiAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSA9PT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KCdSVENQZWVyQ29ubmVjdGlvbiBpcyBjbG9zZWQgd2hlbiB0cnlpbmcgdG8gc2V0IGxvY2FsIGRlc2NyaXB0aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnBjLnNldExvY2FsRGVzY3JpcHRpb24oYW5zd2VyKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgcGVlciBpbml0aWF0ZWQgbmVnb3RpYXRpb24uIFN0ZXAgNC80IG9mIFNEUCBvZmZlci1hbnN3ZXIgcHJvdG9jb2xcbiAgICAgKi9cbiAgICBwcm9jZXNzUmVtb3RlQW5zd2VyKHNkcEFuc3dlcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcicsXG4gICAgICAgICAgICAgICAgc2RwOiBzZHBBbnN3ZXJcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ1NEUCBhbnN3ZXIgcmVjZWl2ZWQsIHNldHRpbmcgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnBjLnNpZ25hbGluZ1N0YXRlID09PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoJ1JUQ1BlZXJDb25uZWN0aW9uIGlzIGNsb3NlZCB3aGVuIHRyeWluZyB0byBzZXQgcmVtb3RlIGRlc2NyaXB0aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcilcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERFQlVHOiBVbmNvbW1lbnQgZm9yIGRldGFpbHMuXG4gICAgICAgICAgICAgICAgICAgIC8vIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIGNvbnN0IHRjID0gdGhpcy5wYy5nZXRUcmFuc2NlaXZlcnMoKS5maW5kKCh0YykgPT4gdGMuc2VuZGVyLnRyYWNrPy5raW5kID09PSBcInZpZGVvXCIpO1xuICAgICAgICAgICAgICAgICAgICAvLyAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICBsb2dnZXIuZGVidWcoYFtwcm9jZXNzUmVtb3RlQW5zd2VyXSBUcmFuc2NlaXZlciBzZW5kIHBhcmFtZXRlcnMgKGVmZmVjdGl2ZSk6XFxuJHtKU09OLnN0cmluZ2lmeSh0Yz8uc2VuZGVyLmdldFBhcmFtZXRlcnMoKSwgbnVsbCwgMil9YCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiByZWplY3QoZXJyb3IpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGFzeW5jIHNldFJlbW90ZURlc2NyaXB0aW9uKHNkcDogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYy5zZXRSZW1vdGVEZXNjcmlwdGlvbihzZHApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGxiYWNrIGZ1bmN0aW9uIGludm9rZWQgd2hlbiBhbiBJQ0UgY2FuZGlkYXRlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ1JlbW90ZSBJQ0UgY2FuZGlkYXRlIHJlY2VpdmVkJywgaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlQ2FuZGlkYXRlc1F1ZXVlLnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5wYy5zaWduYWxpbmdTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Nsb3NlZCc6XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1BlZXJDb25uZWN0aW9uIG9iamVjdCBpcyBjbG9zZWQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3N0YWJsZSc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghIXRoaXMucGMucmVtb3RlRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGMuYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSkudGhlbigoKSA9PiByZXNvbHZlKCkpLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pY2VDYW5kaWRhdGVMaXN0LnB1c2goaWNlQ2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmljZUNhbmRpZGF0ZUxpc3QucHVzaChpY2VDYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFkZEljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZUxpc3RlbmVyKG90aGVySWQ6IHN0cmluZykge1xuICAgICAgICB0aGlzLnBjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGljZUNvbm5lY3Rpb25TdGF0ZTogUlRDSWNlQ29ubmVjdGlvblN0YXRlID0gdGhpcy5wYy5pY2VDb25uZWN0aW9uU3RhdGU7XG4gICAgICAgICAgICBzd2l0Y2ggKGljZUNvbm5lY3Rpb25TdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Rpc2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFBvc3NpYmxlIG5ldHdvcmsgZGlzY29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtc2cxID0gJ0ljZUNvbm5lY3Rpb25TdGF0ZSBvZiBSVENQZWVyQ29ubmVjdGlvbiAnICsgdGhpcy5jb25maWd1cmF0aW9uLmlkICsgJyAoJyArIG90aGVySWQgKyAnKSBjaGFuZ2UgdG8gXCJkaXNjb25uZWN0ZWRcIi4gUG9zc2libGUgbmV0d29yayBkaXNjb25uZWN0aW9uJztcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4obXNnMSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5vbkljZUNvbm5lY3Rpb25TdGF0ZUV4Y2VwdGlvbihFeGNlcHRpb25FdmVudE5hbWUuSUNFX0NPTk5FQ1RJT05fRElTQ09OTkVDVEVELCBtc2cxKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZmFpbGVkJzpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbXNnMiA9ICdJY2VDb25uZWN0aW9uU3RhdGUgb2YgUlRDUGVlckNvbm5lY3Rpb24gJyArIHRoaXMuY29uZmlndXJhdGlvbi5pZCArICcgKCcgKyBvdGhlcklkICsgJykgdG8gXCJmYWlsZWRcIic7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihtc2cyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm9uSWNlQ29ubmVjdGlvblN0YXRlRXhjZXB0aW9uKEV4Y2VwdGlvbkV2ZW50TmFtZS5JQ0VfQ09OTkVDVElPTl9GQUlMRUQsIG1zZzIpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjbG9zZWQnOlxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIubG9nKCdJY2VDb25uZWN0aW9uU3RhdGUgb2YgUlRDUGVlckNvbm5lY3Rpb24gJyArIHRoaXMuY29uZmlndXJhdGlvbi5pZCArICcgKCcgKyBvdGhlcklkICsgJykgY2hhbmdlIHRvIFwiY2xvc2VkXCInKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnbmV3JzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcIm5ld1wiJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNraW5nJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcImNoZWNraW5nXCInKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY29ubmVjdGVkJzpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnSWNlQ29ubmVjdGlvblN0YXRlIG9mIFJUQ1BlZXJDb25uZWN0aW9uICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uaWQgKyAnICgnICsgb3RoZXJJZCArICcpIGNoYW5nZSB0byBcImNvbm5lY3RlZFwiJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ0ljZUNvbm5lY3Rpb25TdGF0ZSBvZiBSVENQZWVyQ29ubmVjdGlvbiAnICsgdGhpcy5jb25maWd1cmF0aW9uLmlkICsgJyAoJyArIG90aGVySWQgKyAnKSBjaGFuZ2UgdG8gXCJjb21wbGV0ZWRcIicpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGhpZGRlblxuICAgICAqL1xuICAgIGdlbmVyYXRlVW5pcXVlSWQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHV1aWR2NCgpO1xuICAgIH1cblxufVxuXG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyUmVjdm9ubHkgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAncmVjdm9ubHknO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyU2VuZG9ubHkgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZG9ubHknO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNQZWVyU2VuZHJlY3YgZXh0ZW5kcyBXZWJSdGNQZWVyIHtcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBXZWJSdGNQZWVyQ29uZmlndXJhdGlvbikge1xuICAgICAgICBjb25maWd1cmF0aW9uLm1vZGUgPSAnc2VuZHJlY3YnO1xuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcbiAgICB9XG59XG4iLCIvKlxuICogKEMpIENvcHlyaWdodCAyMDE3LTIwMjIgT3BlblZpZHUgKGh0dHBzOi8vb3BlbnZpZHUuaW8pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqXG4gKi9cblxuLy8gdHNsaW50OmRpc2FibGU6bm8tc3RyaW5nLWxpdGVyYWxcblxuaW1wb3J0IHsgU3RyZWFtIH0gZnJvbSAnLi4vLi4vT3BlblZpZHUvU3RyZWFtJztcbmltcG9ydCB7IE9wZW5WaWR1TG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL09wZW5WaWR1TG9nZ2VyJztcbmltcG9ydCB7IFBsYXRmb3JtVXRpbHMgfSBmcm9tICcuLi9VdGlscy9QbGF0Zm9ybSc7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xuY29uc3QgbG9nZ2VyOiBPcGVuVmlkdUxvZ2dlciA9IE9wZW5WaWR1TG9nZ2VyLmdldEluc3RhbmNlKCk7XG4vKipcbiAqIEBoaWRkZW5cbiAqL1xubGV0IHBsYXRmb3JtOiBQbGF0Zm9ybVV0aWxzO1xuXG5pbnRlcmZhY2UgV2VicnRjU3RhdHNDb25maWcge1xuICAgIGludGVydmFsOiBudW1iZXIsXG4gICAgaHR0cEVuZHBvaW50OiBzdHJpbmdcbn1cblxuaW50ZXJmYWNlIEpTT05TdGF0c1Jlc3BvbnNlIHtcbiAgICAnQHRpbWVzdGFtcCc6IHN0cmluZyxcbiAgICBwYXJ0aWNpcGFudF9pZDogc3RyaW5nLFxuICAgIHNlc3Npb25faWQ6IHN0cmluZyxcbiAgICBwbGF0Zm9ybTogc3RyaW5nLFxuICAgIHBsYXRmb3JtX2Rlc2NyaXB0aW9uOiBzdHJpbmcsXG4gICAgc3RyZWFtOiBzdHJpbmcsXG4gICAgd2VicnRjX3N0YXRzOiBJV2VicnRjU3RhdHNcbn1cblxuLyoqXG4gKiBDb21tb24gV2ViUnRjU1RhdHMgZm9yIGxhdGVzdCBDaHJvbWl1bSBhbmQgRmlyZWZveCB2ZXJzaW9uc1xuICovXG5pbnRlcmZhY2UgSVdlYnJ0Y1N0YXRzIHtcbiAgICBpbmJvdW5kPzoge1xuICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyLFxuICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzTG9zdDogbnVtYmVyLFxuICAgICAgICAgICAgaml0dGVyOiBudW1iZXJcbiAgICAgICAgfSB8IHt9LFxuICAgICAgICB2aWRlbzoge1xuICAgICAgICAgICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyLFxuICAgICAgICAgICAgcGFja2V0c1JlY2VpdmVkOiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzTG9zdDogbnVtYmVyLFxuICAgICAgICAgICAgaml0dGVyPzogbnVtYmVyLCAvLyBGaXJlZm94XG4gICAgICAgICAgICBqaXR0ZXJCdWZmZXJEZWxheT86IG51bWJlciwgLy8gQ2hyb21lXG4gICAgICAgICAgICBmcmFtZXNEZWNvZGVkOiBudW1iZXIsXG4gICAgICAgICAgICBmaXJDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgbmFja0NvdW50OiBudW1iZXIsXG4gICAgICAgICAgICBwbGlDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgZnJhbWVIZWlnaHQ/OiBudW1iZXIsIC8vIENocm9tZVxuICAgICAgICAgICAgZnJhbWVXaWR0aD86IG51bWJlciwgLy8gQ2hyb21lXG4gICAgICAgICAgICBmcmFtZXNEcm9wcGVkPzogbnVtYmVyLCAvLyBDaHJvbWVcbiAgICAgICAgICAgIGZyYW1lc1JlY2VpdmVkPzogbnVtYmVyIC8vIENocm9tZVxuICAgICAgICB9IHwge31cbiAgICB9LFxuICAgIG91dGJvdW5kPzoge1xuICAgICAgICBhdWRpbzoge1xuICAgICAgICAgICAgYnl0ZXNTZW50OiBudW1iZXIsXG4gICAgICAgICAgICBwYWNrZXRzU2VudDogbnVtYmVyLFxuICAgICAgICB9IHwge30sXG4gICAgICAgIHZpZGVvOiB7XG4gICAgICAgICAgICBieXRlc1NlbnQ6IG51bWJlcixcbiAgICAgICAgICAgIHBhY2tldHNTZW50OiBudW1iZXIsXG4gICAgICAgICAgICBmaXJDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgZnJhbWVzRW5jb2RlZDogbnVtYmVyLFxuICAgICAgICAgICAgbmFja0NvdW50OiBudW1iZXIsXG4gICAgICAgICAgICBwbGlDb3VudDogbnVtYmVyLFxuICAgICAgICAgICAgcXBTdW06IG51bWJlcixcbiAgICAgICAgICAgIGZyYW1lSGVpZ2h0PzogbnVtYmVyLCAvLyBDaHJvbWVcbiAgICAgICAgICAgIGZyYW1lV2lkdGg/OiBudW1iZXIsIC8vIENocm9tZVxuICAgICAgICAgICAgZnJhbWVzU2VudD86IG51bWJlciAvLyBDaHJvbWVcbiAgICAgICAgfSB8IHt9XG4gICAgfSxcbiAgICBjYW5kaWRhdGVwYWlyPzoge1xuICAgICAgICBjdXJyZW50Um91bmRUcmlwVGltZT86IG51bWJlciAvLyBDaHJvbWVcbiAgICAgICAgYXZhaWxhYmxlT3V0Z29pbmdCaXRyYXRlPzogbnVtYmVyIC8vQ2hyb21lXG4gICAgICAgIC8vIGF2YWlsYWJsZUluY29taW5nQml0cmF0ZT86IG51bWJlciAvLyBObyBzdXBwb3J0IGZvciBhbnkgYnJvd3NlcnMgKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SVENJY2VDYW5kaWRhdGVQYWlyU3RhdHMvYXZhaWxhYmxlSW5jb21pbmdCaXRyYXRlKVxuICAgIH1cbn07XG5cbmV4cG9ydCBjbGFzcyBXZWJSdGNTdGF0cyB7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IFNUQVRTX0lURU1fTkFNRSA9ICd3ZWJydGMtc3RhdHMtY29uZmlnJztcblxuICAgIHByaXZhdGUgd2ViUnRjU3RhdHNFbmFibGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSB3ZWJSdGNTdGF0c0ludGVydmFsSWQ6IE5vZGVKUy5UaW1lcjtcbiAgICBwcml2YXRlIHN0YXRzSW50ZXJ2YWwgPSAxO1xuICAgIHByaXZhdGUgUE9TVF9VUkw6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgc3RyZWFtOiBTdHJlYW0pIHtcbiAgICAgICAgcGxhdGZvcm0gPSBQbGF0Zm9ybVV0aWxzLmdldEluc3RhbmNlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2ViUnRjU3RhdHNFbmFibGVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBpbml0V2ViUnRjU3RhdHMoKTogdm9pZCB7XG5cbiAgICAgICAgY29uc3Qgd2VicnRjT2JqID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5TVEFUU19JVEVNX05BTUUpO1xuXG4gICAgICAgIGlmICghIXdlYnJ0Y09iaikge1xuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3Qgd2VicnRjU3RhdHNDb25maWc6IFdlYnJ0Y1N0YXRzQ29uZmlnID0gSlNPTi5wYXJzZSh3ZWJydGNPYmopO1xuICAgICAgICAgICAgLy8gd2VicnRjIG9iamVjdCBmb3VuZCBpbiBsb2NhbCBzdG9yYWdlXG4gICAgICAgICAgICBsb2dnZXIud2FybignV2ViUnRjIHN0YXRzIGVuYWJsZWQgZm9yIHN0cmVhbSAnICsgdGhpcy5zdHJlYW0uc3RyZWFtSWQgKyAnIG9mIGNvbm5lY3Rpb24gJyArIHRoaXMuc3RyZWFtLmNvbm5lY3Rpb24uY29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdsb2NhbFN0b3JhZ2UgaXRlbTogJyArIEpTT04uc3RyaW5naWZ5KHdlYnJ0Y1N0YXRzQ29uZmlnKSk7XG5cbiAgICAgICAgICAgIHRoaXMuUE9TVF9VUkwgPSB3ZWJydGNTdGF0c0NvbmZpZy5odHRwRW5kcG9pbnQ7XG4gICAgICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWwgPSB3ZWJydGNTdGF0c0NvbmZpZy5pbnRlcnZhbDsgIC8vIEludGVydmFsIGluIHNlY29uZHNcblxuICAgICAgICAgICAgdGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kU3RhdHNUb0h0dHBFbmRwb2ludCgpO1xuICAgICAgICAgICAgfSwgdGhpcy5zdGF0c0ludGVydmFsICogMTAwMCk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnV2ViUnRjIHN0YXRzIG5vdCBlbmFibGVkJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB7XG4gICAgLy8gXCJsb2NhbENhbmRpZGF0ZVwiOiB7XG4gICAgLy8gICAgIFwiaWRcIjogXCJSVENJY2VDYW5kaWRhdGVfL3I0UDF5MlFcIixcbiAgICAvLyAgICAgXCJ0aW1lc3RhbXBcIjogMTYxNjA4MDE1NTYxNyxcbiAgICAvLyAgICAgXCJ0eXBlXCI6IFwibG9jYWwtY2FuZGlkYXRlXCIsXG4gICAgLy8gICAgIFwidHJhbnNwb3J0SWRcIjogXCJSVENUcmFuc3BvcnRfMF8xXCIsXG4gICAgLy8gICAgIFwiaXNSZW1vdGVcIjogZmFsc2UsXG4gICAgLy8gICAgIFwibmV0d29ya1R5cGVcIjogXCJ3aWZpXCIsXG4gICAgLy8gICAgIFwiaXBcIjogXCIxMjMuNDUuNjcuODlcIixcbiAgICAvLyAgICAgXCJwb3J0XCI6IDYzMzQwLFxuICAgIC8vICAgICBcInByb3RvY29sXCI6IFwidWRwXCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlVHlwZVwiOiBcInNyZmx4XCIsXG4gICAgLy8gICAgIFwicHJpb3JpdHlcIjogMTY4NjA1MjYwNyxcbiAgICAvLyAgICAgXCJkZWxldGVkXCI6IGZhbHNlLFxuICAgIC8vICAgICBcInJhd1wiOiBbXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjMzNDU0MTI5MjEgMSB1ZHAgMTY4NjA1MjYwNyAxMjMuNDUuNjcuODkgNjMzNDAgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMS4zMSBycG9ydCA2MzM0MCBnZW5lcmF0aW9uIDAgdWZyYWcgMFp0VCBuZXR3b3JrLWlkIDEgbmV0d29yay1jb3N0IDEwXCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjU4MDk0NDgyIDEgdWRwIDQxODg1Njk1IDk4Ljc2LjU0LjMyIDQ0NDMxIHR5cCByZWxheSByYWRkciAxMjMuNDUuNjcuODkgcnBvcnQgNjMzNDAgZ2VuZXJhdGlvbiAwIHVmcmFnIDBadFQgbmV0d29yay1pZCAxIG5ldHdvcmstY29zdCAxMFwiXG4gICAgLy8gICAgIF1cbiAgICAvLyB9LFxuICAgIC8vIFwicmVtb3RlQ2FuZGlkYXRlXCI6IHtcbiAgICAvLyAgICAgXCJpZFwiOiBcIlJUQ0ljZUNhbmRpZGF0ZV8xWU8xOGdwaFwiLFxuICAgIC8vICAgICBcInRpbWVzdGFtcFwiOiAxNjE2MDgwMTU1NjE3LFxuICAgIC8vICAgICBcInR5cGVcIjogXCJyZW1vdGUtY2FuZGlkYXRlXCIsXG4gICAgLy8gICAgIFwidHJhbnNwb3J0SWRcIjogXCJSVENUcmFuc3BvcnRfMF8xXCIsXG4gICAgLy8gICAgIFwiaXNSZW1vdGVcIjogdHJ1ZSxcbiAgICAvLyAgICAgXCJpcFwiOiBcIjEyLjM0LjU2Ljc4XCIsXG4gICAgLy8gICAgIFwicG9ydFwiOiA2NDk4OSxcbiAgICAvLyAgICAgXCJwcm90b2NvbFwiOiBcInVkcFwiLFxuICAgIC8vICAgICBcImNhbmRpZGF0ZVR5cGVcIjogXCJzcmZseFwiLFxuICAgIC8vICAgICBcInByaW9yaXR5XCI6IDE2Nzk4MTkyNjMsXG4gICAgLy8gICAgIFwiZGVsZXRlZFwiOiBmYWxzZSxcbiAgICAvLyAgICAgXCJyYXdcIjogW1xuICAgIC8vICAgICBcImNhbmRpZGF0ZToxNiAxIFVEUCAxNjc5ODE5MjYzIDEyLjM0LjU2Ljc4IDY0OTg5IHR5cCBzcmZseCByYWRkciAxNzIuMTkuMC4xIHJwb3J0IDY0OTg5XCIsXG4gICAgLy8gICAgIFwiY2FuZGlkYXRlOjE2IDEgVURQIDE2Nzk4MTkyNjMgMTIuMzQuNTYuNzggNjQ5ODkgdHlwIHNyZmx4IHJhZGRyIDE3Mi4xOS4wLjEgcnBvcnQgNjQ5ODlcIlxuICAgIC8vICAgICBdXG4gICAgLy8gfVxuICAgIC8vIH1cbiAgICAvLyBIYXZlIGJlZW4gdGVzdGVkIGluOlxuICAgIC8vICAgLSBMaW51eCBEZXNrdG9wOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIDg5LjAuNDM4OS45MFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzQuMC4zOTExLjIxOFxuICAgIC8vICAgICAgIC0gRmlyZWZveCA4NlxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgOTEuMC44MjUuMFxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBXaW5kb3dzIERlc2t0b3A6XG4gICAgLy8gICAgICAgLSBDaHJvbWUgODkuMC40Mzg5LjkwXG4gICAgLy8gICAgICAgLSBPcGVyYSA3NC4wLjM5MTEuMjMyXG4gICAgLy8gICAgICAgLSBGaXJlZm94IDg2LjAuMVxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgODkuMC43NzQuNTRcbiAgICAvLyAgICAgICAtIEVsZWN0cm9uIDExLjMuMCAoQ2hyb21pdW0gODcuMC40MjgwLjE0MSlcbiAgICAvLyAgIC0gTWFjT1MgRGVza3RvcDpcbiAgICAvLyAgICAgICAtIENocm9tZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIEZpcmVmb3ggODcuMFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzUuMC4zOTY5LjkzXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSA4OS4wLjc3NC41N1xuICAgIC8vICAgICAgIC0gU2FmYXJpIDE0LjAgKDE0NjEwLjEuMjguMS45KVxuICAgIC8vICAgICAgIC0gRWxlY3Ryb24gMTEuMy4wIChDaHJvbWl1bSA4Ny4wLjQyODAuMTQxKVxuICAgIC8vICAgLSBBbmRyb2lkOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIE1vYmlsZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIE9wZXJhIDYyLjMuMzE0Ni41Nzc2M1xuICAgIC8vICAgICAgIC0gRmlyZWZveCBNb2JpbGUgODYuNi4xXG4gICAgLy8gICAgICAgLSBNaWNyb3NvZnQgRWRnZSBNb2JpbGUgNDYuMDIuNC41MTQ3XG4gICAgLy8gICAgICAgLSBJb25pYyA1XG4gICAgLy8gICAgICAgLSBSZWFjdCBOYXRpdmUgMC42NFxuICAgIC8vICAgLSBpT1M6XG4gICAgLy8gICAgICAgLSBTYWZhcmkgTW9iaWxlXG4gICAgLy8gICAgICAgLSDCv0lvbmljP1xuICAgIC8vICAgICAgIC0gwr9SZWFjdCBOYXRpdmU/XG4gICAgcHVibGljIGdldFNlbGVjdGVkSWNlQ2FuZGlkYXRlSW5mbygpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBzdGF0c1JlcG9ydDogYW55ID0gYXdhaXQgdGhpcy5zdHJlYW0uZ2V0UlRDUGVlckNvbm5lY3Rpb24oKS5nZXRTdGF0cygpO1xuICAgICAgICAgICAgbGV0IHRyYW5zcG9ydFN0YXQ7XG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQ2FuZGlkYXRlczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbW90ZUNhbmRpZGF0ZXM6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBzdGF0c1JlcG9ydC5mb3JFYWNoKChzdGF0OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdC50eXBlID09PSAndHJhbnNwb3J0JyAmJiAocGxhdGZvcm0uaXNDaHJvbWl1bSgpIHx8IHBsYXRmb3JtLmlzU2FmYXJpQnJvd3NlcigpIHx8IHBsYXRmb3JtLmlzUmVhY3ROYXRpdmUoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNwb3J0U3RhdCA9IHN0YXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCAoc3RhdC50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NhbmRpZGF0ZS1wYWlyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZVBhaXJzLnNldChzdGF0LmlkLCBzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdsb2NhbC1jYW5kaWRhdGUnOlxuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxDYW5kaWRhdGVzLnNldChzdGF0LmlkLCBzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdyZW1vdGUtY2FuZGlkYXRlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZXMuc2V0KHN0YXQuaWQsIHN0YXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBsZXQgc2VsZWN0ZWRDYW5kaWRhdGVQYWlyO1xuICAgICAgICAgICAgaWYgKHRyYW5zcG9ydFN0YXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkQ2FuZGlkYXRlUGFpcklkID0gdHJhbnNwb3J0U3RhdC5zZWxlY3RlZENhbmRpZGF0ZVBhaXJJZFxuICAgICAgICAgICAgICAgIHNlbGVjdGVkQ2FuZGlkYXRlUGFpciA9IGNhbmRpZGF0ZVBhaXJzLmdldChzZWxlY3RlZENhbmRpZGF0ZVBhaXJJZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYmFzaWNhbGx5IEZpcmVmb3hcbiAgICAgICAgICAgICAgICBjb25zdCBsZW5ndGggPSBjYW5kaWRhdGVQYWlycy5zaXplO1xuICAgICAgICAgICAgICAgIGNvbnN0IGl0ZXJhdG9yID0gY2FuZGlkYXRlUGFpcnMudmFsdWVzKCk7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyID0gaXRlcmF0b3IubmV4dCgpLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FuZGlkYXRlUGFpclsnc2VsZWN0ZWQnXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRDYW5kaWRhdGVQYWlyID0gY2FuZGlkYXRlUGFpcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbG9jYWxDYW5kaWRhdGVJZCA9IHNlbGVjdGVkQ2FuZGlkYXRlUGFpci5sb2NhbENhbmRpZGF0ZUlkO1xuICAgICAgICAgICAgY29uc3QgcmVtb3RlQ2FuZGlkYXRlSWQgPSBzZWxlY3RlZENhbmRpZGF0ZVBhaXIucmVtb3RlQ2FuZGlkYXRlSWQ7XG4gICAgICAgICAgICBsZXQgZmluYWxMb2NhbENhbmRpZGF0ZSA9IGxvY2FsQ2FuZGlkYXRlcy5nZXQobG9jYWxDYW5kaWRhdGVJZCk7XG4gICAgICAgICAgICBpZiAoISFmaW5hbExvY2FsQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRMb2NhbEljZUNhbmRpZGF0ZUxpc3QoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjYW5kID0gY2FuZExpc3QuZmlsdGVyKChjOiBSVENJY2VDYW5kaWRhdGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICghIWMuY2FuZGlkYXRlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLmlwKSA+PSAwIHx8IGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxMb2NhbENhbmRpZGF0ZS5hZGRyZXNzKSA+PSAwKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbExvY2FsQ2FuZGlkYXRlLnBvcnQpID49IDApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3ID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgYyBvZiBjYW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbmFsTG9jYWxDYW5kaWRhdGUucmF3LnB1c2goYy5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluYWxMb2NhbENhbmRpZGF0ZSA9ICdFUlJPUjogTm8gYWN0aXZlIGxvY2FsIElDRSBjYW5kaWRhdGUuIFByb2JhYmx5IElDRS1UQ1AgaXMgYmVpbmcgdXNlZCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBmaW5hbFJlbW90ZUNhbmRpZGF0ZSA9IHJlbW90ZUNhbmRpZGF0ZXMuZ2V0KHJlbW90ZUNhbmRpZGF0ZUlkKTtcbiAgICAgICAgICAgIGlmICghIWZpbmFsUmVtb3RlQ2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZExpc3QgPSB0aGlzLnN0cmVhbS5nZXRSZW1vdGVJY2VDYW5kaWRhdGVMaXN0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FuZCA9IGNhbmRMaXN0LmZpbHRlcigoYzogUlRDSWNlQ2FuZGlkYXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoISFjLmNhbmRpZGF0ZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKGMuY2FuZGlkYXRlLmluZGV4T2YoZmluYWxSZW1vdGVDYW5kaWRhdGUuaXApID49IDAgfHwgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5hZGRyZXNzKSA+PSAwKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgYy5jYW5kaWRhdGUuaW5kZXhPZihmaW5hbFJlbW90ZUNhbmRpZGF0ZS5wb3J0KSA+PSAwKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBmaW5hbFJlbW90ZUNhbmRpZGF0ZS5yYXcgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBjIG9mIGNhbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUucmF3LnB1c2goYy5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluYWxSZW1vdGVDYW5kaWRhdGUgPSAnRVJST1I6IE5vIGFjdGl2ZSByZW1vdGUgSUNFIGNhbmRpZGF0ZS4gUHJvYmFibHkgSUNFLVRDUCBpcyBiZWluZyB1c2VkJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgIGxvY2FsQ2FuZGlkYXRlOiBmaW5hbExvY2FsQ2FuZGlkYXRlLFxuICAgICAgICAgICAgICAgIHJlbW90ZUNhbmRpZGF0ZTogZmluYWxSZW1vdGVDYW5kaWRhdGVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RvcFdlYlJ0Y1N0YXRzKCkge1xuICAgICAgICBpZiAodGhpcy53ZWJSdGNTdGF0c0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy53ZWJSdGNTdGF0c0ludGVydmFsSWQpO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ1dlYlJ0YyBzdGF0cyBzdG9wcGVkIGZvciBkaXNwb3NlZCBzdHJlYW0gJyArIHRoaXMuc3RyZWFtLnN0cmVhbUlkICsgJyBvZiBjb25uZWN0aW9uICcgKyB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHNlbmRTdGF0cyh1cmw6IHN0cmluZywgcmVzcG9uc2U6IEpTT05TdGF0c1Jlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjb25maWd1cmF0aW9uOiBSZXF1ZXN0SW5pdCA9IHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgICdDb250ZW50LXR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSxcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCBmZXRjaCh1cmwsIGNvbmZpZ3VyYXRpb24pO1xuXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoYHNlbmRTdGF0cyBlcnJvcjogJHtKU09OLnN0cmluZ2lmeShlcnJvcil9YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHNlbmRTdGF0c1RvSHR0cEVuZHBvaW50KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgd2VicnRjU3RhdHM6IElXZWJydGNTdGF0cyA9IGF3YWl0IHRoaXMuZ2V0Q29tbW9uU3RhdHMoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gdGhpcy5nZW5lcmF0ZUpTT05TdGF0c1Jlc3BvbnNlKHdlYnJ0Y1N0YXRzKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZFN0YXRzKHRoaXMuUE9TVF9VUkwsIHJlc3BvbnNlKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGF2ZSBiZWVuIHRlc3RlZCBpbjpcbiAgICAvLyAgIC0gTGludXggRGVza3RvcDpcbiAgICAvLyAgICAgICAtIENocm9tZSA4OS4wLjQzODkuOTBcbiAgICAvLyAgICAgICAtIE9wZXJhIDc0LjAuMzkxMS4yMThcbiAgICAvLyAgICAgICAtIEZpcmVmb3ggODZcbiAgICAvLyAgICAgICAtIE1pY3Jvc29mdCBFZGdlIDkxLjAuODI1LjBcbiAgICAvLyAgICAgICAtIEVsZWN0cm9uIDExLjMuMCAoQ2hyb21pdW0gODcuMC40MjgwLjE0MSlcbiAgICAvLyAgIC0gV2luZG93cyBEZXNrdG9wOlxuICAgIC8vICAgICAgIC0gQ2hyb21lIDg5LjAuNDM4OS45MFxuICAgIC8vICAgICAgIC0gT3BlcmEgNzQuMC4zOTExLjIzMlxuICAgIC8vICAgICAgIC0gRmlyZWZveCA4Ni4wLjFcbiAgICAvLyAgICAgICAtIE1pY3Jvc29mdCBFZGdlIDg5LjAuNzc0LjU0XG4gICAgLy8gICAgICAgLSBFbGVjdHJvbiAxMS4zLjAgKENocm9taXVtIDg3LjAuNDI4MC4xNDEpXG4gICAgLy8gICAtIE1hY09TIERlc2t0b3A6XG4gICAgLy8gICAgICAgLSBDaHJvbWUgODkuMC40Mzg5LjkwXG4gICAgLy8gICAgICAgLSBPcGVyYSA3NS4wLjM5NjkuOTNcbiAgICAvLyAgICAgICAtIEZpcmVmb3ggODcuMFxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgODkuMC43NzQuNTdcbiAgICAvLyAgICAgICAtIFNhZmFyaSAxNC4wICgxNDYxMC4xLjI4LjEuOSlcbiAgICAvLyAgICAgICAtIEVsZWN0cm9uIDExLjMuMCAoQ2hyb21pdW0gODcuMC40MjgwLjE0MSlcbiAgICAvLyAgIC0gQW5kcm9pZDpcbiAgICAvLyAgICAgICAtIENocm9tZSBNb2JpbGUgODkuMC40Mzg5LjkwXG4gICAgLy8gICAgICAgLSBPcGVyYSA2Mi4zLjMxNDYuNTc3NjNcbiAgICAvLyAgICAgICAtIEZpcmVmb3ggTW9iaWxlIDg2LjYuMVxuICAgIC8vICAgICAgIC0gTWljcm9zb2Z0IEVkZ2UgTW9iaWxlIDQ2LjAyLjQuNTE0N1xuICAgIC8vICAgICAgIC0gSW9uaWMgNVxuICAgIC8vICAgICAgIC0gUmVhY3QgTmF0aXZlIDAuNjRcbiAgICAvLyAgIC0gaU9TOlxuICAgIC8vICAgICAgIC0gU2FmYXJpIE1vYmlsZVxuICAgIC8vICAgICAgIC0gwr9Jb25pYz9cbiAgICAvLyAgICAgICAtIMK/UmVhY3QgTmF0aXZlP1xuICAgIHB1YmxpYyBhc3luYyBnZXRDb21tb25TdGF0cygpOiBQcm9taXNlPElXZWJydGNTdGF0cz4ge1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhdHNSZXBvcnQ6IGFueSA9IGF3YWl0IHRoaXMuc3RyZWFtLmdldFJUQ1BlZXJDb25uZWN0aW9uKCkuZ2V0U3RhdHMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZTogSVdlYnJ0Y1N0YXRzID0gdGhpcy5nZXRXZWJSdGNTdGF0c1Jlc3BvbnNlT3V0bGluZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZpZGVvVHJhY2tTdGF0cyA9IFsnZnJhbWVzUmVjZWl2ZWQnLCAnZnJhbWVzRHJvcHBlZCcsICdmcmFtZXNTZW50JywgJ2ZyYW1lSGVpZ2h0JywgJ2ZyYW1lV2lkdGgnXTtcbiAgICAgICAgICAgICAgICBjb25zdCBjYW5kaWRhdGVQYWlyU3RhdHMgPSBbJ2F2YWlsYWJsZU91dGdvaW5nQml0cmF0ZScsICdjdXJyZW50Um91bmRUcmlwVGltZSddO1xuXG4gICAgICAgICAgICAgICAgc3RhdHNSZXBvcnQuZm9yRWFjaCgoc3RhdDogYW55KSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IG1lZGlhVHlwZSA9IHN0YXQubWVkaWFUeXBlICE9IG51bGwgPyBzdGF0Lm1lZGlhVHlwZSA6IHN0YXQua2luZDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYWRkU3RhdCA9IChkaXJlY3Rpb246IHN0cmluZywga2V5OiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0W2tleV0gIT0gbnVsbCAmJiByZXNwb25zZVtkaXJlY3Rpb25dICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1lZGlhVHlwZSAmJiAodmlkZW9UcmFja1N0YXRzLmluZGV4T2Yoa2V5KSA+IC0xKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVR5cGUgPSAndmlkZW8nO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGlyZWN0aW9uICE9IG51bGwgJiYgbWVkaWFUeXBlICE9IG51bGwgJiYga2V5ICE9IG51bGwgJiYgcmVzcG9uc2VbZGlyZWN0aW9uXVttZWRpYVR5cGVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VbZGlyZWN0aW9uXVttZWRpYVR5cGVdW2tleV0gPSBOdW1iZXIoc3RhdFtrZXldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZGlyZWN0aW9uICE9IG51bGwgJiYga2V5ICE9IG51bGwgJiYgY2FuZGlkYXRlUGFpclN0YXRzLmluY2x1ZGVzKGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FuZGlkYXRlLXBhaXItc3RhdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VbZGlyZWN0aW9uXVtrZXldID0gTnVtYmVyKHN0YXRba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChzdGF0LnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJvdXRib3VuZC1ydHBcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdieXRlc1NlbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdwYWNrZXRzU2VudCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ291dGJvdW5kJywgJ2ZyYW1lc0VuY29kZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICduYWNrQ291bnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdvdXRib3VuZCcsICdmaXJDb3VudCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ291dGJvdW5kJywgJ3BsaUNvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnb3V0Ym91bmQnLCAncXBTdW0nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJpbmJvdW5kLXJ0cFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnYnl0ZXNSZWNlaXZlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAncGFja2V0c1JlY2VpdmVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdwYWNrZXRzTG9zdCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnaml0dGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdmcmFtZXNEZWNvZGVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICduYWNrQ291bnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdpbmJvdW5kJywgJ2ZpckNvdW50Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnaW5ib3VuZCcsICdwbGlDb3VudCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndHJhY2snOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ2luYm91bmQnLCAnaml0dGVyQnVmZmVyRGVsYXknKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdpbmJvdW5kJywgJ2ZyYW1lc1JlY2VpdmVkJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnb3V0Ym91bmQnLCAnZnJhbWVzRHJvcHBlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQoJ291dGJvdW5kJywgJ2ZyYW1lc1NlbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KHRoaXMuc3RyZWFtLmlzTG9jYWwoKSA/ICdvdXRib3VuZCcgOiAnaW5ib3VuZCcsICdmcmFtZUhlaWdodCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFN0YXQodGhpcy5zdHJlYW0uaXNMb2NhbCgpID8gJ291dGJvdW5kJyA6ICdpbmJvdW5kJywgJ2ZyYW1lV2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NhbmRpZGF0ZS1wYWlyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRTdGF0KCdjYW5kaWRhdGVwYWlyJywgJ2N1cnJlbnRSb3VuZFRyaXBUaW1lJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkU3RhdCgnY2FuZGlkYXRlcGFpcicsICdhdmFpbGFibGVPdXRnb2luZ0JpdHJhdGUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRlIGNhbmRpZGF0ZXBhaXIgZnJvbSByZXNwb25zZSBpZiBudWxsXG4gICAgICAgICAgICAgICAgaWYoIXJlc3BvbnNlPy5jYW5kaWRhdGVwYWlyIHx8IE9iamVjdC5rZXlzKDxPYmplY3Q+cmVzcG9uc2UuY2FuZGlkYXRlcGFpcikubGVuZ3RoID09PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHJlc3BvbnNlLmNhbmRpZGF0ZXBhaXI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGdldHRpbmcgY29tbW9uIHN0YXRzOiAnLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZUpTT05TdGF0c1Jlc3BvbnNlKHN0YXRzOiBJV2VicnRjU3RhdHMpOiBKU09OU3RhdHNSZXNwb25zZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnQHRpbWVzdGFtcCc6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgIHBhcnRpY2lwYW50X2lkOiB0aGlzLnN0cmVhbS5jb25uZWN0aW9uLmRhdGEsXG4gICAgICAgICAgICBzZXNzaW9uX2lkOiB0aGlzLnN0cmVhbS5zZXNzaW9uLnNlc3Npb25JZCxcbiAgICAgICAgICAgIHBsYXRmb3JtOiBwbGF0Zm9ybS5nZXROYW1lKCksXG4gICAgICAgICAgICBwbGF0Zm9ybV9kZXNjcmlwdGlvbjogcGxhdGZvcm0uZ2V0RGVzY3JpcHRpb24oKSxcbiAgICAgICAgICAgIHN0cmVhbTogJ3dlYlJUQycsXG4gICAgICAgICAgICB3ZWJydGNfc3RhdHM6IHN0YXRzXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRXZWJSdGNTdGF0c1Jlc3BvbnNlT3V0bGluZSgpOiBJV2VicnRjU3RhdHMge1xuICAgICAgICBpZiAodGhpcy5zdHJlYW0uaXNMb2NhbCgpKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG91dGJvdW5kOiB7XG4gICAgICAgICAgICAgICAgICAgIGF1ZGlvOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW86IHt9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjYW5kaWRhdGVwYWlyOiB7fVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW5ib3VuZDoge1xuICAgICAgICAgICAgICAgICAgICBhdWRpbzoge30sXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvOiB7fVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbn0iXX0= diff --git a/openvidu-internet-explorer/web/resources/images/favicon.ico b/openvidu-internet-explorer/web/resources/images/favicon.ico deleted file mode 100644 index 0e2249ad..00000000 Binary files a/openvidu-internet-explorer/web/resources/images/favicon.ico and /dev/null differ diff --git a/openvidu-internet-explorer/web/resources/images/openvidu_globe_bg_transp_cropped.png b/openvidu-internet-explorer/web/resources/images/openvidu_globe_bg_transp_cropped.png deleted file mode 100644 index e0309e62..00000000 Binary files a/openvidu-internet-explorer/web/resources/images/openvidu_globe_bg_transp_cropped.png and /dev/null differ diff --git a/openvidu-internet-explorer/web/resources/images/openvidu_grey_bg_transp_cropped.png b/openvidu-internet-explorer/web/resources/images/openvidu_grey_bg_transp_cropped.png deleted file mode 100644 index 49f311a6..00000000 Binary files a/openvidu-internet-explorer/web/resources/images/openvidu_grey_bg_transp_cropped.png and /dev/null differ diff --git a/openvidu-internet-explorer/web/resources/images/openvidu_vert_white_bg_trans_cropped.png b/openvidu-internet-explorer/web/resources/images/openvidu_vert_white_bg_trans_cropped.png deleted file mode 100644 index a1c8b2d7..00000000 Binary files a/openvidu-internet-explorer/web/resources/images/openvidu_vert_white_bg_trans_cropped.png and /dev/null differ diff --git a/openvidu-internet-explorer/web/style.css b/openvidu-internet-explorer/web/style.css deleted file mode 100644 index 033e90d8..00000000 --- a/openvidu-internet-explorer/web/style.css +++ /dev/null @@ -1,256 +0,0 @@ -html { - position: relative; - min-height: 100%; -} - -nav { - height: 50px; - width: 100%; - z-index: 1; - background-color: #4d4d4d !important; - border-color: #4d4d4d !important; - border-top-right-radius: 0 !important; - border-top-left-radius: 0 !important; -} - -.navbar-header { - width: 100%; -} - -.nav-icon { - padding: 5px 15px 5px 15px; - float: right; -} - -nav a { - color: #ccc !important; -} - -nav i.fa { - font-size: 40px; - color: #ccc; -} - -nav a:hover { - color: #a9a9a9 !important; -} - -nav i.fa:hover { - color: #a9a9a9; -} - -#main-container { - padding-bottom: 80px; -} - -.horizontal-center { - margin: 0 auto; -} - -.form-control { - color: #0088aa; - font-weight: bold; -} - -.form-control:focus { - border-color: #0088aa; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(0, 136, 170, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(0, 136, 170, 0.6); -} - -input.btn { - font-weight: bold; -} - -.btn { - font-weight: bold !important; -} - -.btn-success { - background-color: #06d362 !important; - border-color: #06d362; -} - -.btn-success:hover { - background-color: #1abd61 !important; - border-color: #1abd61; -} - -.footer { - position: absolute; - bottom: 0; - width: 100%; - height: 60px; - background-color: #4d4d4d; -} - -.footer .text-muted { - margin: 20px 0; - float: left; - color: #ccc; -} - -.openvidu-logo { - height: 35px; - float: right; - margin: 12px 0; - -webkit-transition: all 0.1s ease-in-out; - -moz-transition: all 0.1s ease-in-out; - -o-transition: all 0.1s ease-in-out; - transition: all 0.1s ease-in-out; -} - -.openvidu-logo:hover { - -webkit-filter: grayscale(0.5); - filter: grayscale(0.5); -} - -.demo-logo { - margin: 0; - height: 22px; - float: left; - padding-right: 8px; -} - -a:hover .demo-logo { - -webkit-filter: brightness(0.7); - filter: brightness(0.7); -} - -#join-dialog { - margin-left: auto; - margin-right: auto; - max-width: 70%; -} - -#join-dialog h1 { - color: #4d4d4d; - font-weight: bold; - text-align: center; -} - -#img-div { - text-align: center; - margin-top: 3em; - margin-bottom: 3em; -} - -#img-div img { - height: 250px; -} - -#join-dialog label { - color: #0088aa; -} - -#join-dialog input.btn { - margin-top: 15px; -} - -#session-header { - margin-bottom: 20px; -} - -#session-title { - display: inline-block; -} - -#buttonLeaveSession { - float: right; - margin-top: 20px; -} - -#video-container video { - position: relative; - width: 50%; - cursor: pointer; -} - -#video-container div { - width: 50%; - position: relative; -} - -#video-container p { - display: inline-block; - background: #f8f8f8; - padding-left: 5px; - padding-right: 5px; - color: #777777; - font-weight: bold; - border-bottom-right-radius: 4px; -} - -video { - width: 100%; - height: auto; -} - -#video-container object { - cursor: pointer; -} - -#main-video p { - position: absolute; - display: inline-block; - background: #f8f8f8; - padding-left: 5px; - padding-right: 5px; - font-size: 22px; - color: #777777; - font-weight: bold; - border-bottom-right-radius: 4px; -} - -#session img { - width: 100%; - height: auto; - display: inline-block; - object-fit: contain; - vertical-align: baseline; -} - -#session #video-container img { - position: relative; - float: left; - width: 50%; - cursor: pointer; - object-fit: cover; - height: 180px; -} - - -/* xs ans md screen resolutions*/ - -@media screen and (max-width: 991px) and (orientation: portrait) { - #join-dialog { - max-width: inherit; - } - #img-div img { - height: 10%; - } - #img-div { - margin-top: 2em; - margin-bottom: 2em; - } - .container-fluid>.navbar-collapse, .container-fluid>.navbar-header, .container>.navbar-collapse, .container>.navbar-header { - margin-right: 0; - margin-left: 0; - } - .navbar-header i.fa { - font-size: 30px; - } - .navbar-header a.nav-icon { - padding: 7px 3px 7px 3px; - } -} - -@media only screen and (max-height: 767px) and (orientation: landscape) { - #img-div { - margin-top: 1em; - margin-bottom: 1em; - } - #join-dialog { - max-width: inherit; - } -} \ No newline at end of file