diff --git a/openvidu-mvc-java/.gitignore b/openvidu-mvc-java/.gitignore
deleted file mode 100644
index 950fc085..00000000
--- a/openvidu-mvc-java/.gitignore
+++ /dev/null
@@ -1,24 +0,0 @@
-# Compiled class file
-*.class
-
-# Log file
-*.log
-
-# BlueJ files
-*.ctxt
-
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
-
-# Package Files #
-*.jar
-*.war
-*.ear
-*.zip
-*.tar.gz
-*.rar
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-
-target/
diff --git a/openvidu-mvc-java/LICENSE b/openvidu-mvc-java/LICENSE
deleted file mode 100644
index 8dada3ed..00000000
--- a/openvidu-mvc-java/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-mvc-java/README.md b/openvidu-mvc-java/README.md
deleted file mode 100644
index cba404ff..00000000
--- a/openvidu-mvc-java/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-[](http://www.apache.org/licenses/LICENSE-2.0)
-[](https://github.com/OpenVidu/openvidu/actions/workflows/openvidu-ce-test.yml)
-[](https://docs.openvidu.io/en/stable/?badge=stable)
-[](https://hub.docker.com/r/openvidu/openvidu-server-kms)
-[](https://openvidu.discourse.group/)
-
-[![][OpenViduLogo]](http://openvidu.io)
-
-openvidu-mvc-java
-===
-
-Visit [docs.openvidu.io/en/stable/tutorials/openvidu-mvc-java/](http://docs.openvidu.io/en/stable/tutorials/openvidu-mvc-java/)
-
-[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120
\ No newline at end of file
diff --git a/openvidu-mvc-java/pom.xml b/openvidu-mvc-java/pom.xml
deleted file mode 100644
index 4e80fa81..00000000
--- a/openvidu-mvc-java/pom.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
- 4.0.0
-
- io.openvidu
- openvidu-mvc-java
- 2.22.0
- jar
-
- openvidu-mvc-java
- https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-mvc-java
-
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.1.4.RELEASE
-
-
-
- UTF-8
- 1.8
- io.openvidu.mvc.java.App
- openvidu
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
- junit
- junit
- test
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
-
- org.springframework.boot
- spring-boot-devtools
- true
-
-
- io.openvidu
- openvidu-java-client
- 2.22.0
-
-
-
-
diff --git a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/App.java b/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/App.java
deleted file mode 100644
index 1c2e5ce8..00000000
--- a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/App.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package io.openvidu.mvc.java;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class App {
- public static void main(String[] args) {
- SpringApplication.run(App.class, args);
- }
-
-}
diff --git a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/LoginController.java b/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/LoginController.java
deleted file mode 100644
index 09a8aa19..00000000
--- a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/LoginController.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package io.openvidu.mvc.java;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.servlet.http.HttpSession;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-
-import io.openvidu.java.client.OpenViduRole;
-
-@Controller
-public class LoginController {
-
- public class MyUser {
-
- String name;
- String pass;
- OpenViduRole role;
-
- public MyUser(String name, String pass, OpenViduRole role) {
- this.name = name;
- this.pass = pass;
- this.role = role;
- }
- }
-
- public static Map users = new ConcurrentHashMap<>();
-
- public LoginController() {
- users.put("publisher1", new MyUser("publisher1", "pass", OpenViduRole.PUBLISHER));
- users.put("publisher2", new MyUser("publisher2", "pass", OpenViduRole.PUBLISHER));
- users.put("subscriber", new MyUser("subscriber", "pass", OpenViduRole.SUBSCRIBER));
- }
-
- @RequestMapping(value = "/")
- public String logout(HttpSession httpSession) {
- if (checkUserLogged(httpSession)) {
- return "redirect:/dashboard";
- } else {
- httpSession.invalidate();
- return "index";
- }
- }
-
- @RequestMapping(value = "/dashboard", method = { RequestMethod.GET, RequestMethod.POST })
- public String login(@RequestParam(name = "user", required = false) String user,
- @RequestParam(name = "pass", required = false) String pass, Model model, HttpSession httpSession) {
-
- // Check if the user is already logged in
- String userName = (String) httpSession.getAttribute("loggedUser");
- if (userName != null) {
- // User is already logged. Immediately return dashboard
- model.addAttribute("username", userName);
- return "dashboard";
- }
-
- // User wasn't logged and wants to
- if (login(user, pass)) { // Correct user-pass
-
- // Validate session and return OK
- // Value stored in HttpSession allows us to identify the user in future requests
- httpSession.setAttribute("loggedUser", user);
- model.addAttribute("username", user);
-
- // Return dashboard.html template
- return "dashboard";
-
- } else { // Wrong user-pass
- // Invalidate session and redirect to index.html
- httpSession.invalidate();
- return "redirect:/";
- }
- }
-
- @RequestMapping(value = "/logout", method = RequestMethod.POST)
- public String logout(Model model, HttpSession httpSession) {
- httpSession.invalidate();
- return "redirect:/";
- }
-
- private boolean login(String user, String pass) {
- return (user != null && pass != null && users.containsKey(user) && users.get(user).pass.equals(pass));
- }
-
- private boolean checkUserLogged(HttpSession httpSession) {
- return !(httpSession == null || httpSession.getAttribute("loggedUser") == null);
- }
-}
\ No newline at end of file
diff --git a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/SessionController.java b/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/SessionController.java
deleted file mode 100644
index e79ebb7d..00000000
--- a/openvidu-mvc-java/src/main/java/io/openvidu/mvc/java/SessionController.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package io.openvidu.mvc.java;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.servlet.http.HttpSession;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-
-import io.openvidu.java.client.ConnectionProperties;
-import io.openvidu.java.client.ConnectionType;
-import io.openvidu.java.client.OpenVidu;
-import io.openvidu.java.client.OpenViduRole;
-import io.openvidu.java.client.Session;
-
-@Controller
-public class SessionController {
-
- // OpenVidu object as entrypoint of the SDK
- private OpenVidu openVidu;
-
- // Collection to pair session names and OpenVidu Session objects
- private Map mapSessions = new ConcurrentHashMap<>();
- // Collection to pair session names and tokens (the inner Map pairs tokens and
- // role associated)
- private Map> mapSessionNamesTokens = new ConcurrentHashMap<>();
-
- // URL where our OpenVidu server is listening
- private String OPENVIDU_URL;
- // Secret shared with our OpenVidu server
- private String SECRET;
-
- public SessionController(@Value("${openvidu.secret}") String secret, @Value("${openvidu.url}") String openviduUrl) {
- this.SECRET = secret;
- this.OPENVIDU_URL = openviduUrl;
- this.openVidu = new OpenVidu(OPENVIDU_URL, SECRET);
- }
-
- @RequestMapping(value = "/session", method = RequestMethod.POST)
- public String joinSession(@RequestParam(name = "data") String clientData,
- @RequestParam(name = "session-name") String sessionName, Model model, HttpSession httpSession) {
-
- try {
- checkUserLogged(httpSession);
- } catch (Exception e) {
- return "index";
- }
- System.out.println("Getting sessionId and token | {sessionName}={" + sessionName + "}");
-
- // Role associated to this user
- OpenViduRole role = LoginController.users.get(httpSession.getAttribute("loggedUser")).role;
-
- // Optional data to be passed to other users when this user connects to the
- // video-call. In this case, a JSON with the value we stored in the HttpSession
- // object on login
- String serverData = "{\"serverData\": \"" + httpSession.getAttribute("loggedUser") + "\"}";
-
- // Build connectionProperties object with the serverData and the role
- ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC)
- .role(role).data(serverData).build();
-
- if (this.mapSessions.get(sessionName) != null) {
- // Session already exists
- System.out.println("Existing session " + sessionName);
- try {
-
- // Generate a new token with the recently created connectionProperties
- String token = this.mapSessions.get(sessionName).createConnection(connectionProperties).getToken();
-
- // Update our collection storing the new token
- this.mapSessionNamesTokens.get(sessionName).put(token, role);
-
- // Add all the needed attributes to the template
- model.addAttribute("sessionName", sessionName);
- model.addAttribute("token", token);
- model.addAttribute("nickName", clientData);
- model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
-
- // Return session.html template
- return "session";
-
- } catch (Exception e) {
- // If error just return dashboard.html template
- model.addAttribute("username", httpSession.getAttribute("loggedUser"));
- return "dashboard";
- }
- } else {
- // New session
- System.out.println("New session " + sessionName);
- try {
-
- // Create a new OpenVidu Session
- Session session = this.openVidu.createSession();
- // Generate a new token with the recently created connectionProperties
- String token = session.createConnection(connectionProperties).getToken();
-
- // Store the session and the token in our collections
- this.mapSessions.put(sessionName, session);
- this.mapSessionNamesTokens.put(sessionName, new ConcurrentHashMap<>());
- this.mapSessionNamesTokens.get(sessionName).put(token, role);
-
- // Add all the needed attributes to the template
- model.addAttribute("sessionName", sessionName);
- model.addAttribute("token", token);
- model.addAttribute("nickName", clientData);
- model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
-
- // Return session.html template
- return "session";
-
- } catch (Exception e) {
- // If error just return dashboard.html template
- model.addAttribute("username", httpSession.getAttribute("loggedUser"));
- return "dashboard";
- }
- }
- }
-
- @RequestMapping(value = "/leave-session", method = RequestMethod.POST)
- public String removeUser(@RequestParam(name = "session-name") String sessionName,
- @RequestParam(name = "token") String token, Model model, HttpSession httpSession) throws Exception {
-
- try {
- checkUserLogged(httpSession);
- } catch (Exception e) {
- return "index";
- }
- System.out.println("Removing user | sessioName=" + sessionName + ", token=" + token);
-
- // If the session exists ("TUTORIAL" in this case)
- if (this.mapSessions.get(sessionName) != null && this.mapSessionNamesTokens.get(sessionName) != null) {
-
- // If the token exists
- if (this.mapSessionNamesTokens.get(sessionName).remove(token) != null) {
- // User left the session
- if (this.mapSessionNamesTokens.get(sessionName).isEmpty()) {
- // Last user left: session must be removed
- this.mapSessions.remove(sessionName);
- }
- return "redirect:/dashboard";
-
- } else {
- // The TOKEN wasn't valid
- System.out.println("Problems in the app server: the TOKEN wasn't valid");
- return "redirect:/dashboard";
- }
-
- } else {
- // The SESSION does not exist
- System.out.println("Problems in the app server: the SESSION does not exist");
- return "redirect:/dashboard";
- }
- }
-
- private void checkUserLogged(HttpSession httpSession) throws Exception {
- if (httpSession == null || httpSession.getAttribute("loggedUser") == null) {
- throw new Exception("User not logged");
- }
- }
-
-}
diff --git a/openvidu-mvc-java/src/main/resources/application.properties b/openvidu-mvc-java/src/main/resources/application.properties
deleted file mode 100644
index 2463c1ef..00000000
--- a/openvidu-mvc-java/src/main/resources/application.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-server.port: 5000
-server.ssl.enabled: true
-server.ssl.key-store: classpath:openvidu-selfsigned.jks
-server.ssl.key-store-password: openvidu
-server.ssl.key-store-type: JKS
-server.ssl.key-alias: openvidu-selfsigned
-
-openvidu.url: https://localhost:4443/
-openvidu.secret: MY_SECRET
diff --git a/openvidu-mvc-java/src/main/resources/openvidu-selfsigned.jks b/openvidu-mvc-java/src/main/resources/openvidu-selfsigned.jks
deleted file mode 100644
index 4a02ecc4..00000000
Binary files a/openvidu-mvc-java/src/main/resources/openvidu-selfsigned.jks and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/images/favicon.ico b/openvidu-mvc-java/src/main/resources/static/images/favicon.ico
deleted file mode 100644
index 0e2249ad..00000000
Binary files a/openvidu-mvc-java/src/main/resources/static/images/favicon.ico and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png b/openvidu-mvc-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png
deleted file mode 100644
index e0309e62..00000000
Binary files a/openvidu-mvc-java/src/main/resources/static/images/openvidu_globe_bg_transp_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/images/openvidu_grey_bg_transp_cropped.png b/openvidu-mvc-java/src/main/resources/static/images/openvidu_grey_bg_transp_cropped.png
deleted file mode 100644
index 49f311a6..00000000
Binary files a/openvidu-mvc-java/src/main/resources/static/images/openvidu_grey_bg_transp_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/images/openvidu_vert_white_bg_trans_cropped.png b/openvidu-mvc-java/src/main/resources/static/images/openvidu_vert_white_bg_trans_cropped.png
deleted file mode 100644
index a1c8b2d7..00000000
Binary files a/openvidu-mvc-java/src/main/resources/static/images/openvidu_vert_white_bg_trans_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/images/subscriber-msg.jpg b/openvidu-mvc-java/src/main/resources/static/images/subscriber-msg.jpg
deleted file mode 100644
index 1666fb40..00000000
Binary files a/openvidu-mvc-java/src/main/resources/static/images/subscriber-msg.jpg and /dev/null differ
diff --git a/openvidu-mvc-java/src/main/resources/static/openvidu-browser-2.22.0.js b/openvidu-mvc-java/src/main/resources/static/openvidu-browser-2.22.0.js
deleted file mode 100644
index 89d6c20b..00000000
--- a/openvidu-mvc-java/src/main/resources/static/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-mvc-java/src/main/resources/static/style.css b/openvidu-mvc-java/src/main/resources/static/style.css
deleted file mode 100644
index 20fd6f4e..00000000
--- a/openvidu-mvc-java/src/main/resources/static/style.css
+++ /dev/null
@@ -1,377 +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;
-}
-
-.vertical-center {
- width: -webkit-fit-content;
- width: fit-content;
- margin: auto;
-}
-
-.vertical-center#not-logged form {
- width: -moz-fit-content;
- margin: auto;
-}
-
-.vertical-center#not-logged table {
- width: -moz-fit-content;
- margin: auto;
-}
-
-.vertical-center table {
- margin-top: 3em !important;
-}
-
-.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;
-}
-
-.btn-info {
- background-color: #0088aa !important;
- border-color: #0088aa;
-}
-
-.btn-info:hover {
- background-color: #00708c !important;
- border-color: #00708c;
-}
-
-.btn-warning {
- background-color: #ffcc00 !important;
- border-color: #ffcc00;
- color: #4d4d4d;
-}
-
-.btn-warning:hover {
- background-color: #eabb3a !important;
- border-color: #eabb3a;
- color: #4d4d4d;
-}
-
-.btn-warning:active {
- color: #4d4d4d;
-}
-
-.btn-warning:focus {
- color: #4d4d4d;
-}
-
-.btn-warning:active:focus {
- color: #4d4d4d;
-}
-
-.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 {
- padding-top: 40px;
-}
-
-#not-logged {
- padding-top: 40px;
-}
-
-#join-dialog h1 {
- color: #4d4d4d;
- font-weight: bold;
- text-align: center;
-}
-
-#join-dialog label {
- color: #0088aa;
-}
-
-#join-dialog input.btn {
- margin-top: 15px;
-}
-
-#join-dialog hr {
- background: #4d4d4d;
-}
-
-#img-div {
- text-align: center;
- padding-bottom: 3em;
-}
-
-#img-div img {
- height: 15%;
-}
-
-#logged {
- width: 100%;
-}
-
-#join {
- max-width: 700px;
- margin: auto;
-}
-
-#session-header {
- margin-bottom: 20px;
-}
-
-#session-header form {
- display: inline;
-}
-
-#session-title {
- display: inline-block;
-}
-
-#buttonLeaveSession {
- float: right;
- margin-top: 20px;
-}
-
-#video-container video {
- position: relative;
- float: left;
- width: 50%;
- cursor: pointer;
-}
-
-#video-container div {
- float: left;
- width: 50%;
- position: relative;
- margin-left: -50%;
-}
-
-#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-container p.userName {
- float: right;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 0px;
- font-weight: lighter;
- font-size: 12px;
- background: #777777;
- color: #f8f8f8;
-}
-
-video {
- width: 100%;
- height: auto;
-}
-
-#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;
-}
-
-#main-video p.userName {
- position: absolute;
- right: 0;
- font-size: 16px !important;
- margin-right: 15px;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 0px;
- font-weight: lighter;
- font-size: 12px;
- background: #777777;
- color: #f8f8f8;
-}
-
-
-#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;
-}
-
-table i {
- cursor: pointer;
- margin-left: 1em;
-}
-
-#tooltip-div {
- text-align: left;
-}
-
-#tooltip-div hr {
- margin: 5px 0;
-}
-
-#login-info {
- text-align: right;
-}
-
-#login-info form {
- display: inline;
-}
-
-#login-info div {
- display: inline;
- margin-right: 1em;
-}
-
-#name-user {
- font-weight: bold;
-}
-
-
-/* xs ans md screen resolutions*/
-
-@media screen and (max-width: 991px) {
- #join {
- padding-top: inherit;
- }
-
- #not-logged {
- padding-top: inherit;
- }
- .container .navbar-header {
- margin-right: 0 !important;
- margin-left: 0 !important;
- }
- .nav-icon {
- padding: 9px 8px 9px 8px;
- }
- nav i.fa {
- font-size: 32px;
- }
- .vertical-center {
- padding-top: 10px;
- }
- #img-div {
- padding-bottom: 1em;
- }
- #img-div img {
- height: 10%;
- }
-}
\ No newline at end of file
diff --git a/openvidu-mvc-java/src/main/resources/templates/dashboard.html b/openvidu-mvc-java/src/main/resources/templates/dashboard.html
deleted file mode 100644
index 9ab9bc42..00000000
--- a/openvidu-mvc-java/src/main/resources/templates/dashboard.html
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
- openvidu-mvc-java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Join a video session
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/openvidu-mvc-java/src/main/resources/templates/index.html b/openvidu-mvc-java/src/main/resources/templates/index.html
deleted file mode 100644
index 72dad44f..00000000
--- a/openvidu-mvc-java/src/main/resources/templates/index.html
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-
- openvidu-mvc-java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- User
- Pass
- Role
-
-
- publisher1
- pass
- PUBLISHER
-
-
- publisher2
- pass
- PUBLISHER
-
-
- subscriber
- pass
- SUBSCRIBER
-
-
-
-
-
-
-
-
-
-
diff --git a/openvidu-mvc-java/src/main/resources/templates/session.html b/openvidu-mvc-java/src/main/resources/templates/session.html
deleted file mode 100644
index 1d27b591..00000000
--- a/openvidu-mvc-java/src/main/resources/templates/session.html
+++ /dev/null
@@ -1,254 +0,0 @@
-
-
-
- openvidu-mvc-java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/openvidu-mvc-java/src/test/java/io/openvidu/mvc/java/test/AppTest.java b/openvidu-mvc-java/src/test/java/io/openvidu/mvc/java/test/AppTest.java
deleted file mode 100644
index 83b7f68e..00000000
--- a/openvidu-mvc-java/src/test/java/io/openvidu/mvc/java/test/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package io.openvidu.mvc.java.test;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest
- extends TestCase
-{
- /**
- * Create the test case
- *
- * @param testName name of the test case
- */
- public AppTest( String testName )
- {
- super( testName );
- }
-
- /**
- * @return the suite of tests being tested
- */
- public static Test suite()
- {
- return new TestSuite( AppTest.class );
- }
-
- /**
- * Rigourous Test :-)
- */
- public void testApp()
- {
- assertTrue( true );
- }
-}
diff --git a/openvidu-mvc-node/.gitignore b/openvidu-mvc-node/.gitignore
deleted file mode 100644
index dbe3e1ad..00000000
--- a/openvidu-mvc-node/.gitignore
+++ /dev/null
@@ -1,60 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# Typescript v1 declaration files
-typings/
-
-# Optional npm cache directory
-.npm
-
-# Optional eslint cache
-.eslintcache
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-
-.vscode/
diff --git a/openvidu-mvc-node/LICENSE b/openvidu-mvc-node/LICENSE
deleted file mode 100644
index 8dada3ed..00000000
--- a/openvidu-mvc-node/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-mvc-node/README.md b/openvidu-mvc-node/README.md
deleted file mode 100644
index 6690a47e..00000000
--- a/openvidu-mvc-node/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-[](http://www.apache.org/licenses/LICENSE-2.0)
-[](https://github.com/OpenVidu/openvidu/actions/workflows/openvidu-ce-test.yml)
-[](https://docs.openvidu.io/en/stable/?badge=stable)
-[](https://hub.docker.com/r/openvidu/openvidu-server-kms)
-[](https://openvidu.discourse.group/)
-
-[![][OpenViduLogo]](http://openvidu.io)
-
-openvidu-mvc-node
-===
-
-Visit [docs.openvidu.io/en/stable/tutorials/openvidu-mvc-node/](http://docs.openvidu.io/en/stable/tutorials/openvidu-mvc-node/)
-
-[OpenViduLogo]: https://secure.gravatar.com/avatar/5daba1d43042f2e4e85849733c8e5702?s=120
\ No newline at end of file
diff --git a/openvidu-mvc-node/openviducert.pem b/openvidu-mvc-node/openviducert.pem
deleted file mode 100644
index 545ccee2..00000000
--- a/openvidu-mvc-node/openviducert.pem
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDgzCCAmugAwIBAgIJALDBPXTrlAhlMA0GCSqGSIb3DQEBCwUAMFgxCzAJBgNV
-BAYTAkVTMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhPcGVuVmlkdTEh
-MB8GCSqGSIb3DQEJARYSb3BlbnZpZHVAZ21haWwuY29tMB4XDTE3MDUzMDE1MjQx
-N1oXDTI3MDUyODE1MjQxN1owWDELMAkGA1UEBhMCRVMxEzARBgNVBAgMClNvbWUt
-U3RhdGUxETAPBgNVBAoMCE9wZW5WaWR1MSEwHwYJKoZIhvcNAQkBFhJvcGVudmlk
-dUBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDbK/i
-LN80IBnGUbzA4AFl4KQEX6RCreythnfOSnIcQSTP+KjesZMFgsGV0LteDxeCJ+kq
-4YoS+CW7ojvOEz3xjCgo4tFdevz8ZoeO0RBQIbARbPako4OXC6vWs6LHwCR0aDWo
-9HfS1Uusb8g77csRPRlNA3DGR8dcRTiEBdfHS6Jh/7V7XiDlaxPXj+iIY8PyCqOf
-gv4clDt17R+dendDsgYxbmZaodrppNocMQIyUaDIwI4DZOa8nQYk9uuUhkiAFAQB
-O642bx6NI0qDu5KgtMmbaS6s+rMnrL8eeZOicqff6XoC6tk6GE8Fo4iYkxp2gAiT
-sigaSwpNRWhupISVAgMBAAGjUDBOMB0GA1UdDgQWBBTi3sXqpf42vUNehFU6y4Pn
-PTJFRDAfBgNVHSMEGDAWgBTi3sXqpf42vUNehFU6y4PnPTJFRDAMBgNVHRMEBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBfl0C7XAbPdJzCjCsboMTzfC2B4uwspbST
-MbUGnmNkTwzeOOsrLQmlCznKGprYV9vGR0MwBzYw2swWCzg/2MLN8swW7NF9gMkK
-K61AANxT0qZV/aZhdM7W//pHJoQYsBsQT7cuTrL/VB/niD81uMA/mSWyXIn8KDIy
-CPY6jiZ4qiIJnQWhWm1Cazv6O7wjDisvB1cCJhDvBv42KkFwtigt5MQnBEGOI2LD
-iKCkXfj33E5B6n0sEel68WgYi6rx2tsR9lzAjCRF+jgNd7FfeUi999m7ykgEACR5
-OYRqkVcIXz30r9RxQyFqZLNzyO9oaVZpex8ZbWwEzNXG2ccddnMJ
------END CERTIFICATE-----
diff --git a/openvidu-mvc-node/openvidukey.pem b/openvidu-mvc-node/openvidukey.pem
deleted file mode 100644
index 9b47696d..00000000
--- a/openvidu-mvc-node/openvidukey.pem
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAw2yv4izfNCAZxlG8wOABZeCkBF+kQq3srYZ3zkpyHEEkz/io
-3rGTBYLBldC7Xg8XgifpKuGKEvglu6I7zhM98YwoKOLRXXr8/GaHjtEQUCGwEWz2
-pKODlwur1rOix8AkdGg1qPR30tVLrG/IO+3LET0ZTQNwxkfHXEU4hAXXx0uiYf+1
-e14g5WsT14/oiGPD8gqjn4L+HJQ7de0fnXp3Q7IGMW5mWqHa6aTaHDECMlGgyMCO
-A2TmvJ0GJPbrlIZIgBQEATuuNm8ejSNKg7uSoLTJm2kurPqzJ6y/HnmTonKn3+l6
-AurZOhhPBaOImJMadoAIk7IoGksKTUVobqSElQIDAQABAoIBAGr/2HFjFjbpGJOw
-b0O/oqRQUh2e7EYiCoOcK37E3iPAO1KvmG6OFayfwjSwG9bNNpbqGU2EPeBTA/3v
-PwV/HZxinB5+yhl/3IKp9LDqoR7uwwNXgNf2O3d5SXX91zO9bXhbEn5WlEDYzl00
-uxKtCVF//ZlgN+AoruxDbkVDGbkhKHGzvqOW+BWwbYHPOttQ9TQx2ss5+DekpDFV
-/FuvXGOcSSV/N+WbDwsqUiM8ovkcflEgQjZYlAY4Ro2U2buf3fKEmy1jxSznNp30
-QA4WyYypyS8Hz6S/F4nsjtS3ufCurrWBv4vt2qB+8tH//07NUacjQWZdvEAtaJ+G
-IyJgsOUCgYEA38b2SQiw74fwoK6so2XdpCzOObLQBOT1aeZQjt3v8XZ0MPzwWJZm
-VkMBmolcEw24xA3jHhOQYafAGjRdaKxlRbJyGJqwENfAs7hO5JSLLWWXsorJQcb7
-1OVTFPt7NZopx2Kw7kGGuj9884w57cSl9lsuMptqk8W7pbTo5opOfl8CgYEA35CR
-x23kaFDh8+zKUuSdIrkUJ66cazgOfF0FYKiDewd1sGEdZT+gq7Wo8Hi8cp9q+Kuq
-MkGrTzu21yMi2fo7RKoSOtV4RQViu6PuoYR/KvRq4F4abHEAivAG4xhPQife84IB
-NkDQXaE9EXTP7DXPwj4HV8CnC9LC2qPFU7GVeYsCgYBWPK6c5qSJKrIouif9sDwC
-EOJIighwWmvZK9DPvefB/gw49MEK4qr9g0US8Oxyy07w/wkPhiqV97eoYZW9yPIe
-Me6WXMaNNxgkKlr86+HW1NfpDmMQ3kYefWHPLDsHJSoElJvqtYXeMKlOkjOg1a+/
-iNP83Lftyr3N1jIK5jHpsQKBgE1+clm7qOnT547C7JrxLdrEZs0ehI/R3YuUPvHz
-V6gEvPHHqAXZmVsL3CSG5WOiCNVrw9Ip2zTa0RUf08vVJkg1353PMyJRrJi4SVZp
-dB8ym/1sASLHxNVkQC7l1UtsQKcN0Fe6/b8GzgFICW6qdHqzP55WZFD/3JUnIZZS
-PyrjAoGBAMfuE0Nrw9Fq7f8+U/SsqiW9djJp4R34EF5n8qHkotfRoAbGktCGxLoF
-QMbB9X0ibRMpxEKPHj+V0FXu9zUKFuqoriRc3alQYLNzJEdKeQQ/AN5xjG3ilM6D
-/FunImbvSdJLjR9Ue6vlFdOquHevBCFDiHOJPQJ/y4qyZR5Avluw
------END RSA PRIVATE KEY-----
diff --git a/openvidu-mvc-node/package-lock.json b/openvidu-mvc-node/package-lock.json
deleted file mode 100644
index fb1f069f..00000000
--- a/openvidu-mvc-node/package-lock.json
+++ /dev/null
@@ -1,1381 +0,0 @@
-{
- "name": "openvidu-mvc-node",
- "version": "2.22.0",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "openvidu-mvc-node",
- "version": "2.22.0",
- "license": "Apache-2.0",
- "dependencies": {
- "body-parser": "1.19.0",
- "ejs": "3.1.6",
- "express": "4.17.1",
- "express-session": "1.17.1",
- "openvidu-node-client": "2.22.0"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
- },
- "node_modules/async": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
- "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g=="
- },
- "node_modules/axios": {
- "version": "0.21.4",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
- "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
- "dependencies": {
- "follow-redirects": "^1.14.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
- "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
- "dependencies": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
- },
- "node_modules/content-disposition": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
- "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
- "dependencies": {
- "safe-buffer": "5.1.2"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
- "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
- },
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
- },
- "node_modules/ejs": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
- "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
- "dependencies": {
- "jake": "^10.6.1"
- },
- "bin": {
- "ejs": "bin/cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.17.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
- "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
- "dependencies": {
- "accepts": "~1.3.7",
- "array-flatten": "1.1.1",
- "body-parser": "1.19.0",
- "content-disposition": "0.5.3",
- "content-type": "~1.0.4",
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.1.2",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.5",
- "qs": "6.7.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.1.2",
- "send": "0.17.1",
- "serve-static": "1.14.1",
- "setprototypeof": "1.1.1",
- "statuses": "~1.5.0",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/express-session": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
- "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
- "dependencies": {
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~2.0.0",
- "on-headers": "~1.0.2",
- "parseurl": "~1.3.3",
- "safe-buffer": "5.2.0",
- "uid-safe": "~2.1.5"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/express-session/node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/express-session/node_modules/safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
- },
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
- "dependencies": {
- "minimatch": "^5.0.1"
- }
- },
- "node_modules/filelist/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
- "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
- "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/follow-redirects": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
- "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
- "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
- "dependencies": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/jake": {
- "version": "10.8.5",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
- "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
- "dependencies": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.1",
- "minimatch": "^3.0.4"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- },
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/on-headers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
- "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/openvidu-node-client": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/openvidu-node-client/-/openvidu-node-client-2.22.0.tgz",
- "integrity": "sha512-DzaErycodhfp0H82w8ysCAt+HMGm+GZH0Wt1I+CZBYur1waycj+iWVwk/1LeMUedVrSwC4eTa+WBFqMRLgRCUA==",
- "dependencies": {
- "axios": "0.21.4",
- "buffer": "6.0.3"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/random-bytes": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
- "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
- "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
- "dependencies": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "node_modules/send": {
- "version": "0.17.1",
- "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
- "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "destroy": "~1.0.4",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "~1.7.2",
- "mime": "1.6.0",
- "ms": "2.1.1",
- "on-finished": "~2.3.0",
- "range-parser": "~1.2.1",
- "statuses": "~1.5.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- },
- "node_modules/serve-static": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
- "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
- "dependencies": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.17.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
- "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
- },
- "node_modules/statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
- "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/uid-safe": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
- "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
- "dependencies": {
- "random-bytes": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
- "engines": {
- "node": ">= 0.8"
- }
- }
- },
- "dependencies": {
- "accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "requires": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- }
- },
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
- },
- "async": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
- "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g=="
- },
- "axios": {
- "version": "0.21.4",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
- "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
- "requires": {
- "follow-redirects": "^1.14.0"
- }
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
- },
- "body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
- "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
- "requires": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
- }
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "requires": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
- },
- "content-disposition": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
- "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
- "requires": {
- "safe-buffer": "5.1.2"
- }
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
- },
- "cookie": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
- "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
- },
- "cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
- },
- "destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
- },
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
- },
- "ejs": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
- "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
- "requires": {
- "jake": "^10.6.1"
- }
- },
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
- },
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
- },
- "etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
- },
- "express": {
- "version": "4.17.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
- "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
- "requires": {
- "accepts": "~1.3.7",
- "array-flatten": "1.1.1",
- "body-parser": "1.19.0",
- "content-disposition": "0.5.3",
- "content-type": "~1.0.4",
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.1.2",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.5",
- "qs": "6.7.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.1.2",
- "send": "0.17.1",
- "serve-static": "1.14.1",
- "setprototypeof": "1.1.1",
- "statuses": "~1.5.0",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- }
- },
- "express-session": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
- "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
- "requires": {
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~2.0.0",
- "on-headers": "~1.0.2",
- "parseurl": "~1.3.3",
- "safe-buffer": "5.2.0",
- "uid-safe": "~2.1.5"
- },
- "dependencies": {
- "depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
- },
- "safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
- }
- }
- },
- "filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
- "requires": {
- "minimatch": "^5.0.1"
- },
- "dependencies": {
- "brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "requires": {
- "balanced-match": "^1.0.0"
- }
- },
- "minimatch": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
- "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
- "requires": {
- "brace-expansion": "^2.0.1"
- }
- }
- }
- },
- "finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
- "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- }
- },
- "follow-redirects": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz",
- "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ=="
- },
- "forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
- },
- "fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
- },
- "http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
- "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
- "requires": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
- }
- },
- "iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
- },
- "ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
- },
- "jake": {
- "version": "10.8.5",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
- "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
- "requires": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.1",
- "minimatch": "^3.0.4"
- }
- },
- "media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
- },
- "merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
- },
- "methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
- },
- "mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
- },
- "mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
- },
- "mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "requires": {
- "mime-db": "1.52.0"
- }
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- },
- "negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
- },
- "on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "requires": {
- "ee-first": "1.1.1"
- }
- },
- "on-headers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
- "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
- },
- "openvidu-node-client": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/openvidu-node-client/-/openvidu-node-client-2.22.0.tgz",
- "integrity": "sha512-DzaErycodhfp0H82w8ysCAt+HMGm+GZH0Wt1I+CZBYur1waycj+iWVwk/1LeMUedVrSwC4eTa+WBFqMRLgRCUA==",
- "requires": {
- "axios": "0.21.4",
- "buffer": "6.0.3"
- }
- },
- "parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
- },
- "path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
- },
- "proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "requires": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- }
- },
- "qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
- },
- "random-bytes": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
- "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
- },
- "range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
- },
- "raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
- "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
- "requires": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "send": {
- "version": "0.17.1",
- "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
- "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
- "requires": {
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "destroy": "~1.0.4",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "~1.7.2",
- "mime": "1.6.0",
- "ms": "2.1.1",
- "on-finished": "~2.3.0",
- "range-parser": "~1.2.1",
- "statuses": "~1.5.0"
- },
- "dependencies": {
- "ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- }
- }
- },
- "serve-static": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
- "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
- "requires": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.17.1"
- }
- },
- "setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
- "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
- },
- "statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
- "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
- },
- "type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "requires": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- }
- },
- "uid-safe": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
- "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
- "requires": {
- "random-bytes": "~1.0.0"
- }
- },
- "unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
- },
- "utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
- },
- "vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
- }
- }
-}
diff --git a/openvidu-mvc-node/package.json b/openvidu-mvc-node/package.json
deleted file mode 100644
index 0fdccb48..00000000
--- a/openvidu-mvc-node/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "openvidu-mvc-node",
- "version": "2.22.0",
- "description": "",
- "main": "server.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/OpenVidu/openvidu-tutorials.git"
- },
- "author": "openvidu@gmail.com",
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/OpenVidu/openvidu-tutorials/issues"
- },
- "homepage": "https://github.com/OpenVidu/openvidu-tutorials#readme",
- "dependencies": {
- "body-parser": "1.19.0",
- "ejs": "3.1.6",
- "express": "4.17.1",
- "express-session": "1.17.1",
- "openvidu-node-client": "2.22.0"
- }
-}
diff --git a/openvidu-mvc-node/public/images/favicon.ico b/openvidu-mvc-node/public/images/favicon.ico
deleted file mode 100644
index 0e2249ad..00000000
Binary files a/openvidu-mvc-node/public/images/favicon.ico and /dev/null differ
diff --git a/openvidu-mvc-node/public/images/openvidu_globe_bg_transp_cropped.png b/openvidu-mvc-node/public/images/openvidu_globe_bg_transp_cropped.png
deleted file mode 100644
index e0309e62..00000000
Binary files a/openvidu-mvc-node/public/images/openvidu_globe_bg_transp_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-node/public/images/openvidu_grey_bg_transp_cropped.png b/openvidu-mvc-node/public/images/openvidu_grey_bg_transp_cropped.png
deleted file mode 100644
index 49f311a6..00000000
Binary files a/openvidu-mvc-node/public/images/openvidu_grey_bg_transp_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-node/public/images/openvidu_vert_white_bg_trans_cropped.png b/openvidu-mvc-node/public/images/openvidu_vert_white_bg_trans_cropped.png
deleted file mode 100644
index a1c8b2d7..00000000
Binary files a/openvidu-mvc-node/public/images/openvidu_vert_white_bg_trans_cropped.png and /dev/null differ
diff --git a/openvidu-mvc-node/public/images/subscriber-msg.jpg b/openvidu-mvc-node/public/images/subscriber-msg.jpg
deleted file mode 100644
index 1666fb40..00000000
Binary files a/openvidu-mvc-node/public/images/subscriber-msg.jpg and /dev/null differ
diff --git a/openvidu-mvc-node/public/openvidu-browser-2.22.0.js b/openvidu-mvc-node/public/openvidu-browser-2.22.0.js
deleted file mode 100644
index 89d6c20b..00000000
--- a/openvidu-mvc-node/public/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-mvc-node/public/style.css b/openvidu-mvc-node/public/style.css
deleted file mode 100644
index 20fd6f4e..00000000
--- a/openvidu-mvc-node/public/style.css
+++ /dev/null
@@ -1,377 +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;
-}
-
-.vertical-center {
- width: -webkit-fit-content;
- width: fit-content;
- margin: auto;
-}
-
-.vertical-center#not-logged form {
- width: -moz-fit-content;
- margin: auto;
-}
-
-.vertical-center#not-logged table {
- width: -moz-fit-content;
- margin: auto;
-}
-
-.vertical-center table {
- margin-top: 3em !important;
-}
-
-.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;
-}
-
-.btn-info {
- background-color: #0088aa !important;
- border-color: #0088aa;
-}
-
-.btn-info:hover {
- background-color: #00708c !important;
- border-color: #00708c;
-}
-
-.btn-warning {
- background-color: #ffcc00 !important;
- border-color: #ffcc00;
- color: #4d4d4d;
-}
-
-.btn-warning:hover {
- background-color: #eabb3a !important;
- border-color: #eabb3a;
- color: #4d4d4d;
-}
-
-.btn-warning:active {
- color: #4d4d4d;
-}
-
-.btn-warning:focus {
- color: #4d4d4d;
-}
-
-.btn-warning:active:focus {
- color: #4d4d4d;
-}
-
-.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 {
- padding-top: 40px;
-}
-
-#not-logged {
- padding-top: 40px;
-}
-
-#join-dialog h1 {
- color: #4d4d4d;
- font-weight: bold;
- text-align: center;
-}
-
-#join-dialog label {
- color: #0088aa;
-}
-
-#join-dialog input.btn {
- margin-top: 15px;
-}
-
-#join-dialog hr {
- background: #4d4d4d;
-}
-
-#img-div {
- text-align: center;
- padding-bottom: 3em;
-}
-
-#img-div img {
- height: 15%;
-}
-
-#logged {
- width: 100%;
-}
-
-#join {
- max-width: 700px;
- margin: auto;
-}
-
-#session-header {
- margin-bottom: 20px;
-}
-
-#session-header form {
- display: inline;
-}
-
-#session-title {
- display: inline-block;
-}
-
-#buttonLeaveSession {
- float: right;
- margin-top: 20px;
-}
-
-#video-container video {
- position: relative;
- float: left;
- width: 50%;
- cursor: pointer;
-}
-
-#video-container div {
- float: left;
- width: 50%;
- position: relative;
- margin-left: -50%;
-}
-
-#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-container p.userName {
- float: right;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 0px;
- font-weight: lighter;
- font-size: 12px;
- background: #777777;
- color: #f8f8f8;
-}
-
-video {
- width: 100%;
- height: auto;
-}
-
-#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;
-}
-
-#main-video p.userName {
- position: absolute;
- right: 0;
- font-size: 16px !important;
- margin-right: 15px;
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 0px;
- font-weight: lighter;
- font-size: 12px;
- background: #777777;
- color: #f8f8f8;
-}
-
-
-#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;
-}
-
-table i {
- cursor: pointer;
- margin-left: 1em;
-}
-
-#tooltip-div {
- text-align: left;
-}
-
-#tooltip-div hr {
- margin: 5px 0;
-}
-
-#login-info {
- text-align: right;
-}
-
-#login-info form {
- display: inline;
-}
-
-#login-info div {
- display: inline;
- margin-right: 1em;
-}
-
-#name-user {
- font-weight: bold;
-}
-
-
-/* xs ans md screen resolutions*/
-
-@media screen and (max-width: 991px) {
- #join {
- padding-top: inherit;
- }
-
- #not-logged {
- padding-top: inherit;
- }
- .container .navbar-header {
- margin-right: 0 !important;
- margin-left: 0 !important;
- }
- .nav-icon {
- padding: 9px 8px 9px 8px;
- }
- nav i.fa {
- font-size: 32px;
- }
- .vertical-center {
- padding-top: 10px;
- }
- #img-div {
- padding-bottom: 1em;
- }
- #img-div img {
- height: 10%;
- }
-}
\ No newline at end of file
diff --git a/openvidu-mvc-node/server.js b/openvidu-mvc-node/server.js
deleted file mode 100644
index 9a437ae2..00000000
--- a/openvidu-mvc-node/server.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/* CONFIGURATION */
-
-var OpenVidu = require('openvidu-node-client').OpenVidu;
-var OpenViduRole = require('openvidu-node-client').OpenViduRole;
-
-// Check launch arguments: must receive openvidu-server URL and the secret
-if (process.argv.length != 4) {
- console.log("Usage: node " + __filename + " OPENVIDU_URL OPENVIDU_SECRET");
- process.exit(-1);
-}
-// For demo purposes we ignore self-signed certificate
-process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
-
-// Node imports
-var express = require('express');
-var fs = require('fs');
-var session = require('express-session');
-var https = require('https');
-var bodyParser = require('body-parser'); // Pull information from HTML POST (express4)
-var app = express(); // Create our app with express
-
-// Server configuration
-app.use(session({
- saveUninitialized: true,
- resave: false,
- secret: 'MY_SECRET'
-}));
-app.use(express.static(__dirname + '/public')); // Set the static files location
-app.use(bodyParser.urlencoded({
- 'extended': 'true'
-})); // Parse application/x-www-form-urlencoded
-app.use(bodyParser.json()); // Parse application/json
-app.use(bodyParser.json({
- type: 'application/vnd.api+json'
-})); // Parse application/vnd.api+json as json
-app.set('view engine', 'ejs'); // Embedded JavaScript as template engine
-
-// Listen (start app with node server.js)
-var options = {
- key: fs.readFileSync('openvidukey.pem'),
- cert: fs.readFileSync('openviducert.pem')
-};
-https.createServer(options, app).listen(5000);
-
-// Mock database
-var users = [{
- user: "publisher1",
- pass: "pass",
- role: OpenViduRole.PUBLISHER
-}, {
- user: "publisher2",
- pass: "pass",
- role: OpenViduRole.PUBLISHER
-}, {
- user: "subscriber",
- pass: "pass",
- role: OpenViduRole.SUBSCRIBER
-}];
-
-// Environment variable: URL where our OpenVidu server is listening
-var OPENVIDU_URL = process.argv[2];
-// Environment variable: secret shared with our OpenVidu server
-var OPENVIDU_SECRET = process.argv[3];
-
-// Entrypoint to OpenVidu Node Client SDK
-var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
-
-// Collection to pair session names with OpenVidu Session objects
-var mapSessions = {};
-// Collection to pair session names with tokens
-var mapSessionNamesTokens = {};
-
-console.log("App listening on port 5000");
-
-/* CONFIGURATION */
-
-
-
-/* REST API */
-
-app.post('/', loginController);
-app.get('/', loginController);
-
-function loginController(req, res) {
- if (req.session.loggedUser) { // User is logged
- user = req.session.loggedUser;
- res.redirect('/dashboard');
- } else { // User is not logged
- req.session.destroy();
- res.render('index.ejs');
- }
-}
-
-app.post('/logout', (req, res) => {
- req.session.destroy();
- res.redirect('/');
-});
-
-app.post('/dashboard', dashboardController);
-app.get('/dashboard', dashboardController);
-
-function dashboardController(req, res) {
-
- // Check if the user is already logged in
- if (isLogged(req.session)) {
- // User is already logged. Immediately return dashboard
- user = req.session.loggedUser;
- res.render('dashboard.ejs', {
- user: user
- });
- } else {
- // User wasn't logged and wants to
-
- // Retrieve params from POST body
- var user = req.body.user;
- var pass = req.body.pass;
- console.log("Logging in | {user, pass}={" + user + ", " + pass + "}");
-
- if (login(user, pass)) { // Correct user-pass
- // Validate session and return OK
- // Value stored in req.session allows us to identify the user in future requests
- console.log("'" + user + "' has logged in");
- req.session.loggedUser = user;
- res.render('dashboard.ejs', {
- user: user
- });
- } else { // Wrong user-pass
- // Invalidate session and return index template
- console.log("'" + user + "' invalid credentials");
- req.session.destroy();
- res.redirect('/');
- }
- }
-}
-
-app.post('/session', (req, res) => {
- if (!isLogged(req.session)) {
- req.session.destroy();
- res.redirect('/');
- } else {
- // The nickname sent by the client
- var clientData = req.body.data;
- // The video-call to connect
- var sessionName = req.body.sessionname;
-
- // Role associated to this user
- var role = users.find(u => (u.user === req.session.loggedUser)).role;
-
- // Optional data to be passed to other users when this user connects to the video-call
- // In this case, a JSON with the value we stored in the req.session object on login
- var serverData = JSON.stringify({ serverData: req.session.loggedUser });
-
- console.log("Getting a token | {sessionName}={" + sessionName + "}");
-
- // Build connectionProperties object with the serverData and the role
- var connectionProperties = {
- data: serverData,
- role: role
- };
-
- if (mapSessions[sessionName]) {
- // Session already exists
- console.log('Existing session ' + sessionName);
-
- // Get the existing Session from the collection
- var mySession = mapSessions[sessionName];
-
- // Generate a new token asynchronously with the recently created connectionProperties
- mySession.createConnection(connectionProperties)
- .then(connection => {
-
- // Store the new token in the collection of tokens
- mapSessionNamesTokens[sessionName].push(connection.token);
-
- // Return session template with all the needed attributes
- res.render('session.ejs', {
- sessionId: mySession.getSessionId(),
- token: connection.token,
- nickName: clientData,
- userName: req.session.loggedUser,
- sessionName: sessionName
- });
- })
- .catch(error => {
- console.error(error);
- });
- } else {
- // New session
- console.log('New session ' + sessionName);
-
- // Create a new OpenVidu Session asynchronously
- OV.createSession()
- .then(session => {
- // Store the new Session in the collection of Sessions
- mapSessions[sessionName] = session;
- // Store a new empty array in the collection of tokens
- mapSessionNamesTokens[sessionName] = [];
-
- // Generate a new token asynchronously with the recently created connectionProperties
- session.createConnection(connectionProperties)
- .then(connection => {
-
- // Store the new token in the collection of tokens
- mapSessionNamesTokens[sessionName].push(connection.token);
-
- // Return session template with all the needed attributes
- res.render('session.ejs', {
- sessionName: sessionName,
- token: connection.token,
- nickName: clientData,
- userName: req.session.loggedUser,
- });
- })
- .catch(error => {
- console.error(error);
- });
- })
- .catch(error => {
- console.error(error);
- });
- }
- }
-});
-
-app.post('/leave-session', (req, res) => {
- if (!isLogged(req.session)) {
- req.session.destroy();
- res.render('index.ejs');
- } else {
- // Retrieve params from POST body
- var sessionName = req.body.sessionname;
- var token = req.body.token;
- console.log('Removing user | {sessionName, token}={' + sessionName + ', ' + token + '}');
-
- // If the session exists
- if (mapSessions[sessionName] && mapSessionNamesTokens[sessionName]) {
- var tokens = mapSessionNamesTokens[sessionName];
- var index = tokens.indexOf(token);
-
- // If the token exists
- if (index !== -1) {
- // Token removed
- tokens.splice(index, 1);
- console.log(sessionName + ': ' + tokens.toString());
- } else {
- var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
- console.log(msg);
- res.redirect('/dashboard');
- }
- if (tokens.length == 0) {
- // Last user left: session must be removed
- console.log(sessionName + ' empty!');
- delete mapSessions[sessionName];
- }
- res.redirect('/dashboard');
- } else {
- var msg = 'Problems in the app server: the SESSION does not exist';
- console.log(msg);
- res.status(500).send(msg);
- }
- }
-});
-
-/* REST API */
-
-
-
-/* AUXILIARY METHODS */
-
-function login(user, pass) {
- return (user != null &&
- pass != null &&
- users.find(u => (u.user === user) && (u.pass === pass)));
-}
-
-function isLogged(session) {
- return (session.loggedUser != null);
-}
-
-function getBasicAuth() {
- return 'Basic ' + (new Buffer('OPENVIDUAPP:' + OPENVIDU_SECRET).toString('base64'));
-}
-
-/* AUXILIARY METHODS */
diff --git a/openvidu-mvc-node/views/dashboard.ejs b/openvidu-mvc-node/views/dashboard.ejs
deleted file mode 100644
index 028bce67..00000000
--- a/openvidu-mvc-node/views/dashboard.ejs
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
- openvidu-mvc-node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Join a video session
-
-
-
-
Logged as <%= user %>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/openvidu-mvc-node/views/index.ejs b/openvidu-mvc-node/views/index.ejs
deleted file mode 100644
index 67edeff5..00000000
--- a/openvidu-mvc-node/views/index.ejs
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-
- openvidu-mvc-node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- User
- Pass
- Role
-
-
- publisher1
- pass
- PUBLISHER
-
-
- publisher2
- pass
- PUBLISHER
-
-
- subscriber
- pass
- SUBSCRIBER
-
-
-
-
-
-
-
-
-
-
diff --git a/openvidu-mvc-node/views/session.ejs b/openvidu-mvc-node/views/session.ejs
deleted file mode 100644
index 13276e30..00000000
--- a/openvidu-mvc-node/views/session.ejs
+++ /dev/null
@@ -1,253 +0,0 @@
-
-
-
- openvidu-mvc-node
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-